Skip to content

Commit a0af288

Browse files
committed
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.
1 parent 799e402 commit a0af288

File tree

1 file changed

+170
-0
lines changed

1 file changed

+170
-0
lines changed

dnsapi/dns_googledomains.sh

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

0 commit comments

Comments
 (0)