You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

253 lines
6.8 KiB

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