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.

178 lines
4.5 KiB

2 months ago
  1. #!/usr/bin/env sh
  2. # shellcheck disable=SC2034
  3. dns_googledomains_info='Google Domains
  4. Site: Domains.Google.com
  5. Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_googledomains
  6. Options:
  7. GOOGLEDOMAINS_ACCESS_TOKEN API Access Token
  8. GOOGLEDOMAINS_ZONE Zone
  9. Issues: github.com/acmesh-official/acme.sh/issues/4545
  10. Author: Alex Leigh <leigh@alexleigh.me>
  11. '
  12. GOOGLEDOMAINS_API="https://acmedns.googleapis.com/v1/acmeChallengeSets"
  13. ######## Public functions ########
  14. #Usage: dns_googledomains_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
  15. dns_googledomains_add() {
  16. fulldomain=$1
  17. txtvalue=$2
  18. _info "Invoking Google Domains ACME DNS API."
  19. if ! _dns_googledomains_setup; then
  20. return 1
  21. fi
  22. zone="$(_dns_googledomains_get_zone "$fulldomain")"
  23. if [ -z "$zone" ]; then
  24. _err "Could not find a Google Domains-managed zone containing the requested domain."
  25. return 1
  26. fi
  27. _debug zone "$zone"
  28. _debug txtvalue "$txtvalue"
  29. _info "Adding TXT record for $fulldomain."
  30. if _dns_googledomains_api "$zone" ":rotateChallenges" "{\"accessToken\":\"$GOOGLEDOMAINS_ACCESS_TOKEN\",\"recordsToAdd\":[{\"fqdn\":\"$fulldomain\",\"digest\":\"$txtvalue\"}],\"keepExpiredRecords\":true}"; then
  31. if _contains "$response" "$txtvalue"; then
  32. _info "TXT record added."
  33. return 0
  34. else
  35. _err "Error adding TXT record."
  36. return 1
  37. fi
  38. fi
  39. _err "Error adding TXT record."
  40. return 1
  41. }
  42. #Usage: dns_googledomains_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
  43. dns_googledomains_rm() {
  44. fulldomain=$1
  45. txtvalue=$2
  46. _info "Invoking Google Domains ACME DNS API."
  47. if ! _dns_googledomains_setup; then
  48. return 1
  49. fi
  50. zone="$(_dns_googledomains_get_zone "$fulldomain")"
  51. if [ -z "$zone" ]; then
  52. _err "Could not find a Google Domains-managed domain based on request."
  53. return 1
  54. fi
  55. _debug zone "$zone"
  56. _debug txtvalue "$txtvalue"
  57. _info "Removing TXT record for $fulldomain."
  58. if _dns_googledomains_api "$zone" ":rotateChallenges" "{\"accessToken\":\"$GOOGLEDOMAINS_ACCESS_TOKEN\",\"recordsToRemove\":[{\"fqdn\":\"$fulldomain\",\"digest\":\"$txtvalue\"}],\"keepExpiredRecords\":true}"; then
  59. if _contains "$response" "$txtvalue"; then
  60. _err "Error removing TXT record."
  61. return 1
  62. else
  63. _info "TXT record removed."
  64. return 0
  65. fi
  66. fi
  67. _err "Error removing TXT record."
  68. return 1
  69. }
  70. ######## Private functions ########
  71. _dns_googledomains_setup() {
  72. if [ -n "$GOOGLEDOMAINS_SETUP_COMPLETED" ]; then
  73. return 0
  74. fi
  75. GOOGLEDOMAINS_ACCESS_TOKEN="${GOOGLEDOMAINS_ACCESS_TOKEN:-$(_readaccountconf_mutable GOOGLEDOMAINS_ACCESS_TOKEN)}"
  76. GOOGLEDOMAINS_ZONE="${GOOGLEDOMAINS_ZONE:-$(_readaccountconf_mutable GOOGLEDOMAINS_ZONE)}"
  77. if [ -z "$GOOGLEDOMAINS_ACCESS_TOKEN" ]; then
  78. GOOGLEDOMAINS_ACCESS_TOKEN=""
  79. _err "Google Domains access token was not specified."
  80. _err "Please visit Google Domains Security settings to provision an ACME DNS API access token."
  81. return 1
  82. fi
  83. if [ "$GOOGLEDOMAINS_ZONE" ]; then
  84. _savedomainconf GOOGLEDOMAINS_ACCESS_TOKEN "$GOOGLEDOMAINS_ACCESS_TOKEN"
  85. _savedomainconf GOOGLEDOMAINS_ZONE "$GOOGLEDOMAINS_ZONE"
  86. else
  87. _saveaccountconf_mutable GOOGLEDOMAINS_ACCESS_TOKEN "$GOOGLEDOMAINS_ACCESS_TOKEN"
  88. _clearaccountconf_mutable GOOGLEDOMAINS_ZONE
  89. _clearaccountconf GOOGLEDOMAINS_ZONE
  90. fi
  91. _debug GOOGLEDOMAINS_ACCESS_TOKEN "$GOOGLEDOMAINS_ACCESS_TOKEN"
  92. _debug GOOGLEDOMAINS_ZONE "$GOOGLEDOMAINS_ZONE"
  93. GOOGLEDOMAINS_SETUP_COMPLETED=1
  94. return 0
  95. }
  96. _dns_googledomains_get_zone() {
  97. domain=$1
  98. # Use zone directly if provided
  99. if [ "$GOOGLEDOMAINS_ZONE" ]; then
  100. if ! _dns_googledomains_api "$GOOGLEDOMAINS_ZONE"; then
  101. return 1
  102. fi
  103. echo "$GOOGLEDOMAINS_ZONE"
  104. return 0
  105. fi
  106. i=2
  107. while true; do
  108. curr=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
  109. _debug curr "$curr"
  110. if [ -z "$curr" ]; then
  111. return 1
  112. fi
  113. if _dns_googledomains_api "$curr"; then
  114. echo "$curr"
  115. return 0
  116. fi
  117. i=$(_math "$i" + 1)
  118. done
  119. return 1
  120. }
  121. _dns_googledomains_api() {
  122. zone=$1
  123. apimethod=$2
  124. data="$3"
  125. if [ -z "$data" ]; then
  126. response="$(_get "$GOOGLEDOMAINS_API/$zone$apimethod")"
  127. else
  128. _debug data "$data"
  129. export _H1="Content-Type: application/json"
  130. response="$(_post "$data" "$GOOGLEDOMAINS_API/$zone$apimethod")"
  131. fi
  132. _debug response "$response"
  133. if [ "$?" != "0" ]; then
  134. _err "Error"
  135. return 1
  136. fi
  137. if _contains "$response" "\"error\": {"; then
  138. return 1
  139. fi
  140. return 0
  141. }