]> git.proxmox.com Git - mirror_acme.sh.git/blame - dnsapi/dns_gandi_livedns.sh
dns_gandi: implements personal access token in addition to the (deprecated) API key
[mirror_acme.sh.git] / dnsapi / dns_gandi_livedns.sh
CommitLineData
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 16GANDI_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"
19dns_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.
56dns_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}