From 841b762796d4909d0bc40cfa7e4a9147aa17e28a Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 23 Jun 2017 18:11:11 +0800 Subject: [PATCH 01/95] minor --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 09cc9fd4..70033523 100755 --- a/acme.sh +++ b/acme.sh @@ -453,7 +453,7 @@ if [ "$(printf '\x41')" != 'A' ]; then fi _ESCAPE_XARGS="" -if [ "$(printf %s '\\x41' | xargs printf)" = 'A' ]; then +if _exists xargs && [ "$(printf %s '\\x41' | xargs printf)" = 'A' ]; then _ESCAPE_XARGS=1 fi From eb0ef6bd3dd56af440628b9b0f0edeb3753cf863 Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 27 Jun 2017 19:56:43 +0800 Subject: [PATCH 02/95] fix https://github.com/Neilpang/acme.sh/issues/614#issuecomment-311160843 --- acme.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 70033523..fa969b0f 100755 --- a/acme.sh +++ b/acme.sh @@ -1138,7 +1138,12 @@ _readKeyLengthFromCSR() { echo "$_outcsr" | tr "\t" " " | _egrep_o "^ *ASN1 OID:.*" | cut -d ':' -f 2 | tr -d ' ' else _debug "RSA CSR" - echo "$_outcsr" | tr "\t" " " | (_egrep_o "^ *Public.Key:.*" || _egrep_o "RSA Public.Key:.*") | cut -d '(' -f 2 | cut -d ' ' -f 1 + _rkl="$(echo "$_outcsr" | tr "\t" " " | _egrep_o "^ *Public.Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1)" + if [ "$_rkl" ]; then + echo "$_rkl" + else + echo "$_outcsr" | tr "\t" " " | _egrep_o "RSA Public.Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1 + fi fi } From fa98d72f3a87cf438ba16cccccf61fc268c517df Mon Sep 17 00:00:00 2001 From: RaidenII Date: Tue, 27 Jun 2017 09:21:39 -0400 Subject: [PATCH 03/95] Added preliminary support for DuckDNS TXT record API, a free Dynamic DNS provider --- dnsapi/dns_duckdns.sh | 93 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100755 dnsapi/dns_duckdns.sh diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh new file mode 100755 index 00000000..dc0d49ca --- /dev/null +++ b/dnsapi/dns_duckdns.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env sh + +#Created by RaidenII, to use DuckDNS's API to add/remove text records +#06/27/2017 + +# Currently only support single domain access + +# DuckDNS uses StartSSL as their cert provider +# Seems not supported natively on Linux +# So I fall back to HTTP for API +DuckDNS_API="http://www.duckdns.org/update" + +######## Public functions ##################### + +#Usage: dns_duckdns_add _acme-challenge.domain.duckdns.org "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_duckdns_add() { + fulldomain=$1 + txtvalue=$2 + + # We'll extract the domain/username from full domain + IFS='.' read -r -a fqdn <<< "$fulldomain" + DuckDNS_domain="${fqdn[-3]}" + + if [ -z "$DuckDNS_domain" ]; then + _err "Error extracting the domain." + return 1 + fi + + if [ -z "$DuckDNS_token" ]; then + DuckDNS_token="" + _err "The token for your DuckDNS account is necessary." + _err "You can look it up in your DuckDNS account." + return 1 + fi + + # Now save the credentials. + _saveaccountconf DuckDNS_domain "$DuckDNS_domain" + _saveaccountconf DuckDNS_token "$DuckDNS_token" + + # Unfortunately, DuckDNS does not seems to support lookup domain through API + # So I assume your credentials (which are your domain and token) are correct + # If something goes wrong, we will get a KO response from DuckDNS + + # Now add the TXT record to DuckDNS + _info "Trying to add TXT record" + if _duckdns_rest GET "domains=$DuckDNS_domain&token=$DuckDNS_token&txt=$txtvalue" && [ $response == "OK" ]; then + _info "TXT record has been successfully added to your DuckDNS domain." + _info "Note that all subdomains under this domain uses the same TXT record." + return 0 + else + _err "Errors happened during adding the TXT record." + return 1 + fi +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_duckdns_rm() { + fulldomain=$1 + txtvalue=$2 + + # Now remove the TXT record from DuckDNS + _info "Trying to from TXT record" + if _duckdns_rest GET "domains=$DuckDNS_domain&token=$DuckDNS_token&txt=''&clear=true" && [ $response == "OK" ]; then + _info "TXT record has been successfully removed from your DuckDNS domain." + return 0 + else + _err "Errors happened during removing the TXT record." + return 1 + fi +} + +#################### Private functions below ################################## + +#Usage: method URI data +_duckdns_rest() { + method=$1 + param="$2" + _debug param "$param" + url="$DuckDNS_API?$param" + _debug url "$url" + + # DuckDNS uses GET to update domain info + if [ $method == "GET" ]; then + response="$(_get "$url")" + else + _err "Unsupported method" + return 1 + fi + + _debug response "$response" + return 0 +} From e7dff4756ffef5f14b40363cc2a888977b9d9efd Mon Sep 17 00:00:00 2001 From: RaidenII Date: Tue, 27 Jun 2017 15:28:10 -0400 Subject: [PATCH 04/95] Using HTTPS for DuckDNS API and added instruction. --- dnsapi/dns_duckdns.sh | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index dc0d49ca..847b3fc5 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -4,11 +4,10 @@ #06/27/2017 # Currently only support single domain access +# Due to the fact that DuckDNS uses StartSSL as cert provider, --insecure must be used with acme.sh -# DuckDNS uses StartSSL as their cert provider -# Seems not supported natively on Linux -# So I fall back to HTTP for API -DuckDNS_API="http://www.duckdns.org/update" +DuckDNS_API="https://www.duckdns.org/update" +API_Params="domains=$DuckDNS_domain&token=$DuckDNS_token" ######## Public functions ##################### @@ -43,7 +42,7 @@ dns_duckdns_add() { # Now add the TXT record to DuckDNS _info "Trying to add TXT record" - if _duckdns_rest GET "domains=$DuckDNS_domain&token=$DuckDNS_token&txt=$txtvalue" && [ $response == "OK" ]; then + if _duckdns_rest GET "$API_Params&txt=$txtvalue" && [ $response == "OK" ]; then _info "TXT record has been successfully added to your DuckDNS domain." _info "Note that all subdomains under this domain uses the same TXT record." return 0 @@ -60,8 +59,8 @@ dns_duckdns_rm() { txtvalue=$2 # Now remove the TXT record from DuckDNS - _info "Trying to from TXT record" - if _duckdns_rest GET "domains=$DuckDNS_domain&token=$DuckDNS_token&txt=''&clear=true" && [ $response == "OK" ]; then + _info "Trying to remove TXT record" + if _duckdns_rest GET "$API_Params&txt=''&clear=true" && [ $response == "OK" ]; then _info "TXT record has been successfully removed from your DuckDNS domain." return 0 else @@ -72,7 +71,7 @@ dns_duckdns_rm() { #################### Private functions below ################################## -#Usage: method URI data +#Usage: method URI _duckdns_rest() { method=$1 param="$2" From 9dd62ae0f8de8e125edb8396a1b25aba3d712bd3 Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 28 Jun 2017 19:21:03 +0800 Subject: [PATCH 05/95] fix https://github.com/Neilpang/acme.sh/issues/900 --- Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5254bd11..8f363852 100644 --- a/Dockerfile +++ b/Dockerfile @@ -50,9 +50,10 @@ RUN for verb in help \ RUN printf "%b" '#!'"/usr/bin/env sh\n \ if [ \"\$1\" = \"daemon\" ]; then \n \ - crond -f\n \ + trap \"echo stop && killall crond && exit 0\" SIGTERM SIGINT \n \ + crond && while true; do sleep 1; done;\n \ else \n \ - /root/.acme.sh/acme.sh --config-home /acme.sh \"\$@\"\n \ + exec -- \"\$@\"\n \ fi" >/entry.sh && chmod +x /entry.sh VOLUME /acme.sh From 7d2b6cfeaf888a34526fa291e5d9b5ad350ff6ff Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 28 Jun 2017 19:46:51 +0800 Subject: [PATCH 06/95] fix https://github.com/Neilpang/acme.sh/issues/905 --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 13188982..5b6b03ae 100644 --- a/README.md +++ b/README.md @@ -296,6 +296,9 @@ acme.sh --renew -d example.com Ok, it's finished. +**Take care, this is dns manual mode, it can not be renewed automatically. you will have to add a new txt record to your domain by your hand when you renew your cert.** + +**Please use dns api mode instead.** # 9. Automatic DNS API integration From e64ad5176ef6e4865c0d8fd7da83e318e07ef853 Mon Sep 17 00:00:00 2001 From: RaidenII Date: Wed, 28 Jun 2017 16:15:57 -0400 Subject: [PATCH 07/95] Added Name.com API support. Minor change to DuckDNS API support. --- dnsapi/dns_duckdns.sh | 2 +- dnsapi/dns_namecom.sh | 188 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 1 deletion(-) create mode 100755 dnsapi/dns_namecom.sh diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index 847b3fc5..f86d516e 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -60,7 +60,7 @@ dns_duckdns_rm() { # Now remove the TXT record from DuckDNS _info "Trying to remove TXT record" - if _duckdns_rest GET "$API_Params&txt=''&clear=true" && [ $response == "OK" ]; then + if _duckdns_rest GET "$API_Params&txt=&clear=true" && [ $response == "OK" ]; then _info "TXT record has been successfully removed from your DuckDNS domain." return 0 else diff --git a/dnsapi/dns_namecom.sh b/dnsapi/dns_namecom.sh new file mode 100755 index 00000000..7a84685f --- /dev/null +++ b/dnsapi/dns_namecom.sh @@ -0,0 +1,188 @@ +#!/usr/bin/env sh + +#Author: RaidneII +#Created 06/28/2017 +#Utilize name.com API to finish dns-01 verifications. +######## Public functions ##################### + +namecom_api="https://api.name.com/api/" + +#Usage: dns_namecom_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_namecom_add() { + fulldomain=$1 + txtvalue=$2 + + # First we need name.com credentials. + if [ -z "$namecom_username" ]; then + namecom_username="" + _err "Username for name.com is missing." + _err "Please specify that in your environment variable." + return 1 + fi + + if [ -z "$namecom_token" ]; then + namecom_token="" + _err "API token for name.com is missing." + _err "Please specify that in your environment variable." + return 1 + fi + + # Save them in configuration. + _saveaccountconf namecom_username "$namecom_username" + _saveaccountconf namecom_token "$namecom_token" + + # Login in using API + _namecom_login + + # Find domain in domain list. + if ! _namecom_get_root "$fulldomain"; then + _err "Unable to find domain specified." + _namecom_logout + return 1 + fi + + # Add TXT record. + _namecom_addtxt_json="{\"hostname\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":\"300\",\"priority\":\"10\"}" + if _namecom_rest POST "dns/create/$_domain" "$_namecom_addtxt_json"; then + retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") + _debug retcode "$retcode" + if [ ! -z "$retcode" ]; then + _info "Successfully added TXT record, ready for validation." + _namecom_logout + return 0 + else + _err "Unable to add the DNS record." + _namecom_logout + return 1 + fi + fi +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_namecom_rm() { + fulldomain=$1 + txtvalue=$2 + + _namecom_login + + # Find domain in domain list. + if ! _namecom_get_root "$fulldomain"; then + _err "Unable to find domain specified." + _namecom_logout + return 1 + fi + + # Get the record id. + if _namecom_rest GET "dns/list/$_domain"; then + retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") + _debug retcode "$retcode" + if [ ! -z "$retcode" ]; then + _record_id=$(printf "%s\n" "$response" | _egrep_o "\"record_id\":\"[0-9]+\",\"name\":\"$fulldomain\",\"type\":\"TXT\"" | cut -d : -f 2 | cut -d \" -f 2) + _debug record_id "$_record_id" + _info "Successfully retrieved the record id for ACME challenge." + else + _err "Unable to retrieve the record id." + _namecom_logout + return 1 + fi + fi + + # Remove the DNS record using record id. + _namecom_rmtxt_json="{\"record_id\":\"$_record_id\"}" + if _namecom_rest POST "dns/delete/$_domain" "$_namecom_rmtxt_json"; then + retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") + _debug retcode "$retcode" + if [ ! -z "$retcode" ]; then + _info "Successfully removed the TXT record." + _namecom_logout + return 0 + else + _err "Unable to remove the DNS record." + _namecom_logout + return 1 + fi + fi +} + +#################### Private functions below ################################## +_namecom_rest() { + method=$1 + param=$2 + data=$3 + + export _H1="Content-Type: application/json" + export _H2="Api-Session-Token: $sessionkey" + if [ "$method" != "GET" ]; then + response="$(_post "$data" "$namecom_api/$param" "" "$method")" + else + response="$(_get "$namecom_api/$param")" + fi + + if [ "$?" != "0" ]; then + _err "error $param" + return 1 + fi + + _debug response "$response" + return 0 +} + +_namecom_login() { + namecom_login_json="{\"username\":\"$namecom_username\",\"api_token\":\"$namecom_token\"}" + + if _namecom_rest POST "login" "$namecom_login_json"; then + retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") + _debug retcode "$retcode" + if [ ! -z "$retcode" ]; then + _info "Successfully logged in. Fetching session token..." + sessionkey=$(printf "%s\n" "$response" | _egrep_o "\"session_token\":\".+" | cut -d \" -f 4) + if [ ! -z "$sessionkey" ]; then + _debug sessionkey "$sessionkey" + _info "Session key obtained." + else + _err "Unable to get session key." + return 1 + fi + else + _err "Logging in failed." + return 1 + fi + fi +} + +_namecom_logout() { + if _namecom_rest GET "logout"; then + retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") + if [ ! -z "$retcode" ]; then + _info "Successfully logged out." + else + _err "Error logging out." + return 1 + fi + fi +} + +_namecom_get_root() { + domain=$1 + i=2 + p=1 + + if _namecom_rest GET "domain/list"; then + while true; do + host=$(printf "%s" "$domain" | cut -d . -f $i-100) + if [ -z "$host" ]; then + return 1 + fi + + if _contains "$response" "$host"; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="$host" + return 0 + fi + p=$i + i=$(_math "$i" + 1) + done + fi + return 1 +} From 168d712decb687c4ac665b02df716a7de9c99b6e Mon Sep 17 00:00:00 2001 From: RaidenII Date: Thu, 29 Jun 2017 09:43:11 -0400 Subject: [PATCH 08/95] Fixed URL of Name.com API and removed useless debug for retcode. --- dnsapi/dns_namecom.sh | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/dnsapi/dns_namecom.sh b/dnsapi/dns_namecom.sh index 7a84685f..158a11b0 100755 --- a/dnsapi/dns_namecom.sh +++ b/dnsapi/dns_namecom.sh @@ -5,7 +5,7 @@ #Utilize name.com API to finish dns-01 verifications. ######## Public functions ##################### -namecom_api="https://api.name.com/api/" +namecom_api="https://api.name.com/api" #Usage: dns_namecom_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_namecom_add() { @@ -45,7 +45,6 @@ dns_namecom_add() { _namecom_addtxt_json="{\"hostname\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":\"300\",\"priority\":\"10\"}" if _namecom_rest POST "dns/create/$_domain" "$_namecom_addtxt_json"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - _debug retcode "$retcode" if [ ! -z "$retcode" ]; then _info "Successfully added TXT record, ready for validation." _namecom_logout @@ -76,7 +75,6 @@ dns_namecom_rm() { # Get the record id. if _namecom_rest GET "dns/list/$_domain"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - _debug retcode "$retcode" if [ ! -z "$retcode" ]; then _record_id=$(printf "%s\n" "$response" | _egrep_o "\"record_id\":\"[0-9]+\",\"name\":\"$fulldomain\",\"type\":\"TXT\"" | cut -d : -f 2 | cut -d \" -f 2) _debug record_id "$_record_id" @@ -92,7 +90,6 @@ dns_namecom_rm() { _namecom_rmtxt_json="{\"record_id\":\"$_record_id\"}" if _namecom_rest POST "dns/delete/$_domain" "$_namecom_rmtxt_json"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - _debug retcode "$retcode" if [ ! -z "$retcode" ]; then _info "Successfully removed the TXT record." _namecom_logout @@ -133,7 +130,6 @@ _namecom_login() { if _namecom_rest POST "login" "$namecom_login_json"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - _debug retcode "$retcode" if [ ! -z "$retcode" ]; then _info "Successfully logged in. Fetching session token..." sessionkey=$(printf "%s\n" "$response" | _egrep_o "\"session_token\":\".+" | cut -d \" -f 4) From eeda3062e1c2a79d65e01db192582586e11fb517 Mon Sep 17 00:00:00 2001 From: RaidenII Date: Thu, 29 Jun 2017 15:40:29 -0400 Subject: [PATCH 09/95] Fix against POSIX standard. --- dnsapi/dns_duckdns.sh | 9 ++-- dnsapi/dns_namecom.sh | 104 +++++++++++++++++++++--------------------- 2 files changed, 56 insertions(+), 57 deletions(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index f86d516e..a34c8d36 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -17,8 +17,7 @@ dns_duckdns_add() { txtvalue=$2 # We'll extract the domain/username from full domain - IFS='.' read -r -a fqdn <<< "$fulldomain" - DuckDNS_domain="${fqdn[-3]}" + DuckDNS_domain=$(printf "%s\n" "$fulldomain" | rev | cut -d \. -f 3 | rev) if [ -z "$DuckDNS_domain" ]; then _err "Error extracting the domain." @@ -42,7 +41,7 @@ dns_duckdns_add() { # Now add the TXT record to DuckDNS _info "Trying to add TXT record" - if _duckdns_rest GET "$API_Params&txt=$txtvalue" && [ $response == "OK" ]; then + if _duckdns_rest GET "$API_Params&txt=$txtvalue" && [ "$response" -eq "OK" ]; then _info "TXT record has been successfully added to your DuckDNS domain." _info "Note that all subdomains under this domain uses the same TXT record." return 0 @@ -60,7 +59,7 @@ dns_duckdns_rm() { # Now remove the TXT record from DuckDNS _info "Trying to remove TXT record" - if _duckdns_rest GET "$API_Params&txt=&clear=true" && [ $response == "OK" ]; then + if _duckdns_rest GET "$API_Params&txt=&clear=true" && [ "$response" -eq "OK" ]; then _info "TXT record has been successfully removed from your DuckDNS domain." return 0 else @@ -80,7 +79,7 @@ _duckdns_rest() { _debug url "$url" # DuckDNS uses GET to update domain info - if [ $method == "GET" ]; then + if [ "$method" -eq "GET" ]; then response="$(_get "$url")" else _err "Unsupported method" diff --git a/dnsapi/dns_namecom.sh b/dnsapi/dns_namecom.sh index 158a11b0..9a6e81f9 100755 --- a/dnsapi/dns_namecom.sh +++ b/dnsapi/dns_namecom.sh @@ -45,15 +45,15 @@ dns_namecom_add() { _namecom_addtxt_json="{\"hostname\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":\"300\",\"priority\":\"10\"}" if _namecom_rest POST "dns/create/$_domain" "$_namecom_addtxt_json"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then - _info "Successfully added TXT record, ready for validation." - _namecom_logout - return 0 - else - _err "Unable to add the DNS record." - _namecom_logout - return 1 - fi + if [ ! -z "$retcode" ]; then + _info "Successfully added TXT record, ready for validation." + _namecom_logout + return 0 + else + _err "Unable to add the DNS record." + _namecom_logout + return 1 + fi fi } @@ -75,30 +75,30 @@ dns_namecom_rm() { # Get the record id. if _namecom_rest GET "dns/list/$_domain"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then - _record_id=$(printf "%s\n" "$response" | _egrep_o "\"record_id\":\"[0-9]+\",\"name\":\"$fulldomain\",\"type\":\"TXT\"" | cut -d : -f 2 | cut -d \" -f 2) - _debug record_id "$_record_id" - _info "Successfully retrieved the record id for ACME challenge." - else - _err "Unable to retrieve the record id." - _namecom_logout - return 1 - fi + if [ ! -z "$retcode" ]; then + _record_id=$(printf "%s\n" "$response" | _egrep_o "\"record_id\":\"[0-9]+\",\"name\":\"$fulldomain\",\"type\":\"TXT\"" | cut -d : -f 2 | cut -d \" -f 2) + _debug record_id "$_record_id" + _info "Successfully retrieved the record id for ACME challenge." + else + _err "Unable to retrieve the record id." + _namecom_logout + return 1 + fi fi # Remove the DNS record using record id. _namecom_rmtxt_json="{\"record_id\":\"$_record_id\"}" if _namecom_rest POST "dns/delete/$_domain" "$_namecom_rmtxt_json"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then - _info "Successfully removed the TXT record." - _namecom_logout - return 0 - else - _err "Unable to remove the DNS record." - _namecom_logout - return 1 - fi + if [ ! -z "$retcode" ]; then + _info "Successfully removed the TXT record." + _namecom_logout + return 0 + else + _err "Unable to remove the DNS record." + _namecom_logout + return 1 + fi fi } @@ -130,32 +130,32 @@ _namecom_login() { if _namecom_rest POST "login" "$namecom_login_json"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then - _info "Successfully logged in. Fetching session token..." - sessionkey=$(printf "%s\n" "$response" | _egrep_o "\"session_token\":\".+" | cut -d \" -f 4) - if [ ! -z "$sessionkey" ]; then - _debug sessionkey "$sessionkey" - _info "Session key obtained." - else - _err "Unable to get session key." - return 1 - fi + if [ ! -z "$retcode" ]; then + _info "Successfully logged in. Fetching session token..." + sessionkey=$(printf "%s\n" "$response" | _egrep_o "\"session_token\":\".+" | cut -d \" -f 4) + if [ ! -z "$sessionkey" ]; then + _debug sessionkey "$sessionkey" + _info "Session key obtained." else - _err "Logging in failed." + _err "Unable to get session key." return 1 fi - fi + else + _err "Logging in failed." + return 1 + fi + fi } _namecom_logout() { if _namecom_rest GET "logout"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then - _info "Successfully logged out." - else - _err "Error logging out." - return 1 - fi + if [ ! -z "$retcode" ]; then + _info "Successfully logged out." + else + _err "Error logging out." + return 1 + fi fi } @@ -171,13 +171,13 @@ _namecom_get_root() { return 1 fi - if _contains "$response" "$host"; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) - _domain="$host" - return 0 - fi - p=$i - i=$(_math "$i" + 1) + if _contains "$response" "$host"; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="$host" + return 0 + fi + p=$i + i=$(_math "$i" + 1) done fi return 1 From d0f5aece5f5c1708668faed8e2a7fe5671eceea8 Mon Sep 17 00:00:00 2001 From: RaidenII Date: Thu, 29 Jun 2017 15:43:58 -0400 Subject: [PATCH 10/95] Fix SC2170. --- dnsapi/dns_duckdns.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index a34c8d36..b1937cb8 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -41,7 +41,7 @@ dns_duckdns_add() { # Now add the TXT record to DuckDNS _info "Trying to add TXT record" - if _duckdns_rest GET "$API_Params&txt=$txtvalue" && [ "$response" -eq "OK" ]; then + if _duckdns_rest GET "$API_Params&txt=$txtvalue" && [ "$response" = "OK" ]; then _info "TXT record has been successfully added to your DuckDNS domain." _info "Note that all subdomains under this domain uses the same TXT record." return 0 @@ -59,7 +59,7 @@ dns_duckdns_rm() { # Now remove the TXT record from DuckDNS _info "Trying to remove TXT record" - if _duckdns_rest GET "$API_Params&txt=&clear=true" && [ "$response" -eq "OK" ]; then + if _duckdns_rest GET "$API_Params&txt=&clear=true" && [ "$response" = "OK" ]; then _info "TXT record has been successfully removed from your DuckDNS domain." return 0 else @@ -79,7 +79,7 @@ _duckdns_rest() { _debug url "$url" # DuckDNS uses GET to update domain info - if [ "$method" -eq "GET" ]; then + if [ "$method" = "GET" ]; then response="$(_get "$url")" else _err "Unsupported method" From 17fbfd14db2b71af580afb59cc515f09299ca37e Mon Sep 17 00:00:00 2001 From: RaidenII Date: Fri, 30 Jun 2017 08:32:39 -0400 Subject: [PATCH 11/95] Minor fixes. --- dnsapi/dns_duckdns.sh | 2 +- dnsapi/dns_namecom.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index b1937cb8..cacf5a8c 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -17,7 +17,7 @@ dns_duckdns_add() { txtvalue=$2 # We'll extract the domain/username from full domain - DuckDNS_domain=$(printf "%s\n" "$fulldomain" | rev | cut -d \. -f 3 | rev) + DuckDNS_domain=$(printf "%s\n" "$fulldomain" | rev | cut -d . -f 3 | rev) if [ -z "$DuckDNS_domain" ]; then _err "Error extracting the domain." diff --git a/dnsapi/dns_namecom.sh b/dnsapi/dns_namecom.sh index 9a6e81f9..2c5a5df4 100755 --- a/dnsapi/dns_namecom.sh +++ b/dnsapi/dns_namecom.sh @@ -76,7 +76,7 @@ dns_namecom_rm() { if _namecom_rest GET "dns/list/$_domain"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") if [ ! -z "$retcode" ]; then - _record_id=$(printf "%s\n" "$response" | _egrep_o "\"record_id\":\"[0-9]+\",\"name\":\"$fulldomain\",\"type\":\"TXT\"" | cut -d : -f 2 | cut -d \" -f 2) + _record_id=$(printf "%s\n" "$response" | _egrep_o "\"record_id\":\"[0-9]+\",\"name\":\"$fulldomain\",\"type\":\"TXT\"" | cut -d \" -f 4) _debug record_id "$_record_id" _info "Successfully retrieved the record id for ACME challenge." else From d04434e3ecd286c2109afd313aecf31d2cc7ec49 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 1 Jul 2017 10:54:14 +0800 Subject: [PATCH 12/95] fix alias --- acme.sh | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/acme.sh b/acme.sh index fa969b0f..1f1071d1 100755 --- a/acme.sh +++ b/acme.sh @@ -4679,6 +4679,8 @@ _installalias() { _setopt "$_envfile" "export LE_WORKING_DIR" "=" "\"$LE_WORKING_DIR\"" if [ "$_c_home" ]; then _setopt "$_envfile" "export LE_CONFIG_HOME" "=" "\"$LE_CONFIG_HOME\"" + else + _sed_i "/^export LE_CONFIG_HOME/d" "$_envfile" fi _setopt "$_envfile" "alias $PROJECT_ENTRY" "=" "\"$LE_WORKING_DIR/$PROJECT_ENTRY$_c_entry\"" @@ -4700,6 +4702,8 @@ _installalias() { _setopt "$_cshfile" "setenv LE_WORKING_DIR" " " "\"$LE_WORKING_DIR\"" if [ "$_c_home" ]; then _setopt "$_cshfile" "setenv LE_CONFIG_HOME" " " "\"$LE_CONFIG_HOME\"" + else + _sed_i "/^setenv LE_CONFIG_HOME/d" "$_cshfile" fi _setopt "$_cshfile" "alias $PROJECT_ENTRY" " " "\"$LE_WORKING_DIR/$PROJECT_ENTRY$_c_entry\"" _setopt "$_csh_profile" "source \"$_cshfile\"" @@ -4764,20 +4768,24 @@ install() { _info "Installing to $LE_WORKING_DIR" - if ! mkdir -p "$LE_WORKING_DIR"; then - _err "Can not create working dir: $LE_WORKING_DIR" - return 1 + if [ ! -d "$LE_WORKING_DIR" ]; then + if ! mkdir -p "$LE_WORKING_DIR"; then + _err "Can not create working dir: $LE_WORKING_DIR" + return 1 + fi + + chmod 700 "$LE_WORKING_DIR" fi - chmod 700 "$LE_WORKING_DIR" + if [ ! -d "$LE_CONFIG_HOME" ]; then + if ! mkdir -p "$LE_CONFIG_HOME"; then + _err "Can not create config dir: $LE_CONFIG_HOME" + return 1 + fi - if ! mkdir -p "$LE_CONFIG_HOME"; then - _err "Can not create config dir: $LE_CONFIG_HOME" - return 1 + chmod 700 "$LE_CONFIG_HOME" fi - chmod 700 "$LE_CONFIG_HOME" - cp "$PROJECT_ENTRY" "$LE_WORKING_DIR/" && chmod +x "$LE_WORKING_DIR/$PROJECT_ENTRY" if [ "$?" != "0" ]; then From 63c6ed3fd06263a5ad8ebb2788807bda13237f42 Mon Sep 17 00:00:00 2001 From: RaidenII Date: Sat, 1 Jul 2017 05:14:52 -0700 Subject: [PATCH 13/95] Fixes to follow coding standards. --- dnsapi/dns_duckdns.sh | 16 ++++++++-------- dnsapi/dns_namecom.sh | 32 ++++++++++++++++---------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index cacf5a8c..95df4c21 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -7,7 +7,7 @@ # Due to the fact that DuckDNS uses StartSSL as cert provider, --insecure must be used with acme.sh DuckDNS_API="https://www.duckdns.org/update" -API_Params="domains=$DuckDNS_domain&token=$DuckDNS_token" +API_Params="domains=$DuckDNS_Domain&token=$DuckDNS_Token" ######## Public functions ##################### @@ -17,23 +17,23 @@ dns_duckdns_add() { txtvalue=$2 # We'll extract the domain/username from full domain - DuckDNS_domain=$(printf "%s\n" "$fulldomain" | rev | cut -d . -f 3 | rev) + DuckDNS_Domain=$(echo $fulldomain | _lower_case | _egrep_o '.[^.]*.duckdns.org' | cut -d . -f 2) - if [ -z "$DuckDNS_domain" ]; then + if [ -z "$DuckDNS_Domain" ]; then _err "Error extracting the domain." return 1 fi - if [ -z "$DuckDNS_token" ]; then - DuckDNS_token="" + if [ -z "$DuckDNS_Token" ]; then + DuckDNS_Token="" _err "The token for your DuckDNS account is necessary." _err "You can look it up in your DuckDNS account." return 1 fi # Now save the credentials. - _saveaccountconf DuckDNS_domain "$DuckDNS_domain" - _saveaccountconf DuckDNS_token "$DuckDNS_token" + _saveaccountconf DuckDNS_Domain "$DuckDNS_Domain" + _saveaccountconf DuckDNS_Token "$DuckDNS_Token" # Unfortunately, DuckDNS does not seems to support lookup domain through API # So I assume your credentials (which are your domain and token) are correct @@ -86,6 +86,6 @@ _duckdns_rest() { return 1 fi - _debug response "$response" + _debug2 response "$response" return 0 } diff --git a/dnsapi/dns_namecom.sh b/dnsapi/dns_namecom.sh index 2c5a5df4..15eae6c2 100755 --- a/dnsapi/dns_namecom.sh +++ b/dnsapi/dns_namecom.sh @@ -5,7 +5,7 @@ #Utilize name.com API to finish dns-01 verifications. ######## Public functions ##################### -namecom_api="https://api.name.com/api" +Namecom_API="https://api.name.com/api" #Usage: dns_namecom_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_namecom_add() { @@ -13,23 +13,23 @@ dns_namecom_add() { txtvalue=$2 # First we need name.com credentials. - if [ -z "$namecom_username" ]; then - namecom_username="" + if [ -z "$Namecom_Username" ]; then + Namecom_Username="" _err "Username for name.com is missing." _err "Please specify that in your environment variable." return 1 fi - if [ -z "$namecom_token" ]; then - namecom_token="" + if [ -z "$Namecom_Token" ]; then + Namecom_Token="" _err "API token for name.com is missing." _err "Please specify that in your environment variable." return 1 fi # Save them in configuration. - _saveaccountconf namecom_username "$namecom_username" - _saveaccountconf namecom_token "$namecom_token" + _saveaccountconf Namecom_Username "$Namecom_Username" + _saveaccountconf Namecom_Token "$Namecom_Token" # Login in using API _namecom_login @@ -45,7 +45,7 @@ dns_namecom_add() { _namecom_addtxt_json="{\"hostname\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":\"300\",\"priority\":\"10\"}" if _namecom_rest POST "dns/create/$_domain" "$_namecom_addtxt_json"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then + if [ "$retcode" ]; then _info "Successfully added TXT record, ready for validation." _namecom_logout return 0 @@ -75,7 +75,7 @@ dns_namecom_rm() { # Get the record id. if _namecom_rest GET "dns/list/$_domain"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then + if [ "$retcode" ]; then _record_id=$(printf "%s\n" "$response" | _egrep_o "\"record_id\":\"[0-9]+\",\"name\":\"$fulldomain\",\"type\":\"TXT\"" | cut -d \" -f 4) _debug record_id "$_record_id" _info "Successfully retrieved the record id for ACME challenge." @@ -90,7 +90,7 @@ dns_namecom_rm() { _namecom_rmtxt_json="{\"record_id\":\"$_record_id\"}" if _namecom_rest POST "dns/delete/$_domain" "$_namecom_rmtxt_json"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then + if [ "$retcode" ]; then _info "Successfully removed the TXT record." _namecom_logout return 0 @@ -111,9 +111,9 @@ _namecom_rest() { export _H1="Content-Type: application/json" export _H2="Api-Session-Token: $sessionkey" if [ "$method" != "GET" ]; then - response="$(_post "$data" "$namecom_api/$param" "" "$method")" + response="$(_post "$data" "$Namecom_API/$param" "" "$method")" else - response="$(_get "$namecom_api/$param")" + response="$(_get "$Namecom_API/$param")" fi if [ "$?" != "0" ]; then @@ -121,16 +121,16 @@ _namecom_rest() { return 1 fi - _debug response "$response" + _debug2 response "$response" return 0 } _namecom_login() { - namecom_login_json="{\"username\":\"$namecom_username\",\"api_token\":\"$namecom_token\"}" + namecom_login_json="{\"username\":\"$Namecom_Username\",\"api_token\":\"$Namecom_Token\"}" if _namecom_rest POST "login" "$namecom_login_json"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then + if [ "$retcode" ]; then _info "Successfully logged in. Fetching session token..." sessionkey=$(printf "%s\n" "$response" | _egrep_o "\"session_token\":\".+" | cut -d \" -f 4) if [ ! -z "$sessionkey" ]; then @@ -150,7 +150,7 @@ _namecom_login() { _namecom_logout() { if _namecom_rest GET "logout"; then retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100") - if [ ! -z "$retcode" ]; then + if [ "$retcode" ]; then _info "Successfully logged out." else _err "Error logging out." From 9aed1e2d17331e4c2eeb8ed9f48aa132bdbf07ae Mon Sep 17 00:00:00 2001 From: RaidenII Date: Sat, 1 Jul 2017 05:18:12 -0700 Subject: [PATCH 14/95] Argh. Double quotes. --- dnsapi/dns_duckdns.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_duckdns.sh b/dnsapi/dns_duckdns.sh index 95df4c21..d6987352 100755 --- a/dnsapi/dns_duckdns.sh +++ b/dnsapi/dns_duckdns.sh @@ -17,7 +17,7 @@ dns_duckdns_add() { txtvalue=$2 # We'll extract the domain/username from full domain - DuckDNS_Domain=$(echo $fulldomain | _lower_case | _egrep_o '.[^.]*.duckdns.org' | cut -d . -f 2) + DuckDNS_Domain=$(echo "$fulldomain" | _lower_case | _egrep_o '.[^.]*.duckdns.org' | cut -d . -f 2) if [ -z "$DuckDNS_Domain" ]; then _err "Error extracting the domain." From ea722da3deecf510c64e53df7b7ec4abe8c38123 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 1 Jul 2017 20:31:42 +0800 Subject: [PATCH 15/95] add debug info --- acme.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 1f1071d1..76509af0 100755 --- a/acme.sh +++ b/acme.sh @@ -2999,9 +2999,9 @@ _on_issue_err() { fi #trigger the validation to flush the pending authz + _debug2 "_chk_vlist" "$_chk_vlist" if [ "$_chk_vlist" ]; then ( - _debug2 "_chk_vlist" "$_chk_vlist" _debug2 "start to deactivate authz" ventries=$(echo "$_chk_vlist" | tr "$dvsep" ' ') for ventry in $ventries; do @@ -3498,7 +3498,7 @@ issue() { if [ "$?" != "0" ]; then _clearup - _on_issue_err "$_post_hook" + _on_issue_err "$_post_hook" "$vlist" return 1 fi dnsadded='1' @@ -3510,7 +3510,7 @@ issue() { _debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit." _err "Please add the TXT records to the domains, and retry again." _clearup - _on_issue_err "$_post_hook" + _on_issue_err "$_post_hook" "$vlist" return 1 fi From 14d7bfdab2c3f16c64080aec0dccd0fc9437288c Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 1 Jul 2017 21:47:30 +0800 Subject: [PATCH 16/95] fix deactivate for lower rate limit --- acme.sh | 69 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 22 deletions(-) diff --git a/acme.sh b/acme.sh index 76509af0..6590a00a 100755 --- a/acme.sh +++ b/acme.sh @@ -1152,7 +1152,7 @@ _ss() { if _exists "ss"; then _debug "Using: ss" - ss -ntpl | grep ":$_port " + ss -ntpl 2>/dev/null | grep ":$_port " return 0 fi @@ -4479,26 +4479,51 @@ _deactivate() { _d_type="$2" _initpath + if ! __get_domain_new_authz "$_d_domain"; then + _err "Can not get domain new authz token." + return 1 + fi + + authzUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")" + _debug "authzUri" "$authzUri" + + if [ "$code" ] && [ ! "$code" = '201' ]; then + _err "new-authz error: $response" + return 1 + fi + + entries="$(echo "$response" | _egrep_o '{ *"type":"[^"]*", *"status": *"valid", *"uri"[^}]*')" + if [ -z "$entries" ]; then + _info "No valid entries found." + if [ -z "$thumbprint" ]; then + thumbprint="$(__calc_account_thumbprint)" + fi + _debug "Trigger validation." + vtype="$VTYPE_HTTP" + entry="$(printf "%s\n" "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')" + _debug entry "$entry" + if [ -z "$entry" ]; then + _err "Error, can not get domain token $d" + return 1 + fi + token="$(printf "%s\n" "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')" + _debug token "$token" + + uri="$(printf "%s\n" "$entry" | _egrep_o '"uri":"[^"]*' | cut -d : -f 2,3 | tr -d '"')" + _debug uri "$uri" + + keyauthorization="$token.$thumbprint" + _debug keyauthorization "$keyauthorization" + __trigger_validation "$uri" "$keyauthorization" + + fi + _d_i=0 - _d_max_retry=9 + _d_max_retry=$(echo "$entries" | wc -l) while [ "$_d_i" -lt "$_d_max_retry" ]; do _info "Deactivate: $_d_domain" _d_i="$(_math $_d_i + 1)" - - if ! __get_domain_new_authz "$_d_domain"; then - _err "Can not get domain new authz token." - return 1 - fi - - authzUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")" - _debug "authzUri" "$authzUri" - - if [ ! -z "$code" ] && [ ! "$code" = '201' ]; then - _err "new-authz error: $response" - return 1 - fi - - entry="$(printf "%s\n" "$response" | _egrep_o '{"type":"[^"]*","status":"valid","uri"[^}]*')" + entry="$(echo "$entries" | sed -n "${_d_i}p")" _debug entry "$entry" if [ -z "$entry" ]; then @@ -4520,16 +4545,16 @@ _deactivate() { _info "Deactivate: $_vtype" - if ! _send_signed_request "$authzUri" "{\"resource\": \"authz\", \"status\":\"deactivated\"}"; then + if _send_signed_request "$authzUri" "{\"resource\": \"authz\", \"status\":\"deactivated\"}" && _contains "$response" '"deactivated"'; then + _info "Deactivate: $_vtype success." + else _err "Can not deactivate $_vtype." - return 1 + break fi - _info "Deactivate: $_vtype success." - done _debug "$_d_i" - if [ "$_d_i" -lt "$_d_max_retry" ]; then + if [ "$_d_i" -eq "$_d_max_retry" ]; then _info "Deactivated success!" else _err "Deactivate failed." From 1be222f6ed23e5c793f7a6be834f5c96871d6ffe Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 2 Jul 2017 13:38:44 +0800 Subject: [PATCH 17/95] minor --- acme.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 6590a00a..95964984 100755 --- a/acme.sh +++ b/acme.sh @@ -4614,9 +4614,7 @@ _detect_profile() { fi fi - if [ ! -z "$DETECTED_PROFILE" ]; then - echo "$DETECTED_PROFILE" - fi + echo "$DETECTED_PROFILE" } _initconf() { From c4b2e5829e7ad66941c60e4aa146f227f7df8cb9 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 2 Jul 2017 15:25:35 +0800 Subject: [PATCH 18/95] add always-force-new-domain-key. fix https://github.com/Neilpang/acme.sh/issues/914 --- acme.sh | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 95964984..e8e04e7c 100755 --- a/acme.sh +++ b/acme.sh @@ -1281,7 +1281,7 @@ createDomainKey() { _initpath "$domain" "$_cdl" - if [ ! -f "$CERT_KEY_PATH" ] || ([ "$FORCE" ] && ! [ "$IS_RENEW" ]); then + if [ ! -f "$CERT_KEY_PATH" ] || ([ "$FORCE" ] && ! [ "$IS_RENEW" ]) || [ "$Le_ForceNewDomainKey" = "1" ] ; then if _createkey "$_cdl" "$CERT_KEY_PATH"; then _savedomainconf Le_Keylength "$_cdl" _info "The domain key is here: $(__green $CERT_KEY_PATH)" @@ -3148,7 +3148,7 @@ _regAccount() { return 1 fi if [ "$code" = '202' ]; then - _info "Update success." + _info "Update account tos info success." CA_KEY_HASH="$(__calcAccountKeyHash)" _debug "Calc CA_KEY_HASH" "$CA_KEY_HASH" @@ -3355,7 +3355,7 @@ issue() { else _key=$(_readdomainconf Le_Keylength) _debug "Read key length:$_key" - if [ ! -f "$CERT_KEY_PATH" ] || [ "$_key_length" != "$_key" ]; then + if [ ! -f "$CERT_KEY_PATH" ] || [ "$_key_length" != "$_key" ] || [ "$Le_ForceNewDomainKey" = "1" ]; then if ! createDomainKey "$_main_domain" "$_key_length"; then _err "Create domain key error." _clearup @@ -3885,6 +3885,12 @@ issue() { _cleardomainconf Le_Listen_V4 fi + if [ "$Le_ForceNewDomainKey" = "1" ]; then + _savedomainconf "Le_ForceNewDomainKey" "$Le_ForceNewDomainKey" + else + _cleardomainconf Le_ForceNewDomainKey + fi + Le_NextRenewTime=$(_math "$Le_CertCreateTime" + "$Le_RenewalDays" \* 24 \* 60 \* 60) Le_NextRenewTimeStr=$(_time2str "$Le_NextRenewTime") @@ -5026,6 +5032,7 @@ Parameters: --renew-hook Command to be run once for each successfully renewed certificate. --deploy-hook The hook file to deploy cert --ocsp-must-staple, --ocsp Generate ocsp must Staple extension. + --always-force-new-domain-key Generate new domain key when renewal. Otherwise, the domain key is not changed by default. --auto-upgrade [0|1] Valid for '--upgrade' command, indicating whether to upgrade automatically in future. --listen-v4 Force standalone/tls server to listen at ipv4. --listen-v6 Force standalone/tls server to listen at ipv6. @@ -5506,6 +5513,14 @@ _process() { --ocsp-must-staple | --ocsp) Le_OCSP_Staple="1" ;; + --always-force-new-domain-key) + if [ -z "$2" ] || _startswith "$2" "-"; then + Le_ForceNewDomainKey=1 + else + Le_ForceNewDomainKey="$2" + shift + fi + ;; --log | --logfile) _log="1" _logfile="$2" From 422dd1fa4f57c977ccb4083be9463500b544d293 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 2 Jul 2017 17:02:54 +0800 Subject: [PATCH 19/95] Implement deactivate account: --deactivate-account --- acme.sh | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index e8e04e7c..99c83a04 100755 --- a/acme.sh +++ b/acme.sh @@ -366,6 +366,7 @@ _hasfield() { return 1 #not contains } +# str index [sep] _getfield() { _str="$1" _findex="$2" @@ -3127,7 +3128,7 @@ _regAccount() { _accUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")" _debug "_accUri" "$_accUri" - + _savecaconf "ACCOUNT_URL" "$_accUri" _tos="$(echo "$responseHeaders" | grep "^Link:.*rel=\"terms-of-service\"" | _head_n 1 | _egrep_o "<.*>" | tr -d '<>')" _debug "_tos" "$_tos" if [ -z "$_tos" ]; then @@ -3153,6 +3154,9 @@ _regAccount() { CA_KEY_HASH="$(__calcAccountKeyHash)" _debug "Calc CA_KEY_HASH" "$CA_KEY_HASH" _savecaconf CA_KEY_HASH "$CA_KEY_HASH" + elif [ "$code" = '403' ]; then + _err "It seems that the account key is already deactivated, please use a new account key." + return 1 else _err "Update account error." return 1 @@ -3165,6 +3169,71 @@ _regAccount() { } + +#Implement deactivate account +deactivateaccount() { + _initpath + + if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then + mkdir -p "$CA_DIR" + _info "mv $_OLD_ACCOUNT_KEY to $ACCOUNT_KEY_PATH" + mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH" + fi + + if [ ! -f "$ACCOUNT_JSON_PATH" ] && [ -f "$_OLD_ACCOUNT_JSON" ]; then + mkdir -p "$CA_DIR" + _info "mv $_OLD_ACCOUNT_JSON to $ACCOUNT_JSON_PATH" + mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH" + fi + + if [ ! -f "$ACCOUNT_KEY_PATH" ]; then + _err "Account key is not found at: $ACCOUNT_KEY_PATH" + return 1 + fi + + _accUri=$(_readcaconf "ACCOUNT_URL") + _debug _accUri "$_accUri" + + if [ -z "$_accUri" ]; then + _err "The account url is empty, please run '--update-account' first to update the account info first," + _err "Then try again." + return 1 + fi + + if ! _calcjwk "$ACCOUNT_KEY_PATH"; then + return 1 + fi + _initAPI + + if _send_signed_request "$_accUri" "{\"resource\": \"reg\", \"status\":\"deactivated\"}" && _contains "$response" '"deactivated"'; then + _info "Deactivate account success for $_accUri." + _accid=$(echo "$response" | _egrep_o "\"id\" *: *[^,]*," | cut -d : -f 2 | tr -d ' ,') + elif [ "$code" = "403" ]; then + _info "The account is already deactivated." + _accid=$(_getfield "$_accUri" "999" "/") + else + _err "Deactivate: account failed for $_accUri." + return 1 + fi + + _debug "Account id: $_accid" + if [ "$_accid" ]; then + _deactivated_account_path="$CA_DIR/deactivated/$_accid" + _debug _deactivated_account_path "$_deactivated_account_path" + if mkdir -p "$_deactivated_account_path"; then + _info "Moving deactivated account info to $_deactivated_account_path/" + mv "$CA_CONF" "$_deactivated_account_path/" + mv "$ACCOUNT_JSON_PATH" "$_deactivated_account_path/" + mv "$ACCOUNT_KEY_PATH" "$_deactivated_account_path/" + else + _err "Can not create dir: $_deactivated_account_path, try to remove the deactivated account key." + rm -f "$CA_CONF" + rm -f "$ACCOUNT_JSON_PATH" + rm -f "$ACCOUNT_KEY_PATH" + fi + fi +} + # domain folder file _findHook() { _hookdomain="$1" @@ -4972,6 +5041,7 @@ Commands: --toPkcs8 Convert to pkcs8 format. --update-account Update account info. --register-account Register account key. + --deactivate-account Deactivate the account. --create-account-key Create an account private key, professional use. --create-domain-key Create an domain private key, professional use. --createCSR, -ccsr Create CSR , professional use. @@ -5252,6 +5322,9 @@ _process() { --registeraccount | --register-account) _CMD="registeraccount" ;; + --deactivate-account) + _CMD="deactivateaccount" + ;; --domain | -d) _dvalue="$2" @@ -5667,6 +5740,9 @@ _process() { updateaccount) updateaccount ;; + deactivateaccount) + deactivateaccount + ;; list) list "$_listraw" ;; From a71eba07a1530aba3d6c2a454e40f1436a64996e Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 2 Jul 2017 18:05:55 +0800 Subject: [PATCH 20/95] minor, fix resource name --- acme.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 99c83a04..41818c75 100755 --- a/acme.sh +++ b/acme.sh @@ -2197,7 +2197,9 @@ _initAPI() { export ACME_KEY_CHANGE="https://acme-v01.api.letsencrypt.org/acme/key-change" export ACME_NEW_AUTHZ="https://acme-v01.api.letsencrypt.org/acme/new-authz" export ACME_NEW_ORDER="https://acme-v01.api.letsencrypt.org/acme/new-cert" + export ACME_NEW_ORDER_RES="new-cert" export ACME_NEW_ACCOUNT="https://acme-v01.api.letsencrypt.org/acme/new-reg" + export ACME_NEW_ACCOUNT_RES="new-reg" export ACME_REVOKE_CERT="https://acme-v01.api.letsencrypt.org/acme/revoke-cert" fi @@ -2217,16 +2219,22 @@ _initAPI() { export ACME_NEW_AUTHZ ACME_NEW_ORDER=$(echo "$response" | _egrep_o 'new-cert" *: *"[^"]*"' | cut -d '"' -f 3) + ACME_NEW_ORDER_RES="new-cert" if [ -z "$ACME_NEW_ORDER" ]; then ACME_NEW_ORDER=$(echo "$response" | _egrep_o 'new-order" *: *"[^"]*"' | cut -d '"' -f 3) + ACME_NEW_ORDER_RES="new-order" fi export ACME_NEW_ORDER + export ACME_NEW_ORDER_RES ACME_NEW_ACCOUNT=$(echo "$response" | _egrep_o 'new-reg" *: *"[^"]*"' | cut -d '"' -f 3) + ACME_NEW_ACCOUNT_RES="new-reg" if [ -z "$ACME_NEW_ACCOUNT" ]; then ACME_NEW_ACCOUNT=$(echo "$response" | _egrep_o 'new-account" *: *"[^"]*"' | cut -d '"' -f 3) + ACME_NEW_ACCOUNT_RES="new-account" fi export ACME_NEW_ACCOUNT + export ACME_NEW_ACCOUNT_RES ACME_REVOKE_CERT=$(echo "$response" | _egrep_o 'revoke-cert" *: *"[^"]*"' | cut -d '"' -f 3) export ACME_REVOKE_CERT @@ -3098,7 +3106,7 @@ _regAccount() { fi _initAPI _updateTos="" - _reg_res="new-reg" + _reg_res="$ACME_NEW_ACCOUNT_RES" while true; do _debug AGREEMENT "$AGREEMENT" @@ -3830,7 +3838,7 @@ issue() { _info "Verify finished, start to sign." der="$(_getfile "${CSR_PATH}" "${BEGIN_CSR}" "${END_CSR}" | tr -d "\r\n" | _url_replace)" - if ! _send_signed_request "${ACME_NEW_ORDER}" "{\"resource\": \"new-cert\", \"csr\": \"$der\"}" "needbase64"; then + if ! _send_signed_request "${ACME_NEW_ORDER}" "{\"resource\": \"$ACME_NEW_ORDER_RES\", \"csr\": \"$der\"}" "needbase64"; then _err "Sign failed." _on_issue_err "$_post_hook" return 1 From 1bbc33a0cf2d46067c6d0901e8c94aa7f7749ebf Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 2 Jul 2017 18:24:55 +0800 Subject: [PATCH 21/95] minor fix CA_DIR --- acme.sh | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/acme.sh b/acme.sh index 41818c75..4d272750 100755 --- a/acme.sh +++ b/acme.sh @@ -3082,14 +3082,13 @@ _regAccount() { _initpath _reg_length="$1" + mkdir -p "$CA_DIR" if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then - mkdir -p "$CA_DIR" _info "mv $_OLD_ACCOUNT_KEY to $ACCOUNT_KEY_PATH" mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH" fi if [ ! -f "$ACCOUNT_JSON_PATH" ] && [ -f "$_OLD_ACCOUNT_JSON" ]; then - mkdir -p "$CA_DIR" _info "mv $_OLD_ACCOUNT_JSON to $ACCOUNT_JSON_PATH" mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH" fi @@ -3183,13 +3182,11 @@ deactivateaccount() { _initpath if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then - mkdir -p "$CA_DIR" _info "mv $_OLD_ACCOUNT_KEY to $ACCOUNT_KEY_PATH" mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH" fi if [ ! -f "$ACCOUNT_JSON_PATH" ] && [ -f "$_OLD_ACCOUNT_JSON" ]; then - mkdir -p "$CA_DIR" _info "mv $_OLD_ACCOUNT_JSON to $ACCOUNT_JSON_PATH" mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH" fi From 6b185d20c0be746632fa621a0fee762b65ea9cf9 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sun, 2 Jul 2017 18:40:11 +0800 Subject: [PATCH 22/95] fix format --- acme.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 4d272750..fa090cdf 100755 --- a/acme.sh +++ b/acme.sh @@ -1282,7 +1282,7 @@ createDomainKey() { _initpath "$domain" "$_cdl" - if [ ! -f "$CERT_KEY_PATH" ] || ([ "$FORCE" ] && ! [ "$IS_RENEW" ]) || [ "$Le_ForceNewDomainKey" = "1" ] ; then + if [ ! -f "$CERT_KEY_PATH" ] || ([ "$FORCE" ] && ! [ "$IS_RENEW" ]) || [ "$Le_ForceNewDomainKey" = "1" ]; then if _createkey "$_cdl" "$CERT_KEY_PATH"; then _savedomainconf Le_Keylength "$_cdl" _info "The domain key is here: $(__green $CERT_KEY_PATH)" @@ -3176,7 +3176,6 @@ _regAccount() { } - #Implement deactivate account deactivateaccount() { _initpath From 2e602ef6b078543c79b9c86a179ed039bad30ce6 Mon Sep 17 00:00:00 2001 From: RaidenII Date: Sun, 2 Jul 2017 04:45:07 -0700 Subject: [PATCH 23/95] Added ret value verification. --- dnsapi/dns_namecom.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_namecom.sh b/dnsapi/dns_namecom.sh index 15eae6c2..146db4f6 100755 --- a/dnsapi/dns_namecom.sh +++ b/dnsapi/dns_namecom.sh @@ -32,7 +32,9 @@ dns_namecom_add() { _saveaccountconf Namecom_Token "$Namecom_Token" # Login in using API - _namecom_login + if ! _namecom_login; then + return 1 + fi # Find domain in domain list. if ! _namecom_get_root "$fulldomain"; then @@ -63,7 +65,9 @@ dns_namecom_rm() { fulldomain=$1 txtvalue=$2 - _namecom_login + if ! _namecom_login; then + return 1 + fi # Find domain in domain list. if ! _namecom_get_root "$fulldomain"; then From 1a504118e56dd73ae1fe7b2fb16b58fd76e68765 Mon Sep 17 00:00:00 2001 From: RaidenII Date: Sun, 2 Jul 2017 04:55:06 -0700 Subject: [PATCH 24/95] Updated DNS API support list. --- README.md | 3 ++- dnsapi/README.md | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5b6b03ae..7780b9ab 100644 --- a/README.md +++ b/README.md @@ -334,7 +334,8 @@ You don't have to do anything manually! 1. Dynu API (https://www.dynu.com) 1. DNSimple API 1. NS1.com API - +1. DuckDNS.org API +1. Name.com API And: diff --git a/dnsapi/README.md b/dnsapi/README.md index 5dca829a..7584b31e 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -505,6 +505,37 @@ Ok, let's issue a cert now: acme.sh --issue --dns dns_nsone -d example.com -d www.example.com ``` +## 27. Use DuckDNS.org API + +``` +export DuckDNS_Token="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" +``` + +Please note that since DuckDNS uses StartSSL as their cert provider, thus +--insecure must be used when issuing certs: +``` +acme.sh --insecure --issue --dns dns_duckdns -d mydomain.duckdns.org +``` + +Also, DuckDNS uses the domain name as username for recording changing, so the +account file will always store the lastly used domain name. + +For issues, please report to https://github.com/raidenii/acme.sh/issues. + +## 28. Use Name.com API + +``` +export Namecom_Username="testuser" +export Namecom_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +``` + +And now you can issue certs with: +``` +acme.sh --issue --dns dns_namecom -d example.com -d www.example.com +``` + +For issues, please report to https://github.com/raidenii/acme.sh/issues. + # Use custom API If your API is not supported yet, you can write your own DNS API. From 3002f6dfd5f2324fba4ee9fef1cf8ee8b896b8a9 Mon Sep 17 00:00:00 2001 From: RaidenII Date: Sun, 2 Jul 2017 06:02:44 -0700 Subject: [PATCH 25/95] Updated README.md for Name.com API application. --- dnsapi/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dnsapi/README.md b/dnsapi/README.md index 7584b31e..e956b355 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -525,6 +525,10 @@ For issues, please report to https://github.com/raidenii/acme.sh/issues. ## 28. Use Name.com API ``` +You'll need to fill out the form at https://www.name.com/reseller/apply to apply +for API username and token. +``` + export Namecom_Username="testuser" export Namecom_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` From 333090a96733f6701453ab3f5a1281ed99ff1ab5 Mon Sep 17 00:00:00 2001 From: RaidenII Date: Sun, 2 Jul 2017 06:38:25 -0700 Subject: [PATCH 26/95] Fix README.md for DNS API. --- dnsapi/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/README.md b/dnsapi/README.md index e956b355..57c360b7 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -524,16 +524,16 @@ For issues, please report to https://github.com/raidenii/acme.sh/issues. ## 28. Use Name.com API -``` You'll need to fill out the form at https://www.name.com/reseller/apply to apply for API username and token. -``` +``` export Namecom_Username="testuser" export Namecom_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ``` And now you can issue certs with: + ``` acme.sh --issue --dns dns_namecom -d example.com -d www.example.com ``` From 6963f3880d1e06211bc8c631154868efa8c6bafb Mon Sep 17 00:00:00 2001 From: RaidenII Date: Mon, 3 Jul 2017 03:28:28 -0700 Subject: [PATCH 27/95] Fixes the get_root function so that when domain doesn't exist it will correctly return error. --- dnsapi/dns_namecom.sh | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/dnsapi/dns_namecom.sh b/dnsapi/dns_namecom.sh index 146db4f6..fae56d65 100755 --- a/dnsapi/dns_namecom.sh +++ b/dnsapi/dns_namecom.sh @@ -168,21 +168,26 @@ _namecom_get_root() { i=2 p=1 - if _namecom_rest GET "domain/list"; then - while true; do - host=$(printf "%s" "$domain" | cut -d . -f $i-100) - if [ -z "$host" ]; then - return 1 - fi - - if _contains "$response" "$host"; then - _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) - _domain="$host" - return 0 - fi - p=$i - i=$(_math "$i" + 1) - done + if ! _namecom_rest GET "domain/list"; then + return 1 fi + + # Need to exclude the last field (tld) + numfields=$(echo "$domain" | _egrep_o "\." | wc -l) + while [ $i -le $numfields ]; do + host=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug host "$host" + if [ -z "$host" ]; then + return 1 + fi + + if _contains "$response" "$host"; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain="$host" + return 0 + fi + p=$i + i=$(_math "$i" + 1) + done return 1 } From 7b32bbfc266015b69a3dfc316e03097add2bdd3e Mon Sep 17 00:00:00 2001 From: RaidenII Date: Mon, 3 Jul 2017 08:22:16 -0400 Subject: [PATCH 28/95] Fix for SC2086. --- dnsapi/dns_namecom.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_namecom.sh b/dnsapi/dns_namecom.sh index fae56d65..3af8bf4c 100755 --- a/dnsapi/dns_namecom.sh +++ b/dnsapi/dns_namecom.sh @@ -174,7 +174,7 @@ _namecom_get_root() { # Need to exclude the last field (tld) numfields=$(echo "$domain" | _egrep_o "\." | wc -l) - while [ $i -le $numfields ]; do + while [ $i -le "$numfields" ]; do host=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug host "$host" if [ -z "$host" ]; then From 5f8b60a0e5653595689703fe68d9b3e99d14d1ab Mon Sep 17 00:00:00 2001 From: neilpang Date: Tue, 4 Jul 2017 08:23:09 +0800 Subject: [PATCH 29/95] fix https://github.com/Neilpang/acme.sh/issues/926 don't trigger validation for dns manually mode --- acme.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/acme.sh b/acme.sh index fa090cdf..ef468a45 100755 --- a/acme.sh +++ b/acme.sh @@ -3543,11 +3543,11 @@ issue() { if [ "$d_api" ]; then _info "Found domain api file: $d_api" else - _err "Add the following TXT record:" - _err "Domain: '$(__green "$txtdomain")'" - _err "TXT value: '$(__green "$txt")'" - _err "Please be aware that you prepend _acme-challenge. before your domain" - _err "so the resulting subdomain will be: $txtdomain" + _info "$(__red "Add the following TXT record:")" + _info "$(__red "Domain: '$(__green "$txtdomain")'")" + _info "$(__red "TXT value: '$(__green "$txt")'")" + _info "$(__red "Please be aware that you prepend _acme-challenge. before your domain")" + _info "$(__red "so the resulting subdomain will be: $txtdomain")" continue fi @@ -3583,7 +3583,7 @@ issue() { _debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit." _err "Please add the TXT records to the domains, and retry again." _clearup - _on_issue_err "$_post_hook" "$vlist" + _on_issue_err "$_post_hook" return 1 fi From 81772fb703af18f7d7f8d7b7b7e3a6d61be14554 Mon Sep 17 00:00:00 2001 From: neil Date: Tue, 4 Jul 2017 09:08:54 +0800 Subject: [PATCH 30/95] minor, fix format --- acme.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/acme.sh b/acme.sh index ef468a45..35842f4e 100755 --- a/acme.sh +++ b/acme.sh @@ -3544,10 +3544,10 @@ issue() { _info "Found domain api file: $d_api" else _info "$(__red "Add the following TXT record:")" - _info "$(__red "Domain: '$(__green "$txtdomain")'")" - _info "$(__red "TXT value: '$(__green "$txt")'")" - _info "$(__red "Please be aware that you prepend _acme-challenge. before your domain")" - _info "$(__red "so the resulting subdomain will be: $txtdomain")" + _info "$(__red "Domain: '$(__green "$txtdomain")'")" + _info "$(__red "TXT value: '$(__green "$txt")'")" + _info "$(__red "Please be aware that you prepend _acme-challenge. before your domain")" + _info "$(__red "so the resulting subdomain will be: $txtdomain")" continue fi From 72fcf5ab85779aca28db1f4057e63d4e9ea850d4 Mon Sep 17 00:00:00 2001 From: Lonnie Abelbeck Date: Fri, 7 Jul 2017 09:51:43 -0500 Subject: [PATCH 31/95] Add 'dns_dyn' DNS challenge validation script for Dyn Managed DNS API --- dnsapi/README.md | 33 +++++ dnsapi/dns_dyn.sh | 340 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 373 insertions(+) create mode 100644 dnsapi/dns_dyn.sh diff --git a/dnsapi/README.md b/dnsapi/README.md index 57c360b7..41f89a88 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -540,6 +540,39 @@ acme.sh --issue --dns dns_namecom -d example.com -d www.example.com For issues, please report to https://github.com/raidenii/acme.sh/issues. +## 29. Use Dyn Managed DNS API to automatically issue cert + +First, login to your Dyn Managed DNS account: https://portal.dynect.net/login/ + +It is recommended to add a new user specific for API access. + +The minimum "Zones & Records Permissions" required are: +``` +RecordAdd +RecordUpdate +RecordDelete +RecordGet +ZoneGet +ZoneAddNode +ZoneRemoveNode +ZonePublish +``` + +Pass the API user credentials to the environment: +``` +export DYN_Customer="customer" +export DYN_Username="apiuser" +export DYN_Password="secret" +``` + +Ok, let's issue a cert now: +``` +acme.sh --issue --dns dns_dyn -d example.com -d www.example.com +``` + +The `DYN_Customer`, `DYN_Username` and `DYN_Password` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. + + # Use custom API If your API is not supported yet, you can write your own DNS API. diff --git a/dnsapi/dns_dyn.sh b/dnsapi/dns_dyn.sh new file mode 100644 index 00000000..d3998809 --- /dev/null +++ b/dnsapi/dns_dyn.sh @@ -0,0 +1,340 @@ +#!/usr/bin/env sh +# +# Dyn.com Domain API +# +# Author: Gerd Naschenweng +# https://github.com/magicdude4eva +# +# Dyn Managed DNS API +# https://help.dyn.com/dns-api-knowledge-base/ +# +# It is recommended to add a "Dyn Managed DNS" user specific for API access. +# The "Zones & Records Permissions" required by this script are: +# -- +# RecordAdd +# RecordUpdate +# RecordDelete +# RecordGet +# ZoneGet +# ZoneAddNode +# ZoneRemoveNode +# ZonePublish +# -- +# +# Pass credentials before "acme.sh --issue --dns dns_dyn ..." +# -- +# export DYN_Customer="customer" +# export DYN_Username="apiuser" +# export DYN_Password="secret" +# -- + +DYN_API="https://api.dynect.net/REST" + +#REST_API +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "Challenge-code" +dns_dyn_add() { + fulldomain="$1" + txtvalue="$2" + + DYN_Customer="${DYN_Customer:-$(_readaccountconf_mutable DYN_Customer)}" + DYN_Username="${DYN_Username:-$(_readaccountconf_mutable DYN_Username)}" + DYN_Password="${DYN_Password:-$(_readaccountconf_mutable DYN_Password)}" + if [ -z "$DYN_Customer" ] || [ -z "$DYN_Username" ] || [ -z "$DYN_Password" ]; then + DYN_Customer="" + DYN_Username="" + DYN_Password="" + _err "You must export variables: DYN_Customer, DYN_Username and DYN_Password" + return 1 + fi + + #save the config variables to the account conf file. + _saveaccountconf_mutable DYN_Customer "$DYN_Customer" + _saveaccountconf_mutable DYN_Username "$DYN_Username" + _saveaccountconf_mutable DYN_Password "$DYN_Password" + + if ! _dyn_get_authtoken; then + return 1 + fi + + if [ -z "$_dyn_authtoken" ]; then + _dyn_end_session + return 1 + fi + + if ! _dyn_get_zone; then + _dyn_end_session + return 1 + fi + + if ! _dyn_add_record; then + _dyn_end_session + return 1 + fi + + if ! _dyn_publish_zone; then + _dyn_end_session + return 1 + fi + + _dyn_end_session + + return 0 +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_dyn_rm() { + fulldomain="$1" + txtvalue="$2" + + DYN_Customer="${DYN_Customer:-$(_readaccountconf_mutable DYN_Customer)}" + DYN_Username="${DYN_Username:-$(_readaccountconf_mutable DYN_Username)}" + DYN_Password="${DYN_Password:-$(_readaccountconf_mutable DYN_Password)}" + if [ -z "$DYN_Customer" ] || [ -z "$DYN_Username" ] || [ -z "$DYN_Password" ]; then + DYN_Customer="" + DYN_Username="" + DYN_Password="" + _err "You must export variables: DYN_Customer, DYN_Username and DYN_Password" + return 1 + fi + + if ! _dyn_get_authtoken; then + return 1 + fi + + if [ -z "$_dyn_authtoken" ]; then + _dyn_end_session + return 1 + fi + + if ! _dyn_get_zone; then + _dyn_end_session + return 1 + fi + + if ! _dyn_get_record_id; then + _dyn_end_session + return 1 + fi + + if [ -z "$_dyn_record_id" ]; then + _dyn_end_session + return 1 + fi + + if ! _dyn_rm_record; then + _dyn_end_session + return 1 + fi + + if ! _dyn_publish_zone; then + _dyn_end_session + return 1 + fi + + _dyn_end_session + + return 0 +} + +#################### Private functions below ################################## + +#get Auth-Token +_dyn_get_authtoken() { + + _info "Start Dyn API Session" + + data="{\"customer_name\":\"$DYN_Customer\", \"user_name\":\"$DYN_Username\", \"password\":\"$DYN_Password\"}" + dyn_url="$DYN_API/Session/" + method="POST" + + _debug data "$data" + _debug dyn_url "$dyn_url" + + export _H1="Content-Type: application/json" + + response="$(_post "$data" "$dyn_url" "" "$method")" + sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | head -n 1 | sed 's#^"status" *: *"##')" + + _debug response "$response" + _debug sessionstatus "$sessionstatus" + + if [ "$sessionstatus" = "success" ]; then + _dyn_authtoken="$(printf "%s\n" "$response" | _egrep_o '"token" *: *"[^"]*' | head -n 1 | sed 's#^"token" *: *"##')" + _info "Token received" + _debug _dyn_authtoken "$_dyn_authtoken" + return 0 + fi + + _dyn_authtoken="" + _err "get token failed" + return 1 +} + +#fulldomain=_acme-challenge.www.domain.com +#returns +# _dyn_zone=domain.com +_dyn_get_zone() { + i=2 + while true; do + domain="$(printf "%s" "$fulldomain" | cut -d . -f "$i-100")" + if [ -z "$domain" ]; then + break + fi + + dyn_url="$DYN_API/Zone/$domain/" + + export _H1="Auth-Token: $_dyn_authtoken" + export _H2="Content-Type: application/json" + + response="$(_get "$dyn_url" "" "")" + sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | head -n 1 | sed 's#^"status" *: *"##')" + + _debug dyn_url "$dyn_url" + _debug response "$response" + _debug sessionstatus "$sessionstatus" + + if [ "$sessionstatus" = "success" ]; then + _dyn_zone="$domain" + return 0 + fi + i=$(_math "$i" + 1) + done + + _dyn_zone="" + _err "get zone failed" + return 1 +} + +#add TXT record +_dyn_add_record() { + + _info "Adding TXT record" + + data="{\"rdata\":{\"txtdata\":\"$txtvalue\"},\"ttl\":\"300\"}" + dyn_url="$DYN_API/TXTRecord/$_dyn_zone/$fulldomain/" + method="POST" + + export _H1="Auth-Token: $_dyn_authtoken" + export _H2="Content-Type: application/json" + + response="$(_post "$data" "$dyn_url" "" "$method")" + sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | head -n 1 | sed 's#^"status" *: *"##')" + + _debug response "$response" + _debug sessionstatus "$sessionstatus" + + if [ "$sessionstatus" = "success" ]; then + _info "TXT Record successfully added" + return 0 + fi + + _err "add TXT record failed" + return 1 +} + +#publish the zone +_dyn_publish_zone() { + + _info "Publishing zone" + + data="{\"publish\":\"true\"}" + dyn_url="$DYN_API/Zone/$_dyn_zone/" + method="PUT" + + export _H1="Auth-Token: $_dyn_authtoken" + export _H2="Content-Type: application/json" + + response="$(_post "$data" "$dyn_url" "" "$method")" + sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | head -n 1 | sed 's#^"status" *: *"##')" + + _debug response "$response" + _debug sessionstatus "$sessionstatus" + + if [ "$sessionstatus" = "success" ]; then + _info "Zone published" + return 0 + fi + + _err "publish zone failed" + return 1 +} + +#get record_id of TXT record so we can delete the record +_dyn_get_record_id() { + + _info "Getting record_id of TXT record" + + dyn_url="$DYN_API/TXTRecord/$_dyn_zone/$fulldomain/" + + export _H1="Auth-Token: $_dyn_authtoken" + export _H2="Content-Type: application/json" + + response="$(_get "$dyn_url" "" "")" + sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | head -n 1 | sed 's#^"status" *: *"##')" + + _debug response "$response" + _debug sessionstatus "$sessionstatus" + + if [ "$sessionstatus" = "success" ]; then + _dyn_record_id="$(printf "%s\n" "$response" | _egrep_o "\"data\" *: *\[\"/REST/TXTRecord/$_dyn_zone/$fulldomain/[^\"]*" | head -n 1 | sed "s#^\"data\" *: *\[\"/REST/TXTRecord/$_dyn_zone/$fulldomain/##")" + _debug _dyn_record_id "$_dyn_record_id" + return 0 + fi + + _dyn_record_id="" + _err "getting record_id failed" + return 1 +} + +#delete TXT record +_dyn_rm_record() { + + _info "Deleting TXT record" + + dyn_url="$DYN_API/TXTRecord/$_dyn_zone/$fulldomain/$_dyn_record_id/" + method="DELETE" + + _debug dyn_url "$dyn_url" + + export _H1="Auth-Token: $_dyn_authtoken" + export _H2="Content-Type: application/json" + + response="$(_post "" "$dyn_url" "" "$method")" + sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | head -n 1 | sed 's#^"status" *: *"##')" + + _debug response "$response" + _debug sessionstatus "$sessionstatus" + + if [ "$sessionstatus" = "success" ]; then + _info "TXT record successfully deleted" + return 0 + fi + + _err "delete TXT record failed" + return 1 +} + +#logout +_dyn_end_session() { + + _info "End Dyn API Session" + + dyn_url="$DYN_API/Session/" + method="DELETE" + + _debug dyn_url "$dyn_url" + + export _H1="Auth-Token: $_dyn_authtoken" + export _H2="Content-Type: application/json" + + response="$(_post "" "$dyn_url" "" "$method")" + + _debug response "$response" + + _dyn_authtoken="" + return 0 +} + From 0aba5dc8de914cae7256cacdc189e2f31e491b74 Mon Sep 17 00:00:00 2001 From: Lonnie Abelbeck Date: Fri, 7 Jul 2017 10:22:20 -0500 Subject: [PATCH 32/95] dns_dyn.sh, remove empty line at end --- dnsapi/dns_dyn.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_dyn.sh b/dnsapi/dns_dyn.sh index d3998809..c0dc1c74 100644 --- a/dnsapi/dns_dyn.sh +++ b/dnsapi/dns_dyn.sh @@ -337,4 +337,3 @@ _dyn_end_session() { _dyn_authtoken="" return 0 } - From 528d2f29d34a3d9e417a91f02ffde35cc63b2476 Mon Sep 17 00:00:00 2001 From: Lonnie Abelbeck Date: Fri, 7 Jul 2017 10:33:24 -0500 Subject: [PATCH 33/95] dns_dyn.sh, remove trailing spaces at end of line --- dnsapi/dns_dyn.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_dyn.sh b/dnsapi/dns_dyn.sh index c0dc1c74..e1120018 100644 --- a/dnsapi/dns_dyn.sh +++ b/dnsapi/dns_dyn.sh @@ -240,7 +240,7 @@ _dyn_publish_zone() { _info "Publishing zone" - data="{\"publish\":\"true\"}" + data="{\"publish\":\"true\"}" dyn_url="$DYN_API/Zone/$_dyn_zone/" method="PUT" From 13a8c309f5b4de09ac263a5ad2ae0cbeed044f30 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 8 Jul 2017 09:20:12 +0800 Subject: [PATCH 34/95] fix new shellcheck errors --- .travis.yml | 2 +- dnsapi/dns_aws.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7f7e120c..2ba02b9c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,7 +40,7 @@ script: - if [ "$TRAVIS_OS_NAME" = "linux" ]; then ~/shfmt -l -w -i 2 . ; fi - if [ "$TRAVIS_OS_NAME" = "linux" ]; then git diff --exit-code && echo "shfmt OK" ; fi - if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -V ; fi - - if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck **/*.sh && echo "shellcheck OK" ; fi + - if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -e SC2181 **/*.sh && echo "shellcheck OK" ; fi - cd .. - git clone https://github.com/Neilpang/acmetest.git && cp -r acme.sh acmetest/ && cd acmetest - if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ./letest.sh ; fi diff --git a/dnsapi/dns_aws.sh b/dnsapi/dns_aws.sh index 800c3d09..40782573 100755 --- a/dnsapi/dns_aws.sh +++ b/dnsapi/dns_aws.sh @@ -208,7 +208,7 @@ aws_rest() { kServiceH="$(printf "$Service%s" | _hmac "$Hash" "$kRegionH" hex)" _debug2 kServiceH "$kServiceH" - kSigningH="$(printf "aws4_request%s" | _hmac "$Hash" "$kServiceH" hex)" + kSigningH="$(printf "%s" "aws4_request" | _hmac "$Hash" "$kServiceH" hex)" _debug2 kSigningH "$kSigningH" signature="$(printf "$StringToSign%s" | _hmac "$Hash" "$kSigningH" hex)" From 0b797f596409683f90ed4fd1354f4027d3bf7b3c Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 8 Jul 2017 14:12:31 +0800 Subject: [PATCH 35/95] fix new shellcheck error --- dnsapi/dns_infoblox.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_infoblox.sh b/dnsapi/dns_infoblox.sh index 06ac87ec..4cbb2146 100644 --- a/dnsapi/dns_infoblox.sh +++ b/dnsapi/dns_infoblox.sh @@ -41,10 +41,10 @@ dns_infoblox_add() { export _H2="Authorization: Basic $Infoblox_CredsEncoded" ## Add the challenge record to the Infoblox grid member - result=$(_post "" "$baseurlnObject" "" "POST") + result="$(_post "" "$baseurlnObject" "" "POST")" ## Let's see if we get something intelligible back from the unit - if echo "$result" | egrep "record:txt/.*:.*/$Infoblox_View"; then + if [ "$(echo "$result" | _egrep_o "record:txt/.*:.*/$Infoblox_View")" ]; then _info "Successfully created the txt record" return 0 else @@ -66,7 +66,7 @@ dns_infoblox_rm() { _debug txtvalue "$txtvalue" ## Base64 encode the credentials - Infoblox_CredsEncoded=$(printf "%b" "$Infoblox_Creds" | _base64) + Infoblox_CredsEncoded="$(printf "%b" "$Infoblox_Creds" | _base64)" ## Construct the HTTP Authorization header export _H1="Accept-Language:en-US" @@ -74,17 +74,17 @@ dns_infoblox_rm() { ## Does the record exist? Let's check. baseurlnObject="https://$Infoblox_Server/wapi/v2.2.2/record:txt?name=$fulldomain&text=$txtvalue&view=$Infoblox_View&_return_type=xml-pretty" - result=$(_get "$baseurlnObject") + result="$(_get "$baseurlnObject")" ## Let's see if we get something intelligible back from the grid - if echo "$result" | egrep "record:txt/.*:.*/$Infoblox_View"; then + if [ "$(echo "$result" | _egrep_o "record:txt/.*:.*/$Infoblox_View")" ]; then ## Extract the object reference - objRef=$(printf "%b" "$result" | _egrep_o "record:txt/.*:.*/$Infoblox_View") + objRef="$(printf "%b" "$result" | _egrep_o "record:txt/.*:.*/$Infoblox_View")" objRmUrl="https://$Infoblox_Server/wapi/v2.2.2/$objRef" ## Delete them! All the stale records! - rmResult=$(_post "" "$objRmUrl" "" "DELETE") + rmResult="$(_post "" "$objRmUrl" "" "DELETE")" ## Let's see if that worked - if echo "$rmResult" | egrep "record:txt/.*:.*/$Infoblox_View"; then + if [ "$(echo "$rmResult" | _egrep_o "record:txt/.*:.*/$Infoblox_View")" ]; then _info "Successfully deleted $objRef" return 0 else From 200287254bce74e8deb1f28da611de432015c837 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 8 Jul 2017 17:25:01 +0800 Subject: [PATCH 36/95] add deactivate-account --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 8f363852..5849eb46 100644 --- a/Dockerfile +++ b/Dockerfile @@ -44,6 +44,7 @@ RUN for verb in help \ create-domain-key \ createCSR \ deactivate \ + deactivate-account \ ; do \ printf -- "%b" "#!/usr/bin/env sh\n/root/.acme.sh/acme.sh --${verb} --config-home /acme.sh \"\$@\"" >/usr/local/bin/--${verb} && chmod +x /usr/local/bin/--${verb} \ ; done From babe884b7c7a3b599defc37ff1e392d4c61bd6ad Mon Sep 17 00:00:00 2001 From: Lonnie Abelbeck Date: Sat, 8 Jul 2017 06:39:18 -0500 Subject: [PATCH 37/95] Replace 'head -n' with the '_head_n' function --- dnsapi/dns_dyn.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_dyn.sh b/dnsapi/dns_dyn.sh index e1120018..024e0a38 100644 --- a/dnsapi/dns_dyn.sh +++ b/dnsapi/dns_dyn.sh @@ -156,13 +156,13 @@ _dyn_get_authtoken() { export _H1="Content-Type: application/json" response="$(_post "$data" "$dyn_url" "" "$method")" - sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | head -n 1 | sed 's#^"status" *: *"##')" + sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')" _debug response "$response" _debug sessionstatus "$sessionstatus" if [ "$sessionstatus" = "success" ]; then - _dyn_authtoken="$(printf "%s\n" "$response" | _egrep_o '"token" *: *"[^"]*' | head -n 1 | sed 's#^"token" *: *"##')" + _dyn_authtoken="$(printf "%s\n" "$response" | _egrep_o '"token" *: *"[^"]*' | _head_n 1 | sed 's#^"token" *: *"##')" _info "Token received" _debug _dyn_authtoken "$_dyn_authtoken" return 0 @@ -190,7 +190,7 @@ _dyn_get_zone() { export _H2="Content-Type: application/json" response="$(_get "$dyn_url" "" "")" - sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | head -n 1 | sed 's#^"status" *: *"##')" + sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')" _debug dyn_url "$dyn_url" _debug response "$response" @@ -221,7 +221,7 @@ _dyn_add_record() { export _H2="Content-Type: application/json" response="$(_post "$data" "$dyn_url" "" "$method")" - sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | head -n 1 | sed 's#^"status" *: *"##')" + sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')" _debug response "$response" _debug sessionstatus "$sessionstatus" @@ -248,7 +248,7 @@ _dyn_publish_zone() { export _H2="Content-Type: application/json" response="$(_post "$data" "$dyn_url" "" "$method")" - sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | head -n 1 | sed 's#^"status" *: *"##')" + sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')" _debug response "$response" _debug sessionstatus "$sessionstatus" @@ -273,13 +273,13 @@ _dyn_get_record_id() { export _H2="Content-Type: application/json" response="$(_get "$dyn_url" "" "")" - sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | head -n 1 | sed 's#^"status" *: *"##')" + sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')" _debug response "$response" _debug sessionstatus "$sessionstatus" if [ "$sessionstatus" = "success" ]; then - _dyn_record_id="$(printf "%s\n" "$response" | _egrep_o "\"data\" *: *\[\"/REST/TXTRecord/$_dyn_zone/$fulldomain/[^\"]*" | head -n 1 | sed "s#^\"data\" *: *\[\"/REST/TXTRecord/$_dyn_zone/$fulldomain/##")" + _dyn_record_id="$(printf "%s\n" "$response" | _egrep_o "\"data\" *: *\[\"/REST/TXTRecord/$_dyn_zone/$fulldomain/[^\"]*" | _head_n 1 | sed "s#^\"data\" *: *\[\"/REST/TXTRecord/$_dyn_zone/$fulldomain/##")" _debug _dyn_record_id "$_dyn_record_id" return 0 fi @@ -303,7 +303,7 @@ _dyn_rm_record() { export _H2="Content-Type: application/json" response="$(_post "" "$dyn_url" "" "$method")" - sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | head -n 1 | sed 's#^"status" *: *"##')" + sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')" _debug response "$response" _debug sessionstatus "$sessionstatus" From 9bd2d927559fce8fe393cfb935f96c7fd6fc8723 Mon Sep 17 00:00:00 2001 From: Lonnie Abelbeck Date: Sat, 8 Jul 2017 06:43:21 -0500 Subject: [PATCH 38/95] Update main README.md DNS API list --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7780b9ab..5c306a59 100644 --- a/README.md +++ b/README.md @@ -336,6 +336,7 @@ You don't have to do anything manually! 1. NS1.com API 1. DuckDNS.org API 1. Name.com API +1. Dyn Managed DNS API And: From 42b2adc03ed35a54f6cb2a237dd37f0e498774f2 Mon Sep 17 00:00:00 2001 From: Lonnie Abelbeck Date: Fri, 7 Jul 2017 09:51:43 -0500 Subject: [PATCH 39/95] Add 'dns_dyn' DNS challenge validation script for Dyn Managed DNS API dns_dyn.sh, remove empty line at end dns_dyn.sh, remove trailing spaces at end of line Replace 'head -n' with the '_head_n' function Update main README.md DNS API list --- .travis.yml | 2 +- Dockerfile | 1 + README.md | 1 + dnsapi/README.md | 33 ++++ dnsapi/dns_aws.sh | 2 +- dnsapi/dns_dyn.sh | 339 +++++++++++++++++++++++++++++++++++++++++ dnsapi/dns_infoblox.sh | 16 +- 7 files changed, 384 insertions(+), 10 deletions(-) create mode 100644 dnsapi/dns_dyn.sh diff --git a/.travis.yml b/.travis.yml index 7f7e120c..2ba02b9c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,7 +40,7 @@ script: - if [ "$TRAVIS_OS_NAME" = "linux" ]; then ~/shfmt -l -w -i 2 . ; fi - if [ "$TRAVIS_OS_NAME" = "linux" ]; then git diff --exit-code && echo "shfmt OK" ; fi - if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -V ; fi - - if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck **/*.sh && echo "shellcheck OK" ; fi + - if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -e SC2181 **/*.sh && echo "shellcheck OK" ; fi - cd .. - git clone https://github.com/Neilpang/acmetest.git && cp -r acme.sh acmetest/ && cd acmetest - if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ./letest.sh ; fi diff --git a/Dockerfile b/Dockerfile index 8f363852..5849eb46 100644 --- a/Dockerfile +++ b/Dockerfile @@ -44,6 +44,7 @@ RUN for verb in help \ create-domain-key \ createCSR \ deactivate \ + deactivate-account \ ; do \ printf -- "%b" "#!/usr/bin/env sh\n/root/.acme.sh/acme.sh --${verb} --config-home /acme.sh \"\$@\"" >/usr/local/bin/--${verb} && chmod +x /usr/local/bin/--${verb} \ ; done diff --git a/README.md b/README.md index 7780b9ab..5c306a59 100644 --- a/README.md +++ b/README.md @@ -336,6 +336,7 @@ You don't have to do anything manually! 1. NS1.com API 1. DuckDNS.org API 1. Name.com API +1. Dyn Managed DNS API And: diff --git a/dnsapi/README.md b/dnsapi/README.md index 57c360b7..41f89a88 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -540,6 +540,39 @@ acme.sh --issue --dns dns_namecom -d example.com -d www.example.com For issues, please report to https://github.com/raidenii/acme.sh/issues. +## 29. Use Dyn Managed DNS API to automatically issue cert + +First, login to your Dyn Managed DNS account: https://portal.dynect.net/login/ + +It is recommended to add a new user specific for API access. + +The minimum "Zones & Records Permissions" required are: +``` +RecordAdd +RecordUpdate +RecordDelete +RecordGet +ZoneGet +ZoneAddNode +ZoneRemoveNode +ZonePublish +``` + +Pass the API user credentials to the environment: +``` +export DYN_Customer="customer" +export DYN_Username="apiuser" +export DYN_Password="secret" +``` + +Ok, let's issue a cert now: +``` +acme.sh --issue --dns dns_dyn -d example.com -d www.example.com +``` + +The `DYN_Customer`, `DYN_Username` and `DYN_Password` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. + + # Use custom API If your API is not supported yet, you can write your own DNS API. diff --git a/dnsapi/dns_aws.sh b/dnsapi/dns_aws.sh index 800c3d09..40782573 100755 --- a/dnsapi/dns_aws.sh +++ b/dnsapi/dns_aws.sh @@ -208,7 +208,7 @@ aws_rest() { kServiceH="$(printf "$Service%s" | _hmac "$Hash" "$kRegionH" hex)" _debug2 kServiceH "$kServiceH" - kSigningH="$(printf "aws4_request%s" | _hmac "$Hash" "$kServiceH" hex)" + kSigningH="$(printf "%s" "aws4_request" | _hmac "$Hash" "$kServiceH" hex)" _debug2 kSigningH "$kSigningH" signature="$(printf "$StringToSign%s" | _hmac "$Hash" "$kSigningH" hex)" diff --git a/dnsapi/dns_dyn.sh b/dnsapi/dns_dyn.sh new file mode 100644 index 00000000..024e0a38 --- /dev/null +++ b/dnsapi/dns_dyn.sh @@ -0,0 +1,339 @@ +#!/usr/bin/env sh +# +# Dyn.com Domain API +# +# Author: Gerd Naschenweng +# https://github.com/magicdude4eva +# +# Dyn Managed DNS API +# https://help.dyn.com/dns-api-knowledge-base/ +# +# It is recommended to add a "Dyn Managed DNS" user specific for API access. +# The "Zones & Records Permissions" required by this script are: +# -- +# RecordAdd +# RecordUpdate +# RecordDelete +# RecordGet +# ZoneGet +# ZoneAddNode +# ZoneRemoveNode +# ZonePublish +# -- +# +# Pass credentials before "acme.sh --issue --dns dns_dyn ..." +# -- +# export DYN_Customer="customer" +# export DYN_Username="apiuser" +# export DYN_Password="secret" +# -- + +DYN_API="https://api.dynect.net/REST" + +#REST_API +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "Challenge-code" +dns_dyn_add() { + fulldomain="$1" + txtvalue="$2" + + DYN_Customer="${DYN_Customer:-$(_readaccountconf_mutable DYN_Customer)}" + DYN_Username="${DYN_Username:-$(_readaccountconf_mutable DYN_Username)}" + DYN_Password="${DYN_Password:-$(_readaccountconf_mutable DYN_Password)}" + if [ -z "$DYN_Customer" ] || [ -z "$DYN_Username" ] || [ -z "$DYN_Password" ]; then + DYN_Customer="" + DYN_Username="" + DYN_Password="" + _err "You must export variables: DYN_Customer, DYN_Username and DYN_Password" + return 1 + fi + + #save the config variables to the account conf file. + _saveaccountconf_mutable DYN_Customer "$DYN_Customer" + _saveaccountconf_mutable DYN_Username "$DYN_Username" + _saveaccountconf_mutable DYN_Password "$DYN_Password" + + if ! _dyn_get_authtoken; then + return 1 + fi + + if [ -z "$_dyn_authtoken" ]; then + _dyn_end_session + return 1 + fi + + if ! _dyn_get_zone; then + _dyn_end_session + return 1 + fi + + if ! _dyn_add_record; then + _dyn_end_session + return 1 + fi + + if ! _dyn_publish_zone; then + _dyn_end_session + return 1 + fi + + _dyn_end_session + + return 0 +} + +#Usage: fulldomain txtvalue +#Remove the txt record after validation. +dns_dyn_rm() { + fulldomain="$1" + txtvalue="$2" + + DYN_Customer="${DYN_Customer:-$(_readaccountconf_mutable DYN_Customer)}" + DYN_Username="${DYN_Username:-$(_readaccountconf_mutable DYN_Username)}" + DYN_Password="${DYN_Password:-$(_readaccountconf_mutable DYN_Password)}" + if [ -z "$DYN_Customer" ] || [ -z "$DYN_Username" ] || [ -z "$DYN_Password" ]; then + DYN_Customer="" + DYN_Username="" + DYN_Password="" + _err "You must export variables: DYN_Customer, DYN_Username and DYN_Password" + return 1 + fi + + if ! _dyn_get_authtoken; then + return 1 + fi + + if [ -z "$_dyn_authtoken" ]; then + _dyn_end_session + return 1 + fi + + if ! _dyn_get_zone; then + _dyn_end_session + return 1 + fi + + if ! _dyn_get_record_id; then + _dyn_end_session + return 1 + fi + + if [ -z "$_dyn_record_id" ]; then + _dyn_end_session + return 1 + fi + + if ! _dyn_rm_record; then + _dyn_end_session + return 1 + fi + + if ! _dyn_publish_zone; then + _dyn_end_session + return 1 + fi + + _dyn_end_session + + return 0 +} + +#################### Private functions below ################################## + +#get Auth-Token +_dyn_get_authtoken() { + + _info "Start Dyn API Session" + + data="{\"customer_name\":\"$DYN_Customer\", \"user_name\":\"$DYN_Username\", \"password\":\"$DYN_Password\"}" + dyn_url="$DYN_API/Session/" + method="POST" + + _debug data "$data" + _debug dyn_url "$dyn_url" + + export _H1="Content-Type: application/json" + + response="$(_post "$data" "$dyn_url" "" "$method")" + sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')" + + _debug response "$response" + _debug sessionstatus "$sessionstatus" + + if [ "$sessionstatus" = "success" ]; then + _dyn_authtoken="$(printf "%s\n" "$response" | _egrep_o '"token" *: *"[^"]*' | _head_n 1 | sed 's#^"token" *: *"##')" + _info "Token received" + _debug _dyn_authtoken "$_dyn_authtoken" + return 0 + fi + + _dyn_authtoken="" + _err "get token failed" + return 1 +} + +#fulldomain=_acme-challenge.www.domain.com +#returns +# _dyn_zone=domain.com +_dyn_get_zone() { + i=2 + while true; do + domain="$(printf "%s" "$fulldomain" | cut -d . -f "$i-100")" + if [ -z "$domain" ]; then + break + fi + + dyn_url="$DYN_API/Zone/$domain/" + + export _H1="Auth-Token: $_dyn_authtoken" + export _H2="Content-Type: application/json" + + response="$(_get "$dyn_url" "" "")" + sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')" + + _debug dyn_url "$dyn_url" + _debug response "$response" + _debug sessionstatus "$sessionstatus" + + if [ "$sessionstatus" = "success" ]; then + _dyn_zone="$domain" + return 0 + fi + i=$(_math "$i" + 1) + done + + _dyn_zone="" + _err "get zone failed" + return 1 +} + +#add TXT record +_dyn_add_record() { + + _info "Adding TXT record" + + data="{\"rdata\":{\"txtdata\":\"$txtvalue\"},\"ttl\":\"300\"}" + dyn_url="$DYN_API/TXTRecord/$_dyn_zone/$fulldomain/" + method="POST" + + export _H1="Auth-Token: $_dyn_authtoken" + export _H2="Content-Type: application/json" + + response="$(_post "$data" "$dyn_url" "" "$method")" + sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')" + + _debug response "$response" + _debug sessionstatus "$sessionstatus" + + if [ "$sessionstatus" = "success" ]; then + _info "TXT Record successfully added" + return 0 + fi + + _err "add TXT record failed" + return 1 +} + +#publish the zone +_dyn_publish_zone() { + + _info "Publishing zone" + + data="{\"publish\":\"true\"}" + dyn_url="$DYN_API/Zone/$_dyn_zone/" + method="PUT" + + export _H1="Auth-Token: $_dyn_authtoken" + export _H2="Content-Type: application/json" + + response="$(_post "$data" "$dyn_url" "" "$method")" + sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')" + + _debug response "$response" + _debug sessionstatus "$sessionstatus" + + if [ "$sessionstatus" = "success" ]; then + _info "Zone published" + return 0 + fi + + _err "publish zone failed" + return 1 +} + +#get record_id of TXT record so we can delete the record +_dyn_get_record_id() { + + _info "Getting record_id of TXT record" + + dyn_url="$DYN_API/TXTRecord/$_dyn_zone/$fulldomain/" + + export _H1="Auth-Token: $_dyn_authtoken" + export _H2="Content-Type: application/json" + + response="$(_get "$dyn_url" "" "")" + sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')" + + _debug response "$response" + _debug sessionstatus "$sessionstatus" + + if [ "$sessionstatus" = "success" ]; then + _dyn_record_id="$(printf "%s\n" "$response" | _egrep_o "\"data\" *: *\[\"/REST/TXTRecord/$_dyn_zone/$fulldomain/[^\"]*" | _head_n 1 | sed "s#^\"data\" *: *\[\"/REST/TXTRecord/$_dyn_zone/$fulldomain/##")" + _debug _dyn_record_id "$_dyn_record_id" + return 0 + fi + + _dyn_record_id="" + _err "getting record_id failed" + return 1 +} + +#delete TXT record +_dyn_rm_record() { + + _info "Deleting TXT record" + + dyn_url="$DYN_API/TXTRecord/$_dyn_zone/$fulldomain/$_dyn_record_id/" + method="DELETE" + + _debug dyn_url "$dyn_url" + + export _H1="Auth-Token: $_dyn_authtoken" + export _H2="Content-Type: application/json" + + response="$(_post "" "$dyn_url" "" "$method")" + sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')" + + _debug response "$response" + _debug sessionstatus "$sessionstatus" + + if [ "$sessionstatus" = "success" ]; then + _info "TXT record successfully deleted" + return 0 + fi + + _err "delete TXT record failed" + return 1 +} + +#logout +_dyn_end_session() { + + _info "End Dyn API Session" + + dyn_url="$DYN_API/Session/" + method="DELETE" + + _debug dyn_url "$dyn_url" + + export _H1="Auth-Token: $_dyn_authtoken" + export _H2="Content-Type: application/json" + + response="$(_post "" "$dyn_url" "" "$method")" + + _debug response "$response" + + _dyn_authtoken="" + return 0 +} diff --git a/dnsapi/dns_infoblox.sh b/dnsapi/dns_infoblox.sh index 06ac87ec..4cbb2146 100644 --- a/dnsapi/dns_infoblox.sh +++ b/dnsapi/dns_infoblox.sh @@ -41,10 +41,10 @@ dns_infoblox_add() { export _H2="Authorization: Basic $Infoblox_CredsEncoded" ## Add the challenge record to the Infoblox grid member - result=$(_post "" "$baseurlnObject" "" "POST") + result="$(_post "" "$baseurlnObject" "" "POST")" ## Let's see if we get something intelligible back from the unit - if echo "$result" | egrep "record:txt/.*:.*/$Infoblox_View"; then + if [ "$(echo "$result" | _egrep_o "record:txt/.*:.*/$Infoblox_View")" ]; then _info "Successfully created the txt record" return 0 else @@ -66,7 +66,7 @@ dns_infoblox_rm() { _debug txtvalue "$txtvalue" ## Base64 encode the credentials - Infoblox_CredsEncoded=$(printf "%b" "$Infoblox_Creds" | _base64) + Infoblox_CredsEncoded="$(printf "%b" "$Infoblox_Creds" | _base64)" ## Construct the HTTP Authorization header export _H1="Accept-Language:en-US" @@ -74,17 +74,17 @@ dns_infoblox_rm() { ## Does the record exist? Let's check. baseurlnObject="https://$Infoblox_Server/wapi/v2.2.2/record:txt?name=$fulldomain&text=$txtvalue&view=$Infoblox_View&_return_type=xml-pretty" - result=$(_get "$baseurlnObject") + result="$(_get "$baseurlnObject")" ## Let's see if we get something intelligible back from the grid - if echo "$result" | egrep "record:txt/.*:.*/$Infoblox_View"; then + if [ "$(echo "$result" | _egrep_o "record:txt/.*:.*/$Infoblox_View")" ]; then ## Extract the object reference - objRef=$(printf "%b" "$result" | _egrep_o "record:txt/.*:.*/$Infoblox_View") + objRef="$(printf "%b" "$result" | _egrep_o "record:txt/.*:.*/$Infoblox_View")" objRmUrl="https://$Infoblox_Server/wapi/v2.2.2/$objRef" ## Delete them! All the stale records! - rmResult=$(_post "" "$objRmUrl" "" "DELETE") + rmResult="$(_post "" "$objRmUrl" "" "DELETE")" ## Let's see if that worked - if echo "$rmResult" | egrep "record:txt/.*:.*/$Infoblox_View"; then + if [ "$(echo "$rmResult" | _egrep_o "record:txt/.*:.*/$Infoblox_View")" ]; then _info "Successfully deleted $objRef" return 0 else From 3bf2e89a1a9f68188264aa7cbf0f1b2e17400566 Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Sat, 8 Jul 2017 21:35:22 +0300 Subject: [PATCH 40/95] add pdd.yandex.ru dns api --- dnsapi/dns_yandex.sh | 69 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100755 dnsapi/dns_yandex.sh diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh new file mode 100755 index 00000000..db38eb52 --- /dev/null +++ b/dnsapi/dns_yandex.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env sh +# Author: non7top@gmail.com +# 07 Jul 2017 +# report bugs at https://github.com/non7top/acme.sh + +# Values to export: +# export PDD_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +######## Public functions ##################### + +#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_yandex_add() { + fulldomain="${1}" + txtvalue="${2}" + _debug "Calling: dns_yandex_add() '${fulldomain}' '${txtvalue}'" + _PDD_credentials + export _H1="PddToken: $PDD_Token" + + curDomain="$(echo ${fulldomain}|awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" + curSubdomain="$(echo ${fulldomain} | sed -e 's#$curDomain##')" + curData="domain=${curDomain}&type=TXT&subdomain=${curSubdomain}&ttl=360&content=${txtvalue}" + curUri="https://pddimp.yandex.ru/api2/admin/dns/add" + curResult="$(_post "${curData}" "${curUri}")" + _debug "Result: $curResult" +} + +#Usage: dns_myapi_rm _acme-challenge.www.domain.com +dns_yandex_rm() { + fulldomain="${1}" + _debug "Calling: dns_yandex_rm() '${fulldomain}'" + _PDD_credentials + export _H1="PddToken: $PDD_Token" + local record_id=$( pdd_get_record_id ${fulldomain} ) + + curDomain="$(echo ${fulldomain}|awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" + curSubdomain="$(echo ${fulldomain} | sed -e 's#$curDomain##')" + curUri="https://pddimp.yandex.ru/api2/admin/dns/del" + curData="domain=${curDomain}&record_id=${record_id}" + curResult="$(_post "${curData}" "${curUri}")" + _debug "Result: $curResult" +} + +#################### Private functions below ################################## + +_PDD_credentials() { + if [ -z "${PDD_Token}" ]; then + PDD_Token="" + _err "You haven't specified the ISPConfig Login data." + return 1 + else + _saveaccountconf PDD_Token "${PDD_Token}" + fi +} + +pdd_get_record_id() { + local fulldomain="${1}" + local curDomain="$(echo ${fulldomain}|awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" + local curUri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${curDomain}" + local curResult="$(_get "${curUri}")" + echo ${curResult} | \ +python -c ' +import sys, json; +rs=json.load(sys.stdin)["records"] +for r in rs: + if r["fqdn"]=="${fulldomain}": + print r["record_id"] + exit +' +} From 6445a7674bd31e521e1eec12d16def544893dd69 Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Sat, 8 Jul 2017 21:52:47 +0300 Subject: [PATCH 41/95] fix syntax --- dnsapi/dns_yandex.sh | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index db38eb52..a792d495 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -16,8 +16,8 @@ dns_yandex_add() { _PDD_credentials export _H1="PddToken: $PDD_Token" - curDomain="$(echo ${fulldomain}|awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" - curSubdomain="$(echo ${fulldomain} | sed -e 's#$curDomain##')" + curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" + curSubdomain="$(echo "${fulldomain}" | sed -e 's#$curDomain##')" curData="domain=${curDomain}&type=TXT&subdomain=${curSubdomain}&ttl=360&content=${txtvalue}" curUri="https://pddimp.yandex.ru/api2/admin/dns/add" curResult="$(_post "${curData}" "${curUri}")" @@ -30,10 +30,10 @@ dns_yandex_rm() { _debug "Calling: dns_yandex_rm() '${fulldomain}'" _PDD_credentials export _H1="PddToken: $PDD_Token" - local record_id=$( pdd_get_record_id ${fulldomain} ) + record_id=$( pdd_get_record_id ${fulldomain} ) - curDomain="$(echo ${fulldomain}|awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" - curSubdomain="$(echo ${fulldomain} | sed -e 's#$curDomain##')" + curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" + curSubdomain="$(echo "${fulldomain}" | sed -e 's#$curDomain##')" curUri="https://pddimp.yandex.ru/api2/admin/dns/del" curData="domain=${curDomain}&record_id=${record_id}" curResult="$(_post "${curData}" "${curUri}")" @@ -53,17 +53,17 @@ _PDD_credentials() { } pdd_get_record_id() { - local fulldomain="${1}" - local curDomain="$(echo ${fulldomain}|awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" - local curUri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${curDomain}" - local curResult="$(_get "${curUri}")" + fulldomain="${1}" + curDomain="$(echo "${fulldomain}" |awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" + curUri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${curDomain}" + curResult="$(_get "${curUri}")" echo ${curResult} | \ -python -c ' + python -c " import sys, json; -rs=json.load(sys.stdin)["records"] +rs=json.load(sys.stdin)[\"records\"] for r in rs: - if r["fqdn"]=="${fulldomain}": - print r["record_id"] + if r[\"fqdn\"]==\"${fulldomain}\": + print r[\"record_id\"] exit -' +" } From a2038ab07e485153ac5b73fb5a8991d6c01c2352 Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Sat, 8 Jul 2017 21:57:27 +0300 Subject: [PATCH 42/95] fix syntax --- dnsapi/dns_yandex.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index a792d495..1b4b9ae3 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -16,8 +16,8 @@ dns_yandex_add() { _PDD_credentials export _H1="PddToken: $PDD_Token" - curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" - curSubdomain="$(echo "${fulldomain}" | sed -e 's#$curDomain##')" + curDomain="$( echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" + curSubdomain="$( echo "${fulldomain}" | sed -e "s#$curDomain##" )" curData="domain=${curDomain}&type=TXT&subdomain=${curSubdomain}&ttl=360&content=${txtvalue}" curUri="https://pddimp.yandex.ru/api2/admin/dns/add" curResult="$(_post "${curData}" "${curUri}")" @@ -30,10 +30,10 @@ dns_yandex_rm() { _debug "Calling: dns_yandex_rm() '${fulldomain}'" _PDD_credentials export _H1="PddToken: $PDD_Token" - record_id=$( pdd_get_record_id ${fulldomain} ) + record_id=$( pdd_get_record_id "${fulldomain}" ) - curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" - curSubdomain="$(echo "${fulldomain}" | sed -e 's#$curDomain##')" + curDomain="$( echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" + curSubdomain="$( echo "${fulldomain}" | sed -e "s#$curDomain##" )" curUri="https://pddimp.yandex.ru/api2/admin/dns/del" curData="domain=${curDomain}&record_id=${record_id}" curResult="$(_post "${curData}" "${curUri}")" @@ -57,8 +57,8 @@ pdd_get_record_id() { curDomain="$(echo "${fulldomain}" |awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" curUri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${curDomain}" curResult="$(_get "${curUri}")" - echo ${curResult} | \ - python -c " + echo "${curResult}" \ + | python -c " import sys, json; rs=json.load(sys.stdin)[\"records\"] for r in rs: From bd41f50ba5e7bd55f78fd3658da1470c57a33f0e Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Sat, 8 Jul 2017 22:02:34 +0300 Subject: [PATCH 43/95] fix formatting --- dnsapi/dns_yandex.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index 1b4b9ae3..077e6614 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -16,8 +16,8 @@ dns_yandex_add() { _PDD_credentials export _H1="PddToken: $PDD_Token" - curDomain="$( echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" - curSubdomain="$( echo "${fulldomain}" | sed -e "s#$curDomain##" )" + curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}')" + curSubdomain="$(echo "${fulldomain}" | sed -e "s#$curDomain##")" curData="domain=${curDomain}&type=TXT&subdomain=${curSubdomain}&ttl=360&content=${txtvalue}" curUri="https://pddimp.yandex.ru/api2/admin/dns/add" curResult="$(_post "${curData}" "${curUri}")" @@ -30,10 +30,10 @@ dns_yandex_rm() { _debug "Calling: dns_yandex_rm() '${fulldomain}'" _PDD_credentials export _H1="PddToken: $PDD_Token" - record_id=$( pdd_get_record_id "${fulldomain}" ) + record_id=$(pdd_get_record_id "${fulldomain}") - curDomain="$( echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" - curSubdomain="$( echo "${fulldomain}" | sed -e "s#$curDomain##" )" + curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}')" + curSubdomain="$(echo "${fulldomain}" | sed -e "s#$curDomain##")" curUri="https://pddimp.yandex.ru/api2/admin/dns/del" curData="domain=${curDomain}&record_id=${record_id}" curResult="$(_post "${curData}" "${curUri}")" @@ -54,11 +54,11 @@ _PDD_credentials() { pdd_get_record_id() { fulldomain="${1}" - curDomain="$(echo "${fulldomain}" |awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" + curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}')" curUri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${curDomain}" curResult="$(_get "${curUri}")" echo "${curResult}" \ - | python -c " + | python -c " import sys, json; rs=json.load(sys.stdin)[\"records\"] for r in rs: From 8f3a3b293d46708eef7c6b5018379d721d82e815 Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Sun, 9 Jul 2017 13:00:42 +0300 Subject: [PATCH 44/95] add newline and checks --- dnsapi/dns_yandex.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index 077e6614..fc707816 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -13,7 +13,7 @@ dns_yandex_add() { fulldomain="${1}" txtvalue="${2}" _debug "Calling: dns_yandex_add() '${fulldomain}' '${txtvalue}'" - _PDD_credentials + _PDD_credentials || exit 1 export _H1="PddToken: $PDD_Token" curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}')" @@ -28,7 +28,7 @@ dns_yandex_add() { dns_yandex_rm() { fulldomain="${1}" _debug "Calling: dns_yandex_rm() '${fulldomain}'" - _PDD_credentials + _PDD_credentials || exit 1 export _H1="PddToken: $PDD_Token" record_id=$(pdd_get_record_id "${fulldomain}") @@ -67,3 +67,4 @@ for r in rs: exit " } + From 256cb90f3cf878086fa14b21f0379a11344b8cec Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Sun, 9 Jul 2017 13:15:01 +0300 Subject: [PATCH 45/95] remove awk --- dnsapi/dns_yandex.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index fc707816..f6a7248e 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -16,8 +16,8 @@ dns_yandex_add() { _PDD_credentials || exit 1 export _H1="PddToken: $PDD_Token" - curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}')" - curSubdomain="$(echo "${fulldomain}" | sed -e "s#$curDomain##")" + curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev )" + curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev )" curData="domain=${curDomain}&type=TXT&subdomain=${curSubdomain}&ttl=360&content=${txtvalue}" curUri="https://pddimp.yandex.ru/api2/admin/dns/add" curResult="$(_post "${curData}" "${curUri}")" @@ -32,8 +32,8 @@ dns_yandex_rm() { export _H1="PddToken: $PDD_Token" record_id=$(pdd_get_record_id "${fulldomain}") - curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}')" - curSubdomain="$(echo "${fulldomain}" | sed -e "s#$curDomain##")" + curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev )" + curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev )" curUri="https://pddimp.yandex.ru/api2/admin/dns/del" curData="domain=${curDomain}&record_id=${record_id}" curResult="$(_post "${curData}" "${curUri}")" From 9ec54ef89b50fd2367706c7d1747ccc9d36c63ca Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Sun, 9 Jul 2017 13:21:55 +0300 Subject: [PATCH 46/95] shfmt fixes --- dnsapi/dns_yandex.sh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index f6a7248e..664da77b 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -16,8 +16,8 @@ dns_yandex_add() { _PDD_credentials || exit 1 export _H1="PddToken: $PDD_Token" - curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev )" - curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev )" + curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev)" + curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev)" curData="domain=${curDomain}&type=TXT&subdomain=${curSubdomain}&ttl=360&content=${txtvalue}" curUri="https://pddimp.yandex.ru/api2/admin/dns/add" curResult="$(_post "${curData}" "${curUri}")" @@ -32,8 +32,8 @@ dns_yandex_rm() { export _H1="PddToken: $PDD_Token" record_id=$(pdd_get_record_id "${fulldomain}") - curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev )" - curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev )" + curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev)" + curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev)" curUri="https://pddimp.yandex.ru/api2/admin/dns/del" curData="domain=${curDomain}&record_id=${record_id}" curResult="$(_post "${curData}" "${curUri}")" @@ -67,4 +67,3 @@ for r in rs: exit " } - From 266e9d06194c7eea0dd7854fd7c8fa9da680fcce Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Sun, 9 Jul 2017 20:00:02 +0300 Subject: [PATCH 47/95] remove python --- dnsapi/dns_yandex.sh | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index 664da77b..2a47150c 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -31,6 +31,7 @@ dns_yandex_rm() { _PDD_credentials || exit 1 export _H1="PddToken: $PDD_Token" record_id=$(pdd_get_record_id "${fulldomain}") + _debug "Result: $record_id" curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev)" curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev)" @@ -54,16 +55,10 @@ _PDD_credentials() { pdd_get_record_id() { fulldomain="${1}" - curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}')" + curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev)" + curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev)" curUri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${curDomain}" - curResult="$(_get "${curUri}")" - echo "${curResult}" \ - | python -c " -import sys, json; -rs=json.load(sys.stdin)[\"records\"] -for r in rs: - if r[\"fqdn\"]==\"${fulldomain}\": - print r[\"record_id\"] - exit -" + curResult="$(_get "${curUri}" | _normalizeJson)" + _debug "Result: $curResult" + echo "$curResult" | grep -o "{[^{]*\"content\":[^{]*\"subdomain\":\"${curSubdomain}\"" | sed -n -e 's#.* "record_id": \(.*\),[^,]*#\1#p' } From c4d0aec536dcd8886579d7f528f85217304c7366 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 10 Jul 2017 19:51:55 +0800 Subject: [PATCH 48/95] do not retry for a invalid cert in cronjob. fix https://github.com/Neilpang/acme.sh/issues/939 --- acme.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/acme.sh b/acme.sh index 35842f4e..486f8678 100755 --- a/acme.sh +++ b/acme.sh @@ -4033,6 +4033,11 @@ renew() { return "$RENEW_SKIP" fi + if [ "$IN_CRON" = "1" ] && [ -z "$Le_CertCreateTime" ]; then + _info "Skip invalid cert for: $Le_Domain" + return 0 + fi + IS_RENEW="1" issue "$Le_Webroot" "$Le_Domain" "$Le_Alt" "$Le_Keylength" "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" "$Le_RealFullChainPath" "$Le_PreHook" "$Le_PostHook" "$Le_RenewHook" "$Le_LocalAddress" res="$?" From 10cb7585a7140c7f709e2dcdee27913a55503545 Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Tue, 11 Jul 2017 02:19:39 +0300 Subject: [PATCH 49/95] fix egrep and exit --- dnsapi/dns_yandex.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index 2a47150c..d2ccf18e 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -13,7 +13,7 @@ dns_yandex_add() { fulldomain="${1}" txtvalue="${2}" _debug "Calling: dns_yandex_add() '${fulldomain}' '${txtvalue}'" - _PDD_credentials || exit 1 + _PDD_credentials || return 1 export _H1="PddToken: $PDD_Token" curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev)" @@ -28,7 +28,7 @@ dns_yandex_add() { dns_yandex_rm() { fulldomain="${1}" _debug "Calling: dns_yandex_rm() '${fulldomain}'" - _PDD_credentials || exit 1 + _PDD_credentials || return 1 export _H1="PddToken: $PDD_Token" record_id=$(pdd_get_record_id "${fulldomain}") _debug "Result: $record_id" @@ -60,5 +60,5 @@ pdd_get_record_id() { curUri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${curDomain}" curResult="$(_get "${curUri}" | _normalizeJson)" _debug "Result: $curResult" - echo "$curResult" | grep -o "{[^{]*\"content\":[^{]*\"subdomain\":\"${curSubdomain}\"" | sed -n -e 's#.* "record_id": \(.*\),[^,]*#\1#p' + echo "$curResult" | _egrep_o "{[^{]*\"content\":[^{]*\"subdomain\":\"${curSubdomain}\"" | sed -n -e 's#.* "record_id": \(.*\),[^,]*#\1#p' } From e6a95ecd0889779a39e988b392dcdd9568f34798 Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Wed, 12 Jul 2017 03:51:48 +0300 Subject: [PATCH 50/95] rework root domain detection --- dnsapi/dns_yandex.sh | 57 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index d2ccf18e..4b00219b 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -16,8 +16,9 @@ dns_yandex_add() { _PDD_credentials || return 1 export _H1="PddToken: $PDD_Token" - curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev)" - curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev)" + curDomain=$(_PDD_get_domain $fulldomain) + _debug "Found suitable domain in pdd: $curDomain" + curSubdomain="$(echo "${fulldomain}" | sed -e "s@.${curDomain}\$@@")" curData="domain=${curDomain}&type=TXT&subdomain=${curSubdomain}&ttl=360&content=${txtvalue}" curUri="https://pddimp.yandex.ru/api2/admin/dns/add" curResult="$(_post "${curData}" "${curUri}")" @@ -33,8 +34,10 @@ dns_yandex_rm() { record_id=$(pdd_get_record_id "${fulldomain}") _debug "Result: $record_id" - curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev)" - curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev)" + curDomain=$(_PDD_get_domain $fulldomain) + _debug "Found suitable domain in pdd: $curDomain" + curSubdomain="$(echo "${fulldomain}" | sed -e "s@.${curDomain}\$@@")" + curUri="https://pddimp.yandex.ru/api2/admin/dns/del" curData="domain=${curDomain}&record_id=${record_id}" curResult="$(_post "${curData}" "${curUri}")" @@ -43,10 +46,47 @@ dns_yandex_rm() { #################### Private functions below ################################## +_PDD_get_domain() { + fulldomain="${1}" + __page=1 + __last=0 + while [ $__last -eq 0 ]; do + uri1="https://pddimp.yandex.ru/api2/admin/domain/domains?page=${__page}&on_page=20" + res1=$(_get $uri1 | _normalizeJson) + #_debug "$res1" + __found=$(echo "$res1" | sed -n -e 's#.* "found": \([^,]*\),.*#\1#p') + _debug "found: $__found results on page" + if [ $__found -lt 20 ]; then + _debug "last page: $__page" + __last=1 + fi + + __all_domains="$__all_domains $(echo "$res1" | sed -e "s@,@\n@g" | grep '"name"' | cut -d: -f2 | sed -e 's@"@@g')" + + __page=$(_math $__page + 1) + done + + k=2 + while [ $k -lt 10 ]; do + __t=$(echo "$fulldomain" | cut -d . -f $k-100) + _debug "finding zone for domain $__t" + for d in $__all_domains; do + if [ "$d" == "$__t" ]; then + echo "$__t" + return + fi + done + k=$(_math $k + 1) + done + _err "No suitable domain found in your account" + return 1 +} + _PDD_credentials() { if [ -z "${PDD_Token}" ]; then PDD_Token="" - _err "You haven't specified the ISPConfig Login data." + _err "You need to export PDD_Token=xxxxxxxxxxxxxxxxx" + _err "You can get it at https://pddimp.yandex.ru/api2/admin/get_token" return 1 else _saveaccountconf PDD_Token "${PDD_Token}" @@ -55,8 +95,11 @@ _PDD_credentials() { pdd_get_record_id() { fulldomain="${1}" - curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev)" - curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev)" + + curDomain=$(_PDD_get_domain $fulldomain) + _debug "Found suitable domain in pdd: $curDomain" + curSubdomain="$(echo "${fulldomain}" | sed -e "s@.${curDomain}\$@@")" + curUri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${curDomain}" curResult="$(_get "${curUri}" | _normalizeJson)" _debug "Result: $curResult" From 6a9b4db448775b59913563aaeb3280296a0febc3 Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Wed, 12 Jul 2017 04:07:18 +0300 Subject: [PATCH 51/95] fix formatting --- dnsapi/dns_yandex.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index 4b00219b..eb60d5af 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -16,7 +16,7 @@ dns_yandex_add() { _PDD_credentials || return 1 export _H1="PddToken: $PDD_Token" - curDomain=$(_PDD_get_domain $fulldomain) + curDomain=$(_PDD_get_domain "$fulldomain") _debug "Found suitable domain in pdd: $curDomain" curSubdomain="$(echo "${fulldomain}" | sed -e "s@.${curDomain}\$@@")" curData="domain=${curDomain}&type=TXT&subdomain=${curSubdomain}&ttl=360&content=${txtvalue}" @@ -34,7 +34,7 @@ dns_yandex_rm() { record_id=$(pdd_get_record_id "${fulldomain}") _debug "Result: $record_id" - curDomain=$(_PDD_get_domain $fulldomain) + curDomain=$(_PDD_get_domain "$fulldomain") _debug "Found suitable domain in pdd: $curDomain" curSubdomain="$(echo "${fulldomain}" | sed -e "s@.${curDomain}\$@@")" @@ -52,11 +52,11 @@ _PDD_get_domain() { __last=0 while [ $__last -eq 0 ]; do uri1="https://pddimp.yandex.ru/api2/admin/domain/domains?page=${__page}&on_page=20" - res1=$(_get $uri1 | _normalizeJson) + res1=$(_get "$uri1" | _normalizeJson) #_debug "$res1" __found=$(echo "$res1" | sed -n -e 's#.* "found": \([^,]*\),.*#\1#p') _debug "found: $__found results on page" - if [ $__found -lt 20 ]; then + if [ "$__found" -lt 20 ]; then _debug "last page: $__page" __last=1 fi @@ -71,7 +71,7 @@ _PDD_get_domain() { __t=$(echo "$fulldomain" | cut -d . -f $k-100) _debug "finding zone for domain $__t" for d in $__all_domains; do - if [ "$d" == "$__t" ]; then + if [ "$d" = "$__t" ]; then echo "$__t" return fi @@ -96,7 +96,7 @@ _PDD_credentials() { pdd_get_record_id() { fulldomain="${1}" - curDomain=$(_PDD_get_domain $fulldomain) + curDomain=$(_PDD_get_domain "$fulldomain") _debug "Found suitable domain in pdd: $curDomain" curSubdomain="$(echo "${fulldomain}" | sed -e "s@.${curDomain}\$@@")" From 7d64e141e45be32479773f8a4fb44bd8304dacc1 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Wed, 12 Jul 2017 20:24:54 +0200 Subject: [PATCH 52/95] Add dns_he - DNS API script for Hurricane Electric DNS service ... Although not yet fully Posix compatible. --- dnsapi/README.md | 18 +++++ dnsapi/dns_he.sh | 200 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 218 insertions(+) create mode 100755 dnsapi/dns_he.sh diff --git a/dnsapi/README.md b/dnsapi/README.md index 41f89a88..15399048 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -572,6 +572,24 @@ acme.sh --issue --dns dns_dyn -d example.com -d www.example.com The `DYN_Customer`, `DYN_Username` and `DYN_Password` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. +# 30. Use Hurricane Electric + +Hurricane Electric doesn't have an API so just set your login credentials like so: + +``` +export HE_Username="yourusername" +export HE_Password="password" +``` + +Then you can issue your certificate: + +``` +acme.sh --issue --dns dns_he -d example.com -d www.example.com +``` + +The `HE_Username` and `HE_Password` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed. + +Please report any issues to https://github.com/angel333/acme.sh or to . # Use custom API diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh new file mode 100755 index 00000000..269db8d2 --- /dev/null +++ b/dnsapi/dns_he.sh @@ -0,0 +1,200 @@ +#!/usr/bin/env sh + +# TODO Somehow use _get instead of curl - not sure how to support +# cookies though... + +######################################################################## +# Hurricane Electric hook script for acme.sh +# +# Environment variables: +# +# - $HE_Username (your dns.he.net username) +# - $HE_Password (your dns.he.net password) +# +# Author: Ondrej Simek +# Git repo: https://github.com/angel333/acme.sh + + +#-- dns_he_add() - Add TXT record -------------------------------------- +# Usage: dns_he_add _acme-challenge.subdomain.domain.com "XyZ123..." + +dns_he_add() { + _full_domain=$1 + _txt_value=$2 + _info "Using DNS-01 Hurricane Electric hook" + + _authenticate || return 1 + _saveaccountconf HE_Username "$HE_Username" + _saveaccountconf HE_Password "$HE_Password" + + # fills in the $_zone_id + _find_zone $_full_domain || return 1 + _debug "Zone id \"$_zone_id\" will be used." + + curl -L --silent --show-error --cookie "$_he_cookie" \ + --form "account=" \ + --form "menu=edit_zone" \ + --form "Type=TXT" \ + --form "hosted_dns_zoneid=$_zone_id" \ + --form "hosted_dns_recordid=" \ + --form "hosted_dns_editzone=1" \ + --form "Priority=" \ + --form "Name=$_full_domain" \ + --form "Content=$_txt_value" \ + --form "TTL=300" \ + --form "hosted_dns_editrecord=Submit" \ + "https://dns.he.net/" \ + > /dev/null +} + + +#-- dns_he_rm() - Remove TXT record ------------------------------------ +# Usage: dns_he_rm _acme-challenge.subdomain.domain.com "XyZ123..." + +dns_he_rm() { + _full_domain=$1 + _txt_value=$2 + _info "Cleaning up after DNS-01 Hurricane Electric hook" + + _authenticate || return 1 + + # fills in the $_zone_id + _find_zone $_full_domain || return 1 + _debug "Zone id \"$_zone_id\" will be used." + + # Find the record id to clean + _record_id=$( \ + curl -L --silent --show-error --cookie "$_he_cookie" \ + "https://dns.he.net/?hosted_dns_zoneid=$_zone_id&menu=edit_zone&hosted_dns_editzone" \ + | grep -A 1 "data=\"\("\)\?${_txt_value}\("\)\?\"" \ + | tail -n 1 \ + | _egrep_o "'[[:digit:]]+','[^']+','TXT'" \ + | cut -b 2- \ + | _egrep_o "[[:digit:]]+" \ + | head -n1) # ... oh my, what have I done... + + # Remove the record + curl -L --silent --show-error --cookie "$_he_cookie" \ + --form "menu=edit_zone" \ + --form "hosted_dns_zoneid=$_zone_id" \ + --form "hosted_dns_recordid=$_record_id" \ + --form "hosted_dns_editzone=1" \ + --form "hosted_dns_delrecord=1" \ + --form "hosted_dns_delconfirm=delete" \ + --form "hosted_dns_editzone=1" \ + "https://dns.he.net/" \ + | grep '
Successfully removed record.
' \ + > /dev/null + if [ $? -eq 0 ]; then + _info "Record removed successfuly." + else + _err \ + "Could not clean (remove) up the record. Please go to HE" \ + "administration interface and clean it by hand." + fi +} + + +########################## PRIVATE FUNCTIONS ########################### + + +#-- _find_zone() ------------------------------------------------------- + +# Usage: _authenticate +# +# - needs $HE_Username and $HE_Password +# - sets the $_he_cookie + +_authenticate() { + if [ -z "$HE_Username" ] && [ -z "$HE_Password" ]; then + _err \ + 'No auth details provided. Please set user credentials using the \ + \$HE_Username and \$HE_Password envoronment variables.' + return 1 + fi + # Just get a session + _he_cookie=$( \ + curl -L --silent --show-error -I "https://dns.he.net/" \ + | grep '^Set-Cookie:' \ + | _egrep_o 'CGISESSID=[a-z0-9]*') + # Attempt login + curl -L --silent --show-error --cookie "$_he_cookie" \ + --form "email=${HE_Username}" \ + --form "pass=${HE_Password}" \ + "https://dns.he.net/" \ + > /dev/null + # TODO detect unsuccessful logins +} + + +#-- _find_zone() ------------------------------------------------------- + +# Returns the most specific zone found in administration interface. +# +# - needs $_he_cookie +# +# Example: +# +# _find_zone first.second.third.co.uk +# +# ... will return the first zone that exists in admin out of these: +# - "first.second.third.co.uk" +# - "second.third.co.uk" +# - "third.co.uk" +# - "co.uk" <-- unlikely +# - "uk" <-' +# +# (another approach would be something like this: +# https://github.com/hlandau/acme/blob/master/_doc/dns.hook +# - that's better if there are multiple pages. It's so much simpler. +# ) + +_find_zone() { + + _domain="$1" + + ## _all_zones is an array that looks like this: + ## ( zone1:id zone2:id ... ) + _all_zones=( $(curl -L --silent --show-error --cookie "$_he_cookie" \ + "https://dns.he.net/" \ + | _egrep_o "delete_dom.*name=\"[^\"]+\" value=\"[0-9]+" \ + | cut -d '"' -f 3,5 --output-delimiter=":" \ + ) ) + + _strip_counter=1 + while [ true ] + do + _attempted_zone=$(echo $_domain | cut -d . -f ${_strip_counter}-) + + # All possible zone names have been tried + if [ "$_attempted_zone" == "" ] + then + _err "No zone for domain \"$_domain\" found." + break + fi + + # Walk through all zones on the account + #echo "$_all_zones" | while IFS=' ' read _zone_name _zone_id + for i in ${_all_zones[@]} + do + _zone_name=$(echo $i | cut -d ':' -f 1) + _zone_id=$(echo $i | cut -d ':' -f 2) + if [ "$_zone_name" == "$_attempted_zone" ] + then + # Zone found - we got $_zone_name and $_zone_id, let's get out... + _debug "Found relevant zone \"$_zone_name\" with id" \ + "\"$_zone_id\" - will be used for domain \"$_domain\"." + return 0 + fi + done + + _debug "Zone \"$_attempted_zone\" doesn't exist, let's try another \ + variation." + _strip_counter=$(expr $_strip_counter + 1) + done + + # No zone found. + return 1 +} + +# vim: et:ts=2:sw=2: From accbda9d2f91c48c31f5e10ec073c44054647919 Mon Sep 17 00:00:00 2001 From: neilpang Date: Thu, 13 Jul 2017 20:52:44 +0800 Subject: [PATCH 53/95] output log --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 5849eb46..7ca042ea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ ADD ./ /install_acme.sh/ RUN cd /install_acme.sh && ([ -f /install_acme.sh/acme.sh ] && /install_acme.sh/acme.sh --install || curl https://get.acme.sh | sh) && rm -rf /install_acme.sh/ -RUN ln -s /root/.acme.sh/acme.sh /usr/local/bin/acme.sh +RUN ln -s /root/.acme.sh/acme.sh /usr/local/bin/acme.sh && crontab -l | sed 's#> /dev/null##' | crontab - RUN for verb in help \ version \ From 84a251c8c7eea52e819445c4d407fefc2b52c852 Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Thu, 13 Jul 2017 17:05:57 +0300 Subject: [PATCH 54/95] add documentation --- README.md | 1 + dnsapi/README.md | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/README.md b/README.md index 7780b9ab..afb8a761 100644 --- a/README.md +++ b/README.md @@ -335,6 +335,7 @@ You don't have to do anything manually! 1. DNSimple API 1. NS1.com API 1. DuckDNS.org API +1. Yandex PDD API (https://pdd.yandex.ru) 1. Name.com API diff --git a/dnsapi/README.md b/dnsapi/README.md index 57c360b7..55fd65a2 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -522,6 +522,21 @@ account file will always store the lastly used domain name. For issues, please report to https://github.com/raidenii/acme.sh/issues. + +## 27. Use pdd.yandex.ru API + +``` +export PDD_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +``` + +Follow these instructions to get the token for your domain https://tech.yandex.com/domain/doc/concepts/access-docpage/ +``` +acme.sh --issue --dns dns_yandex -d mydomain.example.org +``` + +For issues, please report to https://github.com/non7top/acme.sh/issues. + + ## 28. Use Name.com API You'll need to fill out the form at https://www.name.com/reseller/apply to apply From bdee66fe2942affb0ba0675785d6c0ef567fbf8e Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Thu, 13 Jul 2017 18:37:13 +0300 Subject: [PATCH 55/95] minor fixes --- dnsapi/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/README.md b/dnsapi/README.md index 55fd65a2..71154033 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -523,7 +523,7 @@ account file will always store the lastly used domain name. For issues, please report to https://github.com/raidenii/acme.sh/issues. -## 27. Use pdd.yandex.ru API +## 28. Use pdd.yandex.ru API ``` export PDD_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -537,7 +537,7 @@ acme.sh --issue --dns dns_yandex -d mydomain.example.org For issues, please report to https://github.com/non7top/acme.sh/issues. -## 28. Use Name.com API +## 29. Use Name.com API You'll need to fill out the form at https://www.name.com/reseller/apply to apply for API username and token. From a460ac021fadffda93359b9acab6508cafcd6c24 Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Sat, 8 Jul 2017 21:35:22 +0300 Subject: [PATCH 56/95] add pdd.yandex.ru dns api --- dnsapi/dns_yandex.sh | 69 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100755 dnsapi/dns_yandex.sh diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh new file mode 100755 index 00000000..db38eb52 --- /dev/null +++ b/dnsapi/dns_yandex.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env sh +# Author: non7top@gmail.com +# 07 Jul 2017 +# report bugs at https://github.com/non7top/acme.sh + +# Values to export: +# export PDD_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +######## Public functions ##################### + +#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_yandex_add() { + fulldomain="${1}" + txtvalue="${2}" + _debug "Calling: dns_yandex_add() '${fulldomain}' '${txtvalue}'" + _PDD_credentials + export _H1="PddToken: $PDD_Token" + + curDomain="$(echo ${fulldomain}|awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" + curSubdomain="$(echo ${fulldomain} | sed -e 's#$curDomain##')" + curData="domain=${curDomain}&type=TXT&subdomain=${curSubdomain}&ttl=360&content=${txtvalue}" + curUri="https://pddimp.yandex.ru/api2/admin/dns/add" + curResult="$(_post "${curData}" "${curUri}")" + _debug "Result: $curResult" +} + +#Usage: dns_myapi_rm _acme-challenge.www.domain.com +dns_yandex_rm() { + fulldomain="${1}" + _debug "Calling: dns_yandex_rm() '${fulldomain}'" + _PDD_credentials + export _H1="PddToken: $PDD_Token" + local record_id=$( pdd_get_record_id ${fulldomain} ) + + curDomain="$(echo ${fulldomain}|awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" + curSubdomain="$(echo ${fulldomain} | sed -e 's#$curDomain##')" + curUri="https://pddimp.yandex.ru/api2/admin/dns/del" + curData="domain=${curDomain}&record_id=${record_id}" + curResult="$(_post "${curData}" "${curUri}")" + _debug "Result: $curResult" +} + +#################### Private functions below ################################## + +_PDD_credentials() { + if [ -z "${PDD_Token}" ]; then + PDD_Token="" + _err "You haven't specified the ISPConfig Login data." + return 1 + else + _saveaccountconf PDD_Token "${PDD_Token}" + fi +} + +pdd_get_record_id() { + local fulldomain="${1}" + local curDomain="$(echo ${fulldomain}|awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" + local curUri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${curDomain}" + local curResult="$(_get "${curUri}")" + echo ${curResult} | \ +python -c ' +import sys, json; +rs=json.load(sys.stdin)["records"] +for r in rs: + if r["fqdn"]=="${fulldomain}": + print r["record_id"] + exit +' +} From a09b2c0074f43e017966cb22018100774df76832 Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Sat, 8 Jul 2017 21:52:47 +0300 Subject: [PATCH 57/95] fix syntax --- dnsapi/dns_yandex.sh | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index db38eb52..a792d495 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -16,8 +16,8 @@ dns_yandex_add() { _PDD_credentials export _H1="PddToken: $PDD_Token" - curDomain="$(echo ${fulldomain}|awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" - curSubdomain="$(echo ${fulldomain} | sed -e 's#$curDomain##')" + curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" + curSubdomain="$(echo "${fulldomain}" | sed -e 's#$curDomain##')" curData="domain=${curDomain}&type=TXT&subdomain=${curSubdomain}&ttl=360&content=${txtvalue}" curUri="https://pddimp.yandex.ru/api2/admin/dns/add" curResult="$(_post "${curData}" "${curUri}")" @@ -30,10 +30,10 @@ dns_yandex_rm() { _debug "Calling: dns_yandex_rm() '${fulldomain}'" _PDD_credentials export _H1="PddToken: $PDD_Token" - local record_id=$( pdd_get_record_id ${fulldomain} ) + record_id=$( pdd_get_record_id ${fulldomain} ) - curDomain="$(echo ${fulldomain}|awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" - curSubdomain="$(echo ${fulldomain} | sed -e 's#$curDomain##')" + curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" + curSubdomain="$(echo "${fulldomain}" | sed -e 's#$curDomain##')" curUri="https://pddimp.yandex.ru/api2/admin/dns/del" curData="domain=${curDomain}&record_id=${record_id}" curResult="$(_post "${curData}" "${curUri}")" @@ -53,17 +53,17 @@ _PDD_credentials() { } pdd_get_record_id() { - local fulldomain="${1}" - local curDomain="$(echo ${fulldomain}|awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" - local curUri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${curDomain}" - local curResult="$(_get "${curUri}")" + fulldomain="${1}" + curDomain="$(echo "${fulldomain}" |awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" + curUri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${curDomain}" + curResult="$(_get "${curUri}")" echo ${curResult} | \ -python -c ' + python -c " import sys, json; -rs=json.load(sys.stdin)["records"] +rs=json.load(sys.stdin)[\"records\"] for r in rs: - if r["fqdn"]=="${fulldomain}": - print r["record_id"] + if r[\"fqdn\"]==\"${fulldomain}\": + print r[\"record_id\"] exit -' +" } From e9d540779257ac5378ea594391de387393a03c84 Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Sat, 8 Jul 2017 21:57:27 +0300 Subject: [PATCH 58/95] fix syntax --- dnsapi/dns_yandex.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index a792d495..1b4b9ae3 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -16,8 +16,8 @@ dns_yandex_add() { _PDD_credentials export _H1="PddToken: $PDD_Token" - curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" - curSubdomain="$(echo "${fulldomain}" | sed -e 's#$curDomain##')" + curDomain="$( echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" + curSubdomain="$( echo "${fulldomain}" | sed -e "s#$curDomain##" )" curData="domain=${curDomain}&type=TXT&subdomain=${curSubdomain}&ttl=360&content=${txtvalue}" curUri="https://pddimp.yandex.ru/api2/admin/dns/add" curResult="$(_post "${curData}" "${curUri}")" @@ -30,10 +30,10 @@ dns_yandex_rm() { _debug "Calling: dns_yandex_rm() '${fulldomain}'" _PDD_credentials export _H1="PddToken: $PDD_Token" - record_id=$( pdd_get_record_id ${fulldomain} ) + record_id=$( pdd_get_record_id "${fulldomain}" ) - curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" - curSubdomain="$(echo "${fulldomain}" | sed -e 's#$curDomain##')" + curDomain="$( echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" + curSubdomain="$( echo "${fulldomain}" | sed -e "s#$curDomain##" )" curUri="https://pddimp.yandex.ru/api2/admin/dns/del" curData="domain=${curDomain}&record_id=${record_id}" curResult="$(_post "${curData}" "${curUri}")" @@ -57,8 +57,8 @@ pdd_get_record_id() { curDomain="$(echo "${fulldomain}" |awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" curUri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${curDomain}" curResult="$(_get "${curUri}")" - echo ${curResult} | \ - python -c " + echo "${curResult}" \ + | python -c " import sys, json; rs=json.load(sys.stdin)[\"records\"] for r in rs: From 18cb11dcbf932fe324c9d0426546e63770cf7355 Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Sat, 8 Jul 2017 22:02:34 +0300 Subject: [PATCH 59/95] fix formatting --- dnsapi/dns_yandex.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index 1b4b9ae3..077e6614 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -16,8 +16,8 @@ dns_yandex_add() { _PDD_credentials export _H1="PddToken: $PDD_Token" - curDomain="$( echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" - curSubdomain="$( echo "${fulldomain}" | sed -e "s#$curDomain##" )" + curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}')" + curSubdomain="$(echo "${fulldomain}" | sed -e "s#$curDomain##")" curData="domain=${curDomain}&type=TXT&subdomain=${curSubdomain}&ttl=360&content=${txtvalue}" curUri="https://pddimp.yandex.ru/api2/admin/dns/add" curResult="$(_post "${curData}" "${curUri}")" @@ -30,10 +30,10 @@ dns_yandex_rm() { _debug "Calling: dns_yandex_rm() '${fulldomain}'" _PDD_credentials export _H1="PddToken: $PDD_Token" - record_id=$( pdd_get_record_id "${fulldomain}" ) + record_id=$(pdd_get_record_id "${fulldomain}") - curDomain="$( echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" - curSubdomain="$( echo "${fulldomain}" | sed -e "s#$curDomain##" )" + curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}')" + curSubdomain="$(echo "${fulldomain}" | sed -e "s#$curDomain##")" curUri="https://pddimp.yandex.ru/api2/admin/dns/del" curData="domain=${curDomain}&record_id=${record_id}" curResult="$(_post "${curData}" "${curUri}")" @@ -54,11 +54,11 @@ _PDD_credentials() { pdd_get_record_id() { fulldomain="${1}" - curDomain="$(echo "${fulldomain}" |awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}' )" + curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}')" curUri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${curDomain}" curResult="$(_get "${curUri}")" echo "${curResult}" \ - | python -c " + | python -c " import sys, json; rs=json.load(sys.stdin)[\"records\"] for r in rs: From 42ab7a5d725109a15df5d0a049232a3f461908bc Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Sun, 9 Jul 2017 13:00:42 +0300 Subject: [PATCH 60/95] add newline and checks --- dnsapi/dns_yandex.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index 077e6614..fc707816 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -13,7 +13,7 @@ dns_yandex_add() { fulldomain="${1}" txtvalue="${2}" _debug "Calling: dns_yandex_add() '${fulldomain}' '${txtvalue}'" - _PDD_credentials + _PDD_credentials || exit 1 export _H1="PddToken: $PDD_Token" curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}')" @@ -28,7 +28,7 @@ dns_yandex_add() { dns_yandex_rm() { fulldomain="${1}" _debug "Calling: dns_yandex_rm() '${fulldomain}'" - _PDD_credentials + _PDD_credentials || exit 1 export _H1="PddToken: $PDD_Token" record_id=$(pdd_get_record_id "${fulldomain}") @@ -67,3 +67,4 @@ for r in rs: exit " } + From d61b687853e00f72dbfc1d7137767ba0ae4fdf57 Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Sun, 9 Jul 2017 13:15:01 +0300 Subject: [PATCH 61/95] remove awk --- dnsapi/dns_yandex.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index fc707816..f6a7248e 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -16,8 +16,8 @@ dns_yandex_add() { _PDD_credentials || exit 1 export _H1="PddToken: $PDD_Token" - curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}')" - curSubdomain="$(echo "${fulldomain}" | sed -e "s#$curDomain##")" + curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev )" + curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev )" curData="domain=${curDomain}&type=TXT&subdomain=${curSubdomain}&ttl=360&content=${txtvalue}" curUri="https://pddimp.yandex.ru/api2/admin/dns/add" curResult="$(_post "${curData}" "${curUri}")" @@ -32,8 +32,8 @@ dns_yandex_rm() { export _H1="PddToken: $PDD_Token" record_id=$(pdd_get_record_id "${fulldomain}") - curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}')" - curSubdomain="$(echo "${fulldomain}" | sed -e "s#$curDomain##")" + curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev )" + curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev )" curUri="https://pddimp.yandex.ru/api2/admin/dns/del" curData="domain=${curDomain}&record_id=${record_id}" curResult="$(_post "${curData}" "${curUri}")" From 57d1db58db275bda6e89608d5af75ae4f60320f7 Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Sun, 9 Jul 2017 13:21:55 +0300 Subject: [PATCH 62/95] shfmt fixes --- dnsapi/dns_yandex.sh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index f6a7248e..664da77b 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -16,8 +16,8 @@ dns_yandex_add() { _PDD_credentials || exit 1 export _H1="PddToken: $PDD_Token" - curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev )" - curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev )" + curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev)" + curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev)" curData="domain=${curDomain}&type=TXT&subdomain=${curSubdomain}&ttl=360&content=${txtvalue}" curUri="https://pddimp.yandex.ru/api2/admin/dns/add" curResult="$(_post "${curData}" "${curUri}")" @@ -32,8 +32,8 @@ dns_yandex_rm() { export _H1="PddToken: $PDD_Token" record_id=$(pdd_get_record_id "${fulldomain}") - curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev )" - curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev )" + curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev)" + curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev)" curUri="https://pddimp.yandex.ru/api2/admin/dns/del" curData="domain=${curDomain}&record_id=${record_id}" curResult="$(_post "${curData}" "${curUri}")" @@ -67,4 +67,3 @@ for r in rs: exit " } - From a0df46258dfb327ff5f2de471b13d1250b4ea3e3 Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Sun, 9 Jul 2017 20:00:02 +0300 Subject: [PATCH 63/95] remove python --- dnsapi/dns_yandex.sh | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index 664da77b..2a47150c 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -31,6 +31,7 @@ dns_yandex_rm() { _PDD_credentials || exit 1 export _H1="PddToken: $PDD_Token" record_id=$(pdd_get_record_id "${fulldomain}") + _debug "Result: $record_id" curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev)" curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev)" @@ -54,16 +55,10 @@ _PDD_credentials() { pdd_get_record_id() { fulldomain="${1}" - curDomain="$(echo "${fulldomain}" | awk -F. '{printf("%s.%s\n",$(NF-1), $NF)}')" + curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev)" + curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev)" curUri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${curDomain}" - curResult="$(_get "${curUri}")" - echo "${curResult}" \ - | python -c " -import sys, json; -rs=json.load(sys.stdin)[\"records\"] -for r in rs: - if r[\"fqdn\"]==\"${fulldomain}\": - print r[\"record_id\"] - exit -" + curResult="$(_get "${curUri}" | _normalizeJson)" + _debug "Result: $curResult" + echo "$curResult" | grep -o "{[^{]*\"content\":[^{]*\"subdomain\":\"${curSubdomain}\"" | sed -n -e 's#.* "record_id": \(.*\),[^,]*#\1#p' } From fceb728501472961e73ed8bbdd292311de31cd40 Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Tue, 11 Jul 2017 02:19:39 +0300 Subject: [PATCH 64/95] fix egrep and exit --- dnsapi/dns_yandex.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index 2a47150c..d2ccf18e 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -13,7 +13,7 @@ dns_yandex_add() { fulldomain="${1}" txtvalue="${2}" _debug "Calling: dns_yandex_add() '${fulldomain}' '${txtvalue}'" - _PDD_credentials || exit 1 + _PDD_credentials || return 1 export _H1="PddToken: $PDD_Token" curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev)" @@ -28,7 +28,7 @@ dns_yandex_add() { dns_yandex_rm() { fulldomain="${1}" _debug "Calling: dns_yandex_rm() '${fulldomain}'" - _PDD_credentials || exit 1 + _PDD_credentials || return 1 export _H1="PddToken: $PDD_Token" record_id=$(pdd_get_record_id "${fulldomain}") _debug "Result: $record_id" @@ -60,5 +60,5 @@ pdd_get_record_id() { curUri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${curDomain}" curResult="$(_get "${curUri}" | _normalizeJson)" _debug "Result: $curResult" - echo "$curResult" | grep -o "{[^{]*\"content\":[^{]*\"subdomain\":\"${curSubdomain}\"" | sed -n -e 's#.* "record_id": \(.*\),[^,]*#\1#p' + echo "$curResult" | _egrep_o "{[^{]*\"content\":[^{]*\"subdomain\":\"${curSubdomain}\"" | sed -n -e 's#.* "record_id": \(.*\),[^,]*#\1#p' } From eb6be88fac9510aa137b3dea9e16b56aa3d10c1e Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Wed, 12 Jul 2017 03:51:48 +0300 Subject: [PATCH 65/95] rework root domain detection --- dnsapi/dns_yandex.sh | 57 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index d2ccf18e..4b00219b 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -16,8 +16,9 @@ dns_yandex_add() { _PDD_credentials || return 1 export _H1="PddToken: $PDD_Token" - curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev)" - curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev)" + curDomain=$(_PDD_get_domain $fulldomain) + _debug "Found suitable domain in pdd: $curDomain" + curSubdomain="$(echo "${fulldomain}" | sed -e "s@.${curDomain}\$@@")" curData="domain=${curDomain}&type=TXT&subdomain=${curSubdomain}&ttl=360&content=${txtvalue}" curUri="https://pddimp.yandex.ru/api2/admin/dns/add" curResult="$(_post "${curData}" "${curUri}")" @@ -33,8 +34,10 @@ dns_yandex_rm() { record_id=$(pdd_get_record_id "${fulldomain}") _debug "Result: $record_id" - curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev)" - curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev)" + curDomain=$(_PDD_get_domain $fulldomain) + _debug "Found suitable domain in pdd: $curDomain" + curSubdomain="$(echo "${fulldomain}" | sed -e "s@.${curDomain}\$@@")" + curUri="https://pddimp.yandex.ru/api2/admin/dns/del" curData="domain=${curDomain}&record_id=${record_id}" curResult="$(_post "${curData}" "${curUri}")" @@ -43,10 +46,47 @@ dns_yandex_rm() { #################### Private functions below ################################## +_PDD_get_domain() { + fulldomain="${1}" + __page=1 + __last=0 + while [ $__last -eq 0 ]; do + uri1="https://pddimp.yandex.ru/api2/admin/domain/domains?page=${__page}&on_page=20" + res1=$(_get $uri1 | _normalizeJson) + #_debug "$res1" + __found=$(echo "$res1" | sed -n -e 's#.* "found": \([^,]*\),.*#\1#p') + _debug "found: $__found results on page" + if [ $__found -lt 20 ]; then + _debug "last page: $__page" + __last=1 + fi + + __all_domains="$__all_domains $(echo "$res1" | sed -e "s@,@\n@g" | grep '"name"' | cut -d: -f2 | sed -e 's@"@@g')" + + __page=$(_math $__page + 1) + done + + k=2 + while [ $k -lt 10 ]; do + __t=$(echo "$fulldomain" | cut -d . -f $k-100) + _debug "finding zone for domain $__t" + for d in $__all_domains; do + if [ "$d" == "$__t" ]; then + echo "$__t" + return + fi + done + k=$(_math $k + 1) + done + _err "No suitable domain found in your account" + return 1 +} + _PDD_credentials() { if [ -z "${PDD_Token}" ]; then PDD_Token="" - _err "You haven't specified the ISPConfig Login data." + _err "You need to export PDD_Token=xxxxxxxxxxxxxxxxx" + _err "You can get it at https://pddimp.yandex.ru/api2/admin/get_token" return 1 else _saveaccountconf PDD_Token "${PDD_Token}" @@ -55,8 +95,11 @@ _PDD_credentials() { pdd_get_record_id() { fulldomain="${1}" - curDomain="$(echo "${fulldomain}" | rev | cut -d . -f 1-2 | rev)" - curSubdomain="$(echo "${fulldomain}" | rev | cut -d . -f 3- | rev)" + + curDomain=$(_PDD_get_domain $fulldomain) + _debug "Found suitable domain in pdd: $curDomain" + curSubdomain="$(echo "${fulldomain}" | sed -e "s@.${curDomain}\$@@")" + curUri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${curDomain}" curResult="$(_get "${curUri}" | _normalizeJson)" _debug "Result: $curResult" From c848d3ee22b085a18ff52567efb7d0f213374f7b Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Wed, 12 Jul 2017 04:07:18 +0300 Subject: [PATCH 66/95] fix formatting --- dnsapi/dns_yandex.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dnsapi/dns_yandex.sh b/dnsapi/dns_yandex.sh index 4b00219b..eb60d5af 100755 --- a/dnsapi/dns_yandex.sh +++ b/dnsapi/dns_yandex.sh @@ -16,7 +16,7 @@ dns_yandex_add() { _PDD_credentials || return 1 export _H1="PddToken: $PDD_Token" - curDomain=$(_PDD_get_domain $fulldomain) + curDomain=$(_PDD_get_domain "$fulldomain") _debug "Found suitable domain in pdd: $curDomain" curSubdomain="$(echo "${fulldomain}" | sed -e "s@.${curDomain}\$@@")" curData="domain=${curDomain}&type=TXT&subdomain=${curSubdomain}&ttl=360&content=${txtvalue}" @@ -34,7 +34,7 @@ dns_yandex_rm() { record_id=$(pdd_get_record_id "${fulldomain}") _debug "Result: $record_id" - curDomain=$(_PDD_get_domain $fulldomain) + curDomain=$(_PDD_get_domain "$fulldomain") _debug "Found suitable domain in pdd: $curDomain" curSubdomain="$(echo "${fulldomain}" | sed -e "s@.${curDomain}\$@@")" @@ -52,11 +52,11 @@ _PDD_get_domain() { __last=0 while [ $__last -eq 0 ]; do uri1="https://pddimp.yandex.ru/api2/admin/domain/domains?page=${__page}&on_page=20" - res1=$(_get $uri1 | _normalizeJson) + res1=$(_get "$uri1" | _normalizeJson) #_debug "$res1" __found=$(echo "$res1" | sed -n -e 's#.* "found": \([^,]*\),.*#\1#p') _debug "found: $__found results on page" - if [ $__found -lt 20 ]; then + if [ "$__found" -lt 20 ]; then _debug "last page: $__page" __last=1 fi @@ -71,7 +71,7 @@ _PDD_get_domain() { __t=$(echo "$fulldomain" | cut -d . -f $k-100) _debug "finding zone for domain $__t" for d in $__all_domains; do - if [ "$d" == "$__t" ]; then + if [ "$d" = "$__t" ]; then echo "$__t" return fi @@ -96,7 +96,7 @@ _PDD_credentials() { pdd_get_record_id() { fulldomain="${1}" - curDomain=$(_PDD_get_domain $fulldomain) + curDomain=$(_PDD_get_domain "$fulldomain") _debug "Found suitable domain in pdd: $curDomain" curSubdomain="$(echo "${fulldomain}" | sed -e "s@.${curDomain}\$@@")" From 377fe5ecdeb750a95ffdb38b669d66d77ad0a03d Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Thu, 13 Jul 2017 17:05:57 +0300 Subject: [PATCH 67/95] add documentation --- README.md | 1 + dnsapi/README.md | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/README.md b/README.md index 5c306a59..ae73b0fe 100644 --- a/README.md +++ b/README.md @@ -335,6 +335,7 @@ You don't have to do anything manually! 1. DNSimple API 1. NS1.com API 1. DuckDNS.org API +1. Yandex PDD API (https://pdd.yandex.ru) 1. Name.com API 1. Dyn Managed DNS API diff --git a/dnsapi/README.md b/dnsapi/README.md index 41f89a88..afaf94f8 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -522,6 +522,21 @@ account file will always store the lastly used domain name. For issues, please report to https://github.com/raidenii/acme.sh/issues. + +## 27. Use pdd.yandex.ru API + +``` +export PDD_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +``` + +Follow these instructions to get the token for your domain https://tech.yandex.com/domain/doc/concepts/access-docpage/ +``` +acme.sh --issue --dns dns_yandex -d mydomain.example.org +``` + +For issues, please report to https://github.com/non7top/acme.sh/issues. + + ## 28. Use Name.com API You'll need to fill out the form at https://www.name.com/reseller/apply to apply From 283ef9adb7a9f5f33e04ce03b6db158802a30f3a Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Thu, 13 Jul 2017 18:37:13 +0300 Subject: [PATCH 68/95] minor fixes --- dnsapi/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/README.md b/dnsapi/README.md index afaf94f8..3d571af1 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -523,7 +523,7 @@ account file will always store the lastly used domain name. For issues, please report to https://github.com/raidenii/acme.sh/issues. -## 27. Use pdd.yandex.ru API +## 28. Use pdd.yandex.ru API ``` export PDD_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -537,7 +537,7 @@ acme.sh --issue --dns dns_yandex -d mydomain.example.org For issues, please report to https://github.com/non7top/acme.sh/issues. -## 28. Use Name.com API +## 29. Use Name.com API You'll need to fill out the form at https://www.name.com/reseller/apply to apply for API username and token. From ae302ee600b1a07bd1132676ab204df72208e15b Mon Sep 17 00:00:00 2001 From: Vladimir Berezhnoy Date: Fri, 14 Jul 2017 03:51:08 +0300 Subject: [PATCH 69/95] reformat docs --- README.md | 2 +- dnsapi/README.md | 29 +++++++++++++---------------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index ae73b0fe..5a3a3adf 100644 --- a/README.md +++ b/README.md @@ -335,9 +335,9 @@ You don't have to do anything manually! 1. DNSimple API 1. NS1.com API 1. DuckDNS.org API -1. Yandex PDD API (https://pdd.yandex.ru) 1. Name.com API 1. Dyn Managed DNS API +1. Yandex PDD API (https://pdd.yandex.ru) And: diff --git a/dnsapi/README.md b/dnsapi/README.md index 3d571af1..d3dff12a 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -522,22 +522,7 @@ account file will always store the lastly used domain name. For issues, please report to https://github.com/raidenii/acme.sh/issues. - -## 28. Use pdd.yandex.ru API - -``` -export PDD_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -``` - -Follow these instructions to get the token for your domain https://tech.yandex.com/domain/doc/concepts/access-docpage/ -``` -acme.sh --issue --dns dns_yandex -d mydomain.example.org -``` - -For issues, please report to https://github.com/non7top/acme.sh/issues. - - -## 29. Use Name.com API +## 28. Use Name.com API You'll need to fill out the form at https://www.name.com/reseller/apply to apply for API username and token. @@ -587,6 +572,18 @@ acme.sh --issue --dns dns_dyn -d example.com -d www.example.com The `DYN_Customer`, `DYN_Username` and `DYN_Password` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. +## 30. Use pdd.yandex.ru API + +``` +export PDD_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +``` + +Follow these instructions to get the token for your domain https://tech.yandex.com/domain/doc/concepts/access-docpage/ +``` +acme.sh --issue --dns dns_yandex -d mydomain.example.org +``` + +For issues, please report to https://github.com/non7top/acme.sh/issues. # Use custom API From 4285d81ca9d2805e99cf4ed0b601891b4ffd77ce Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Sun, 23 Jul 2017 05:00:02 +0200 Subject: [PATCH 70/95] Get rid of curl. --- dnsapi/dns_he.sh | 102 +++++++++++++++++------------------------------ 1 file changed, 37 insertions(+), 65 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 269db8d2..141268ac 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -1,8 +1,5 @@ #!/usr/bin/env sh -# TODO Somehow use _get instead of curl - not sure how to support -# cookies though... - ######################################################################## # Hurricane Electric hook script for acme.sh # @@ -23,7 +20,12 @@ dns_he_add() { _txt_value=$2 _info "Using DNS-01 Hurricane Electric hook" - _authenticate || return 1 + if [ -z "$HE_Username" ] && [ -z "$HE_Password" ]; then + _err \ + 'No auth details provided. Please set user credentials using the \ + \$HE_Username and \$HE_Password envoronment variables.' + return 1 + fi _saveaccountconf HE_Username "$HE_Username" _saveaccountconf HE_Password "$HE_Password" @@ -31,20 +33,20 @@ dns_he_add() { _find_zone $_full_domain || return 1 _debug "Zone id \"$_zone_id\" will be used." - curl -L --silent --show-error --cookie "$_he_cookie" \ - --form "account=" \ - --form "menu=edit_zone" \ - --form "Type=TXT" \ - --form "hosted_dns_zoneid=$_zone_id" \ - --form "hosted_dns_recordid=" \ - --form "hosted_dns_editzone=1" \ - --form "Priority=" \ - --form "Name=$_full_domain" \ - --form "Content=$_txt_value" \ - --form "TTL=300" \ - --form "hosted_dns_editrecord=Submit" \ - "https://dns.he.net/" \ - > /dev/null + body="email=${HE_Username}&pass=${HE_Password}" + body="$body&account=" + body="$body&account=" + body="$body&menu=edit_zone" + body="$body&Type=TXT" + body="$body&hosted_dns_zoneid=$_zone_id" + body="$body&hosted_dns_recordid=" + body="$body&hosted_dns_editzone=1" + body="$body&Priority=" + body="$body&Name=$_full_domain" + body="$body&Content=$_txt_value" + body="$body&TTL=300" + body="$body&hosted_dns_editrecord=Submit" + _post $body "https://dns.he.net/" >/dev/null } @@ -56,16 +58,16 @@ dns_he_rm() { _txt_value=$2 _info "Cleaning up after DNS-01 Hurricane Electric hook" - _authenticate || return 1 - # fills in the $_zone_id _find_zone $_full_domain || return 1 _debug "Zone id \"$_zone_id\" will be used." # Find the record id to clean - _record_id=$( \ - curl -L --silent --show-error --cookie "$_he_cookie" \ - "https://dns.he.net/?hosted_dns_zoneid=$_zone_id&menu=edit_zone&hosted_dns_editzone" \ + body="email=${HE_Username}&pass=${HE_Password}" + body="$body&hosted_dns_zoneid=$_zone_id" + body="$body&menu=edit_zone" + body="$body&hosted_dns_editzone=" + _record_id=$(_post $body "https://dns.he.net/" \ | grep -A 1 "data=\"\("\)\?${_txt_value}\("\)\?\"" \ | tail -n 1 \ | _egrep_o "'[[:digit:]]+','[^']+','TXT'" \ @@ -74,15 +76,15 @@ dns_he_rm() { | head -n1) # ... oh my, what have I done... # Remove the record - curl -L --silent --show-error --cookie "$_he_cookie" \ - --form "menu=edit_zone" \ - --form "hosted_dns_zoneid=$_zone_id" \ - --form "hosted_dns_recordid=$_record_id" \ - --form "hosted_dns_editzone=1" \ - --form "hosted_dns_delrecord=1" \ - --form "hosted_dns_delconfirm=delete" \ - --form "hosted_dns_editzone=1" \ - "https://dns.he.net/" \ + body="email=${HE_Username}&pass=${HE_Password}" + body="$body&menu=edit_zone" + body="$body&hosted_dns_zoneid=$_zone_id" + body="$body&hosted_dns_recordid=$_record_id" + body="$body&hosted_dns_editzone=1" + body="$body&hosted_dns_delrecord=1" + body="$body&hosted_dns_delconfirm=delete" + body="$body&hosted_dns_editzone=1" + _post $body "https://dns.he.net/" \ | grep '
Successfully removed record.
' \ > /dev/null if [ $? -eq 0 ]; then @@ -98,41 +100,10 @@ dns_he_rm() { ########################## PRIVATE FUNCTIONS ########################### -#-- _find_zone() ------------------------------------------------------- - -# Usage: _authenticate -# -# - needs $HE_Username and $HE_Password -# - sets the $_he_cookie - -_authenticate() { - if [ -z "$HE_Username" ] && [ -z "$HE_Password" ]; then - _err \ - 'No auth details provided. Please set user credentials using the \ - \$HE_Username and \$HE_Password envoronment variables.' - return 1 - fi - # Just get a session - _he_cookie=$( \ - curl -L --silent --show-error -I "https://dns.he.net/" \ - | grep '^Set-Cookie:' \ - | _egrep_o 'CGISESSID=[a-z0-9]*') - # Attempt login - curl -L --silent --show-error --cookie "$_he_cookie" \ - --form "email=${HE_Username}" \ - --form "pass=${HE_Password}" \ - "https://dns.he.net/" \ - > /dev/null - # TODO detect unsuccessful logins -} - - #-- _find_zone() ------------------------------------------------------- # Returns the most specific zone found in administration interface. # -# - needs $_he_cookie -# # Example: # # _find_zone first.second.third.co.uk @@ -155,8 +126,9 @@ _find_zone() { ## _all_zones is an array that looks like this: ## ( zone1:id zone2:id ... ) - _all_zones=( $(curl -L --silent --show-error --cookie "$_he_cookie" \ - "https://dns.he.net/" \ + + body="email=${HE_Username}&pass=${HE_Password}" + _all_zones=( $(_post $body "https://dns.he.net/" \ | _egrep_o "delete_dom.*name=\"[^\"]+\" value=\"[0-9]+" \ | cut -d '"' -f 3,5 --output-delimiter=":" \ ) ) From 8ca45d3d03718c4ba7dc89eb030209ebe2be9ac7 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Sun, 23 Jul 2017 05:13:33 +0200 Subject: [PATCH 71/95] Add HE to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5a3a3adf..7d4353c6 100644 --- a/README.md +++ b/README.md @@ -338,6 +338,7 @@ You don't have to do anything manually! 1. Name.com API 1. Dyn Managed DNS API 1. Yandex PDD API (https://pdd.yandex.ru) +1. Hurricane Electric DNS service (https://dns.he.net) And: From f7299403f7b7c0642fee665a7780ef0d8794681f Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Sun, 23 Jul 2017 07:31:55 +0200 Subject: [PATCH 72/95] Incorporate Neilpang's comments --- dnsapi/dns_he.sh | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 141268ac..019a7a0b 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -20,7 +20,7 @@ dns_he_add() { _txt_value=$2 _info "Using DNS-01 Hurricane Electric hook" - if [ -z "$HE_Username" ] && [ -z "$HE_Password" ]; then + if [ -z "$HE_Username" ] || [ -z "$HE_Password" ]; then _err \ 'No auth details provided. Please set user credentials using the \ \$HE_Username and \$HE_Password envoronment variables.' @@ -46,7 +46,8 @@ dns_he_add() { body="$body&Content=$_txt_value" body="$body&TTL=300" body="$body&hosted_dns_editrecord=Submit" - _post $body "https://dns.he.net/" >/dev/null + response="$(_post $body "https://dns.he.net/")" + _debug2 response "$response" } @@ -68,12 +69,14 @@ dns_he_rm() { body="$body&menu=edit_zone" body="$body&hosted_dns_editzone=" _record_id=$(_post $body "https://dns.he.net/" \ - | grep -A 1 "data=\"\("\)\?${_txt_value}\("\)\?\"" \ - | tail -n 1 \ - | _egrep_o "'[[:digit:]]+','[^']+','TXT'" \ - | cut -b 2- \ - | _egrep_o "[[:digit:]]+" \ - | head -n1) # ... oh my, what have I done... + | tr -d '\n' \ + | _egrep_o "data=\""${_txt_value}"([^>]+>){6}[^<]+<[^;]+;deleteRecord\('[0-9]+','${_full_domain}','TXT'\)" \ + | _egrep_o "[0-9]+','${_full_domain}','TXT'\)$" \ + | _egrep_o "^[0-9]+" + ) + # The series of egreps above could have been done a bit shorter but + # I wanted to double-check whether it's the correct record (in case + # HE changes their website somehow). # Remove the record body="email=${HE_Username}&pass=${HE_Password}" @@ -134,12 +137,12 @@ _find_zone() { ) ) _strip_counter=1 - while [ true ] + while true do _attempted_zone=$(echo $_domain | cut -d . -f ${_strip_counter}-) # All possible zone names have been tried - if [ "$_attempted_zone" == "" ] + if [ -z "$_attempted_zone" ] then _err "No zone for domain \"$_domain\" found." break @@ -151,7 +154,7 @@ _find_zone() { do _zone_name=$(echo $i | cut -d ':' -f 1) _zone_id=$(echo $i | cut -d ':' -f 2) - if [ "$_zone_name" == "$_attempted_zone" ] + if [ "$_zone_name" = "$_attempted_zone" ] then # Zone found - we got $_zone_name and $_zone_id, let's get out... _debug "Found relevant zone \"$_zone_name\" with id" \ @@ -162,7 +165,7 @@ _find_zone() { _debug "Zone \"$_attempted_zone\" doesn't exist, let's try another \ variation." - _strip_counter=$(expr $_strip_counter + 1) + _strip_counter=$(_math $_strip_counter + 1) done # No zone found. From 3281043e2784154345b10aef7b107893ea7ff78b Mon Sep 17 00:00:00 2001 From: Brian Candler Date: Tue, 25 Jul 2017 09:39:15 +0100 Subject: [PATCH 73/95] Clarify keylength parameter to _isEccKey() and _initpath() Closes #950 --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 486f8678..38965ddc 100755 --- a/acme.sh +++ b/acme.sh @@ -926,7 +926,7 @@ _sign() { } -#keylength +#keylength or isEcc flag (empty str => not ecc) _isEccKey() { _length="$1" @@ -2251,7 +2251,7 @@ _initAPI() { _debug "ACME_REVOKE_CERT" "$ACME_REVOKE_CERT" } -#[domain] [keylength] +#[domain] [keylength or isEcc flag] _initpath() { __initHome From 29b21b828b01b37ad9f6536cba27af79a1f6aac3 Mon Sep 17 00:00:00 2001 From: Jeremy Knope Date: Wed, 26 Jul 2017 09:44:11 -0400 Subject: [PATCH 74/95] Fix DNS API scripts on *BSD \n isn't available in all regex/sed --- dnsapi/dns_ad.sh | 3 ++- dnsapi/dns_do.sh | 6 ++++-- dnsapi/dns_freedns.sh | 6 ++++-- dnsapi/dns_linode.sh | 6 ++++-- dnsapi/dns_vscale.sh | 3 ++- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_ad.sh b/dnsapi/dns_ad.sh index fc4a664b..79b8c2ab 100755 --- a/dnsapi/dns_ad.sh +++ b/dnsapi/dns_ad.sh @@ -92,7 +92,8 @@ _get_root() { p=1 if _ad_rest GET "domain/"; then - response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" + response="$(echo "$response" | tr -d "\n" | sed 's/{/\ +&/g')" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh index 3a2f8f49..fb6d7dec 100755 --- a/dnsapi/dns_do.sh +++ b/dnsapi/dns_do.sh @@ -69,9 +69,11 @@ _dns_do_list_rrs() { fi _rr_list="$(echo "${response}" \ | tr -d "\n\r\t" \ - | sed -e 's//\n/g' \ + | sed -e 's//\ +/g' \ | grep ">$(_regexcape "$fulldomain")" \ - | sed -e 's/<\/item>/\n/g' \ + | sed -e 's/<\/item>/\ +/g' \ | grep '>id[0-9]{1,16}<' \ | tr -d '><')" diff --git a/dnsapi/dns_freedns.sh b/dnsapi/dns_freedns.sh index 53da4118..d9677632 100755 --- a/dnsapi/dns_freedns.sh +++ b/dnsapi/dns_freedns.sh @@ -77,7 +77,8 @@ dns_freedns_add() { | grep -i -e ']*>/\n/Ig' \ + | sed 's/<\/TR[^>]*>/\ +/Ig' \ | sed 's/<\/\?\(TABLE\|TR\)[^>]*>//Ig' \ | sed 's/^]*>\|<\/\?T[DH][^>]*>$//Ig' \ | sed 's/<\/T[DH][^>]*>]*>/,/Ig' \ @@ -216,7 +217,8 @@ dns_freedns_rm() { | grep -i -e ']*>/\n/Ig' \ + | sed 's/<\/TR[^>]*>/\ +/Ig' \ | sed 's/<\/\?\(TABLE\|TR\)[^>]*>//Ig' \ | sed 's/^]*>\|<\/\?T[DH][^>]*>$//Ig' \ | sed 's/<\/T[DH][^>]*>]*>/,/Ig' \ diff --git a/dnsapi/dns_linode.sh b/dnsapi/dns_linode.sh index 6d54e6c1..d84ad5fb 100755 --- a/dnsapi/dns_linode.sh +++ b/dnsapi/dns_linode.sh @@ -68,7 +68,8 @@ dns_linode_rm() { _parameters="&DomainID=$_domain_id" if _rest GET "domain.resource.list" "$_parameters" && [ -n "$response" ]; then - response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" + response="$(echo "$response" | tr -d "\n" | sed 's/{/\ +&/g')" resource="$(echo "$response" | _egrep_o "{.*\"NAME\":\s*\"$_sub_domain\".*}")" if [ "$resource" ]; then @@ -128,7 +129,8 @@ _get_root() { p=1 if _rest GET "domain.list"; then - response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" + response="$(echo "$response" | tr -d "\n" | sed 's/{/\ +&/g')" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" diff --git a/dnsapi/dns_vscale.sh b/dnsapi/dns_vscale.sh index e50b7d8b..fcd162c9 100755 --- a/dnsapi/dns_vscale.sh +++ b/dnsapi/dns_vscale.sh @@ -93,7 +93,8 @@ _get_root() { p=1 if _vscale_rest GET "domains/"; then - response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" + response="$(echo "$response" | tr -d "\n" | sed 's/{/\ +&/g')" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" From ff74778dea38ef22fb13fbdf452991c4a70135a1 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Wed, 26 Jul 2017 20:15:34 +0200 Subject: [PATCH 75/95] Fix few issues from Travis --- dnsapi/dns_he.sh | 45 ++++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 019a7a0b..1a6f8dbc 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -21,16 +21,14 @@ dns_he_add() { _info "Using DNS-01 Hurricane Electric hook" if [ -z "$HE_Username" ] || [ -z "$HE_Password" ]; then - _err \ - 'No auth details provided. Please set user credentials using the \ - \$HE_Username and \$HE_Password envoronment variables.' + _err "No auth details provided. Please set user credentials using the \$HE_Username and \$HE_Password envoronment variables." return 1 fi _saveaccountconf HE_Username "$HE_Username" _saveaccountconf HE_Password "$HE_Password" # fills in the $_zone_id - _find_zone $_full_domain || return 1 + _find_zone "$_full_domain" || return 1 _debug "Zone id \"$_zone_id\" will be used." body="email=${HE_Username}&pass=${HE_Password}" @@ -46,11 +44,10 @@ dns_he_add() { body="$body&Content=$_txt_value" body="$body&TTL=300" body="$body&hosted_dns_editrecord=Submit" - response="$(_post $body "https://dns.he.net/")" + response="$(_post "$body" "https://dns.he.net/")" _debug2 response "$response" } - #-- dns_he_rm() - Remove TXT record ------------------------------------ # Usage: dns_he_rm _acme-challenge.subdomain.domain.com "XyZ123..." @@ -60,7 +57,7 @@ dns_he_rm() { _info "Cleaning up after DNS-01 Hurricane Electric hook" # fills in the $_zone_id - _find_zone $_full_domain || return 1 + _find_zone "$_full_domain" || return 1 _debug "Zone id \"$_zone_id\" will be used." # Find the record id to clean @@ -68,7 +65,7 @@ dns_he_rm() { body="$body&hosted_dns_zoneid=$_zone_id" body="$body&menu=edit_zone" body="$body&hosted_dns_editzone=" - _record_id=$(_post $body "https://dns.he.net/" \ + _record_id=$(_post "$body" "https://dns.he.net/" \ | tr -d '\n' \ | _egrep_o "data=\""${_txt_value}"([^>]+>){6}[^<]+<[^;]+;deleteRecord\('[0-9]+','${_full_domain}','TXT'\)" \ | _egrep_o "[0-9]+','${_full_domain}','TXT'\)$" \ @@ -87,9 +84,9 @@ dns_he_rm() { body="$body&hosted_dns_delrecord=1" body="$body&hosted_dns_delconfirm=delete" body="$body&hosted_dns_editzone=1" - _post $body "https://dns.he.net/" \ + _post "$body" "https://dns.he.net/" \ | grep '
Successfully removed record.
' \ - > /dev/null + >/dev/null if [ $? -eq 0 ]; then _info "Record removed successfuly." else @@ -99,12 +96,9 @@ dns_he_rm() { fi } - ########################## PRIVATE FUNCTIONS ########################### - #-- _find_zone() ------------------------------------------------------- - # Returns the most specific zone found in administration interface. # # Example: @@ -131,31 +125,28 @@ _find_zone() { ## ( zone1:id zone2:id ... ) body="email=${HE_Username}&pass=${HE_Password}" - _all_zones=( $(_post $body "https://dns.he.net/" \ + # TODO arrays aren't supported in POSIX sh + _all_zones=($(_post $body "https://dns.he.net/" \ | _egrep_o "delete_dom.*name=\"[^\"]+\" value=\"[0-9]+" \ - | cut -d '"' -f 3,5 --output-delimiter=":" \ - ) ) + | cut -d '"' -f 3,5 --output-delimiter=":" + )) _strip_counter=1 - while true - do - _attempted_zone=$(echo $_domain | cut -d . -f ${_strip_counter}-) + while true; do + _attempted_zone=$(echo "$_domain" | cut -d . -f ${_strip_counter}-) # All possible zone names have been tried - if [ -z "$_attempted_zone" ] - then + if [ -z "$_attempted_zone" ]; then _err "No zone for domain \"$_domain\" found." break fi # Walk through all zones on the account #echo "$_all_zones" | while IFS=' ' read _zone_name _zone_id - for i in ${_all_zones[@]} - do - _zone_name=$(echo $i | cut -d ':' -f 1) - _zone_id=$(echo $i | cut -d ':' -f 2) - if [ "$_zone_name" = "$_attempted_zone" ] - then + for i in ${_all_zones[@]}; do + _zone_name=$(echo "$i" | cut -d ':' -f 1) + _zone_id=$(echo "$i" | cut -d ':' -f 2) + if [ "$_zone_name" = "$_attempted_zone" ]; then # Zone found - we got $_zone_name and $_zone_id, let's get out... _debug "Found relevant zone \"$_zone_name\" with id" \ "\"$_zone_id\" - will be used for domain \"$_domain\"." From 1546b7e5a971578cef11f960a44aadad3a45b754 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Wed, 26 Jul 2017 20:21:36 +0200 Subject: [PATCH 76/95] Missing quotes --- dnsapi/dns_he.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 1a6f8dbc..3e23b2e0 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -126,7 +126,7 @@ _find_zone() { body="email=${HE_Username}&pass=${HE_Password}" # TODO arrays aren't supported in POSIX sh - _all_zones=($(_post $body "https://dns.he.net/" \ + _all_zones=($(_post "$body" "https://dns.he.net/" \ | _egrep_o "delete_dom.*name=\"[^\"]+\" value=\"[0-9]+" \ | cut -d '"' -f 3,5 --output-delimiter=":" )) From d39649f30d6718d7b0ec7e1e746a518b23bfd9be Mon Sep 17 00:00:00 2001 From: Jeremy Knope Date: Thu, 27 Jul 2017 08:52:46 -0400 Subject: [PATCH 77/95] Revert non-linode scripts since they're untested --- dnsapi/dns_ad.sh | 3 +-- dnsapi/dns_do.sh | 6 ++---- dnsapi/dns_freedns.sh | 6 ++---- dnsapi/dns_vscale.sh | 3 +-- 4 files changed, 6 insertions(+), 12 deletions(-) diff --git a/dnsapi/dns_ad.sh b/dnsapi/dns_ad.sh index 79b8c2ab..fc4a664b 100755 --- a/dnsapi/dns_ad.sh +++ b/dnsapi/dns_ad.sh @@ -92,8 +92,7 @@ _get_root() { p=1 if _ad_rest GET "domain/"; then - response="$(echo "$response" | tr -d "\n" | sed 's/{/\ -&/g')" + response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" diff --git a/dnsapi/dns_do.sh b/dnsapi/dns_do.sh index fb6d7dec..3a2f8f49 100755 --- a/dnsapi/dns_do.sh +++ b/dnsapi/dns_do.sh @@ -69,11 +69,9 @@ _dns_do_list_rrs() { fi _rr_list="$(echo "${response}" \ | tr -d "\n\r\t" \ - | sed -e 's//\ -/g' \ + | sed -e 's//\n/g' \ | grep ">$(_regexcape "$fulldomain")" \ - | sed -e 's/<\/item>/\ -/g' \ + | sed -e 's/<\/item>/\n/g' \ | grep '>id[0-9]{1,16}<' \ | tr -d '><')" diff --git a/dnsapi/dns_freedns.sh b/dnsapi/dns_freedns.sh index d9677632..53da4118 100755 --- a/dnsapi/dns_freedns.sh +++ b/dnsapi/dns_freedns.sh @@ -77,8 +77,7 @@ dns_freedns_add() { | grep -i -e ']*>/\ -/Ig' \ + | sed 's/<\/TR[^>]*>/\n/Ig' \ | sed 's/<\/\?\(TABLE\|TR\)[^>]*>//Ig' \ | sed 's/^]*>\|<\/\?T[DH][^>]*>$//Ig' \ | sed 's/<\/T[DH][^>]*>]*>/,/Ig' \ @@ -217,8 +216,7 @@ dns_freedns_rm() { | grep -i -e ']*>/\ -/Ig' \ + | sed 's/<\/TR[^>]*>/\n/Ig' \ | sed 's/<\/\?\(TABLE\|TR\)[^>]*>//Ig' \ | sed 's/^]*>\|<\/\?T[DH][^>]*>$//Ig' \ | sed 's/<\/T[DH][^>]*>]*>/,/Ig' \ diff --git a/dnsapi/dns_vscale.sh b/dnsapi/dns_vscale.sh index fcd162c9..e50b7d8b 100755 --- a/dnsapi/dns_vscale.sh +++ b/dnsapi/dns_vscale.sh @@ -93,8 +93,7 @@ _get_root() { p=1 if _vscale_rest GET "domains/"; then - response="$(echo "$response" | tr -d "\n" | sed 's/{/\ -&/g')" + response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" From aefed1d1b9a5264f460aa94e119cb8a40f8bdddd Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Thu, 27 Jul 2017 18:04:53 +0200 Subject: [PATCH 78/95] Get rid of shell arrays. --- dnsapi/dns_he.sh | 69 +++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 24 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 3e23b2e0..ada5f794 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -121,16 +121,19 @@ _find_zone() { _domain="$1" - ## _all_zones is an array that looks like this: - ## ( zone1:id zone2:id ... ) - body="email=${HE_Username}&pass=${HE_Password}" - # TODO arrays aren't supported in POSIX sh - _all_zones=($(_post "$body" "https://dns.he.net/" \ - | _egrep_o "delete_dom.*name=\"[^\"]+\" value=\"[0-9]+" \ - | cut -d '"' -f 3,5 --output-delimiter=":" - )) + _matches=$(_post "$body" "https://dns.he.net/" \ + | _egrep_o "delete_dom.*name=\"[^\"]+\" value=\"[0-9]+" + ) + # Zone names and zone IDs are in same order + _zone_ids=$(echo "$_matches" | cut -d '"' -f 5 --output-delimiter=":") + _zone_names=$(echo "$_matches" | cut -d '"' -f 3 --output-delimiter=":") + _debug2 "These are the zones on this HE account:" + _debug2 "$_zone_names" + _debug2 "And these are their respective IDs:" + _debug2 "$_zone_ids" + # Walk through all possible zone names _strip_counter=1 while true; do _attempted_zone=$(echo "$_domain" | cut -d . -f ${_strip_counter}-) @@ -138,28 +141,46 @@ _find_zone() { # All possible zone names have been tried if [ -z "$_attempted_zone" ]; then _err "No zone for domain \"$_domain\" found." - break + return 1 fi - # Walk through all zones on the account - #echo "$_all_zones" | while IFS=' ' read _zone_name _zone_id - for i in ${_all_zones[@]}; do - _zone_name=$(echo "$i" | cut -d ':' -f 1) - _zone_id=$(echo "$i" | cut -d ':' -f 2) - if [ "$_zone_name" = "$_attempted_zone" ]; then - # Zone found - we got $_zone_name and $_zone_id, let's get out... - _debug "Found relevant zone \"$_zone_name\" with id" \ - "\"$_zone_id\" - will be used for domain \"$_domain\"." - return 0 - fi - done + _debug "Looking for zone \"${_attempted_zone}\"" + _line_num=$(echo "$_zone_names" | _find_linenum "$_attempted_zone") + if [ -n "$_line_num" ]; then + _zone_id=$(echo "$_zone_ids" | sed "${_line_num}q;d") + _debug "Found relevant zone \"$_attempted_zone\" with id" \ + "\"$_zone_id\" - will be used for domain \"$_domain\"." + return 0 + fi - _debug "Zone \"$_attempted_zone\" doesn't exist, let's try another \ - variation." + _debug "Zone \"$_attempted_zone\" doesn't exist, let's try a less" \ + "specific zone." _strip_counter=$(_math $_strip_counter + 1) done +} - # No zone found. +#-- _find_linenum()----------------------------------------------------- +# Returns line number of line (supplied as an argument) in STDIN. +# +# Example: +# +# printf "a\nb\nc" | _find_linenum "b" +# +# This will: +# - print out 2 because that's the line number of "b" +# - return code 0 because it was found + +_find_linenum() { + _current_line_num=0 + while read line; do + _current_line_num=$(expr "$_current_line_num" + 1) + if [ "$line" = "$1" ]; then + # Found! Let's echo the line number and quit + echo $_current_line_num + return 0 + fi + done + # Not found return 1 } From 235b5b0c154331879b70fd149d1fe7df19eac4c8 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Thu, 27 Jul 2017 18:06:19 +0200 Subject: [PATCH 79/95] Small cosmetic fixes. --- dnsapi/dns_he.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index ada5f794..51418aa9 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -11,7 +11,6 @@ # Author: Ondrej Simek # Git repo: https://github.com/angel333/acme.sh - #-- dns_he_add() - Add TXT record -------------------------------------- # Usage: dns_he_add _acme-challenge.subdomain.domain.com "XyZ123..." @@ -86,7 +85,7 @@ dns_he_rm() { body="$body&hosted_dns_editzone=1" _post "$body" "https://dns.he.net/" \ | grep '
Successfully removed record.
' \ - >/dev/null + >/dev/null if [ $? -eq 0 ]; then _info "Record removed successfuly." else From 577380e98e33c32f87d74df07d0d9d862b89b5be Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Thu, 27 Jul 2017 18:44:55 +0200 Subject: [PATCH 80/95] Few fixes for shellcheck --- dnsapi/dns_he.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 51418aa9..9b789d35 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -154,7 +154,7 @@ _find_zone() { _debug "Zone \"$_attempted_zone\" doesn't exist, let's try a less" \ "specific zone." - _strip_counter=$(_math $_strip_counter + 1) + _strip_counter=$(_math "$_strip_counter" + 1) done } @@ -171,11 +171,11 @@ _find_zone() { _find_linenum() { _current_line_num=0 - while read line; do - _current_line_num=$(expr "$_current_line_num" + 1) + while read -r line; do + _current_line_num=$(_math "$_current_line_num" + 1) if [ "$line" = "$1" ]; then # Found! Let's echo the line number and quit - echo $_current_line_num + echo "$_current_line_num" return 0 fi done From 8e6cf669ad01905d4d9e22f7a2874dcba8c7e263 Mon Sep 17 00:00:00 2001 From: Jeremy Knope Date: Thu, 27 Jul 2017 14:15:19 -0400 Subject: [PATCH 81/95] Try awk instead for \n replacements --- dnsapi/dns_linode.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_linode.sh b/dnsapi/dns_linode.sh index d84ad5fb..ee3b1c8b 100755 --- a/dnsapi/dns_linode.sh +++ b/dnsapi/dns_linode.sh @@ -68,8 +68,7 @@ dns_linode_rm() { _parameters="&DomainID=$_domain_id" if _rest GET "domain.resource.list" "$_parameters" && [ -n "$response" ]; then - response="$(echo "$response" | tr -d "\n" | sed 's/{/\ -&/g')" + response="$(echo "$response" | tr -d "\n" | awk '{ gsub("{","\n{",$1); print $1 }')" resource="$(echo "$response" | _egrep_o "{.*\"NAME\":\s*\"$_sub_domain\".*}")" if [ "$resource" ]; then @@ -129,8 +128,7 @@ _get_root() { p=1 if _rest GET "domain.list"; then - response="$(echo "$response" | tr -d "\n" | sed 's/{/\ -&/g')" + response="$(echo "$response" | tr -d "\n" | awk '{ gsub("{","\n{",$1); print $1 }')" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" From 8534e3b2f7fd16477b811c262f60e9b63cb85e32 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Fri, 28 Jul 2017 13:58:47 +0200 Subject: [PATCH 82/95] Make shellcheck happier --- dnsapi/dns_he.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 9b789d35..3ca00af9 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -20,6 +20,8 @@ dns_he_add() { _info "Using DNS-01 Hurricane Electric hook" if [ -z "$HE_Username" ] || [ -z "$HE_Password" ]; then + HE_Username= + HE_Password= _err "No auth details provided. Please set user credentials using the \$HE_Username and \$HE_Password envoronment variables." return 1 fi From d6780f9e49f18bf503f46c5d4859289e593935c0 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Fri, 28 Jul 2017 15:29:35 +0200 Subject: [PATCH 83/95] Retain an exit code --- dnsapi/dns_he.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 3ca00af9..ab4393c7 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -46,7 +46,9 @@ dns_he_add() { body="$body&TTL=300" body="$body&hosted_dns_editrecord=Submit" response="$(_post "$body" "https://dns.he.net/")" + exitcode=$? _debug2 response "$response" + return $exitvalue } #-- dns_he_rm() - Remove TXT record ------------------------------------ From ab1efd923b56b9014f07e7fcac7a81325d93d0b8 Mon Sep 17 00:00:00 2001 From: Jeremy Knope Date: Fri, 28 Jul 2017 10:26:56 -0400 Subject: [PATCH 84/95] back to sed --- dnsapi/dns_linode.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_linode.sh b/dnsapi/dns_linode.sh index ee3b1c8b..00634d5d 100755 --- a/dnsapi/dns_linode.sh +++ b/dnsapi/dns_linode.sh @@ -68,7 +68,7 @@ dns_linode_rm() { _parameters="&DomainID=$_domain_id" if _rest GET "domain.resource.list" "$_parameters" && [ -n "$response" ]; then - response="$(echo "$response" | tr -d "\n" | awk '{ gsub("{","\n{",$1); print $1 }')" + response="$(echo "$response" | tr -d "\n" | sed $'s/{/\\\n&/g')" resource="$(echo "$response" | _egrep_o "{.*\"NAME\":\s*\"$_sub_domain\".*}")" if [ "$resource" ]; then @@ -128,7 +128,7 @@ _get_root() { p=1 if _rest GET "domain.list"; then - response="$(echo "$response" | tr -d "\n" | awk '{ gsub("{","\n{",$1); print $1 }')" + response="$(echo "$response" | tr -d "\n" | sed $'s/{/\\\n&/g')" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" From ccf9a9976c1b7cf31c60a4b74ead0f30fba1de28 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Fri, 28 Jul 2017 18:33:25 +0200 Subject: [PATCH 85/95] Fix the previous rushed commit. --- dnsapi/dns_he.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index ab4393c7..2fb1101e 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -46,9 +46,14 @@ dns_he_add() { body="$body&TTL=300" body="$body&hosted_dns_editrecord=Submit" response="$(_post "$body" "https://dns.he.net/")" - exitcode=$? + exit_code="$?" + if [ "$exit_code" -eq 0 ]; then + _info "TXT record added successfuly." + else + _err "Couldn't add the TXT record." + return "$exit_code" + fi _debug2 response "$response" - return $exitvalue } #-- dns_he_rm() - Remove TXT record ------------------------------------ @@ -90,7 +95,7 @@ dns_he_rm() { _post "$body" "https://dns.he.net/" \ | grep '
Successfully removed record.
' \ >/dev/null - if [ $? -eq 0 ]; then + if [ "$?" -eq 0 ]; then _info "Record removed successfuly." else _err \ From a5c56c547d024493bb90732cda20108d09392715 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 29 Jul 2017 15:23:31 +0800 Subject: [PATCH 86/95] minor, fix dns param --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 38965ddc..9486bcc5 100755 --- a/acme.sh +++ b/acme.sh @@ -5440,7 +5440,7 @@ _process() { ;; --dns) wvalue="dns" - if ! _startswith "$2" "-"; then + if [ "$2" ] && ! _startswith "$2" "-"; then wvalue="$2" shift fi From 31b67ab92efd23802acb8510126418b83e1af8db Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Sat, 29 Jul 2017 13:52:28 +0200 Subject: [PATCH 87/95] Few non-critical fixes. --- dnsapi/dns_he.sh | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 2fb1101e..a160e16a 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -28,13 +28,12 @@ dns_he_add() { _saveaccountconf HE_Username "$HE_Username" _saveaccountconf HE_Password "$HE_Password" - # fills in the $_zone_id + # Fills in the $_zone_id _find_zone "$_full_domain" || return 1 _debug "Zone id \"$_zone_id\" will be used." body="email=${HE_Username}&pass=${HE_Password}" body="$body&account=" - body="$body&account=" body="$body&menu=edit_zone" body="$body&Type=TXT" body="$body&hosted_dns_zoneid=$_zone_id" @@ -91,16 +90,13 @@ dns_he_rm() { body="$body&hosted_dns_editzone=1" body="$body&hosted_dns_delrecord=1" body="$body&hosted_dns_delconfirm=delete" - body="$body&hosted_dns_editzone=1" _post "$body" "https://dns.he.net/" \ | grep '
Successfully removed record.
' \ >/dev/null if [ "$?" -eq 0 ]; then _info "Record removed successfuly." else - _err \ - "Could not clean (remove) up the record. Please go to HE" \ - "administration interface and clean it by hand." + _err "Could not clean (remove) up the record. Please go to HE administration interface and clean it by hand." fi } @@ -134,8 +130,8 @@ _find_zone() { | _egrep_o "delete_dom.*name=\"[^\"]+\" value=\"[0-9]+" ) # Zone names and zone IDs are in same order - _zone_ids=$(echo "$_matches" | cut -d '"' -f 5 --output-delimiter=":") - _zone_names=$(echo "$_matches" | cut -d '"' -f 3 --output-delimiter=":") + _zone_ids=$(echo "$_matches" | cut -d '"' -f 5) + _zone_names=$(echo "$_matches" | cut -d '"' -f 3) _debug2 "These are the zones on this HE account:" _debug2 "$_zone_names" _debug2 "And these are their respective IDs:" @@ -156,13 +152,11 @@ _find_zone() { _line_num=$(echo "$_zone_names" | _find_linenum "$_attempted_zone") if [ -n "$_line_num" ]; then _zone_id=$(echo "$_zone_ids" | sed "${_line_num}q;d") - _debug "Found relevant zone \"$_attempted_zone\" with id" \ - "\"$_zone_id\" - will be used for domain \"$_domain\"." + _debug "Found relevant zone \"$_attempted_zone\" with id \"$_zone_id\" - will be used for domain \"$_domain\"." return 0 fi - _debug "Zone \"$_attempted_zone\" doesn't exist, let's try a less" \ - "specific zone." + _debug "Zone \"$_attempted_zone\" doesn't exist, let's try a less specific zone." _strip_counter=$(_math "$_strip_counter" + 1) done } From a25b2af66cd6a4c69ee673ec32aaebd068079042 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Sat, 29 Jul 2017 14:25:07 +0200 Subject: [PATCH 88/95] Get rid of _find_num --- dnsapi/dns_he.sh | 41 ++++++++++++----------------------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index a160e16a..7dde55d4 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -149,9 +149,18 @@ _find_zone() { fi _debug "Looking for zone \"${_attempted_zone}\"" - _line_num=$(echo "$_zone_names" | _find_linenum "$_attempted_zone") - if [ -n "$_line_num" ]; then - _zone_id=$(echo "$_zone_ids" | sed "${_line_num}q;d") + + # Take care of "." and only match whole lines. Note that grep -F + # cannot be used because there's no way to make it match whole + # lines. + regex="^$(echo "$_attempted_zone" | sed 's/\./\\./g')$" + line_num=$(echo "$_zone_names" \ + | grep -n "$regex" \ + | cut -d : -f 1 + ) + + if [ -n "$line_num" ]; then + _zone_id=$(echo "$_zone_ids" | sed "${line_num}q;d") _debug "Found relevant zone \"$_attempted_zone\" with id \"$_zone_id\" - will be used for domain \"$_domain\"." return 0 fi @@ -160,30 +169,4 @@ _find_zone() { _strip_counter=$(_math "$_strip_counter" + 1) done } - -#-- _find_linenum()----------------------------------------------------- -# Returns line number of line (supplied as an argument) in STDIN. -# -# Example: -# -# printf "a\nb\nc" | _find_linenum "b" -# -# This will: -# - print out 2 because that's the line number of "b" -# - return code 0 because it was found - -_find_linenum() { - _current_line_num=0 - while read -r line; do - _current_line_num=$(_math "$_current_line_num" + 1) - if [ "$line" = "$1" ]; then - # Found! Let's echo the line number and quit - echo "$_current_line_num" - return 0 - fi - done - # Not found - return 1 -} - # vim: et:ts=2:sw=2: From f438ff4bab695818932149d5b6bcecb1b6bed712 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Sat, 29 Jul 2017 14:29:13 +0200 Subject: [PATCH 89/95] Fix an improbable corner case. --- dnsapi/dns_he.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 7dde55d4..152d469c 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -72,10 +72,11 @@ dns_he_rm() { body="$body&hosted_dns_zoneid=$_zone_id" body="$body&menu=edit_zone" body="$body&hosted_dns_editzone=" + domain_regex="$(echo "$_full_domain" | sed 's/\./\\./g')" # escape dots _record_id=$(_post "$body" "https://dns.he.net/" \ | tr -d '\n' \ - | _egrep_o "data=\""${_txt_value}"([^>]+>){6}[^<]+<[^;]+;deleteRecord\('[0-9]+','${_full_domain}','TXT'\)" \ - | _egrep_o "[0-9]+','${_full_domain}','TXT'\)$" \ + | _egrep_o "data=\""${_txt_value}"([^>]+>){6}[^<]+<[^;]+;deleteRecord\('[0-9]+','${domain_regex}','TXT'\)" \ + | _egrep_o "[0-9]+','${domain_regex}','TXT'\)$" \ | _egrep_o "^[0-9]+" ) # The series of egreps above could have been done a bit shorter but From baa1160594921e465ee798b77c5add4ed6b1d907 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Sat, 29 Jul 2017 14:31:27 +0200 Subject: [PATCH 90/95] Make Shellcheck happier about exit codes --- dnsapi/dns_he.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 152d469c..3a1e6979 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -94,10 +94,12 @@ dns_he_rm() { _post "$body" "https://dns.he.net/" \ | grep '
Successfully removed record.
' \ >/dev/null - if [ "$?" -eq 0 ]; then + exit_code="$?" + if [ "$exit_code" -eq 0 ]; then _info "Record removed successfuly." else _err "Could not clean (remove) up the record. Please go to HE administration interface and clean it by hand." + return "$exit_code" fi } From 4dd69a8b1adaacfbb5a4894a8a5fc0403e3b4e88 Mon Sep 17 00:00:00 2001 From: Ondrej Simek Date: Sat, 29 Jul 2017 14:40:56 +0200 Subject: [PATCH 91/95] Exit codes, exit codes... Exit codes everywhere... --- dnsapi/dns_he.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_he.sh b/dnsapi/dns_he.sh index 3a1e6979..7d86eb7a 100755 --- a/dnsapi/dns_he.sh +++ b/dnsapi/dns_he.sh @@ -50,9 +50,9 @@ dns_he_add() { _info "TXT record added successfuly." else _err "Couldn't add the TXT record." - return "$exit_code" fi _debug2 response "$response" + return "$exit_code" } #-- dns_he_rm() - Remove TXT record ------------------------------------ From 8eab77f3c607075ff1cd59b59f76b074f1d46605 Mon Sep 17 00:00:00 2001 From: Brian Candler Date: Mon, 24 Jul 2017 14:23:01 +0100 Subject: [PATCH 92/95] Add deployment script for unifi controller --- acme.sh | 28 +++++++++++--- deploy/unifi.sh | 100 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 deploy/unifi.sh diff --git a/acme.sh b/acme.sh index 9486bcc5..60eef4bb 100755 --- a/acme.sh +++ b/acme.sh @@ -1182,6 +1182,28 @@ _ss() { return 1 } +#outfile key cert cacert [password [name [caname]]] +_toPkcs() { + _cpfx="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + pfxPassword="$5" + pfxName="$6" + pfxCaname="$7" + + if [ "$pfxCaname" ]; then + ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:$pfxPassword" -name "$pfxName" -caname "$pfxCaname" + elif [ "$pfxName" ]; then + ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:$pfxPassword" -name "$pfxName" + elif [ "$pfxPassword" ]; then + ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:$pfxPassword" + else + ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" + fi + +} + #domain [password] [isEcc] toPkcs() { domain="$1" @@ -1195,11 +1217,7 @@ toPkcs() { _initpath "$domain" "$_isEcc" - if [ "$pfxPassword" ]; then - ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" -password "pass:$pfxPassword" - else - ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" - fi + _toPkcs "$CERT_PFX_PATH" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$pfxPassword" if [ "$?" = "0" ]; then _info "Success, Pfx is exported to: $CERT_PFX_PATH" diff --git a/deploy/unifi.sh b/deploy/unifi.sh new file mode 100644 index 00000000..184aa62e --- /dev/null +++ b/deploy/unifi.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env sh + +#Here is a script to deploy cert to unifi server. + +#returns 0 means success, otherwise error. + +#DEPLOY_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" +#DEPLOY_UNIFI_KEYPASS="aircontrolenterprise" +#DEPLOY_UNIFI_RELOAD="service unifi restart" + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +unifi_deploy() { + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + if ! _exists keytool; then + _err "keytool not found" + return 1 + fi + + DEFAULT_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" + _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-$DEFAULT_UNIFI_KEYSTORE}" + DEFAULT_UNIFI_KEYPASS="aircontrolenterprise" + _unifi_keypass="${DEPLOY_UNIFI_KEYPASS:-$DEFAULT_UNIFI_KEYPASS}" + DEFAULT_UNIFI_RELOAD="service unifi restart" + _reload="${DEPLOY_UNIFI_RELOAD:-$DEFAULT_UNIFI_RELOAD}" + + _debug _unifi_keystore "$_unifi_keystore" + if [ ! -f "$_unifi_keystore" ]; then + if [ -z "$DEPLOY_UNIFI_KEYSTORE" ]; then + _err "unifi keystore is not found, please define DEPLOY_UNIFI_KEYSTORE" + return 1 + else + _err "It seems that the specified unifi keystore is not valid, please check." + return 1 + fi + fi + if [ ! -w "$_unifi_keystore" ]; then + _err "The file $_unifi_keystore is not writable, please change the permission." + return 1 + fi + + _info "Generate import pkcs12" + _import_pkcs12="$(_mktemp)" + _toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root + if [ "$?" != "0" ]; then + _err "Oops, error creating import pkcs12, please report bug to us." + return 1 + fi + + _info "Modify unifi keystore: $_unifi_keystore" + if keytool -importkeystore \ + -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ + -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \ + -alias unifi -noprompt; then + _info "Import keystore success!" + rm "$_import_pkcs12" + else + _err "Import unifi keystore error, please report bug to us." + rm "$_import_pkcs12" + return 1 + fi + + _info "Run reload: $_reload" + if eval "$_reload"; then + _info "Reload success!" + if [ "$DEPLOY_UNIFI_KEYSTORE" ]; then + _savedomainconf DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" + else + _cleardomainconf DEPLOY_UNIFI_KEYSTORE + fi + if [ "$DEPLOY_UNIFI_KEYPASS" ]; then + _savedomainconf DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" + else + _cleardomainconf DEPLOY_UNIFI_KEYPASS + fi + if [ "$DEPLOY_UNIFI_RELOAD" ]; then + _savedomainconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" + else + _cleardomainconf DEPLOY_UNIFI_RELOAD + fi + return 0 + else + _err "Reload error" + return 1 + fi + return 0 + +} From cd3a4573f26c03315121f505ac97b45c511d9cb9 Mon Sep 17 00:00:00 2001 From: Jeremy Knope Date: Mon, 31 Jul 2017 08:37:30 -0400 Subject: [PATCH 93/95] Fix shell check errors --- dnsapi/dns_linode.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_linode.sh b/dnsapi/dns_linode.sh index 00634d5d..26ca53e4 100755 --- a/dnsapi/dns_linode.sh +++ b/dnsapi/dns_linode.sh @@ -68,7 +68,7 @@ dns_linode_rm() { _parameters="&DomainID=$_domain_id" if _rest GET "domain.resource.list" "$_parameters" && [ -n "$response" ]; then - response="$(echo "$response" | tr -d "\n" | sed $'s/{/\\\n&/g')" + response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")" resource="$(echo "$response" | _egrep_o "{.*\"NAME\":\s*\"$_sub_domain\".*}")" if [ "$resource" ]; then @@ -128,7 +128,7 @@ _get_root() { p=1 if _rest GET "domain.list"; then - response="$(echo "$response" | tr -d "\n" | sed $'s/{/\\\n&/g')" + response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" From c145f24621455f8608c179fc253d1fd00244bb6f Mon Sep 17 00:00:00 2001 From: Jeremy Knope Date: Thu, 3 Aug 2017 09:47:45 -0400 Subject: [PATCH 94/95] Remove extra space --- dnsapi/dns_linode.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_linode.sh b/dnsapi/dns_linode.sh index 26ca53e4..ead5b164 100755 --- a/dnsapi/dns_linode.sh +++ b/dnsapi/dns_linode.sh @@ -68,7 +68,7 @@ dns_linode_rm() { _parameters="&DomainID=$_domain_id" if _rest GET "domain.resource.list" "$_parameters" && [ -n "$response" ]; then - response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")" + response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")" resource="$(echo "$response" | _egrep_o "{.*\"NAME\":\s*\"$_sub_domain\".*}")" if [ "$resource" ]; then @@ -128,7 +128,7 @@ _get_root() { p=1 if _rest GET "domain.list"; then - response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")" + response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")" while true; do h=$(printf "%s" "$domain" | cut -d . -f $i-100) _debug h "$h" From 5c3b41bd93c2c4e6da40c445cd5f15a1ba3f7274 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 4 Aug 2017 21:57:45 +0800 Subject: [PATCH 95/95] format --- dnsapi/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/README.md b/dnsapi/README.md index 0888517b..b3b6344e 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -585,7 +585,7 @@ acme.sh --issue --dns dns_yandex -d mydomain.example.org For issues, please report to https://github.com/non7top/acme.sh/issues. -# 31. Use Hurricane Electric +## 31. Use Hurricane Electric Hurricane Electric doesn't have an API so just set your login credentials like so: