]> git.proxmox.com Git - mirror_acme.sh.git/blame - dnsapi/dns_gcloud.sh
Merge pull request #4158 from lufi42/dev
[mirror_acme.sh.git] / dnsapi / dns_gcloud.sh
CommitLineData
0a3ac1f5
JL
1#!/usr/bin/env sh
2
3# Author: Janos Lenart <janos@lenart.io>
4
5######## Public functions #####################
6
7# Usage: dns_gcloud_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
8dns_gcloud_add() {
9 fulldomain=$1
10 txtvalue=$2
11 _info "Using gcloud"
12 _debug fulldomain "$fulldomain"
13 _debug txtvalue "$txtvalue"
14
15 _dns_gcloud_find_zone || return $?
16
17 # Add an extra RR
18 _dns_gcloud_start_tr || return $?
19 _dns_gcloud_get_rrdatas || return $?
20 echo "$rrdatas" | _dns_gcloud_remove_rrs || return $?
16775800 21 printf "%s\n%s\n" "$rrdatas" "\"$txtvalue\"" | grep -v '^$' | _dns_gcloud_add_rrs || return $?
0a3ac1f5
JL
22 _dns_gcloud_execute_tr || return $?
23
24 _info "$fulldomain record added"
25}
26
27# Usage: dns_gcloud_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
28# Remove the txt record after validation.
29dns_gcloud_rm() {
30 fulldomain=$1
31 txtvalue=$2
32 _info "Using gcloud"
33 _debug fulldomain "$fulldomain"
34 _debug txtvalue "$txtvalue"
35
36 _dns_gcloud_find_zone || return $?
37
38 # Remove one RR
39 _dns_gcloud_start_tr || return $?
40 _dns_gcloud_get_rrdatas || return $?
41 echo "$rrdatas" | _dns_gcloud_remove_rrs || return $?
e947870d 42 echo "$rrdatas" | grep -F -v -- "\"$txtvalue\"" | _dns_gcloud_add_rrs || return $?
0a3ac1f5
JL
43 _dns_gcloud_execute_tr || return $?
44
45 _info "$fulldomain record added"
46}
47
48#################### Private functions below ##################################
49
50_dns_gcloud_start_tr() {
16775800 51 if ! trd=$(mktemp -d); then
0a3ac1f5
JL
52 _err "_dns_gcloud_start_tr: failed to create temporary directory"
53 return 1
54 fi
55 tr="$trd/tr.yaml"
56 _debug tr "$tr"
57
58 if ! gcloud dns record-sets transaction start \
16775800
JL
59 --transaction-file="$tr" \
60 --zone="$managedZone"; then
0a3ac1f5
JL
61 rm -r "$trd"
62 _err "_dns_gcloud_start_tr: failed to execute transaction"
63 return 1
64 fi
65}
66
67_dns_gcloud_execute_tr() {
68 if ! gcloud dns record-sets transaction execute \
16775800
JL
69 --transaction-file="$tr" \
70 --zone="$managedZone"; then
71 _debug tr "$(cat "$tr")"
0a3ac1f5
JL
72 rm -r "$trd"
73 _err "_dns_gcloud_execute_tr: failed to execute transaction"
74 return 1
75 fi
76 rm -r "$trd"
77
16775800 78 for i in $(seq 1 120); do
0a3ac1f5 79 if gcloud dns record-sets changes list \
441f8f3c 80 --zone="$managedZone" \
19c43451 81 --filter='status != done' |
82 grep -q '^.*'; then
16775800
JL
83 _info "_dns_gcloud_execute_tr: waiting for transaction to be comitted ($i/120)..."
84 sleep 5
0a3ac1f5
JL
85 else
86 return 0
87 fi
88 done
89
90 _err "_dns_gcloud_execute_tr: transaction is still pending after 10 minutes"
91 rm -r "$trd"
92 return 1
93}
94
95_dns_gcloud_remove_rrs() {
145b1f4f 96 if ! xargs -r gcloud dns record-sets transaction remove \
16775800
JL
97 --name="$fulldomain." \
98 --ttl="$ttl" \
99 --type=TXT \
100 --zone="$managedZone" \
c2b14d30 101 --transaction-file="$tr" --; then
16775800 102 _debug tr "$(cat "$tr")"
0a3ac1f5
JL
103 rm -r "$trd"
104 _err "_dns_gcloud_remove_rrs: failed to remove RRs"
105 return 1
106 fi
107}
108
109_dns_gcloud_add_rrs() {
110 ttl=60
145b1f4f 111 if ! xargs -r gcloud dns record-sets transaction add \
16775800
JL
112 --name="$fulldomain." \
113 --ttl="$ttl" \
114 --type=TXT \
115 --zone="$managedZone" \
c2b14d30 116 --transaction-file="$tr" --; then
16775800 117 _debug tr "$(cat "$tr")"
0a3ac1f5
JL
118 rm -r "$trd"
119 _err "_dns_gcloud_add_rrs: failed to add RRs"
120 return 1
121 fi
122}
123
124_dns_gcloud_find_zone() {
125 # Prepare a filter that matches zones that are suiteable for this entry.
126 # For example, _acme-challenge.something.domain.com might need to go into something.domain.com or domain.com;
127 # this function finds the longest postfix that has a managed zone.
128 part="$fulldomain"
129 filter="dnsName=( "
130 while [ "$part" != "" ]; do
131 filter="$filter$part. "
16775800 132 part="$(echo "$part" | sed 's/[^.]*\.*//')"
0a3ac1f5 133 done
70fdb104 134 filter="$filter) AND visibility=public"
0a3ac1f5
JL
135 _debug filter "$filter"
136
98d27c4a 137 # List domains and find the zone with the deepest sub-domain (in case of some levels of delegation)
0a3ac1f5 138 if ! match=$(gcloud dns managed-zones list \
16775800 139 --format="value(name, dnsName)" \
19c43451 140 --filter="$filter" |
141 while read -r dnsName name; do
2d72b25c 142 printf "%s\t%s\t%s\n" "$(echo "$name" | awk -F"." '{print NF-1}')" "$dnsName" "$name"
19c43451 143 done |
144 sort -n -r | _head_n 1 | cut -f2,3 | grep '^.*'); then
0a3ac1f5
JL
145 _err "_dns_gcloud_find_zone: Can't find a matching managed zone! Perhaps wrong project or gcloud credentials?"
146 return 1
147 fi
148
149 dnsName=$(echo "$match" | cut -f2)
150 _debug dnsName "$dnsName"
151 managedZone=$(echo "$match" | cut -f1)
152 _debug managedZone "$managedZone"
153}
154
155_dns_gcloud_get_rrdatas() {
156 if ! rrdatas=$(gcloud dns record-sets list \
16775800
JL
157 --zone="$managedZone" \
158 --name="$fulldomain." \
159 --type=TXT \
160 --format="value(ttl,rrdatas)"); then
0a3ac1f5
JL
161 _err "_dns_gcloud_get_rrdatas: Failed to list record-sets"
162 rm -r "$trd"
163 return 1
164 fi
165 ttl=$(echo "$rrdatas" | cut -f1)
401fd37e
RS
166 # starting with version 353.0.0 gcloud seems to
167 # separate records with a semicolon instead of commas
168 # see also https://cloud.google.com/sdk/docs/release-notes#35300_2021-08-17
169 rrdatas=$(echo "$rrdatas" | cut -f2 | sed 's/"[,;]"/"\n"/g')
0a3ac1f5 170}