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