]> git.proxmox.com Git - mirror_acme.sh.git/blame - dnsapi/dns_huaweicloud.sh
feat: add huaweicloud error handling
[mirror_acme.sh.git] / dnsapi / dns_huaweicloud.sh
CommitLineData
b8e5c0d8
EM
1#!/usr/bin/env sh
2
3# HUAWEICLOUD_Username
4# HUAWEICLOUD_Password
5# HUAWEICLOUD_ProjectID
6
7iam_api="https://iam.myhuaweicloud.com"
8fbec785 8dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" # Should work
b8e5c0d8
EM
9
10######## Public functions #####################
11
12# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
13# Used to add txt record
14#
15# Ref: https://support.huaweicloud.com/intl/zh-cn/api-dns/zh-cn_topic_0132421999.html
16#
17
18dns_huaweicloud_add() {
19 fulldomain=$1
20 txtvalue=$2
21
22 HUAWEICLOUD_Username="${HUAWEICLOUD_Username:-$(_readaccountconf_mutable HUAWEICLOUD_Username)}"
23 HUAWEICLOUD_Password="${HUAWEICLOUD_Password:-$(_readaccountconf_mutable HUAWEICLOUD_Password)}"
24 HUAWEICLOUD_ProjectID="${HUAWEICLOUD_ProjectID:-$(_readaccountconf_mutable HUAWEICLOUD_ProjectID)}"
25
c4ddddd4
EM
26 # Check information
27 if [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Password}" ] || [ -z "${HUAWEICLOUD_ProjectID}" ]; then
28 _err "Not enough information provided to dns_huaweicloud!"
f6f6550b
EM
29 return 1
30 fi
31
8fbec785 32 unset token # Clear token
b8e5c0d8 33 token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")"
8fbec785
EM
34 if [ -z "${token}" ]; then # Check token
35 _err "dns_api(dns_huaweicloud): Error getting token."
36 return 1
37 fi
38 _debug "Access token is: ${token}"
39
40 unset zoneid
b8e5c0d8 41 zoneid="$(_get_zoneid "${token}" "${fulldomain}")"
8fbec785
EM
42 if [ -z "${zoneid}" ]; then
43 _err "dns_api(dns_huaweicloud): Error getting zone id."
44 return 1
45 fi
46 _debug "Zone ID is: ${zoneid}"
b8e5c0d8
EM
47
48 _debug "Adding Record"
49 _add_record "${token}" "${fulldomain}" "${txtvalue}"
50 ret="$?"
51 if [ "${ret}" != "0" ]; then
8fbec785 52 _err "dns_api(dns_huaweicloud): Error adding record."
b8e5c0d8
EM
53 return 1
54 fi
55
56 # Do saving work if all succeeded
57 _saveaccountconf_mutable HUAWEICLOUD_Username "${HUAWEICLOUD_Username}"
58 _saveaccountconf_mutable HUAWEICLOUD_Password "${HUAWEICLOUD_Password}"
59 _saveaccountconf_mutable HUAWEICLOUD_ProjectID "${HUAWEICLOUD_ProjectID}"
60 return 0
61}
62
63# Usage: fulldomain txtvalue
64# Used to remove the txt record after validation
65#
66# Ref: https://support.huaweicloud.com/intl/zh-cn/api-dns/dns_api_64005.html
67#
68
69dns_huaweicloud_rm() {
70 fulldomain=$1
71 txtvalue=$2
72
73 HUAWEICLOUD_Username="${HUAWEICLOUD_Username:-$(_readaccountconf_mutable HUAWEICLOUD_Username)}"
74 HUAWEICLOUD_Password="${HUAWEICLOUD_Password:-$(_readaccountconf_mutable HUAWEICLOUD_Password)}"
75 HUAWEICLOUD_ProjectID="${HUAWEICLOUD_ProjectID:-$(_readaccountconf_mutable HUAWEICLOUD_ProjectID)}"
76
c4ddddd4
EM
77 # Check information
78 if [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Password}" ] || [ -z "${HUAWEICLOUD_ProjectID}" ]; then
79 _err "Not enough information provided to dns_huaweicloud!"
e01fb503
EM
80 return 1
81 fi
82
8fbec785 83 unset token # Clear token
b8e5c0d8 84 token="$(_get_token "${HUAWEICLOUD_Username}" "${HUAWEICLOUD_Password}" "${HUAWEICLOUD_ProjectID}")"
8fbec785
EM
85 if [ -z "${token}" ]; then # Check token
86 _err "dns_api(dns_huaweicloud): Error getting token."
87 return 1
88 fi
89 _debug "Access token is: ${token}"
90
91 unset zoneid
b8e5c0d8 92 zoneid="$(_get_zoneid "${token}" "${fulldomain}")"
8fbec785
EM
93 if [ -z "${zoneid}" ]; then
94 _err "dns_api(dns_huaweicloud): Error getting zone id."
95 return 1
96 fi
97 _debug "Zone ID is: ${zoneid}"
7db592d2
EM
98
99 # Remove all records
c4ddddd4
EM
100 # Therotically HuaweiCloud does not allow more than one record set
101 # But remove them recurringly to increase robusty
b8e5c0d8 102 while [ "${record_id}" != "0" ]; do
28ce1c12 103 _debug "Removing Record"
b8e5c0d8
EM
104 _rm_record "${token}" "${zoneid}" "${record_id}"
105 record_id="$(_get_recordset_id "${token}" "${fulldomain}" "${zoneid}")"
106 done
107 return 0
108}
109
110################### Private functions below ##################################
111
112# _get_zoneid
113#
114# _token=$1
115# _domain_string=$2
116#
117# printf "%s" "${_zoneid}"
118_get_zoneid() {
119 _token=$1
120 _domain_string=$2
121 export _H1="X-Auth-Token: ${_token}"
122
123 i=1
124 while true; do
125 h=$(printf "%s" "${_domain_string}" | cut -d . -f $i-100)
126 if [ -z "$h" ]; then
127 #not valid
128 return 1
129 fi
130 _debug "$h"
131 response=$(_get "${dns_api}/v2/zones?name=${h}")
132
133 if _contains "${response}" "id"; then
134 _debug "Get Zone ID Success."
135 _zoneid=$(echo "${response}" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")
136 printf "%s" "${_zoneid}"
137 return 0
138 fi
139
140 i=$(_math "$i" + 1)
141 done
142 return 1
143}
144
145_get_recordset_id() {
146 _token=$1
147 _domain=$2
148 _zoneid=$3
149 export _H1="X-Auth-Token: ${_token}"
150
151 response=$(_get "${dns_api}/v2/zones/${_zoneid}/recordsets?name=${_domain}")
152 if _contains "${response}" "id"; then
153 _id="$(echo "${response}" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")"
154 printf "%s" "${_id}"
155 return 0
156 fi
157 printf "%s" "0"
158 return 1
159}
160
161_add_record() {
162 _token=$1
163 _domain=$2
164 _txtvalue=$3
f6f6550b
EM
165
166 # Get Existing Records
167 export _H1="X-Auth-Token: ${_token}"
5d0657c4
EM
168 response=$(_get "${dns_api}/v2/zones/${zoneid}/recordsets?name=${_domain}")
169
c4ddddd4 170 _debug2 "${response}"
fd511966 171 _exist_record=$(echo "${response}" | _egrep_o '"records":[^]]*' | sed 's/\"records\"\:\[//g')
f6f6550b
EM
172 _debug "${_exist_record}"
173
174 # Check if record exist
175 # Generate body data
f6f6550b 176 if [ -z "${_exist_record}" ]; then
5d0657c4 177 _post_body="{
f6f6550b
EM
178 \"name\": \"${_domain}.\",
179 \"description\": \"ACME Challenge\",
180 \"type\": \"TXT\",
181 \"ttl\": 1,
182 \"records\": [
183 \"\\\"${_txtvalue}\\\"\"
184 ]
185 }"
c4ddddd4
EM
186 else
187 _post_body="{
188 \"name\": \"${_domain}.\",
189 \"description\": \"ACME Challenge\",
190 \"type\": \"TXT\",
191 \"ttl\": 1,
192 \"records\": [
193 ${_exist_record},
194 \"\\\"${_txtvalue}\\\"\"
195 ]
196 }"
f6f6550b 197 fi
5d0657c4
EM
198
199 _record_id="$(_get_recordset_id "${_token}" "${_domain}" "${zoneid}")"
200 _debug "Record Set ID is: ${_record_id}"
201
202 # Remove all records
203 while [ "${_record_id}" != "0" ]; do
204 _debug "Removing Record"
205 _rm_record "${_token}" "${zoneid}" "${_record_id}"
206 _record_id="$(_get_recordset_id "${_token}" "${_domain}" "${zoneid}")"
5d0657c4
EM
207 done
208
209 # Add brand new records with all old and new records
b8e5c0d8
EM
210 export _H2="Content-Type: application/json"
211 export _H1="X-Auth-Token: ${_token}"
212
c4ddddd4 213 _debug2 "${_post_body}"
5d0657c4 214 _post "${_post_body}" "${dns_api}/v2/zones/${zoneid}/recordsets" >/dev/null
b8e5c0d8
EM
215 _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")"
216 if [ "$_code" != "202" ]; then
217 _err "dns_huaweicloud: http code ${_code}"
218 return 1
219 fi
220 return 0
221}
222
5d0657c4
EM
223# _rm_record $token $zoneid $recordid
224# assume ${dns_api} exist
225# no output
226# return 0
b8e5c0d8
EM
227_rm_record() {
228 _token=$1
229 _zone_id=$2
230 _record_id=$3
231
232 export _H2="Content-Type: application/json"
233 export _H1="X-Auth-Token: ${_token}"
234
5d0657c4
EM
235 _post "" "${dns_api}/v2/zones/${_zone_id}/recordsets/${_record_id}" false "DELETE" >/dev/null
236 return $?
b8e5c0d8
EM
237}
238
239_get_token() {
240 _username=$1
241 _password=$2
242 _project=$3
243
244 _debug "Getting Token"
245 body="{
246 \"auth\": {
247 \"identity\": {
248 \"methods\": [
249 \"password\"
250 ],
251 \"password\": {
252 \"user\": {
253 \"name\": \"${_username}\",
254 \"password\": \"${_password}\",
255 \"domain\": {
256 \"name\": \"${_username}\"
257 }
258 }
259 }
260 },
261 \"scope\": {
262 \"project\": {
263 \"id\": \"${_project}\"
264 }
265 }
266 }
267 }"
268 export _H1="Content-Type: application/json;charset=utf8"
269 _post "${body}" "${iam_api}/v3/auth/tokens" >/dev/null
270 _code=$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")
271 _token=$(grep "^X-Subject-Token" "$HTTP_HEADER" | cut -d " " -f 2-)
272 _debug2 "${_code}"
273 printf "%s" "${_token}"
274 return 0
275}