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.

173 lines
4.3 KiB

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