-
-
Notifications
You must be signed in to change notification settings - Fork 5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4542 from alexleigh/master
Add support for Google Domains DNS API.
- Loading branch information
Showing
1 changed file
with
173 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |