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.

197 lines
6.2 KiB

5 years ago
  1. #!/usr/bin/env sh
  2. # Author: Radek Sprta <sprta@vshosting.cz>
  3. #CLOUDDNS_EMAIL=XXXXX
  4. #CLOUDDNS_PASSWORD="YYYYYYYYY"
  5. #CLOUDDNS_CLIENT_ID=XXXXX
  6. CLOUDDNS_API='https://admin.vshosting.cloud/clouddns'
  7. CLOUDDNS_LOGIN_API='https://admin.vshosting.cloud/api/public/auth/login'
  8. ######## Public functions #####################
  9. # Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
  10. dns_clouddns_add() {
  11. fulldomain=$1
  12. txtvalue=$2
  13. _debug "fulldomain" "$fulldomain"
  14. CLOUDDNS_CLIENT_ID="${CLOUDDNS_CLIENT_ID:-$(_readaccountconf_mutable CLOUDDNS_CLIENT_ID)}"
  15. CLOUDDNS_EMAIL="${CLOUDDNS_EMAIL:-$(_readaccountconf_mutable CLOUDDNS_EMAIL)}"
  16. CLOUDDNS_PASSWORD="${CLOUDDNS_PASSWORD:-$(_readaccountconf_mutable CLOUDDNS_PASSWORD)}"
  17. if [ -z "$CLOUDDNS_PASSWORD" ] || [ -z "$CLOUDDNS_EMAIL" ] || [ -z "$CLOUDDNS_CLIENT_ID" ]; then
  18. CLOUDDNS_CLIENT_ID=""
  19. CLOUDDNS_EMAIL=""
  20. CLOUDDNS_PASSWORD=""
  21. _err "You didn't specify a CloudDNS password, email and client ID yet."
  22. return 1
  23. fi
  24. if ! _contains "$CLOUDDNS_EMAIL" "@"; then
  25. _err "It seems that the CLOUDDNS_EMAIL=$CLOUDDNS_EMAIL is not a valid email address."
  26. _err "Please check and retry."
  27. return 1
  28. fi
  29. # Save CloudDNS client id, email and password to config file
  30. _saveaccountconf_mutable CLOUDDNS_CLIENT_ID "$CLOUDDNS_CLIENT_ID"
  31. _saveaccountconf_mutable CLOUDDNS_EMAIL "$CLOUDDNS_EMAIL"
  32. _saveaccountconf_mutable CLOUDDNS_PASSWORD "$CLOUDDNS_PASSWORD"
  33. _debug "First detect the root zone"
  34. if ! _get_root "$fulldomain"; then
  35. _err "Invalid domain"
  36. return 1
  37. fi
  38. _debug _domain_id "$_domain_id"
  39. _debug _sub_domain "$_sub_domain"
  40. _debug _domain "$_domain"
  41. # Add TXT record
  42. data="{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"value\":\"$txtvalue\",\"domainId\":\"$_domain_id\"}"
  43. if _clouddns_api POST "record-txt" "$data"; then
  44. if _contains "$response" "$txtvalue"; then
  45. _info "Added, OK"
  46. elif _contains "$response" '"code":4136'; then
  47. _info "Already exists, OK"
  48. else
  49. _err "Add TXT record error."
  50. return 1
  51. fi
  52. fi
  53. _debug "Publishing record changes"
  54. _clouddns_api PUT "domain/$_domain_id/publish" "{\"soaTtl\":300}"
  55. }
  56. # Usage: rm _acme-challenge.www.domain.com
  57. dns_clouddns_rm() {
  58. fulldomain=$1
  59. _debug "fulldomain" "$fulldomain"
  60. CLOUDDNS_CLIENT_ID="${CLOUDDNS_CLIENT_ID:-$(_readaccountconf_mutable CLOUDDNS_CLIENT_ID)}"
  61. CLOUDDNS_EMAIL="${CLOUDDNS_EMAIL:-$(_readaccountconf_mutable CLOUDDNS_EMAIL)}"
  62. CLOUDDNS_PASSWORD="${CLOUDDNS_PASSWORD:-$(_readaccountconf_mutable CLOUDDNS_PASSWORD)}"
  63. _debug "First detect the root zone"
  64. if ! _get_root "$fulldomain"; then
  65. _err "Invalid domain"
  66. return 1
  67. fi
  68. _debug _domain_id "$_domain_id"
  69. _debug _sub_domain "$_sub_domain"
  70. _debug _domain "$_domain"
  71. # Get record ID
  72. _clouddns_api GET "domain/$_domain_id"
  73. if _contains "$response" "lastDomainRecordList"; then
  74. re="\"lastDomainRecordList\".*\"id\":\"([^\"}]*)\"[^}]*\"name\":\"$fulldomain.\","
  75. _last_domains=$(echo "$response" | _egrep_o "$re")
  76. re2="\"id\":\"([^\"}]*)\"[^}]*\"name\":\"$fulldomain.\","
  77. _record_id=$(echo "$_last_domains" | _egrep_o "$re2" | _head_n 1 | cut -d : -f 2 | cut -d , -f 1 | tr -d "\"")
  78. _debug _record_id "$_record_id"
  79. else
  80. _err "Could not retrieve record ID"
  81. return 1
  82. fi
  83. _info "Removing record"
  84. if _clouddns_api DELETE "record/$_record_id"; then
  85. if _contains "$response" "\"error\":"; then
  86. _err "Could not remove record"
  87. return 1
  88. fi
  89. fi
  90. _debug "Publishing record changes"
  91. _clouddns_api PUT "domain/$_domain_id/publish" "{\"soaTtl\":300}"
  92. }
  93. #################### Private functions below ##################################
  94. # Usage: _get_root _acme-challenge.www.domain.com
  95. # Returns:
  96. # _sub_domain=_acme-challenge.www
  97. # _domain=domain.com
  98. # _domain_id=sdjkglgdfewsdfg
  99. _get_root() {
  100. domain=$1
  101. # Get domain root
  102. data="{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$CLOUDDNS_CLIENT_ID\"}]}"
  103. _clouddns_api "POST" "domain/search" "$data"
  104. domain_slice="$domain"
  105. while [ -z "$domain_root" ]; do
  106. if _contains "$response" "\"domainName\":\"$domain_slice\.\""; then
  107. domain_root="$domain_slice"
  108. _debug domain_root "$domain_root"
  109. fi
  110. domain_slice="$(echo "$domain_slice" | cut -d . -f 2-)"
  111. done
  112. # Get domain id
  113. data="{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$CLOUDDNS_CLIENT_ID\"}, \
  114. {\"name\": \"domainName\", \"operator\": \"eq\", \"value\": \"$domain_root.\"}]}"
  115. _clouddns_api "POST" "domain/search" "$data"
  116. if _contains "$response" "\"id\":\""; then
  117. re='domainType\":\"[^\"]*\",\"id\":\"([^\"]*)\",' # Match domain id
  118. _domain_id=$(echo "$response" | _egrep_o "$re" | _head_n 1 | cut -d : -f 3 | tr -d "\",")
  119. if [ "$_domain_id" ]; then
  120. _sub_domain=$(printf "%s" "$domain" | sed "s/.$domain_root//")
  121. _domain="$domain_root"
  122. return 0
  123. fi
  124. _err 'Domain name not found on your CloudDNS account'
  125. return 1
  126. fi
  127. return 1
  128. }
  129. # Usage: _clouddns_api GET domain/search '{"data": "value"}'
  130. # Returns:
  131. # response='{"message": "api response"}'
  132. _clouddns_api() {
  133. method=$1
  134. endpoint="$2"
  135. data="$3"
  136. _debug endpoint "$endpoint"
  137. if [ -z "$CLOUDDNS_TOKEN" ]; then
  138. _clouddns_login
  139. fi
  140. _debug CLOUDDNS_TOKEN "$CLOUDDNS_TOKEN"
  141. export _H1="Content-Type: application/json"
  142. export _H2="Authorization: Bearer $CLOUDDNS_TOKEN"
  143. if [ "$method" != "GET" ]; then
  144. _debug data "$data"
  145. response="$(_post "$data" "$CLOUDDNS_API/$endpoint" "" "$method" | tr -d '\t\r\n ')"
  146. else
  147. response="$(_get "$CLOUDDNS_API/$endpoint" | tr -d '\t\r\n ')"
  148. fi
  149. # shellcheck disable=SC2181
  150. if [ "$?" != "0" ]; then
  151. _err "Error $endpoint"
  152. return 1
  153. fi
  154. _debug2 response "$response"
  155. return 0
  156. }
  157. # Returns:
  158. # CLOUDDNS_TOKEN=dslfje2rj23l
  159. _clouddns_login() {
  160. login_data="{\"email\": \"$CLOUDDNS_EMAIL\", \"password\": \"$CLOUDDNS_PASSWORD\"}"
  161. response="$(_post "$login_data" "$CLOUDDNS_LOGIN_API" "" "POST" "Content-Type: application/json")"
  162. if _contains "$response" "\"accessToken\":\""; then
  163. CLOUDDNS_TOKEN=$(echo "$response" | _egrep_o "\"accessToken\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")
  164. export CLOUDDNS_TOKEN
  165. else
  166. echo 'Could not get CloudDNS access token; check your credentials'
  167. return 1
  168. fi
  169. return 0
  170. }