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.

245 lines
7.6 KiB

4 years ago
4 years ago
4 years ago
  1. #!/usr/bin/env sh
  2. # shellcheck disable=SC2034
  3. dns_dgon_info='DigitalOcean.com
  4. Site: DigitalOcean.com/help/api/
  5. Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_dgon
  6. Options:
  7. DO_API_KEY API Key
  8. Author: <github@thewer.com>
  9. '
  10. ##################### Public functions #####################
  11. ## Create the text record for validation.
  12. ## Usage: fulldomain txtvalue
  13. ## EG: "_acme-challenge.www.other.domain.com" "XKrxpRBosdq0HG9i01zxXp5CPBs"
  14. dns_dgon_add() {
  15. fulldomain="$(echo "$1" | _lower_case)"
  16. txtvalue=$2
  17. DO_API_KEY="${DO_API_KEY:-$(_readaccountconf_mutable DO_API_KEY)}"
  18. # Check if API Key Exists
  19. if [ -z "$DO_API_KEY" ]; then
  20. DO_API_KEY=""
  21. _err "You did not specify DigitalOcean API key."
  22. _err "Please export DO_API_KEY and try again."
  23. return 1
  24. fi
  25. _info "Using digitalocean dns validation - add record"
  26. _debug fulldomain "$fulldomain"
  27. _debug txtvalue "$txtvalue"
  28. ## save the env vars (key and domain split location) for later automated use
  29. _saveaccountconf_mutable DO_API_KEY "$DO_API_KEY"
  30. ## split the domain for DO API
  31. if ! _get_base_domain "$fulldomain"; then
  32. _err "domain not found in your account for addition"
  33. return 1
  34. fi
  35. _debug _sub_domain "$_sub_domain"
  36. _debug _domain "$_domain"
  37. ## Set the header with our post type and key auth key
  38. export _H1="Content-Type: application/json"
  39. export _H2="Authorization: Bearer $DO_API_KEY"
  40. PURL='https://api.digitalocean.com/v2/domains/'$_domain'/records'
  41. PBODY='{"type":"TXT","name":"'$_sub_domain'","data":"'$txtvalue'","ttl":120}'
  42. _debug PURL "$PURL"
  43. _debug PBODY "$PBODY"
  44. ## the create request - post
  45. ## args: BODY, URL, [need64, httpmethod]
  46. response="$(_post "$PBODY" "$PURL")"
  47. ## check response
  48. if [ "$?" != "0" ]; then
  49. _err "error in response: $response"
  50. return 1
  51. fi
  52. _debug2 response "$response"
  53. ## finished correctly
  54. return 0
  55. }
  56. ## Remove the txt record after validation.
  57. ## Usage: fulldomain txtvalue
  58. ## EG: "_acme-challenge.www.other.domain.com" "XKrxpRBosdq0HG9i01zxXp5CPBs"
  59. dns_dgon_rm() {
  60. fulldomain="$(echo "$1" | _lower_case)"
  61. txtvalue=$2
  62. DO_API_KEY="${DO_API_KEY:-$(_readaccountconf_mutable DO_API_KEY)}"
  63. # Check if API Key Exists
  64. if [ -z "$DO_API_KEY" ]; then
  65. DO_API_KEY=""
  66. _err "You did not specify DigitalOcean API key."
  67. _err "Please export DO_API_KEY and try again."
  68. return 1
  69. fi
  70. _info "Using digitalocean dns validation - remove record"
  71. _debug fulldomain "$fulldomain"
  72. _debug txtvalue "$txtvalue"
  73. ## split the domain for DO API
  74. if ! _get_base_domain "$fulldomain"; then
  75. _err "domain not found in your account for removal"
  76. return 1
  77. fi
  78. _debug _sub_domain "$_sub_domain"
  79. _debug _domain "$_domain"
  80. ## Set the header with our post type and key auth key
  81. export _H1="Content-Type: application/json"
  82. export _H2="Authorization: Bearer $DO_API_KEY"
  83. ## get URL for the list of domains
  84. ## may get: "links":{"pages":{"last":".../v2/domains/DOM/records?page=2","next":".../v2/domains/DOM/records?page=2"}}
  85. GURL="https://api.digitalocean.com/v2/domains/$_domain/records"
  86. ## Get all the matching records
  87. while true; do
  88. ## 1) get the URL
  89. ## the create request - get
  90. ## args: URL, [onlyheader, timeout]
  91. domain_list="$(_get "$GURL")"
  92. ## check response
  93. if [ "$?" != "0" ]; then
  94. _err "error in domain_list response: $domain_list"
  95. return 1
  96. fi
  97. _debug2 domain_list "$domain_list"
  98. ## 2) find records
  99. ## check for what we are looking for: "type":"A","name":"$_sub_domain"
  100. record="$(echo "$domain_list" | _egrep_o "\"id\"\s*\:\s*\"*[0-9]+\"*[^}]*\"name\"\s*\:\s*\"$_sub_domain\"[^}]*\"data\"\s*\:\s*\"$txtvalue\"")"
  101. if [ -n "$record" ]; then
  102. ## we found records
  103. rec_ids="$(echo "$record" | _egrep_o "id\"\s*\:\s*\"*[0-9]+" | _egrep_o "[0-9]+")"
  104. _debug rec_ids "$rec_ids"
  105. if [ -n "$rec_ids" ]; then
  106. echo "$rec_ids" | while IFS= read -r rec_id; do
  107. ## delete the record
  108. ## delete URL for removing the one we dont want
  109. DURL="https://api.digitalocean.com/v2/domains/$_domain/records/$rec_id"
  110. ## the create request - delete
  111. ## args: BODY, URL, [need64, httpmethod]
  112. response="$(_post "" "$DURL" "" "DELETE")"
  113. ## check response (sort of)
  114. if [ "$?" != "0" ]; then
  115. _err "error in remove response: $response"
  116. return 1
  117. fi
  118. _debug2 response "$response"
  119. done
  120. fi
  121. fi
  122. ## 3) find the next page
  123. nextpage="$(echo "$domain_list" | _egrep_o "\"links\".*" | _egrep_o "\"next\".*" | _egrep_o "http.*page\=[0-9]+")"
  124. if [ -z "$nextpage" ]; then
  125. break
  126. fi
  127. _debug2 nextpage "$nextpage"
  128. GURL="$nextpage"
  129. done
  130. ## finished correctly
  131. return 0
  132. }
  133. ##################### Private functions below #####################
  134. ## Split the domain provided into the "bade domain" and the "start prefix".
  135. ## This function searches for the longest subdomain in your account
  136. ## for the full domain given and splits it into the base domain (zone)
  137. ## and the prefix/record to be added/removed
  138. ## USAGE: fulldomain
  139. ## EG: "_acme-challenge.two.three.four.domain.com"
  140. ## returns
  141. ## _sub_domain="_acme-challenge.two"
  142. ## _domain="three.four.domain.com" *IF* zone "three.four.domain.com" exists
  143. ## if only "domain.com" exists it will return
  144. ## _sub_domain="_acme-challenge.two.three.four"
  145. ## _domain="domain.com"
  146. _get_base_domain() {
  147. # args
  148. fulldomain="$(echo "$1" | _lower_case)"
  149. _debug fulldomain "$fulldomain"
  150. # domain max legal length = 253
  151. MAX_DOM=255
  152. ## get a list of domains for the account to check thru
  153. ## Set the headers
  154. export _H1="Content-Type: application/json"
  155. export _H2="Authorization: Bearer $DO_API_KEY"
  156. _debug DO_API_KEY "$DO_API_KEY"
  157. ## get URL for the list of domains
  158. ## may get: "links":{"pages":{"last":".../v2/domains/DOM/records?page=2","next":".../v2/domains/DOM/records?page=2"}}
  159. DOMURL="https://api.digitalocean.com/v2/domains"
  160. found=""
  161. ## while we dont have a matching domain we keep going
  162. while [ -z "$found" ]; do
  163. ## get the domain list (current page)
  164. domain_list="$(_get "$DOMURL")"
  165. ## check response
  166. if [ "$?" != "0" ]; then
  167. _err "error in domain_list response: $domain_list"
  168. return 1
  169. fi
  170. _debug2 domain_list "$domain_list"
  171. i=1
  172. while [ $i -gt 0 ]; do
  173. ## get next longest domain
  174. _domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-"$MAX_DOM")
  175. ## check we got something back from our cut (or are we at the end)
  176. if [ -z "$_domain" ]; then
  177. break
  178. fi
  179. ## we got part of a domain back - grep it out
  180. found="$(echo "$domain_list" | _egrep_o "\"name\"\s*\:\s*\"$_domain\"")"
  181. ## check if it exists
  182. if [ -n "$found" ]; then
  183. ## exists - exit loop returning the parts
  184. sub_point=$(_math $i - 1)
  185. _sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-"$sub_point")
  186. _debug _domain "$_domain"
  187. _debug _sub_domain "$_sub_domain"
  188. return 0
  189. fi
  190. ## increment cut point $i
  191. i=$(_math $i + 1)
  192. done
  193. if [ -z "$found" ]; then
  194. ## find the next page if we dont have a match
  195. nextpage="$(echo "$domain_list" | _egrep_o "\"links\".*" | _egrep_o "\"next\".*" | _egrep_o "http.*page\=[0-9]+")"
  196. if [ -z "$nextpage" ]; then
  197. _err "no record and no nextpage in digital ocean DNS removal"
  198. return 1
  199. fi
  200. _debug2 nextpage "$nextpage"
  201. DOMURL="$nextpage"
  202. fi
  203. done
  204. ## we went through the entire domain zone list and dint find one that matched
  205. ## doesnt look like we can add in the record
  206. _err "domain not found in DigitalOcean account, but we should never get here"
  207. return 1
  208. }