]>
Commit | Line | Data |
---|---|---|
b8e5c0d8 EM |
1 | #!/usr/bin/env sh |
2 | ||
3 | # HUAWEICLOUD_Username | |
4 | # HUAWEICLOUD_Password | |
5 | # HUAWEICLOUD_ProjectID | |
6 | ||
7 | iam_api="https://iam.myhuaweicloud.com" | |
8fbec785 | 8 | dns_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 | ||
18 | dns_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 | ||
69 | dns_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 | } |