Skip to content

Commit 97f87c4

Browse files
authored
Merge pull request #4542 from alexleigh/master
Add support for Google Domains DNS API.
2 parents 42a5cd9 + 2d8c0c0 commit 97f87c4

File tree

1 file changed

+173
-0
lines changed

1 file changed

+173
-0
lines changed

dnsapi/dns_googledomains.sh

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
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 zone containing the requested domain."
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 "Please 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+
_debug GOOGLEDOMAINS_ACCESS_TOKEN "$GOOGLEDOMAINS_ACCESS_TOKEN"
109+
_debug GOOGLEDOMAINS_ZONE "$GOOGLEDOMAINS_ZONE"
110+
111+
GOOGLEDOMAINS_SETUP_COMPLETED=1
112+
return 0
113+
}
114+
115+
_dns_googledomains_get_zone() {
116+
domain=$1
117+
118+
# Use zone directly if provided
119+
if [ "$GOOGLEDOMAINS_ZONE" ]; then
120+
if ! _dns_googledomains_api "$GOOGLEDOMAINS_ZONE"; then
121+
return 1
122+
fi
123+
124+
echo "$GOOGLEDOMAINS_ZONE"
125+
return 0
126+
fi
127+
128+
i=2
129+
while true; do
130+
curr=$(printf "%s" "$domain" | cut -d . -f $i-100)
131+
_debug curr "$curr"
132+
133+
if [ -z "$curr" ]; then
134+
return 1
135+
fi
136+
137+
if _dns_googledomains_api "$curr"; then
138+
echo "$curr"
139+
return 0
140+
fi
141+
142+
i=$(_math "$i" + 1)
143+
done
144+
145+
return 1
146+
}
147+
148+
_dns_googledomains_api() {
149+
zone=$1
150+
apimethod=$2
151+
data="$3"
152+
153+
if [ -z "$data" ]; then
154+
response="$(_get "$GOOGLEDOMAINS_API/$zone$apimethod")"
155+
else
156+
_debug data "$data"
157+
export _H1="Content-Type: application/json"
158+
response="$(_post "$data" "$GOOGLEDOMAINS_API/$zone$apimethod")"
159+
fi
160+
161+
_debug response "$response"
162+
163+
if [ "$?" != "0" ]; then
164+
_err "Error"
165+
return 1
166+
fi
167+
168+
if _contains "$response" "\"error\": {"; then
169+
return 1
170+
fi
171+
172+
return 0
173+
}

0 commit comments

Comments
 (0)