]>
Commit | Line | Data |
---|---|---|
fab2d9dc FC |
1 | #!/usr/bin/env sh |
2 | ||
3 | # Gandi LiveDNS v5 API | |
1a08be0a JF |
4 | # https://api.gandi.net/docs/livedns/ |
5 | # https://api.gandi.net/docs/authentication/ for token + apikey (deprecated) authentication | |
fab2d9dc FC |
6 | # currently under beta |
7 | # | |
8 | # Requires GANDI API KEY set in GANDI_LIVEDNS_KEY set as environment variable | |
9 | # | |
10 | #Author: Frédéric Crozat <fcrozat@suse.com> | |
29a5311a | 11 | # Dominik Röttsches <drott@google.com> |
fab2d9dc FC |
12 | #Report Bugs here: https://github.com/fcrozat/acme.sh |
13 | # | |
14 | ######## Public functions ##################### | |
15 | ||
856811bd | 16 | GANDI_LIVEDNS_API="https://dns.api.gandi.net/api/v5" |
fab2d9dc FC |
17 | |
18 | #Usage: dns_gandi_livedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" | |
19 | dns_gandi_livedns_add() { | |
20 | fulldomain=$1 | |
21 | txtvalue=$2 | |
22 | ||
1a08be0a JF |
23 | if [ -z "$GANDI_LIVEDNS_KEY" -a -z "$GANDI_LIVEDNS_TOKEN" ]; then |
24 | _err "No Token or API key (deprecated) specified for Gandi LiveDNS." | |
25 | _err "Create your token or key and export it as GANDI_LIVEDNS_KEY or GANDI_LIVEDNS_TOKEN respectively" | |
fab2d9dc FC |
26 | return 1 |
27 | fi | |
28 | ||
1a08be0a JF |
29 | # Keep only one secret in configuration |
30 | if [ -n "$GANDI_LIVEDNS_TOKEN" ]; then | |
31 | _saveaccountconf GANDI_LIVEDNS_TOKEN "$GANDI_LIVEDNS_TOKEN" | |
32 | _clearaccountconf GANDI_LIVEDNS_KEY | |
33 | elif [ -n "$GANDI_LIVEDNS_KEY" ]; then | |
34 | _saveaccountconf GANDI_LIVEDNS_KEY "$GANDI_LIVEDNS_KEY" | |
35 | _clearaccountconf GANDI_LIVEDNS_TOKEN | |
36 | fi | |
37 | ||
38 | ||
39 | ||
fab2d9dc FC |
40 | |
41 | _debug "First detect the root zone" | |
42 | if ! _get_root "$fulldomain"; then | |
43 | _err "invalid domain" | |
44 | return 1 | |
45 | fi | |
46 | _debug fulldomain "$fulldomain" | |
47 | _debug txtvalue "$txtvalue" | |
48 | _debug domain "$_domain" | |
49 | _debug sub_domain "$_sub_domain" | |
50 | ||
29a5311a | 51 | _dns_gandi_append_record "$_domain" "$_sub_domain" "$txtvalue" |
fab2d9dc FC |
52 | } |
53 | ||
54 | #Usage: fulldomain txtvalue | |
55 | #Remove the txt record after validation. | |
56 | dns_gandi_livedns_rm() { | |
57 | fulldomain=$1 | |
58 | txtvalue=$2 | |
59 | ||
60 | _debug "First detect the root zone" | |
61 | if ! _get_root "$fulldomain"; then | |
62 | _err "invalid domain" | |
63 | return 1 | |
64 | fi | |
65 | ||
66 | _debug fulldomain "$fulldomain" | |
67 | _debug domain "$_domain" | |
68 | _debug sub_domain "$_sub_domain" | |
29a5311a | 69 | _debug txtvalue "$txtvalue" |
fab2d9dc | 70 | |
29a5311a DR |
71 | if ! _dns_gandi_existing_rrset_values "$_domain" "$_sub_domain"; then |
72 | return 1 | |
73 | fi | |
74 | _new_rrset_values=$(echo "$_rrset_values" | sed "s/...$txtvalue...//g") | |
75 | # Cleanup dangling commata. | |
76 | _new_rrset_values=$(echo "$_new_rrset_values" | sed "s/, ,/ ,/g") | |
77 | _new_rrset_values=$(echo "$_new_rrset_values" | sed "s/, *\]/\]/g") | |
78 | _new_rrset_values=$(echo "$_new_rrset_values" | sed "s/\[ *,/\[/g") | |
79 | _debug "New rrset_values" "$_new_rrset_values" | |
80 | ||
81 | _gandi_livedns_rest PUT \ | |
82 | "domains/$_domain/records/$_sub_domain/TXT" \ | |
19c43451 | 83 | "{\"rrset_ttl\": 300, \"rrset_values\": $_new_rrset_values}" && |
84 | _contains "$response" '{"message": "DNS Record Created"}' && | |
85 | _info "Removing record $(__green "success")" | |
fab2d9dc FC |
86 | } |
87 | ||
88 | #################### Private functions below ################################## | |
89 | #_acme-challenge.www.domain.com | |
90 | #returns | |
91 | # _sub_domain=_acme-challenge.www | |
92 | # _domain=domain.com | |
93 | _get_root() { | |
94 | domain=$1 | |
95 | i=2 | |
96 | p=1 | |
97 | while true; do | |
98 | h=$(printf "%s" "$domain" | cut -d . -f $i-100) | |
d24a87ca | 99 | _debug h "$h" |
fab2d9dc FC |
100 | if [ -z "$h" ]; then |
101 | #not valid | |
102 | return 1 | |
103 | fi | |
104 | ||
105 | if ! _gandi_livedns_rest GET "domains/$h"; then | |
106 | return 1 | |
107 | fi | |
108 | ||
9683ffe1 | 109 | if _contains "$response" '"code": 401'; then |
110 | _err "$response" | |
111 | return 1 | |
112 | elif _contains "$response" '"code": 404'; then | |
fab2d9dc FC |
113 | _debug "$h not found" |
114 | else | |
115 | _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) | |
116 | _domain="$h" | |
117 | return 0 | |
118 | fi | |
119 | p="$i" | |
120 | i=$(_math "$i" + 1) | |
121 | done | |
122 | return 1 | |
123 | } | |
124 | ||
29a5311a DR |
125 | _dns_gandi_append_record() { |
126 | domain=$1 | |
127 | sub_domain=$2 | |
128 | txtvalue=$3 | |
129 | ||
130 | if _dns_gandi_existing_rrset_values "$domain" "$sub_domain"; then | |
131 | _debug "Appending new value" | |
132 | _rrset_values=$(echo "$_rrset_values" | sed "s/\"]/\",\"$txtvalue\"]/") | |
133 | else | |
134 | _debug "Creating new record" "$_rrset_values" | |
135 | _rrset_values="[\"$txtvalue\"]" | |
136 | fi | |
137 | _debug new_rrset_values "$_rrset_values" | |
138 | _gandi_livedns_rest PUT "domains/$_domain/records/$sub_domain/TXT" \ | |
19c43451 | 139 | "{\"rrset_ttl\": 300, \"rrset_values\": $_rrset_values}" && |
140 | _contains "$response" '{"message": "DNS Record Created"}' && | |
141 | _info "Adding record $(__green "success")" | |
29a5311a DR |
142 | } |
143 | ||
144 | _dns_gandi_existing_rrset_values() { | |
145 | domain=$1 | |
146 | sub_domain=$2 | |
147 | if ! _gandi_livedns_rest GET "domains/$domain/records/$sub_domain"; then | |
148 | return 1 | |
149 | fi | |
150 | if ! _contains "$response" '"rrset_type": "TXT"'; then | |
151 | _debug "Does not have a _acme-challenge TXT record yet." | |
152 | return 1 | |
153 | fi | |
154 | if _contains "$response" '"rrset_values": \[\]'; then | |
155 | _debug "Empty rrset_values for TXT record, no previous TXT record." | |
156 | return 1 | |
157 | fi | |
158 | _debug "Already has TXT record." | |
19c43451 | 159 | _rrset_values=$(echo "$response" | _egrep_o 'rrset_values.*\[.*\]' | |
160 | _egrep_o '\[".*\"]') | |
29a5311a DR |
161 | return 0 |
162 | } | |
163 | ||
fab2d9dc FC |
164 | _gandi_livedns_rest() { |
165 | m=$1 | |
166 | ep="$2" | |
167 | data="$3" | |
168 | _debug "$ep" | |
169 | ||
170 | export _H1="Content-Type: application/json" | |
1a08be0a JF |
171 | |
172 | if [ -n "$GANDI_LIVEDNS_TOKEN" ]; then | |
173 | export _H2="Authorization: Bearer $GANDI_LIVEDNS_TOKEN" | |
174 | else | |
175 | export _H2="X-Api-Key: $GANDI_LIVEDNS_KEY" | |
176 | fi | |
fab2d9dc | 177 | |
9683ffe1 | 178 | if [ "$m" = "GET" ]; then |
179 | response="$(_get "$GANDI_LIVEDNS_API/$ep")" | |
180 | else | |
fab2d9dc FC |
181 | _debug data "$data" |
182 | response="$(_post "$data" "$GANDI_LIVEDNS_API/$ep" "" "$m")" | |
fab2d9dc FC |
183 | fi |
184 | ||
185 | if [ "$?" != "0" ]; then | |
186 | _err "error $ep" | |
187 | return 1 | |
188 | fi | |
189 | _debug2 response "$response" | |
190 | return 0 | |
191 | } |