]>
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 | ||
558e706b | 23 | if [ -z "$GANDI_LIVEDNS_KEY" ] && [ -z "$GANDI_LIVEDNS_TOKEN" ]; then |
1a08be0a JF |
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 | ||
fab2d9dc FC |
38 | _debug "First detect the root zone" |
39 | if ! _get_root "$fulldomain"; then | |
40 | _err "invalid domain" | |
41 | return 1 | |
42 | fi | |
43 | _debug fulldomain "$fulldomain" | |
44 | _debug txtvalue "$txtvalue" | |
45 | _debug domain "$_domain" | |
46 | _debug sub_domain "$_sub_domain" | |
47 | ||
29a5311a | 48 | _dns_gandi_append_record "$_domain" "$_sub_domain" "$txtvalue" |
fab2d9dc FC |
49 | } |
50 | ||
51 | #Usage: fulldomain txtvalue | |
52 | #Remove the txt record after validation. | |
53 | dns_gandi_livedns_rm() { | |
54 | fulldomain=$1 | |
55 | txtvalue=$2 | |
56 | ||
57 | _debug "First detect the root zone" | |
58 | if ! _get_root "$fulldomain"; then | |
59 | _err "invalid domain" | |
60 | return 1 | |
61 | fi | |
62 | ||
63 | _debug fulldomain "$fulldomain" | |
64 | _debug domain "$_domain" | |
65 | _debug sub_domain "$_sub_domain" | |
29a5311a | 66 | _debug txtvalue "$txtvalue" |
fab2d9dc | 67 | |
29a5311a DR |
68 | if ! _dns_gandi_existing_rrset_values "$_domain" "$_sub_domain"; then |
69 | return 1 | |
70 | fi | |
71 | _new_rrset_values=$(echo "$_rrset_values" | sed "s/...$txtvalue...//g") | |
72 | # Cleanup dangling commata. | |
73 | _new_rrset_values=$(echo "$_new_rrset_values" | sed "s/, ,/ ,/g") | |
74 | _new_rrset_values=$(echo "$_new_rrset_values" | sed "s/, *\]/\]/g") | |
75 | _new_rrset_values=$(echo "$_new_rrset_values" | sed "s/\[ *,/\[/g") | |
76 | _debug "New rrset_values" "$_new_rrset_values" | |
77 | ||
78 | _gandi_livedns_rest PUT \ | |
79 | "domains/$_domain/records/$_sub_domain/TXT" \ | |
19c43451 | 80 | "{\"rrset_ttl\": 300, \"rrset_values\": $_new_rrset_values}" && |
81 | _contains "$response" '{"message": "DNS Record Created"}' && | |
82 | _info "Removing record $(__green "success")" | |
fab2d9dc FC |
83 | } |
84 | ||
85 | #################### Private functions below ################################## | |
86 | #_acme-challenge.www.domain.com | |
87 | #returns | |
88 | # _sub_domain=_acme-challenge.www | |
89 | # _domain=domain.com | |
90 | _get_root() { | |
91 | domain=$1 | |
92 | i=2 | |
93 | p=1 | |
94 | while true; do | |
95 | h=$(printf "%s" "$domain" | cut -d . -f $i-100) | |
d24a87ca | 96 | _debug h "$h" |
fab2d9dc FC |
97 | if [ -z "$h" ]; then |
98 | #not valid | |
99 | return 1 | |
100 | fi | |
101 | ||
102 | if ! _gandi_livedns_rest GET "domains/$h"; then | |
103 | return 1 | |
104 | fi | |
105 | ||
9683ffe1 | 106 | if _contains "$response" '"code": 401'; then |
107 | _err "$response" | |
108 | return 1 | |
109 | elif _contains "$response" '"code": 404'; then | |
fab2d9dc FC |
110 | _debug "$h not found" |
111 | else | |
112 | _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) | |
113 | _domain="$h" | |
114 | return 0 | |
115 | fi | |
116 | p="$i" | |
117 | i=$(_math "$i" + 1) | |
118 | done | |
119 | return 1 | |
120 | } | |
121 | ||
29a5311a DR |
122 | _dns_gandi_append_record() { |
123 | domain=$1 | |
124 | sub_domain=$2 | |
125 | txtvalue=$3 | |
126 | ||
127 | if _dns_gandi_existing_rrset_values "$domain" "$sub_domain"; then | |
128 | _debug "Appending new value" | |
129 | _rrset_values=$(echo "$_rrset_values" | sed "s/\"]/\",\"$txtvalue\"]/") | |
130 | else | |
131 | _debug "Creating new record" "$_rrset_values" | |
132 | _rrset_values="[\"$txtvalue\"]" | |
133 | fi | |
134 | _debug new_rrset_values "$_rrset_values" | |
135 | _gandi_livedns_rest PUT "domains/$_domain/records/$sub_domain/TXT" \ | |
19c43451 | 136 | "{\"rrset_ttl\": 300, \"rrset_values\": $_rrset_values}" && |
137 | _contains "$response" '{"message": "DNS Record Created"}' && | |
138 | _info "Adding record $(__green "success")" | |
29a5311a DR |
139 | } |
140 | ||
141 | _dns_gandi_existing_rrset_values() { | |
142 | domain=$1 | |
143 | sub_domain=$2 | |
144 | if ! _gandi_livedns_rest GET "domains/$domain/records/$sub_domain"; then | |
145 | return 1 | |
146 | fi | |
147 | if ! _contains "$response" '"rrset_type": "TXT"'; then | |
148 | _debug "Does not have a _acme-challenge TXT record yet." | |
149 | return 1 | |
150 | fi | |
151 | if _contains "$response" '"rrset_values": \[\]'; then | |
152 | _debug "Empty rrset_values for TXT record, no previous TXT record." | |
153 | return 1 | |
154 | fi | |
155 | _debug "Already has TXT record." | |
19c43451 | 156 | _rrset_values=$(echo "$response" | _egrep_o 'rrset_values.*\[.*\]' | |
157 | _egrep_o '\[".*\"]') | |
29a5311a DR |
158 | return 0 |
159 | } | |
160 | ||
fab2d9dc FC |
161 | _gandi_livedns_rest() { |
162 | m=$1 | |
163 | ep="$2" | |
164 | data="$3" | |
165 | _debug "$ep" | |
166 | ||
167 | export _H1="Content-Type: application/json" | |
1a08be0a JF |
168 | |
169 | if [ -n "$GANDI_LIVEDNS_TOKEN" ]; then | |
170 | export _H2="Authorization: Bearer $GANDI_LIVEDNS_TOKEN" | |
171 | else | |
172 | export _H2="X-Api-Key: $GANDI_LIVEDNS_KEY" | |
173 | fi | |
fab2d9dc | 174 | |
9683ffe1 | 175 | if [ "$m" = "GET" ]; then |
176 | response="$(_get "$GANDI_LIVEDNS_API/$ep")" | |
177 | else | |
fab2d9dc FC |
178 | _debug data "$data" |
179 | response="$(_post "$data" "$GANDI_LIVEDNS_API/$ep" "" "$m")" | |
fab2d9dc FC |
180 | fi |
181 | ||
182 | if [ "$?" != "0" ]; then | |
183 | _err "error $ep" | |
184 | return 1 | |
185 | fi | |
186 | _debug2 response "$response" | |
187 | return 0 | |
188 | } |