From a0eb51e982d824892087baed2b2778f0462294fc Mon Sep 17 00:00:00 2001 From: thewer Date: Sun, 5 Mar 2017 23:04:28 +1000 Subject: [PATCH 1/7] Added native DigitalOcean automatic dns API --- README.md | 1 + dnsapi/dns_digitalocean.sh | 190 +++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100755 dnsapi/dns_digitalocean.sh diff --git a/README.md b/README.md index fd867015..e2fb2eb1 100644 --- a/README.md +++ b/README.md @@ -295,6 +295,7 @@ You don't have to do anything manually! 1. cyon.ch 1. Domain-Offensive/Resellerinterface/Domainrobot API 1. Gandi LiveDNS API +1. DigitalOcean API (native) **More APIs coming soon...** diff --git a/dnsapi/dns_digitalocean.sh b/dnsapi/dns_digitalocean.sh new file mode 100755 index 00000000..cabebff2 --- /dev/null +++ b/dnsapi/dns_digitalocean.sh @@ -0,0 +1,190 @@ +#!/usr/bin/env sh + + +## Will be called by acme.sh to add the txt record to your api system. +## returns 0 means success, otherwise error. + +## Author: thewer + +## +## Environment Variables Required: +## +## DO_API_KEY="75310dc4ca779ac39a19f6355db573b49ce92ae126553ebd61ac3a3ae34834cc" +## +## DO_DOMAIN_START="3" +## start of the digital ocean dns base domain from the LEFT +## (EG: one.two.three.four.five.com -> one.two & three.four.five.com) +## + + +##################### Public functions ##################### + + +## Create the text record for validation. +## Usage: fulldomain txtvalue +## EG: "_acme-challenge.www.other.domain.com" "XKrxpRBosdq0HG9i01zxXp5CPBs" +dns_digitalocean_add() { + fulldomain=$1 + txtvalue=$2 + _info "Using digitalocean dns validation - add record" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + _debug DO_DOMAIN_START "$DO_DOMAIN_START" + + ## split the domain for DO API + if ! _get_base_domain "$fulldomain" "$DO_DOMAIN_START"; then + _err "invalid domain or split" + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + ## Set the header with our post type and key auth key + _H1="Content-Type: application/json" + _H2="Authorization: Bearer $DO_API_KEY" + PURL='https://api.digitalocean.com/v2/domains/'$_domain'/records' + PBODY='{"type":"TXT","name":"'$_sub_domain'","data":"'$txtvalue'"}' + + _debug PURL "$PURL" + _debug PBODY "$PBODY" + + ## the create request - post + ## args: BODY, URL, [need64, httpmethod] + response="$(_post "$PBODY" "$PURL")" + + ## check response (sort of) + if [ "$?" != "0" ]; then + _err "error in response: $response" + return 1 + fi + _debug response "$response" + + ## check for result and get the ID so we can delete it later + #response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" + #do_id="$(echo "$response" | _egrep_o "id\"\s*\:\s*\d+" | _egrep_o "\d+" )" + #if [ -z "$do_id" ]; then + # _err "error getting ID from response: $response" + # return 1; + #fi + #_debug do_id "$do_id" + + ## finished correctly + return 0 +} + + +## Remove the txt record after validation. +## Usage: fulldomain txtvalue +## EG: "_acme-challenge.www.other.domain.com" "XKrxpRBosdq0HG9i01zxXp5CPBs" +dns_digitalocean_rm() { + fulldomain=$1 + txtvalue=$2 + _info "Using digitalocean dns validation - remove record" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + _debug DO_DOMAIN_START "$DO_DOMAIN_START" + + ## split the domain for DO API + if ! _get_base_domain "$fulldomain" "$DO_DOMAIN_START"; then + _err "invalid domain or split in remove" + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + ## Set the header with our post type and key auth key + _H1="Content-Type: application/json" + _H2="Authorization: Bearer $DO_API_KEY" + ## get URL for the list of domains + ## may get: "links":{"pages":{"last":".../v2/domains/DOM/records?page=2","next":".../v2/domains/DOM/records?page=2"}} + GURL="https://api.digitalocean.com/v2/domains/$_domain/records" + + ## while we dont have a record ID we keep going + while [ -z "$record" ]; do + ## 1) get the URL + ## the create request - get + ## args: URL, [onlyheader, timeout] + domain_list="$(_get "$GURL")" + ## 2) find record + ## check for what we are looing for: "type":"A","name":"$_sub_domain" + record="$(echo "$domain_list" | _egrep_o "\"id\"\s*\:\s*\"*\d+\"*[^}]*\"name\"\s*\:\s*\"$_sub_domain\"[^}]*\"data\"\s*\:\s*\"$txtvalue\"" )" + ## 3) check record and get next page + if [ -z "$record" ]; then + ## find the next page if we dont have a match + nextpage="$(echo "$domain_list" | _egrep_o "\"links\".*" | _egrep_o "\"next\".*" | _egrep_o "http.*page\=\d+" )" + if [ -z "$nextpage" ]; then + _err "no record and no nextpage in digital ocean DNS removal" + return 1 + fi + _debug nextpage "$nextpage" + GURL="$nextpage" + fi + ## we break out of the loop when we have a record + done + + ## we found the record + rec_id="$(echo "$record" | _egrep_o "id\"\s*\:\s*\"*\d+" | _egrep_o "\d+" )" + _debug rec_id "$rec_id" + + ## delete the record + ## delete URL for removing the one we dont want + DURL="https://api.digitalocean.com/v2/domains/$_domain/records/$rec_id" + + ## the create request - delete + ## args: BODY, URL, [need64, httpmethod] + response="$(_post "" "$DURL" "" "DELETE")" + + ## check response (sort of) + if [ "$?" != "0" ]; then + _err "error in remove response: $response" + return 1 + fi + _debug response "$response" + + ## finished correctly + return 0 +} + + +##################### Private functions below ##################### + + +## Split the domain provided at "base_domain_start_position" from the FRONT +## USAGE: fulldomain base_domain_start_position +## EG: "_acme-challenge.two.three.four.domain.com" "3" +## returns +## _sub_domain="_acme-challenge.two" +## _domain="three.four.domain.com" +_get_base_domain() { + # args + domain=$1 + dom_point=$2 + sub_point=$(_math $dom_point - 1) + _debug "split domain" "$domain" + _debug "split dom_point" "$dom_point" + _debug "split sub_point" "$sub_point" + + # domain max length - 253 + MAX_DOM=255 + + ## cut in half and check + _domain=$(printf "%s" "$domain" | cut -d . -f $dom_point-$MAX_DOM) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$sub_point) + if [ -z "$_domain" ]; then + ## not valid + _err "invalid split location" + return 1 + fi + if [ -z "$_sub_domain" ]; then + ## not valid + _err "invalid split location" + return 1 + fi + + _debug "split _domain" "$_domain" + _debug "split _sub_domain" "$_sub_domain" + + ## all ok + return 0 +} + From 657ddf6d9e1840027fb637857cfc5834fffeb8bd Mon Sep 17 00:00:00 2001 From: thewer Date: Sun, 5 Mar 2017 23:09:38 +1000 Subject: [PATCH 2/7] Removed unrequited commented code --- dnsapi/dns_digitalocean.sh | 9 --------- 1 file changed, 9 deletions(-) diff --git a/dnsapi/dns_digitalocean.sh b/dnsapi/dns_digitalocean.sh index cabebff2..50dd43d0 100755 --- a/dnsapi/dns_digitalocean.sh +++ b/dnsapi/dns_digitalocean.sh @@ -59,15 +59,6 @@ dns_digitalocean_add() { fi _debug response "$response" - ## check for result and get the ID so we can delete it later - #response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" - #do_id="$(echo "$response" | _egrep_o "id\"\s*\:\s*\d+" | _egrep_o "\d+" )" - #if [ -z "$do_id" ]; then - # _err "error getting ID from response: $response" - # return 1; - #fi - #_debug do_id "$do_id" - ## finished correctly return 0 } From e2d74b46163d28d2d84e19fd4c828229dc07c873 Mon Sep 17 00:00:00 2001 From: thewer Date: Mon, 6 Mar 2017 00:00:15 +1000 Subject: [PATCH 3/7] removed extra newlines, change tab indent to 2 spaces --- dnsapi/dns_digitalocean.sh | 273 ++++++++++++++++++------------------- 1 file changed, 133 insertions(+), 140 deletions(-) diff --git a/dnsapi/dns_digitalocean.sh b/dnsapi/dns_digitalocean.sh index 50dd43d0..534298eb 100755 --- a/dnsapi/dns_digitalocean.sh +++ b/dnsapi/dns_digitalocean.sh @@ -1,6 +1,5 @@ #!/usr/bin/env sh - ## Will be called by acme.sh to add the txt record to your api system. ## returns 0 means success, otherwise error. @@ -16,130 +15,125 @@ ## (EG: one.two.three.four.five.com -> one.two & three.four.five.com) ## - ##################### Public functions ##################### - ## Create the text record for validation. ## Usage: fulldomain txtvalue ## EG: "_acme-challenge.www.other.domain.com" "XKrxpRBosdq0HG9i01zxXp5CPBs" dns_digitalocean_add() { - fulldomain=$1 - txtvalue=$2 - _info "Using digitalocean dns validation - add record" - _debug fulldomain "$fulldomain" - _debug txtvalue "$txtvalue" - _debug DO_DOMAIN_START "$DO_DOMAIN_START" - - ## split the domain for DO API - if ! _get_base_domain "$fulldomain" "$DO_DOMAIN_START"; then - _err "invalid domain or split" - return 1 - fi - _debug _sub_domain "$_sub_domain" - _debug _domain "$_domain" - - ## Set the header with our post type and key auth key - _H1="Content-Type: application/json" - _H2="Authorization: Bearer $DO_API_KEY" - PURL='https://api.digitalocean.com/v2/domains/'$_domain'/records' - PBODY='{"type":"TXT","name":"'$_sub_domain'","data":"'$txtvalue'"}' - - _debug PURL "$PURL" - _debug PBODY "$PBODY" - - ## the create request - post - ## args: BODY, URL, [need64, httpmethod] - response="$(_post "$PBODY" "$PURL")" - - ## check response (sort of) - if [ "$?" != "0" ]; then - _err "error in response: $response" - return 1 - fi - _debug response "$response" - - ## finished correctly - return 0 + fulldomain=$1 + txtvalue=$2 + _info "Using digitalocean dns validation - add record" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + _debug DO_DOMAIN_START "$DO_DOMAIN_START" + + ## split the domain for DO API + if ! _get_base_domain "$fulldomain" "$DO_DOMAIN_START"; then + _err "invalid domain or split" + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + ## Set the header with our post type and key auth key + export _H1="Content-Type: application/json" + export _H2="Authorization: Bearer $DO_API_KEY" + PURL='https://api.digitalocean.com/v2/domains/'$_domain'/records' + PBODY='{"type":"TXT","name":"'$_sub_domain'","data":"'$txtvalue'"}' + + _debug PURL "$PURL" + _debug PBODY "$PBODY" + + ## the create request - post + ## args: BODY, URL, [need64, httpmethod] + response="$(_post "$PBODY" "$PURL")" + + ## check response (sort of) + if [ "$?" != "0" ]; then + _err "error in response: $response" + return 1 + fi + _debug response "$response" + + ## finished correctly + return 0 } - ## Remove the txt record after validation. ## Usage: fulldomain txtvalue ## EG: "_acme-challenge.www.other.domain.com" "XKrxpRBosdq0HG9i01zxXp5CPBs" dns_digitalocean_rm() { - fulldomain=$1 - txtvalue=$2 - _info "Using digitalocean dns validation - remove record" - _debug fulldomain "$fulldomain" - _debug txtvalue "$txtvalue" - _debug DO_DOMAIN_START "$DO_DOMAIN_START" - - ## split the domain for DO API - if ! _get_base_domain "$fulldomain" "$DO_DOMAIN_START"; then - _err "invalid domain or split in remove" - return 1 - fi - _debug _sub_domain "$_sub_domain" - _debug _domain "$_domain" - - ## Set the header with our post type and key auth key - _H1="Content-Type: application/json" - _H2="Authorization: Bearer $DO_API_KEY" - ## get URL for the list of domains - ## may get: "links":{"pages":{"last":".../v2/domains/DOM/records?page=2","next":".../v2/domains/DOM/records?page=2"}} - GURL="https://api.digitalocean.com/v2/domains/$_domain/records" - - ## while we dont have a record ID we keep going - while [ -z "$record" ]; do - ## 1) get the URL - ## the create request - get - ## args: URL, [onlyheader, timeout] - domain_list="$(_get "$GURL")" - ## 2) find record - ## check for what we are looing for: "type":"A","name":"$_sub_domain" - record="$(echo "$domain_list" | _egrep_o "\"id\"\s*\:\s*\"*\d+\"*[^}]*\"name\"\s*\:\s*\"$_sub_domain\"[^}]*\"data\"\s*\:\s*\"$txtvalue\"" )" - ## 3) check record and get next page - if [ -z "$record" ]; then - ## find the next page if we dont have a match - nextpage="$(echo "$domain_list" | _egrep_o "\"links\".*" | _egrep_o "\"next\".*" | _egrep_o "http.*page\=\d+" )" - if [ -z "$nextpage" ]; then - _err "no record and no nextpage in digital ocean DNS removal" - return 1 - fi - _debug nextpage "$nextpage" - GURL="$nextpage" - fi - ## we break out of the loop when we have a record - done - - ## we found the record - rec_id="$(echo "$record" | _egrep_o "id\"\s*\:\s*\"*\d+" | _egrep_o "\d+" )" - _debug rec_id "$rec_id" - - ## delete the record - ## delete URL for removing the one we dont want - DURL="https://api.digitalocean.com/v2/domains/$_domain/records/$rec_id" - - ## the create request - delete - ## args: BODY, URL, [need64, httpmethod] - response="$(_post "" "$DURL" "" "DELETE")" - - ## check response (sort of) - if [ "$?" != "0" ]; then - _err "error in remove response: $response" - return 1 - fi - _debug response "$response" - - ## finished correctly - return 0 + fulldomain=$1 + txtvalue=$2 + _info "Using digitalocean dns validation - remove record" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + _debug DO_DOMAIN_START "$DO_DOMAIN_START" + + ## split the domain for DO API + if ! _get_base_domain "$fulldomain" "$DO_DOMAIN_START"; then + _err "invalid domain or split in remove" + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + ## Set the header with our post type and key auth key + export _H1="Content-Type: application/json" + export _H2="Authorization: Bearer $DO_API_KEY" + ## get URL for the list of domains + ## may get: "links":{"pages":{"last":".../v2/domains/DOM/records?page=2","next":".../v2/domains/DOM/records?page=2"}} + GURL="https://api.digitalocean.com/v2/domains/$_domain/records" + + ## while we dont have a record ID we keep going + while [ -z "$record" ]; do + ## 1) get the URL + ## the create request - get + ## args: URL, [onlyheader, timeout] + domain_list="$(_get "$GURL")" + ## 2) find record + ## check for what we are looing for: "type":"A","name":"$_sub_domain" + record="$(echo "$domain_list" | _egrep_o "\"id\"\s*\:\s*\"*\d+\"*[^}]*\"name\"\s*\:\s*\"$_sub_domain\"[^}]*\"data\"\s*\:\s*\"$txtvalue\"" )" + ## 3) check record and get next page + if [ -z "$record" ]; then + ## find the next page if we dont have a match + nextpage="$(echo "$domain_list" | _egrep_o "\"links\".*" | _egrep_o "\"next\".*" | _egrep_o "http.*page\=\d+" )" + if [ -z "$nextpage" ]; then + _err "no record and no nextpage in digital ocean DNS removal" + return 1 + fi + _debug nextpage "$nextpage" + GURL="$nextpage" + fi + ## we break out of the loop when we have a record + done + + ## we found the record + rec_id="$(echo "$record" | _egrep_o "id\"\s*\:\s*\"*\d+" | _egrep_o "\d+" )" + _debug rec_id "$rec_id" + + ## delete the record + ## delete URL for removing the one we dont want + DURL="https://api.digitalocean.com/v2/domains/$_domain/records/$rec_id" + + ## the create request - delete + ## args: BODY, URL, [need64, httpmethod] + response="$(_post "" "$DURL" "" "DELETE")" + + ## check response (sort of) + if [ "$?" != "0" ]; then + _err "error in remove response: $response" + return 1 + fi + _debug response "$response" + + ## finished correctly + return 0 } - ##################### Private functions below ##################### - ## Split the domain provided at "base_domain_start_position" from the FRONT ## USAGE: fulldomain base_domain_start_position ## EG: "_acme-challenge.two.three.four.domain.com" "3" @@ -147,35 +141,34 @@ dns_digitalocean_rm() { ## _sub_domain="_acme-challenge.two" ## _domain="three.four.domain.com" _get_base_domain() { - # args - domain=$1 - dom_point=$2 - sub_point=$(_math $dom_point - 1) - _debug "split domain" "$domain" - _debug "split dom_point" "$dom_point" - _debug "split sub_point" "$sub_point" - - # domain max length - 253 - MAX_DOM=255 - - ## cut in half and check - _domain=$(printf "%s" "$domain" | cut -d . -f $dom_point-$MAX_DOM) - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$sub_point) - if [ -z "$_domain" ]; then - ## not valid - _err "invalid split location" - return 1 - fi - if [ -z "$_sub_domain" ]; then - ## not valid - _err "invalid split location" - return 1 - fi - - _debug "split _domain" "$_domain" - _debug "split _sub_domain" "$_sub_domain" - - ## all ok - return 0 + # args + domain=$1 + dom_point=$2 + sub_point=$(_math "$dom_point" - 1) + _debug "split domain" "$domain" + _debug "split dom_point" "$dom_point" + _debug "split sub_point" "$sub_point" + + # domain max length - 253 + MAX_DOM=255 + + ## cut in half and check + _domain=$(printf "%s" "$domain" | cut -d . -f "$dom_point"-"$MAX_DOM") + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$sub_point") + if [ -z "$_domain" ]; then + ## not valid + _err "invalid split location" + return 1 + fi + if [ -z "$_sub_domain" ]; then + ## not valid + _err "invalid split location" + return 1 + fi + + _debug "split _domain" "$_domain" + _debug "split _sub_domain" "$_sub_domain" + + ## all ok + return 0 } - From 1002a10af4c0acceacbb23aaf2baa31a2ea7a63e Mon Sep 17 00:00:00 2001 From: thewer Date: Mon, 6 Mar 2017 07:07:25 +1000 Subject: [PATCH 4/7] Removed more extra spaces --- dnsapi/dns_digitalocean.sh | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/dnsapi/dns_digitalocean.sh b/dnsapi/dns_digitalocean.sh index 534298eb..b84ade29 100755 --- a/dnsapi/dns_digitalocean.sh +++ b/dnsapi/dns_digitalocean.sh @@ -35,7 +35,7 @@ dns_digitalocean_add() { fi _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - + ## Set the header with our post type and key auth key export _H1="Content-Type: application/json" export _H2="Authorization: Bearer $DO_API_KEY" @@ -48,14 +48,14 @@ dns_digitalocean_add() { ## the create request - post ## args: BODY, URL, [need64, httpmethod] response="$(_post "$PBODY" "$PURL")" - + ## check response (sort of) if [ "$?" != "0" ]; then _err "error in response: $response" return 1 fi _debug response "$response" - + ## finished correctly return 0 } @@ -78,7 +78,7 @@ dns_digitalocean_rm() { fi _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" - + ## Set the header with our post type and key auth key export _H1="Content-Type: application/json" export _H2="Authorization: Bearer $DO_API_KEY" @@ -94,11 +94,11 @@ dns_digitalocean_rm() { domain_list="$(_get "$GURL")" ## 2) find record ## check for what we are looing for: "type":"A","name":"$_sub_domain" - record="$(echo "$domain_list" | _egrep_o "\"id\"\s*\:\s*\"*\d+\"*[^}]*\"name\"\s*\:\s*\"$_sub_domain\"[^}]*\"data\"\s*\:\s*\"$txtvalue\"" )" + record="$(echo "$domain_list" | _egrep_o "\"id\"\s*\:\s*\"*\d+\"*[^}]*\"name\"\s*\:\s*\"$_sub_domain\"[^}]*\"data\"\s*\:\s*\"$txtvalue\"")" ## 3) check record and get next page if [ -z "$record" ]; then ## find the next page if we dont have a match - nextpage="$(echo "$domain_list" | _egrep_o "\"links\".*" | _egrep_o "\"next\".*" | _egrep_o "http.*page\=\d+" )" + nextpage="$(echo "$domain_list" | _egrep_o "\"links\".*" | _egrep_o "\"next\".*" | _egrep_o "http.*page\=\d+")" if [ -z "$nextpage" ]; then _err "no record and no nextpage in digital ocean DNS removal" return 1 @@ -110,24 +110,24 @@ dns_digitalocean_rm() { done ## we found the record - rec_id="$(echo "$record" | _egrep_o "id\"\s*\:\s*\"*\d+" | _egrep_o "\d+" )" + rec_id="$(echo "$record" | _egrep_o "id\"\s*\:\s*\"*\d+" | _egrep_o "\d+")" _debug rec_id "$rec_id" - + ## delete the record ## delete URL for removing the one we dont want DURL="https://api.digitalocean.com/v2/domains/$_domain/records/$rec_id" - + ## the create request - delete ## args: BODY, URL, [need64, httpmethod] response="$(_post "" "$DURL" "" "DELETE")" - + ## check response (sort of) if [ "$?" != "0" ]; then _err "error in remove response: $response" return 1 fi _debug response "$response" - + ## finished correctly return 0 } @@ -148,7 +148,7 @@ _get_base_domain() { _debug "split domain" "$domain" _debug "split dom_point" "$dom_point" _debug "split sub_point" "$sub_point" - + # domain max length - 253 MAX_DOM=255 @@ -165,10 +165,10 @@ _get_base_domain() { _err "invalid split location" return 1 fi - + _debug "split _domain" "$_domain" _debug "split _sub_domain" "$_sub_domain" - + ## all ok return 0 } From a0efb134b5fa1dda0210f804e345ad3025fb6bc3 Mon Sep 17 00:00:00 2001 From: thewer Date: Mon, 6 Mar 2017 18:28:28 +1000 Subject: [PATCH 5/7] added GitHub location for any support problems --- dnsapi/dns_digitalocean.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/dnsapi/dns_digitalocean.sh b/dnsapi/dns_digitalocean.sh index b84ade29..5296ad15 100755 --- a/dnsapi/dns_digitalocean.sh +++ b/dnsapi/dns_digitalocean.sh @@ -4,6 +4,7 @@ ## returns 0 means success, otherwise error. ## Author: thewer +## GitHub: https://github.com/gitwer/acme.sh ## ## Environment Variables Required: From a493033f7daeb684c6a1ea4a01128f2242eea9af Mon Sep 17 00:00:00 2001 From: thewer Date: Wed, 8 Mar 2017 21:07:08 +1000 Subject: [PATCH 6/7] Saved environment vars into config file, shortened module to dgon, lowered some debug levels --- dnsapi/{dns_digitalocean.sh => dns_dgon.sh} | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) rename dnsapi/{dns_digitalocean.sh => dns_dgon.sh} (94%) diff --git a/dnsapi/dns_digitalocean.sh b/dnsapi/dns_dgon.sh similarity index 94% rename from dnsapi/dns_digitalocean.sh rename to dnsapi/dns_dgon.sh index 5296ad15..48cbe429 100755 --- a/dnsapi/dns_digitalocean.sh +++ b/dnsapi/dns_dgon.sh @@ -21,7 +21,7 @@ ## Create the text record for validation. ## Usage: fulldomain txtvalue ## EG: "_acme-challenge.www.other.domain.com" "XKrxpRBosdq0HG9i01zxXp5CPBs" -dns_digitalocean_add() { +dns_dgon_add() { fulldomain=$1 txtvalue=$2 _info "Using digitalocean dns validation - add record" @@ -29,6 +29,10 @@ dns_digitalocean_add() { _debug txtvalue "$txtvalue" _debug DO_DOMAIN_START "$DO_DOMAIN_START" + ## save the env vars (key and domain split location) for later automated use + _saveaccountconf DO_API_KEY "$DO_API_KEY" + _saveaccountconf DO_DOMAIN_START "$DO_DOMAIN_START" + ## split the domain for DO API if ! _get_base_domain "$fulldomain" "$DO_DOMAIN_START"; then _err "invalid domain or split" @@ -55,7 +59,7 @@ dns_digitalocean_add() { _err "error in response: $response" return 1 fi - _debug response "$response" + _debug2 response "$response" ## finished correctly return 0 @@ -64,7 +68,7 @@ dns_digitalocean_add() { ## Remove the txt record after validation. ## Usage: fulldomain txtvalue ## EG: "_acme-challenge.www.other.domain.com" "XKrxpRBosdq0HG9i01zxXp5CPBs" -dns_digitalocean_rm() { +dns_dgon_rm() { fulldomain=$1 txtvalue=$2 _info "Using digitalocean dns validation - remove record" @@ -104,7 +108,7 @@ dns_digitalocean_rm() { _err "no record and no nextpage in digital ocean DNS removal" return 1 fi - _debug nextpage "$nextpage" + _debug2 nextpage "$nextpage" GURL="$nextpage" fi ## we break out of the loop when we have a record @@ -127,7 +131,7 @@ dns_digitalocean_rm() { _err "error in remove response: $response" return 1 fi - _debug response "$response" + _debug2 response "$response" ## finished correctly return 0 From 2a21be79195452cadc1d39f819490b7ff21bd54a Mon Sep 17 00:00:00 2001 From: thewer Date: Wed, 8 Mar 2017 23:46:06 +1000 Subject: [PATCH 7/7] Removed requirement for domain split location by getting available domains automatically. Removed uppercase domain removal bug. --- dnsapi/README.md | 13 ++++++ dnsapi/dns_dgon.sh | 110 ++++++++++++++++++++++++++++----------------- 2 files changed, 81 insertions(+), 42 deletions(-) diff --git a/dnsapi/README.md b/dnsapi/README.md index 18c1ca9f..e7c4847e 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -349,6 +349,19 @@ Ok, let's issue a cert now: acme.sh --issue --dns dns_gandi_livedns -d example.com -d www.example.com ``` +## 19. Use DigitalOcean API (native) + +You need to obtain a read and write capable API key from your DigitalOcean account. See: https://www.digitalocean.com/help/api/ + +``` +export DO_API_KEY="75310dc4ca779ac39a19f6355db573b49ce92ae126553ebd61ac3a3ae34834cc" +``` + +Ok, let's issue a cert now: +``` +acme.sh --issue --dns dns_dgon -d example.com -d www.example.com +``` + # Use custom API If your API is not supported yet, you can write your own DNS API. diff --git a/dnsapi/dns_dgon.sh b/dnsapi/dns_dgon.sh index 48cbe429..e79fa037 100755 --- a/dnsapi/dns_dgon.sh +++ b/dnsapi/dns_dgon.sh @@ -11,10 +11,6 @@ ## ## DO_API_KEY="75310dc4ca779ac39a19f6355db573b49ce92ae126553ebd61ac3a3ae34834cc" ## -## DO_DOMAIN_START="3" -## start of the digital ocean dns base domain from the LEFT -## (EG: one.two.three.four.five.com -> one.two & three.four.five.com) -## ##################### Public functions ##################### @@ -22,20 +18,18 @@ ## Usage: fulldomain txtvalue ## EG: "_acme-challenge.www.other.domain.com" "XKrxpRBosdq0HG9i01zxXp5CPBs" dns_dgon_add() { - fulldomain=$1 + fulldomain="$(echo "$1" | tr '[:upper:]' '[:lower:]')" txtvalue=$2 _info "Using digitalocean dns validation - add record" _debug fulldomain "$fulldomain" _debug txtvalue "$txtvalue" - _debug DO_DOMAIN_START "$DO_DOMAIN_START" ## save the env vars (key and domain split location) for later automated use _saveaccountconf DO_API_KEY "$DO_API_KEY" - _saveaccountconf DO_DOMAIN_START "$DO_DOMAIN_START" ## split the domain for DO API - if ! _get_base_domain "$fulldomain" "$DO_DOMAIN_START"; then - _err "invalid domain or split" + if ! _get_base_domain "$fulldomain"; then + _err "domain not found in your account for addition" return 1 fi _debug _sub_domain "$_sub_domain" @@ -54,7 +48,7 @@ dns_dgon_add() { ## args: BODY, URL, [need64, httpmethod] response="$(_post "$PBODY" "$PURL")" - ## check response (sort of) + ## check response if [ "$?" != "0" ]; then _err "error in response: $response" return 1 @@ -69,16 +63,15 @@ dns_dgon_add() { ## Usage: fulldomain txtvalue ## EG: "_acme-challenge.www.other.domain.com" "XKrxpRBosdq0HG9i01zxXp5CPBs" dns_dgon_rm() { - fulldomain=$1 + fulldomain="$(echo "$1" | tr '[:upper:]' '[:lower:]')" txtvalue=$2 _info "Using digitalocean dns validation - remove record" _debug fulldomain "$fulldomain" _debug txtvalue "$txtvalue" - _debug DO_DOMAIN_START "$DO_DOMAIN_START" ## split the domain for DO API - if ! _get_base_domain "$fulldomain" "$DO_DOMAIN_START"; then - _err "invalid domain or split in remove" + if ! _get_base_domain "$fulldomain"; then + _err "domain not found in your account for removal" return 1 fi _debug _sub_domain "$_sub_domain" @@ -139,41 +132,74 @@ dns_dgon_rm() { ##################### Private functions below ##################### -## Split the domain provided at "base_domain_start_position" from the FRONT -## USAGE: fulldomain base_domain_start_position -## EG: "_acme-challenge.two.three.four.domain.com" "3" +## Split the domain provided into the "bade domain" and the "start prefix". +## This function searches for the longest subdomain in your account +## for the full domain given and splits it into the base domain (zone) +## and the prefix/record to be added/removed +## USAGE: fulldomain +## EG: "_acme-challenge.two.three.four.domain.com" ## returns ## _sub_domain="_acme-challenge.two" -## _domain="three.four.domain.com" +## _domain="three.four.domain.com" *IF* zone "three.four.domain.com" exists +## if only "domain.com" exists it will return +## _sub_domain="_acme-challenge.two.three.four" +## _domain="domain.com" _get_base_domain() { # args - domain=$1 - dom_point=$2 - sub_point=$(_math "$dom_point" - 1) - _debug "split domain" "$domain" - _debug "split dom_point" "$dom_point" - _debug "split sub_point" "$sub_point" - - # domain max length - 253 + fulldomain="$(echo "$1" | tr '[:upper:]' '[:lower:]')" + _debug fulldomain "$fulldomain" + + # domain max legal length = 253 MAX_DOM=255 - ## cut in half and check - _domain=$(printf "%s" "$domain" | cut -d . -f "$dom_point"-"$MAX_DOM") - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$sub_point") - if [ -z "$_domain" ]; then - ## not valid - _err "invalid split location" - return 1 - fi - if [ -z "$_sub_domain" ]; then - ## not valid - _err "invalid split location" + ## get a list of domains for the account to check thru + ## Set the headers + export _H1="Content-Type: application/json" + export _H2="Authorization: Bearer $DO_API_KEY" + _debug DO_API_KEY "$DO_API_KEY" + ## get URL for the list of domains + ## havent seen this request paginated, tested with 18 domains (more requres manual requests with DO) + DOMURL="https://api.digitalocean.com/v2/domains" + + ## get the domain list (DO gives basically a full XFER!) + domain_list="$(_get "$DOMURL")" + + ## check response + if [ "$?" != "0" ]; then + _err "error in domain_list response: $domain_list" return 1 fi + _debug2 domain_list "$domain_list" + + ## for each shortening of our $fulldomain, check if it exists in the $domain_list + ## can never start on 1 (aka whole $fulldomain) as $fulldomain starts with "_acme-challenge" + i=2 + while [ $i -gt 0 ]; do + ## get next longest domain + _domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-"$MAX_DOM") + ## check we got something back from our cut (or are we at the end) + if [ -z "$_domain" ]; then + ## we got to the end of the domain - invalid domain + _err "domain not found in DigitalOcean account" + return 1 + fi + ## we got part of a domain back - grep it out + found="$(echo "$domain_list" | _egrep_o "\"name\"\s*\:\s*\"$_domain\"")" + ## check if it exists + if [ ! -z "$found" ]; then + ## exists - exit loop returning the parts + sub_point=$(_math $i - 1) + _sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-"$sub_point") + _debug _domain "$_domain" + _debug _sub_domain "$_sub_domain" + return 0 + fi + ## increment cut point $i + i=$(_math $i + 1) + done - _debug "split _domain" "$_domain" - _debug "split _sub_domain" "$_sub_domain" - - ## all ok - return 0 + ## we went through the entire domain zone list and dint find one that matched + ## doesnt look like we can add in the record + _err "domain not found in DigitalOcean account, but we should never get here" + return 1 }