From 66e38ae69e4487155cbc555f1230ac641e2b5f5a Mon Sep 17 00:00:00 2001 From: shar0119 Date: Mon, 3 Apr 2017 13:46:39 -0700 Subject: [PATCH 01/16] Updated Readme.md file (1 of 2) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e0c1e7d6..567ec5ba 100644 --- a/README.md +++ b/README.md @@ -313,6 +313,7 @@ You don't have to do anything manually! 1. DigitalOcean API (native) 1. ClouDNS.net API 1. Infoblox NIOS API (https://www.infoblox.com/) +1. Dynu API (https://www.dynu.com) **More APIs coming soon...** From 9cf65e31cd599e567498d2d7972d858857d629b8 Mon Sep 17 00:00:00 2001 From: shar0119 Date: Tue, 25 Apr 2017 19:37:56 -0700 Subject: [PATCH 02/16] Resolved conflict. Resolved conflict. --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 567ec5ba..cdcd40c3 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ - DOES NOT require `root/sudoer` access. - Docker friendly -It's probably the `easiest&smallest&smartest` shell script to automatically issue & renew the free certificates from Let's Encrypt. +It's probably the `easiest & smartest` shell script to automatically issue & renew the free certificates from Let's Encrypt. Wiki: https://github.com/Neilpang/acme.sh/wiki @@ -31,6 +31,7 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa) - [Centminmod](http://centminmod.com/letsencrypt-acmetool-https.html) - [splynx](https://forum.splynx.com/t/free-ssl-cert-for-splynx-lets-encrypt/297) - [archlinux](https://aur.archlinux.org/packages/acme.sh-git/) +- [opnsense.org](https://github.com/opnsense/plugins/tree/master/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient) - [more...](https://github.com/Neilpang/acme.sh/wiki/Blogs-and-tutorials) # Tested OS @@ -313,6 +314,7 @@ You don't have to do anything manually! 1. DigitalOcean API (native) 1. ClouDNS.net API 1. Infoblox NIOS API (https://www.infoblox.com/) +1. VSCALE (https://vscale.io/) 1. Dynu API (https://www.dynu.com) **More APIs coming soon...** From 0138e167e91164bffc86eee29b4f140a1d03c93e Mon Sep 17 00:00:00 2001 From: thecantero Date: Thu, 27 Apr 2017 18:23:43 +0800 Subject: [PATCH 03/16] Update to support Kong-v0.10.x The previous one is for Kong-v0.9.x only. This change will allow it to work with v0.10.x. More info at: https://github.com/Mashape/kong/blob/4f960abe33fe3d45510944f062e571d63dc3a673/UPGRADE.md#upgrade-to-010x https://getkong.org/docs/0.10.x/admin-api/#add-certificate --- deploy/kong.sh | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/deploy/kong.sh b/deploy/kong.sh index e1873f35..67eef693 100755 --- a/deploy/kong.sh +++ b/deploy/kong.sh @@ -31,14 +31,15 @@ kong_deploy() { _debug _cca "$_cca" _debug _cfullchain "$_cfullchain" - #Get uuid linked to the domain - uuid=$(_get "$KONG_URL/apis?request_host=$_cdomain" | _normalizeJson | _egrep_o '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}') - if [ -z "$uuid" ]; then - _err "Unable to get Kong uuid for domain $_cdomain" - _err "Make sure that KONG_URL is correctly configured" - _err "Make sure that a Kong api request_host match the domain" - _err "Kong url: $KONG_URL" - return 1 + #Get ssl_uuid linked to the domain + ssl_uuid=$(_get "$KONG_URL/certificates/$_cdomain" | _normalizeJson | _egrep_o '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}') + if [ -z "$ssl_uuid" ]; then + _debug "Unable to get Kong ssl_uuid for domain $_cdomain" + _debug "Make sure that KONG_URL is correctly configured" + _debug "Make sure that a Kong certificate match the sni" + _debug "Kong url: $KONG_URL" + _info "No existing certificate, creating..." + #return 1 fi #Save kong url if it's succesful (First run case) _saveaccountconf KONG_URL "$KONG_URL" @@ -48,12 +49,15 @@ kong_deploy() { #Set Header _H1="Content-Type: multipart/form-data; boundary=$delim" #Generate data for request (Multipart/form-data with mixed content) - #set name to ssl - content="--$delim${nl}Content-Disposition: form-data; name=\"name\"${nl}${nl}ssl" + content="--$delim${nl}" + if [ -z "$ssl_uuid" ]; then + #set sni to domain + content="$content{nl}Content-Disposition: form-data; name=\"snis\"${nl}${nl}$_cdomain" + fi #add key - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"config.key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")" #Add cert - content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"config.cert\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")" + content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"cert\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")" #Close multipart content="$content${nl}--$delim--${nl}" #Convert CRLF @@ -61,17 +65,16 @@ kong_deploy() { #DEBUG _debug header "$_H1" _debug content "$content" - #Check if ssl plugins is aready enabled (if not => POST else => PATCH) - ssl_uuid=$(_get "$KONG_URL/apis/$uuid/plugins" | _egrep_o '"id":"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"[a-zA-Z0-9\-\,\"_\:]*"name":"ssl"' | _egrep_o '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}') - _debug ssl_uuid "$ssl_uuid" + #Check if sslcreated (if not => POST else => PATCH) + if [ -z "$ssl_uuid" ]; then #Post certificate to Kong - response=$(_post "$content" "$KONG_URL/apis/$uuid/plugins" "" "POST") + response=$(_post "$content" "$KONG_URL/certificates" "" "POST") else #patch - response=$(_post "$content" "$KONG_URL/apis/$uuid/plugins/$ssl_uuid" "" "PATCH") + response=$(_post "$content" "$KONG_URL/certificates/$ssl_uuid" "" "PATCH") fi - if ! [ "$(echo "$response" | _egrep_o "ssl")" = "ssl" ]; then + if ! [ "$(echo "$response" | _egrep_o "created_at")" = "created_at" ]; then _err "An error occurred with cert upload. Check response:" _err "$response" return 1 From de3bac53bfb99e1b192bed48a1c5dcf694e2a606 Mon Sep 17 00:00:00 2001 From: thecantero Date: Thu, 27 Apr 2017 20:06:47 +0800 Subject: [PATCH 04/16] update README --- deploy/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/deploy/README.md b/deploy/README.md index d8c2f57c..232fdb4a 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -21,8 +21,11 @@ acme.sh --deploy -d example.com --deploy-hook cpanel ## 2. Deploy ssl cert on kong proxy engine based on api. Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert). +Currently supports Kong-v0.10.x. -(TODO) +```sh +acme.sh --deploy -d ftp.example.com --deploy-hook kong +``` ## 3. Deploy the cert to remote server through SSH access. From 4b02ee5b468814b2a19e9dd783b458264acbe776 Mon Sep 17 00:00:00 2001 From: thecantero Date: Thu, 27 Apr 2017 20:38:08 +0800 Subject: [PATCH 05/16] Typo fix --- deploy/kong.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/kong.sh b/deploy/kong.sh index 67eef693..79dc3916 100755 --- a/deploy/kong.sh +++ b/deploy/kong.sh @@ -67,7 +67,7 @@ kong_deploy() { _debug content "$content" #Check if sslcreated (if not => POST else => PATCH) - if [ -z "$ssl_uuid" ]; then + if [ ! -z "$ssl_uuid" ]; then #Post certificate to Kong response=$(_post "$content" "$KONG_URL/certificates" "" "POST") else From c140fe9bae8926e3724545330505edc3e1355833 Mon Sep 17 00:00:00 2001 From: thecantero Date: Thu, 27 Apr 2017 20:39:53 +0800 Subject: [PATCH 06/16] Typo Fix --- deploy/kong.sh | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/deploy/kong.sh b/deploy/kong.sh index 79dc3916..9d1f40a7 100755 --- a/deploy/kong.sh +++ b/deploy/kong.sh @@ -1,6 +1,3 @@ -#!/usr/bin/env sh - -# This deploy hook will deploy ssl cert on kong proxy engine based on api request_host parameter. # Note that ssl plugin should be available on Kong instance # The hook will match cdomain to request_host, in case of multiple domain it will always take the first # one (acme.sh behaviour). @@ -49,10 +46,9 @@ kong_deploy() { #Set Header _H1="Content-Type: multipart/form-data; boundary=$delim" #Generate data for request (Multipart/form-data with mixed content) - content="--$delim${nl}" if [ -z "$ssl_uuid" ]; then #set sni to domain - content="$content{nl}Content-Disposition: form-data; name=\"snis\"${nl}${nl}$_cdomain" + content="--$delim${nl}Content-Disposition: form-data; name=\"snis\"${nl}${nl}$_cdomain" fi #add key content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")" @@ -67,7 +63,7 @@ kong_deploy() { _debug content "$content" #Check if sslcreated (if not => POST else => PATCH) - if [ ! -z "$ssl_uuid" ]; then + if [ -z "$ssl_uuid" ]; then #Post certificate to Kong response=$(_post "$content" "$KONG_URL/certificates" "" "POST") else From 824ffa24f497a69bd4b0cb0cf10520b27d326514 Mon Sep 17 00:00:00 2001 From: Andre Cantero Date: Fri, 28 Apr 2017 00:21:21 +0800 Subject: [PATCH 07/16] Add shebang --- deploy/kong.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/deploy/kong.sh b/deploy/kong.sh index 9d1f40a7..dce92096 100755 --- a/deploy/kong.sh +++ b/deploy/kong.sh @@ -1,3 +1,4 @@ +#!/usr/bin/env sh # Note that ssl plugin should be available on Kong instance # The hook will match cdomain to request_host, in case of multiple domain it will always take the first # one (acme.sh behaviour). From 1231b71245588f107bc9667c16925afeac0f4e4e Mon Sep 17 00:00:00 2001 From: Andre Cantero Date: Fri, 28 Apr 2017 00:25:30 +0800 Subject: [PATCH 08/16] Update the notes --- deploy/kong.sh | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/deploy/kong.sh b/deploy/kong.sh index dce92096..d3a6bc47 100755 --- a/deploy/kong.sh +++ b/deploy/kong.sh @@ -1,11 +1,7 @@ #!/usr/bin/env sh -# Note that ssl plugin should be available on Kong instance -# The hook will match cdomain to request_host, in case of multiple domain it will always take the first -# one (acme.sh behaviour). -# If ssl config already exist it will update only cert and key not touching other parameter -# If ssl config doesn't exist it will only upload cert and key and not set other parameter -# Not that we deploy full chain -# See https://getkong.org/plugins/dynamic-ssl/ for other options +# If certificate already exist it will update only cert and key not touching other parameter +# If certificate doesn't exist it will only upload cert and key and not set other parameter +# Note that we deploy full chain # Written by Geoffroi Genot ######## Public functions ##################### From 1994c6828ecaaefa50beb8fb5616ed51a3b98c48 Mon Sep 17 00:00:00 2001 From: Matthew Turney Date: Mon, 5 Dec 2016 21:53:02 -0600 Subject: [PATCH 09/16] include dnsimple api Even though DNSimple is technically covered with lexicon not all systems can install python pip's easily. For these systems it is useful to have pure shell script API interactions. --- README.md | 1 + dnsapi/README.md | 36 +++++++-- dnsapi/dns_dnsimple.sh | 163 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 193 insertions(+), 7 deletions(-) create mode 100644 dnsapi/dns_dnsimple.sh diff --git a/README.md b/README.md index 0a320369..34b9243a 100644 --- a/README.md +++ b/README.md @@ -292,6 +292,7 @@ You don't have to do anything manually! 1. CloudFlare.com API 1. DNSPod.cn API +1. DNSimple API 1. CloudXNS.com API 1. GoDaddy.com API 1. OVH, kimsufi, soyoustart and runabove API diff --git a/dnsapi/README.md b/dnsapi/README.md index 12d76bef..ad03ea79 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -422,31 +422,31 @@ acme.sh --issue --dns dns_cloudns -d example.com -d www.example.com ``` ## 22. Use Infoblox API - + First you need to create/obtain API credentials on your Infoblox appliance. - + ``` export Infoblox_Creds="username:password" export Infoblox_Server="ip or fqdn of infoblox appliance" ``` - + Ok, let's issue a cert now: ``` acme.sh --issue --dns dns_infoblox -d example.com -d www.example.com ``` - + Note: This script will automatically create and delete the ephemeral txt record. The `Infoblox_Creds` and `Infoblox_Server` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. ## 23. Use VSCALE API - + First you need to create/obtain API tokens on your [settings panel](https://vscale.io/panel/settings/tokens/). - + ``` VSCALE_API_KEY="sdfsdfsdfljlbjkljlkjsdfoiwje" ``` - + Ok, let's issue a cert now: ``` acme.sh --issue --dns dns_vscale -d example.com -d www.example.com @@ -468,6 +468,28 @@ acme.sh --issue --dns dns_dynu -d example.com -d www.example.com The `Dynu_ClientId` and `Dynu_Secret` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. +## 25. Use DNSimple API + +First you need to login to your DNSimple account and generate a new oauth token. + +https://dnsimple.com/a/{your account id}/account/access_tokens + +Note that this is an _account_ token and not a user token. The account token is +needed to infer the `account_id` used in requests. A user token will not be able +to determine the correct account to use. + +``` +export DNSimple_OAUTH_TOKEN="sdfsdfsdfljlbjkljlkjsdfoiwje" +``` + +To issue the cert just specify the `dns_dnsimple` API. + +``` +acme.sh --issue --dns dns_dnsimple -d example.com +``` + +The `DNSimple_OAUTH_TOKEN` will be saved in `~/.acme.sh/account.conf` and will +be reused when needed. # Use custom API diff --git a/dnsapi/dns_dnsimple.sh b/dnsapi/dns_dnsimple.sh new file mode 100644 index 00000000..d714d36c --- /dev/null +++ b/dnsapi/dns_dnsimple.sh @@ -0,0 +1,163 @@ +#!/usr/bin/env sh + +# DNSimple domain api +# +# This is your oauth token which can be acquired on the account page. Please +# note that this must be an _account_ token and not a _user_ token. +# https://dnsimple.com/a//account/access_tokens +# DNSimple_OAUTH_TOKEN="sdfsdfsdfljlbjkljlkjsdfoiwje" + +DNSimple_API="https://api.dnsimple.com/v2" + +######## Public functions ##################### + +# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_dnsimple_add() { + fulldomain=$1 + txtvalue=$2 + + if [ -z "$DNSimple_OAUTH_TOKEN" ]; then + DNSimple_OAUTH_TOKEN="" + _err "You have not set the dnsimple oauth token yet." + _err "Please visit https://dnsimple.com/user to generate it." + return 1 + fi + + # save the oauth token for later + _saveaccountconf DNSimple_OAUTH_TOKEN "$DNSimple_OAUTH_TOKEN" + + _debug "Retrive account ID" + if ! _get_account_id; then + _err "failed to retrive account id" + return 1 + fi + _debug _account_id "$_account_id" + + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _domain "$_domain" + _debug _sub_domain "$_sub_domain" + + _debug "Getting txt records" + _dnsimple_rest GET "$_account_id/zones/$_domain/records?per_page=100" + + if ! _contains "$response" "\"id\":"; then + _err "Error" + return 1 + fi + + count=$(printf "%s" "$response" | _egrep_o "\"name\":\"$_sub_domain\"" | wc -l | _egrep_o "[0-9]+") + _debug count "$count" + + if [ "$count" = "0" ]; then + _info "Adding record" + if _dnsimple_rest POST "$_account_id/zones/$_domain/records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then + if printf -- "%s" "$response" | grep "\"name\":\"$_sub_domain\"" >/dev/null; then + _info "Added" + return 0 + else + _err "Add txt record error." + return 1 + fi + fi + _err "Add txt record error." + else + _info "Updating record" + record_id=$(printf "%s" "$response" | _egrep_o "\"id\":[^,]*,\"zone_id\":\"[^,]*\",\"parent_id\":null,\"name\":\"$_sub_domain\"" | cut -d: -f2 | cut -d, -f1) + _debug "record_id" "$record_id" + + _dnsimple_rest PATCH "$_account_id/zones/$_domain/records/$record_id" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}" + if [ "$?" = "0" ]; then + _info "Updated!" + #todo: check if the record takes effect + return 0 + fi + _err "Update error" + return 1 + fi +} + +# fulldomain +dns_dnsimple_rm() { + fulldomain=$1 + +} + +#################### Private functions bellow ################################## +# _acme-challenge.www.domain.com +# returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +_get_root() { + domain=$1 + i=2 + p=1 + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + if [ -z "$h" ]; then + # not valid + return 1 + fi + + if ! _dnsimple_rest GET "$_account_id/zones/$h"; then + return 1 + fi + + if _contains "$response" 'not found'; then + _debug "$h not found" + else + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="$h" + return 0 + fi + p="$i" + i=$(_math "$i" + 1) + done + return 1 +} + +_get_account_id() { + if ! _dnsimple_rest GET "whoami"; then + return 1 + fi + + if _contains "$response" "\"account\":null"; then + _err "no account associated with this token" + return 1 + fi + + if _contains "$response" "timeout"; then + _err "timeout retrieving account_id" + return 1 + fi + + _account_id=$(printf "%s" "$response" | _egrep_o "\"id\":[^,]*,\"email\":" | cut -d: -f2 | cut -d, -f1) + return 0 +} + +_dnsimple_rest() { + method=$1 + path="$2" + data="$3" + request_url="$DNSimple_API/$path" + _debug "$path" + + _H1="Accept: application/json" + _H2="Authorization: Bearer $DNSimple_OAUTH_TOKEN" + if [ "$data" ]; then + _H1="Content-Type: application/json" + _debug data "$data" + response="$(_post "$data" "$request_url" "" "$method")" + else + response="$(_get "$request_url")" + fi + + if [ "$?" != "0" ]; then + _err "error $request_url" + return 1 + fi + _debug2 response "$response" + return 0 +} From 2b092539618fc4ca627f9aa2b7b021488e222397 Mon Sep 17 00:00:00 2001 From: Matthew Turney Date: Tue, 6 Dec 2016 08:32:14 -0600 Subject: [PATCH 10/16] link to contributor repo for support issues relating to the dnsimple API integration --- dnsapi/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dnsapi/README.md b/dnsapi/README.md index ad03ea79..f53d8ad4 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -491,6 +491,9 @@ acme.sh --issue --dns dns_dnsimple -d example.com The `DNSimple_OAUTH_TOKEN` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. +If you have any issues with this integration please report them to +https://github.com/pho3nixf1re/acme.sh/issues. + # Use custom API If your API is not supported yet, you can write your own DNS API. From f4e81953ce59731c3c46f7dc6937417851bd6e88 Mon Sep 17 00:00:00 2001 From: Matthew Turney Date: Sun, 12 Feb 2017 16:07:05 -0600 Subject: [PATCH 11/16] provide a more general purpose request function This allows for more flexibility in the future. Most importantly being able to do more than just GET requests but any HTTP method. Specifically needed for DELETE requests. --- acme.sh | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 7ce947ea..3ccd8dc4 100755 --- a/acme.sh +++ b/acme.sh @@ -1592,12 +1592,17 @@ _post() { return $_ret } -# url getheader timeout _get() { - _debug GET + _request "$1" "$2" "$3" GET +} + +# url getheader timeout +_request() { url="$1" onlyheader="$2" t="$3" + method="$4" + _debug method $method _debug url "$url" _debug "timeout" "$t" @@ -1611,6 +1616,9 @@ _get() { if [ "$t" ]; then _CURL="$_CURL --connect-timeout $t" fi + if [ "$method" ]; then + _CURL="$_CURL -X $method" + fi _debug "_CURL" "$_CURL" if [ "$onlyheader" ]; then $_CURL -I --user-agent "$USER_AGENT" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$url" @@ -1633,6 +1641,9 @@ _get() { if [ "$t" ]; then _WGET="$_WGET --timeout=$t" fi + if [ "$method" ]; then + _WGET="$_WGET --method=$method" + fi _debug "_WGET" "$_WGET" if [ "$onlyheader" ]; then $_WGET --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" -S -O /dev/null "$url" 2>&1 | sed 's/^[ ]*//g' From f9b419d1e40c6056675891e846841158f36dc01a Mon Sep 17 00:00:00 2001 From: Matthew Turney Date: Sun, 12 Feb 2017 16:08:32 -0600 Subject: [PATCH 12/16] cleanup dns in dnsimple api integration Implement the `_rm()` method for the DNSimple integration. This also required some changes and cleanup to DRY up the code. --- dnsapi/dns_dnsimple.sh | 96 +++++++++++++++++++++++++++++++----------- 1 file changed, 72 insertions(+), 24 deletions(-) diff --git a/dnsapi/dns_dnsimple.sh b/dnsapi/dns_dnsimple.sh index d714d36c..dde6638e 100644 --- a/dnsapi/dns_dnsimple.sh +++ b/dnsapi/dns_dnsimple.sh @@ -26,49 +26,35 @@ dns_dnsimple_add() { # save the oauth token for later _saveaccountconf DNSimple_OAUTH_TOKEN "$DNSimple_OAUTH_TOKEN" - _debug "Retrive account ID" if ! _get_account_id; then _err "failed to retrive account id" return 1 fi - _debug _account_id "$_account_id" if ! _get_root "$fulldomain"; then _err "invalid domain" return 1 fi - _debug _domain "$_domain" - _debug _sub_domain "$_sub_domain" - _debug "Getting txt records" - _dnsimple_rest GET "$_account_id/zones/$_domain/records?per_page=100" + _get_records $_account_id $_domain $_sub_domain - if ! _contains "$response" "\"id\":"; then - _err "Error" - return 1 - fi - - count=$(printf "%s" "$response" | _egrep_o "\"name\":\"$_sub_domain\"" | wc -l | _egrep_o "[0-9]+") - _debug count "$count" - - if [ "$count" = "0" ]; then + if [ "$_records_count" = "0" ]; then _info "Adding record" if _dnsimple_rest POST "$_account_id/zones/$_domain/records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then if printf -- "%s" "$response" | grep "\"name\":\"$_sub_domain\"" >/dev/null; then _info "Added" return 0 else - _err "Add txt record error." + _err "Unexpected response while adding text record." return 1 fi fi _err "Add txt record error." else _info "Updating record" - record_id=$(printf "%s" "$response" | _egrep_o "\"id\":[^,]*,\"zone_id\":\"[^,]*\",\"parent_id\":null,\"name\":\"$_sub_domain\"" | cut -d: -f2 | cut -d, -f1) - _debug "record_id" "$record_id" + _extract_record_id $_records $_sub_domain - _dnsimple_rest PATCH "$_account_id/zones/$_domain/records/$record_id" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}" + _dnsimple_rest PATCH "$_account_id/zones/$_domain/records/$_record_id" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}" if [ "$?" = "0" ]; then _info "Updated!" #todo: check if the record takes effect @@ -83,6 +69,31 @@ dns_dnsimple_add() { dns_dnsimple_rm() { fulldomain=$1 + if ! _get_account_id; then + _err "failed to retrive account id" + return 1 + fi + + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _get_records $_account_id $_domain $_sub_domain + _extract_record_id $_records $_sub_domain + + if [ "$_record_id" ]; then + _dnsimple_rest DELETE "$_account_id/zones/$_domain/records/$_record_id" + + if [ "$?" = "0" ]; then + _info "removed record" "$_record_id" + return 0 + fi + fi + + _err "failed to remove record" "$_record_id" + return 1 + } #################### Private functions bellow ################################## @@ -93,7 +104,7 @@ dns_dnsimple_rm() { _get_root() { domain=$1 i=2 - p=1 + previous=1 while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) if [ -z "$h" ]; then @@ -108,17 +119,24 @@ _get_root() { if _contains "$response" 'not found'; then _debug "$h not found" else - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$previous) _domain="$h" + + _debug _domain "$_domain" + _debug _sub_domain "$_sub_domain" + return 0 fi - p="$i" + + previous="$i" i=$(_math "$i" + 1) done return 1 } +# returns _account_id _get_account_id() { + _debug "retrive account id" if ! _dnsimple_rest GET "whoami"; then return 1 fi @@ -129,14 +147,44 @@ _get_account_id() { fi if _contains "$response" "timeout"; then - _err "timeout retrieving account_id" + _err "timeout retrieving account id" return 1 fi _account_id=$(printf "%s" "$response" | _egrep_o "\"id\":[^,]*,\"email\":" | cut -d: -f2 | cut -d, -f1) + _debug _account_id "$_account_id" + return 0 } +# returns +# _records +# _records_count +_get_records() { + account_id=$1 + domain=$2 + sub_domain=$3 + + _debug "fetching txt records" + _dnsimple_rest GET "$account_id/zones/$domain/records?per_page=100" + + if ! _contains "$response" "\"id\":"; then + _err "failed to retrieve records" + return 1 + fi + + _records_count=$(printf "%s" "$response" | _egrep_o "\"name\":\"$sub_domain\"" | wc -l | _egrep_o "[0-9]+") + _records=$response + _debug _records_count "$_records_count" +} + +# returns _record_id +_extract_record_id() { + _record_id=$(printf "%s" "$_records" | _egrep_o "\"id\":[^,]*,\"zone_id\":\"[^,]*\",\"parent_id\":null,\"name\":\"$_sub_domain\"" | cut -d: -f2 | cut -d, -f1) + _debug "_record_id" "$_record_id" +} + +# returns response _dnsimple_rest() { method=$1 path="$2" @@ -151,7 +199,7 @@ _dnsimple_rest() { _debug data "$data" response="$(_post "$data" "$request_url" "" "$method")" else - response="$(_get "$request_url")" + response="$(_request "$request_url" "" "" "$method")" fi if [ "$?" != "0" ]; then From 326ac485b35e2783365f5ab660caec28fc64d794 Mon Sep 17 00:00:00 2001 From: Matthew Turney Date: Sun, 12 Feb 2017 16:15:37 -0600 Subject: [PATCH 13/16] link to repo for dnsimple integration support --- dnsapi/dns_dnsimple.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/dnsapi/dns_dnsimple.sh b/dnsapi/dns_dnsimple.sh index dde6638e..f1c841dc 100644 --- a/dnsapi/dns_dnsimple.sh +++ b/dnsapi/dns_dnsimple.sh @@ -1,6 +1,7 @@ #!/usr/bin/env sh # DNSimple domain api +# https://github.com/pho3nixf1re/acme.sh/issues # # This is your oauth token which can be acquired on the account page. Please # note that this must be an _account_ token and not a _user_ token. From 2f4111a2e2ed01c27e070b375fa3f0179d0b46d3 Mon Sep 17 00:00:00 2001 From: Matthew Turney Date: Mon, 13 Feb 2017 11:37:34 -0600 Subject: [PATCH 14/16] fixup shellcheck style issues --- dnsapi/dns_dnsimple.sh | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/dnsapi/dns_dnsimple.sh b/dnsapi/dns_dnsimple.sh index f1c841dc..d92c6137 100644 --- a/dnsapi/dns_dnsimple.sh +++ b/dnsapi/dns_dnsimple.sh @@ -37,7 +37,7 @@ dns_dnsimple_add() { return 1 fi - _get_records $_account_id $_domain $_sub_domain + _get_records "$_account_id" "$_domain" "$_sub_domain" if [ "$_records_count" = "0" ]; then _info "Adding record" @@ -53,14 +53,17 @@ dns_dnsimple_add() { _err "Add txt record error." else _info "Updating record" - _extract_record_id $_records $_sub_domain + _extract_record_id "$_records" "$_sub_domain" + + if _dnsimple_rest \ + PATCH \ + "$_account_id/zones/$_domain/records/$_record_id" \ + "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then - _dnsimple_rest PATCH "$_account_id/zones/$_domain/records/$_record_id" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}" - if [ "$?" = "0" ]; then _info "Updated!" - #todo: check if the record takes effect return 0 fi + _err "Update error" return 1 fi @@ -80,13 +83,12 @@ dns_dnsimple_rm() { return 1 fi - _get_records $_account_id $_domain $_sub_domain - _extract_record_id $_records $_sub_domain + _get_records "$_account_id" "$_domain" "$_sub_domain" + _extract_record_id "$_records" "$_sub_domain" if [ "$_record_id" ]; then - _dnsimple_rest DELETE "$_account_id/zones/$_domain/records/$_record_id" - if [ "$?" = "0" ]; then + if _dnsimple_rest DELETE "$_account_id/zones/$_domain/records/$_record_id"; then _info "removed record" "$_record_id" return 0 fi @@ -193,8 +195,9 @@ _dnsimple_rest() { request_url="$DNSimple_API/$path" _debug "$path" - _H1="Accept: application/json" - _H2="Authorization: Bearer $DNSimple_OAUTH_TOKEN" + export _H1="Accept: application/json" + export _H2="Authorization: Bearer $DNSimple_OAUTH_TOKEN" + if [ "$data" ]; then _H1="Content-Type: application/json" _debug data "$data" From 5b21cbe0de81f858e29a5abf3e3c0c35ae6a18d3 Mon Sep 17 00:00:00 2001 From: Matthew Turney Date: Mon, 1 May 2017 20:56:04 -0500 Subject: [PATCH 15/16] Revert "provide a more general purpose request function" This reverts commit aa86652db8d3132fb7fe0c0253dded7deb7dce2c. This is not actually necessary and can be accomplished with the post function. --- acme.sh | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/acme.sh b/acme.sh index 3ccd8dc4..7ce947ea 100755 --- a/acme.sh +++ b/acme.sh @@ -1592,17 +1592,12 @@ _post() { return $_ret } -_get() { - _request "$1" "$2" "$3" GET -} - # url getheader timeout -_request() { +_get() { + _debug GET url="$1" onlyheader="$2" t="$3" - method="$4" - _debug method $method _debug url "$url" _debug "timeout" "$t" @@ -1616,9 +1611,6 @@ _request() { if [ "$t" ]; then _CURL="$_CURL --connect-timeout $t" fi - if [ "$method" ]; then - _CURL="$_CURL -X $method" - fi _debug "_CURL" "$_CURL" if [ "$onlyheader" ]; then $_CURL -I --user-agent "$USER_AGENT" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$url" @@ -1641,9 +1633,6 @@ _request() { if [ "$t" ]; then _WGET="$_WGET --timeout=$t" fi - if [ "$method" ]; then - _WGET="$_WGET --method=$method" - fi _debug "_WGET" "$_WGET" if [ "$onlyheader" ]; then $_WGET --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" -S -O /dev/null "$url" 2>&1 | sed 's/^[ ]*//g' From 533238712536e3a11c2b09b4d0d480891cfd3d9f Mon Sep 17 00:00:00 2001 From: Matthew Turney Date: Tue, 2 May 2017 08:51:43 -0500 Subject: [PATCH 16/16] Use _post to send a DELETE request for DNSimple record removal. --- dnsapi/dns_dnsimple.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_dnsimple.sh b/dnsapi/dns_dnsimple.sh index d92c6137..0bfe2b99 100644 --- a/dnsapi/dns_dnsimple.sh +++ b/dnsapi/dns_dnsimple.sh @@ -198,12 +198,12 @@ _dnsimple_rest() { export _H1="Accept: application/json" export _H2="Authorization: Bearer $DNSimple_OAUTH_TOKEN" - if [ "$data" ]; then + if [ "$data" ] || [ "$method" = "DELETE" ]; then _H1="Content-Type: application/json" _debug data "$data" response="$(_post "$data" "$request_url" "" "$method")" else - response="$(_request "$request_url" "" "" "$method")" + response="$(_get "$request_url" "" "" "$method")" fi if [ "$?" != "0" ]; then