Browse Source
Add support for Google Domains DNS API.
Add support for Google Domains DNS API.
https://domains.google/learn/gts-acme/ This is an ACME API for Google Domains customers, which is different from the Google Cloud Domains API for Google Cloud customers.pull/4542/head
Alex Leigh
2 years ago
1 changed files with 173 additions and 0 deletions
@ -0,0 +1,173 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
# Author: Alex Leigh <leigh at alexleigh dot me> |
||||
|
# Created: 2023-03-02 |
||||
|
|
||||
|
#GOOGLEDOMAINS_ACCESS_TOKEN="xxxx" |
||||
|
#GOOGLEDOMAINS_ZONE="xxxx" |
||||
|
GOOGLEDOMAINS_API="https://acmedns.googleapis.com/v1/acmeChallengeSets" |
||||
|
|
||||
|
######## Public functions ######## |
||||
|
|
||||
|
#Usage: dns_googledomains_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" |
||||
|
dns_googledomains_add() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
_info "Invoking Google Domains ACME DNS API." |
||||
|
|
||||
|
if ! _dns_googledomains_setup; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
zone="$(_dns_googledomains_get_zone "$fulldomain")" |
||||
|
if [ -z "$zone" ]; then |
||||
|
_err "Could not find a Google Domains-managed zone containing the requested domain." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_debug zone "$zone" |
||||
|
_debug txtvalue "$txtvalue" |
||||
|
|
||||
|
_info "Adding TXT record for $fulldomain." |
||||
|
if _dns_googledomains_api "$zone" ":rotateChallenges" "{\"accessToken\":\"$GOOGLEDOMAINS_ACCESS_TOKEN\",\"recordsToAdd\":[{\"fqdn\":\"$fulldomain\",\"digest\":\"$txtvalue\"}],\"keepExpiredRecords\":true}"; then |
||||
|
if _contains "$response" "$txtvalue"; then |
||||
|
_info "TXT record added." |
||||
|
return 0 |
||||
|
else |
||||
|
_err "Error adding TXT record." |
||||
|
return 1 |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
_err "Error adding TXT record." |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
#Usage: dns_googledomains_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" |
||||
|
dns_googledomains_rm() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
_info "Invoking Google Domains ACME DNS API." |
||||
|
|
||||
|
if ! _dns_googledomains_setup; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
zone="$(_dns_googledomains_get_zone "$fulldomain")" |
||||
|
if [ -z "$zone" ]; then |
||||
|
_err "Could not find a Google Domains-managed domain based on request." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_debug zone "$zone" |
||||
|
_debug txtvalue "$txtvalue" |
||||
|
|
||||
|
_info "Removing TXT record for $fulldomain." |
||||
|
if _dns_googledomains_api "$zone" ":rotateChallenges" "{\"accessToken\":\"$GOOGLEDOMAINS_ACCESS_TOKEN\",\"recordsToRemove\":[{\"fqdn\":\"$fulldomain\",\"digest\":\"$txtvalue\"}],\"keepExpiredRecords\":true}"; then |
||||
|
if _contains "$response" "$txtvalue"; then |
||||
|
_err "Error removing TXT record." |
||||
|
return 1 |
||||
|
else |
||||
|
_info "TXT record removed." |
||||
|
return 0 |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
_err "Error removing TXT record." |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
######## Private functions ######## |
||||
|
|
||||
|
_dns_googledomains_setup() { |
||||
|
if [ -n "$GOOGLEDOMAINS_SETUP_COMPLETED" ]; then |
||||
|
return 0 |
||||
|
fi |
||||
|
|
||||
|
GOOGLEDOMAINS_ACCESS_TOKEN="${GOOGLEDOMAINS_ACCESS_TOKEN:-$(_readaccountconf_mutable GOOGLEDOMAINS_ACCESS_TOKEN)}" |
||||
|
GOOGLEDOMAINS_ZONE="${GOOGLEDOMAINS_ZONE:-$(_readaccountconf_mutable GOOGLEDOMAINS_ZONE)}" |
||||
|
|
||||
|
if [ -z "$GOOGLEDOMAINS_ACCESS_TOKEN" ]; then |
||||
|
GOOGLEDOMAINS_ACCESS_TOKEN="" |
||||
|
_err "Google Domains access token was not specified." |
||||
|
_err "Please visit Google Domains Security settings to provision an ACME DNS API access token." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if [ "$GOOGLEDOMAINS_ZONE" ]; then |
||||
|
_savedomainconf GOOGLEDOMAINS_ACCESS_TOKEN "$GOOGLEDOMAINS_ACCESS_TOKEN" |
||||
|
_savedomainconf GOOGLEDOMAINS_ZONE "$GOOGLEDOMAINS_ZONE" |
||||
|
else |
||||
|
_saveaccountconf_mutable GOOGLEDOMAINS_ACCESS_TOKEN "$GOOGLEDOMAINS_ACCESS_TOKEN" |
||||
|
_clearaccountconf_mutable GOOGLEDOMAINS_ZONE |
||||
|
_clearaccountconf GOOGLEDOMAINS_ZONE |
||||
|
fi |
||||
|
|
||||
|
_debug GOOGLEDOMAINS_ACCESS_TOKEN "$GOOGLEDOMAINS_ACCESS_TOKEN" |
||||
|
_debug GOOGLEDOMAINS_ZONE "$GOOGLEDOMAINS_ZONE" |
||||
|
|
||||
|
GOOGLEDOMAINS_SETUP_COMPLETED=1 |
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
_dns_googledomains_get_zone() { |
||||
|
domain=$1 |
||||
|
|
||||
|
# Use zone directly if provided |
||||
|
if [ "$GOOGLEDOMAINS_ZONE" ]; then |
||||
|
if ! _dns_googledomains_api "$GOOGLEDOMAINS_ZONE"; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
echo "$GOOGLEDOMAINS_ZONE" |
||||
|
return 0 |
||||
|
fi |
||||
|
|
||||
|
i=2 |
||||
|
while true; do |
||||
|
curr=$(printf "%s" "$domain" | cut -d . -f $i-100) |
||||
|
_debug curr "$curr" |
||||
|
|
||||
|
if [ -z "$curr" ]; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if _dns_googledomains_api "$curr"; then |
||||
|
echo "$curr" |
||||
|
return 0 |
||||
|
fi |
||||
|
|
||||
|
i=$(_math "$i" + 1) |
||||
|
done |
||||
|
|
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
_dns_googledomains_api() { |
||||
|
zone=$1 |
||||
|
apimethod=$2 |
||||
|
data="$3" |
||||
|
|
||||
|
if [ -z "$data" ]; then |
||||
|
response="$(_get "$GOOGLEDOMAINS_API/$zone$apimethod")" |
||||
|
else |
||||
|
_debug data "$data" |
||||
|
export _H1="Content-Type: application/json" |
||||
|
response="$(_post "$data" "$GOOGLEDOMAINS_API/$zone$apimethod")" |
||||
|
fi |
||||
|
|
||||
|
_debug response "$response" |
||||
|
|
||||
|
if [ "$?" != "0" ]; then |
||||
|
_err "Error" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if _contains "$response" "\"error\": {"; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
return 0 |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue