]> git.proxmox.com Git - mirror_acme.sh.git/blob - dnsapi/dns_dynv6.sh
9c6d330d681fa4819135666ba7127a86d73b1cc8
[mirror_acme.sh.git] / dnsapi / dns_dynv6.sh
1 #!/usr/bin/env sh
2 #Author StefanAbl
3 #Usage specify a private keyfile to use with dynv6 'export KEY="path/to/keyfile"'
4 #or use the HTTP REST API by by specifying a token 'export DYNV6_TOKEN="value"
5 #if no keyfile is specified, you will be asked if you want to create one in /home/$USER/.ssh/dynv6 and /home/$USER/.ssh/dynv6.pub
6
7 dynv6_api="https://dynv6.com/api/v2"
8 ######## Public functions #####################
9 # Please Read this guide first: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide
10 #Usage: dns_dynv6_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
11 dns_dynv6_add() {
12 fulldomain=$1
13 txtvalue=$2
14 _info "Using dynv6 api"
15 _debug fulldomain "$fulldomain"
16 _debug txtvalue "$txtvalue"
17 <<<<<<< HEAD
18 <<<<<<< HEAD
19
20 =======
21 >>>>>>> no supporting HTTP API as well
22 _get_authentication
23 if [ "$dynv6_token" ]; then
24 _dns_dynv6_add_http
25 return $?
26 <<<<<<< HEAD
27 =======
28 _get_keyfile
29 _info "using keyfile $dynv6_keyfile"
30 _your_hosts="$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts)"
31 if ! _get_domain "$fulldomain" "$_your_hosts"; then
32 _err "Host not found on your account"
33 return 1
34 fi
35 _debug "found host on your account"
36 returnval="$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts \""$_host"\" records set \""$_record"\" txt data \""$txtvalue"\")"
37 _debug "Dynv6 returend this after record was added: $returnval"
38 if _contains "$returnval" "created"; then
39 return 0
40 elif _contains "$returnval" "updated"; then
41 return 0
42 >>>>>>> first attempt to make travis happy
43 else
44 =======
45 else
46 >>>>>>> no supporting HTTP API as well
47 _info "using key file $dynv6_keyfile"
48 _your_hosts="$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts)"
49 if ! _get_domain "$fulldomain" "$_your_hosts"; then
50 _err "Host not found on your account"
51 return 1
52 fi
53 _debug "found host on your account"
54 returnval="$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts \""$_host"\" records set \""$_record"\" txt data \""$txtvalue"\")"
55 _debug "Dynv6 returned this after record was added: $returnval"
56 if _contains "$returnval" "created"; then
57 return 0
58 elif _contains "$returnval" "updated"; then
59 return 0
60 else
61 _err "Something went wrong! it does not seem like the record was added successfully"
62 return 1
63 fi
64 return 1
65 fi
66 return 1
67 }
68 #Usage: fulldomain txtvalue
69 #Remove the txt record after validation.
70 dns_dynv6_rm() {
71 fulldomain=$1
72 txtvalue=$2
73 _info "Using dynv6 API"
74 _debug fulldomain "$fulldomain"
75 _debug txtvalue "$txtvalue"
76 <<<<<<< HEAD
77 <<<<<<< HEAD
78 _get_authentication
79 if [ "$dynv6_token" ]; then
80 _dns_dynv6_rm_http
81 return $?
82 else
83 =======
84 _get_authentication
85 if [ "$dynv6_token" ]; then
86 _dns_dynv6_rm_http
87 return $?
88 else
89 >>>>>>> no supporting HTTP API as well
90 _info "using key file $dynv6_keyfile"
91 _your_hosts="$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts)"
92 if ! _get_domain "$fulldomain" "$_your_hosts"; then
93 _err "Host not found on your account"
94 return 1
95 fi
96 _debug "found host on your account"
97 _info "$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts "\"$_host\"" records del "\"$_record\"" txt)"
98 return 0
99 <<<<<<< HEAD
100 fi
101 =======
102 _get_keyfile
103 _info "using keyfile $dynv6_keyfile"
104 _your_hosts="$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts)"
105 if ! _get_domain "$fulldomain" "$_your_hosts"; then
106 _err "Host not found on your account"
107 return 1
108 fi
109 _debug "found host on your account"
110 _info "$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts "\"$_host\"" records del "\"$_record\"" txt)"
111 return 0
112 >>>>>>> first attempt to make travis happy
113 =======
114 fi
115 >>>>>>> no supporting HTTP API as well
116 }
117 #################### Private functions below ##################################
118 #Usage: No Input required
119 #returns
120 #dynv6_keyfile the path to the new key file that has been generated
121 _generate_new_key() {
122 dynv6_keyfile="$(eval echo ~"$USER")/.ssh/dynv6"
123 _info "Path to key file used: $dynv6_keyfile"
124 if [ ! -f "$dynv6_keyfile" ] && [ ! -f "$dynv6_keyfile.pub" ]; then
125 _debug "generating key in $dynv6_keyfile and $dynv6_keyfile.pub"
126 ssh-keygen -f "$dynv6_keyfile" -t ssh-ed25519 -N ''
127 else
128 _err "There is already a file in $dynv6_keyfile or $dynv6_keyfile.pub"
129 return 1
130 fi
131 }
132
133 #Usage: _acme-challenge.www.example.dynv6.net "$_your_hosts"
134 #where _your_hosts is the output of ssh -i ~/.ssh/dynv6.pub api@dynv6.com hosts
135 #returns
136 #_host= example.dynv6.net
137 #_record=_acme-challenge.www
138 #aborts if not a valid domain
139 _get_domain() {
140 #_your_hosts="$(ssh -i ~/.ssh/dynv6.pub api@dynv6.com hosts)"
141 _full_domain="$1"
142 _your_hosts="$2"
143
144 _your_hosts="$(echo "$_your_hosts" | awk '/\./ {print $1}')"
145 for l in $_your_hosts; do
146 #echo "host: $l"
147 if test "${_full_domain#*$l}" != "$_full_domain"; then
148 _record="${_full_domain%.$l}"
149 _host=$l
150 _debug "The host is $_host and the record $_record"
151 return 0
152 fi
153 done
154 _err "Either their is no such host on your dnyv6 account or it cannot be accessed with this key"
155 return 1
156 }
157
158 # Usage: No input required
159 #returns
160 #dynv6_keyfile path to the key that will be used
161 _get_authentication() {
162 <<<<<<< HEAD
163 dynv6_token="${DYNV6_TOKEN:-$(_readaccountconf_mutable dynv6_token)}"
164 if [ "$dynv6_token" ]; then
165 _debug "Found HTTP Token. Going to use the HTTP API and not the SSH API"
166 if [ "$DYNV6_TOKEN" ]; then
167 _saveaccountconf_mutable dynv6_token "$dynv6_token"
168 fi
169 else
170 =======
171 if [ "$DYNV6_TOKEN" ]; then
172 _debug "Going to use the HTTP Token you specifed and saving it for futur use"
173 _saveaccountconf_mutable dynv6_token "$DYNV6_TOKEN"
174 dynv6_token="$DYNV6_TOKEN"
175 elif [ "$(_readaccountconf_mutable dynv6_token)" ]; then
176 _debug "Found a previously used HTTP token going to use that"
177 dynv6_token="$(_readaccountconf_mutable dynv6_token)"
178 else
179 >>>>>>> no supporting HTTP API as well
180 _debug "no HTTP token found. Looking for an SSH key"
181 dynv6_keyfile="${dynv6_keyfile:-$(_readaccountconf_mutable dynv6_keyfile)}"
182 _debug "Your key is $dynv6_keyfile"
183 if [ -z "$dynv6_keyfile" ]; then
184 if [ -z "$KEY" ]; then
185 _err "You did not specify a key to use with dynv6"
186 _info "Creating new dynv6 API key to add to dynv6.com"
187 _generate_new_key
188 _info "Please add this key to dynv6.com $(cat "$dynv6_keyfile.pub")"
189 _info "Hit Enter to continue"
190 read -r _
191 #save the credentials to the account conf file.
192 else
193 dynv6_keyfile="$KEY"
194 fi
195 _saveaccountconf_mutable dynv6_keyfile "$dynv6_keyfile"
196 <<<<<<< HEAD
197 fi
198 fi
199 }
200
201 _dns_dynv6_add_http() {
202 _debug "Got HTTP token form _get_authentication method. Going to use the HTTP API"
203 if ! _get_zone_id "$fulldomain"; then
204 _err "Could not find a matching zone for $fulldomain. Maybe your HTTP Token is not authorized to access the zone"
205 return 1
206 fi
207 _get_zone_name "$_zone_id"
208 record="${fulldomain%%.$_zone_name}"
209 _set_record TXT "$record" "$txtvalue"
210 if _contains "$response" "$txtvalue"; then
211 _info "Successfully added record"
212 return 0
213 else
214 _err "Something went wrong while adding the record"
215 return 1
216 fi
217 }
218
219 _dns_dynv6_rm_http() {
220 _debug "Got HTTP token form _get_authentication method. Going to use the HTTP API"
221 if ! _get_zone_id "$fulldomain"; then
222 _err "Could not find a matching zone for $fulldomain. Maybe your HTTP Token is not authorized to access the zone"
223 return 1
224 fi
225 _get_zone_name "$_zone_id"
226 record="${fulldomain%%.$_zone_name}"
227 _get_record_id "$_zone_id" "$record" "$txtvalue"
228 _del_record "$_zone_id" "$_record_id"
229 if [ -z "$response" ]; then
230 _info "Successfully deleted record"
231 return 0
232 else
233 _err "Something went wrong while deleting the record"
234 return 1
235 fi
236 }
237
238 #get the zoneid for a specifc record or zone
239 #usage: _get_zone_id §record
240 #where $record is the record to get the id for
241 #returns _zone_id the id of the zone
242 _get_zone_id() {
243 record="$1"
244 _debug "getting zone id for $record"
245 _dynv6_rest GET zones
246
247 zones="$(echo "$response" | tr '}' '\n' | tr ',' '\n' | grep name | sed 's/\[//g' | tr -d '{' | tr -d '"')"
248 #echo $zones
249
250 selected=""
251 for z in $zones; do
252 z="${z#name:}"
253 _debug zone: "$z"
254 if _contains "$record" "$z"; then
255 _debug "$z found in $record"
256 selected="$z"
257 fi
258 done
259 if [ -z "$selected" ]; then
260 _err "no zone found"
261 return 1
262 fi
263
264 zone_id="$(echo "$response" | tr '}' '\n' | grep "$selected" | tr ',' '\n' | grep id | tr -d '"')"
265 _zone_id="${zone_id#id:}"
266 _debug "zone id: $_zone_id"
267 }
268
269 _get_zone_name() {
270 _zone_id="$1"
271 _dynv6_rest GET zones/"$_zone_id"
272 _zone_name="$(echo "$response" | tr ',' '\n' | tr -d '{' | grep name | tr -d '"')"
273 _zone_name="${_zone_name#name:}"
274 }
275
276 #usaage _get_record_id $zone_id $record
277 # where zone_id is thevalue returned by _get_zone_id
278 # and record ist in the form _acme.www for an fqdn of _acme.www.example.com
279 # returns _record_id
280 _get_record_id() {
281 _zone_id="$1"
282 record="$2"
283 value="$3"
284 _dynv6_rest GET "zones/$_zone_id/records"
285 if ! _get_record_id_from_response "$response"; then
286 _err "no such record $record found in zone $_zone_id"
287 return 1
288 fi
289 }
290
291 _get_record_id_from_response() {
292 response="$1"
293 _record_id="$(echo "$response" | tr '}' '\n' | grep "\"name\":\"$record\"" | grep "\"data\":\"$value\"" | tr ',' '\n' | grep id | tr -d '"' | tr -d 'id:')"
294 #_record_id="${_record_id#id:}"
295 if [ -z "$_record_id" ]; then
296 _err "no such record: $record found in zone $_zone_id"
297 return 1
298 fi
299 _debug "record id: $_record_id"
300 return 0
301 }
302 #usage: _set_record TXT _acme_challenge.www longvalue 12345678
303 #zone id is optional can also be set as vairable bevor calling this method
304 _set_record() {
305 type="$1"
306 record="$2"
307 value="$3"
308 if [ "$4" ]; then
309 _zone_id="$4"
310 fi
311 data="{\"name\": \"$record\", \"data\": \"$value\", \"type\": \"$type\"}"
312 #data='{ "name": "acme.test.thorn.dynv6.net", "type": "A", "data": "192.168.0.1"}'
313 echo "$data"
314 #"{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":120}"
315 _dynv6_rest POST "zones/$_zone_id/records" "$data"
316 }
317 _del_record() {
318 _zone_id=$1
319 _record_id=$2
320 _dynv6_rest DELETE zones/"$_zone_id"/records/"$_record_id"
321 }
322
323 _dynv6_rest() {
324 m=$1 #method GET,POST,DELETE or PUT
325 ep="$2" #the endpoint
326 data="$3"
327 _debug "$ep"
328
329 token_trimmed=$(echo "$dynv6_token" | tr -d '"')
330
331 export _H1="Authorization: Bearer $token_trimmed"
332 export _H2="Content-Type: application/json"
333
334 if [ "$m" != "GET" ]; then
335 _debug data "$data"
336 response="$(_post "$data" "$dynv6_api/$ep" "" "$m")"
337 else
338 response="$(_get "$dynv6_api/$ep")"
339 =======
340 fi
341 >>>>>>> no supporting HTTP API as well
342 fi
343 }
344
345
346
347 _dns_dynv6_add_http(){
348 _debug "Got HTTP token form _get_authentication method. Going to use the HTTP API"
349 if ! _get_zone_id "$fulldomain" ;then
350 _err "Could not find a matching zone for $fulldomain. Maybe your HTTP Token is not authorized to access the zone"
351 return 1
352 fi
353 _get_zone_name "$_zone_id"
354 record="${fulldomain%%.$_zone_name}"
355 _set_record TXT "$record" "$txtvalue"
356 if _contains "$response" "$txtvalue"; then
357 _info "Successfully added record"
358 return 0
359 else
360 _err "Something went wrong while adding the record"
361 return 1
362 fi
363 }
364
365 _dns_dynv6_rm_http(){
366 _debug "Got HTTP token form _get_authentication method. Going to use the HTTP API"
367 if ! _get_zone_id "$fulldomain" ;then
368 _err "Could not find a matching zone for $fulldomain. Maybe your HTTP Token is not authorized to access the zone"
369 return 1
370 fi
371 _get_zone_name "$_zone_id"
372 record="${fulldomain%%.$_zone_name}"
373 _get_record_id "$_zone_id" "$record" "$txtvalue"
374 _del_record "$_zone_id" "$_record_id"
375 if [ -z "$response" ] ; then
376 _info "Successfully deleted record"
377 return 0
378 else
379 _err "Something went wrong while deleting the record"
380 return 1
381 fi
382 }
383
384
385 #get the zoneid for a specifc record or zone
386 #usage: _get_zone_id §record
387 #where $record is the record to get the id for
388 #returns _zone_id the id of the zone
389 _get_zone_id(){
390 record="$1"
391 _debug "getting zone id for $record"
392 _dynv6_rest GET zones
393
394 zones="$(echo "$response" | tr '}' '\n' | tr ',' '\n' | grep name | sed 's/\[//g' | tr -d '{' | tr -d '"')"
395 #echo $zones
396
397 selected=""
398 for z in $zones; do
399 z="${z#name:}"
400 _debug zone: "$z"
401 if _contains "$record" "$z"; then
402 _debug "$z found in $record"
403 selected="$z"
404 fi
405 done
406 if [ -z "$selected" ]; then
407 _err "no zone found"
408 return 1
409 fi
410
411 zone_id="$(echo "$response" | tr '}' '\n' | grep "$selected" | tr ',' '\n' | grep id | tr -d '"')"
412 _zone_id="${zone_id#id:}"
413 _debug "zone id: $_zone_id"
414 }
415
416 _get_zone_name(){
417 _zone_id="$1"
418 _dynv6_rest GET zones/"$_zone_id"
419 _zone_name="$(echo "$response" | tr ',' '\n'| tr -d '{'|grep name|tr -d '"')"
420 _zone_name="${_zone_name#name:}"
421 }
422
423 #usaage _get_record_id $zone_id $record
424 # where zone_id is thevalue returned by _get_zone_id
425 # and record ist in the form _acme.www for an fqdn of _acme.www.example.com
426 # returns _record_id
427 _get_record_id(){
428 _zone_id="$1"
429 record="$2"
430 value="$3"
431 _dynv6_rest GET "zones/$_zone_id/records"
432 if ! _get_record_id_from_response "$response" ; then
433 _err "no such record $record found in zone $_zone_id"
434 return 1
435 fi
436 }
437
438 _get_record_id_from_response(){
439 response="$1"
440 _record_id="$(echo "$response" | tr '}' '\n' | grep "\"name\":\"$record\"" | grep "\"data\":\"$value\"" | tr ',' '\n' | grep id |tr -d '"'|tr -d 'id:')"
441 #_record_id="${_record_id#id:}"
442 if [ -z "$_record_id" ]; then
443 _err "no such record: $record found in zone $_zone_id"
444 return 1
445 fi
446 _debug "record id: $_record_id"
447 return 0
448 }
449 #usage: _set_record TXT _acme_challenge.www longvalue 12345678
450 #zone id is optional can also be set as vairable bevor calling this method
451 _set_record(){
452 type="$1"
453 record="$2"
454 value="$3"
455 if [ "$4" ]; then
456 _zone_id="$4"
457 fi
458 data="{\"name\": \"$record\", \"data\": \"$value\", \"type\": \"$type\"}"
459 #data='{ "name": "acme.test.thorn.dynv6.net", "type": "A", "data": "192.168.0.1"}'
460 echo "$data"
461 #"{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":120}"
462 _dynv6_rest POST "zones/$_zone_id/records" "$data"
463 }
464 _del_record(){
465 _zone_id=$1
466 _record_id=$2
467 _dynv6_rest DELETE zones/"$_zone_id"/records/"$_record_id"
468 }
469
470 _dynv6_rest() {
471 m=$1 #method GET,POST,DELETE or PUT
472 ep="$2" #the endpoint
473 data="$3"
474 _debug "$ep"
475
476 token_trimmed=$(echo "$dynv6_token" | tr -d '"')
477
478 export _H1="Authorization: Bearer $token_trimmed"
479 export _H2="Content-Type: application/json"
480
481 if [ "$m" != "GET" ]; then
482 _debug data "$data"
483 response="$(_post "$data" "$dynv6_api/$ep" "" "$m")"
484 else
485 response="$(_get "$dynv6_api/$ep")"
486 fi
487
488 if [ "$?" != "0" ]; then
489 _err "error $ep"
490 return 1
491 fi
492 _debug2 response "$response"
493 return 0
494 }
495