dns_rackspace.sh 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. #!/usr/bin/env sh
  2. #
  3. #
  4. #RACKSPACE_Username=""
  5. #
  6. #RACKSPACE_Apikey=""
  7. RACKSPACE_Endpoint="https://dns.api.rackspacecloud.com/v1.0"
  8. # 20190213 - The name & id fields swapped in the API response; fix sed
  9. # 20190101 - Duplicating file for new pull request to dev branch
  10. # Original - tcocca:rackspace_dnsapi https://github.com/Neilpang/acme.sh/pull/1297
  11. ######## Public functions #####################
  12. #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
  13. dns_rackspace_add() {
  14. fulldomain="$1"
  15. _debug fulldomain="$fulldomain"
  16. txtvalue="$2"
  17. _debug txtvalue="$txtvalue"
  18. _rackspace_check_auth || return 1
  19. _rackspace_check_rootzone || return 1
  20. _info "Creating TXT record."
  21. if ! _rackspace_rest POST "$RACKSPACE_Tenant/domains/$_domain_id/records" "{\"records\":[{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"data\":\"$txtvalue\",\"ttl\":300}]}"; then
  22. return 1
  23. fi
  24. _debug2 response "$response"
  25. if ! _contains "$response" "$txtvalue" >/dev/null; then
  26. _err "Could not add TXT record."
  27. return 1
  28. fi
  29. return 0
  30. }
  31. #fulldomain txtvalue
  32. dns_rackspace_rm() {
  33. fulldomain=$1
  34. _debug fulldomain="$fulldomain"
  35. txtvalue=$2
  36. _debug txtvalue="$txtvalue"
  37. _rackspace_check_auth || return 1
  38. _rackspace_check_rootzone || return 1
  39. _info "Checking for TXT record."
  40. if ! _get_recordid "$_domain_id" "$fulldomain" "$txtvalue"; then
  41. _err "Could not get TXT record id."
  42. return 1
  43. fi
  44. if [ "$_dns_record_id" = "" ]; then
  45. _err "TXT record not found."
  46. return 1
  47. fi
  48. _info "Removing TXT record."
  49. if ! _delete_txt_record "$_domain_id" "$_dns_record_id"; then
  50. _err "Could not remove TXT record $_dns_record_id."
  51. fi
  52. return 0
  53. }
  54. #################### Private functions below ##################################
  55. #_acme-challenge.www.domain.com
  56. #returns
  57. # _sub_domain=_acme-challenge.www
  58. # _domain=domain.com
  59. # _domain_id=sdjkglgdfewsdfg
  60. _get_root_zone() {
  61. domain="$1"
  62. i=2
  63. p=1
  64. while true; do
  65. h=$(printf "%s" "$domain" | cut -d . -f $i-100)
  66. _debug h "$h"
  67. if [ -z "$h" ]; then
  68. #not valid
  69. return 1
  70. fi
  71. if ! _rackspace_rest GET "$RACKSPACE_Tenant/domains"; then
  72. return 1
  73. fi
  74. _debug2 response "$response"
  75. if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
  76. # Response looks like:
  77. # {"ttl":300,"accountId":12345,"id":1111111,"name":"example.com","emailAddress": ...<and so on>
  78. _domain_id=$(echo "$response" | sed -n "s/^.*\"id\":\([^,]*\),\"name\":\"$h\",.*/\1/p")
  79. _debug2 domain_id "$_domain_id"
  80. if [ -n "$_domain_id" ]; then
  81. _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
  82. _domain=$h
  83. return 0
  84. fi
  85. return 1
  86. fi
  87. p=$i
  88. i=$(_math "$i" + 1)
  89. done
  90. return 1
  91. }
  92. _get_recordid() {
  93. domainid="$1"
  94. fulldomain="$2"
  95. txtvalue="$3"
  96. if ! _rackspace_rest GET "$RACKSPACE_Tenant/domains/$domainid/records?name=$fulldomain&type=TXT"; then
  97. return 1
  98. fi
  99. _debug response "$response"
  100. if ! _contains "$response" "$txtvalue"; then
  101. _dns_record_id=0
  102. return 0
  103. fi
  104. _dns_record_id=$(echo "$response" | tr '{' "\n" | grep "\"data\":\"$txtvalue\"" | sed -n 's/^.*"id":"\([^"]*\)".*/\1/p')
  105. _debug _dns_record_id "$_dns_record_id"
  106. return 0
  107. }
  108. _delete_txt_record() {
  109. domainid="$1"
  110. _dns_record_id="$2"
  111. if ! _rackspace_rest DELETE "$RACKSPACE_Tenant/domains/$domainid/records?id=$_dns_record_id"; then
  112. return 1
  113. fi
  114. _debug response "$response"
  115. if ! _contains "$response" "RUNNING"; then
  116. return 1
  117. fi
  118. return 0
  119. }
  120. _rackspace_rest() {
  121. m="$1"
  122. ep="$2"
  123. data="$3"
  124. _debug ep "$ep"
  125. export _H1="Accept: application/json"
  126. export _H2="X-Auth-Token: $RACKSPACE_Token"
  127. export _H3="X-Project-Id: $RACKSPACE_Tenant"
  128. export _H4="Content-Type: application/json"
  129. if [ "$m" != "GET" ]; then
  130. _debug data "$data"
  131. response="$(_post "$data" "$RACKSPACE_Endpoint/$ep" "" "$m")"
  132. retcode=$?
  133. else
  134. _info "Getting $RACKSPACE_Endpoint/$ep"
  135. response="$(_get "$RACKSPACE_Endpoint/$ep")"
  136. retcode=$?
  137. fi
  138. if [ "$retcode" != "0" ]; then
  139. _err "error $ep"
  140. return 1
  141. fi
  142. _debug2 response "$response"
  143. return 0
  144. }
  145. _rackspace_authorization() {
  146. export _H1="Content-Type: application/json"
  147. data="{\"auth\":{\"RAX-KSKEY:apiKeyCredentials\":{\"username\":\"$RACKSPACE_Username\",\"apiKey\":\"$RACKSPACE_Apikey\"}}}"
  148. _debug data "$data"
  149. response="$(_post "$data" "https://identity.api.rackspacecloud.com/v2.0/tokens" "" "POST")"
  150. retcode=$?
  151. _debug2 response "$response"
  152. if [ "$retcode" != "0" ]; then
  153. _err "Authentication failed."
  154. return 1
  155. fi
  156. if _contains "$response" "token"; then
  157. RACKSPACE_Token="$(echo "$response" | _normalizeJson | sed -n 's/^.*"token":{.*,"id":"\([^"]*\)",".*/\1/p')"
  158. RACKSPACE_Tenant="$(echo "$response" | _normalizeJson | sed -n 's/^.*"token":{.*,"id":"\([^"]*\)"}.*/\1/p')"
  159. _debug RACKSPACE_Token "$RACKSPACE_Token"
  160. _debug RACKSPACE_Tenant "$RACKSPACE_Tenant"
  161. fi
  162. return 0
  163. }
  164. _rackspace_check_auth() {
  165. # retrieve the rackspace creds
  166. RACKSPACE_Username="${RACKSPACE_Username:-$(_readaccountconf_mutable RACKSPACE_Username)}"
  167. RACKSPACE_Apikey="${RACKSPACE_Apikey:-$(_readaccountconf_mutable RACKSPACE_Apikey)}"
  168. # check their vals for null
  169. if [ -z "$RACKSPACE_Username" ] || [ -z "$RACKSPACE_Apikey" ]; then
  170. RACKSPACE_Username=""
  171. RACKSPACE_Apikey=""
  172. _err "You didn't specify a Rackspace username and api key."
  173. _err "Please set those values and try again."
  174. return 1
  175. fi
  176. # save the username and api key to the account conf file.
  177. _saveaccountconf_mutable RACKSPACE_Username "$RACKSPACE_Username"
  178. _saveaccountconf_mutable RACKSPACE_Apikey "$RACKSPACE_Apikey"
  179. if [ -z "$RACKSPACE_Token" ]; then
  180. _info "Getting authorization token."
  181. if ! _rackspace_authorization; then
  182. _err "Can not get token."
  183. fi
  184. fi
  185. }
  186. _rackspace_check_rootzone() {
  187. _debug "First detect the root zone"
  188. if ! _get_root_zone "$fulldomain"; then
  189. _err "invalid domain"
  190. return 1
  191. fi
  192. _debug _domain_id "$_domain_id"
  193. _debug _sub_domain "$_sub_domain"
  194. _debug _domain "$_domain"
  195. }