From e36fbd6af5c56b4672077694e7db9adebcb49d25 Mon Sep 17 00:00:00 2001 From: Grant Millar Date: Fri, 20 Apr 2018 09:41:07 +0100 Subject: [PATCH 01/61] Fix DNSimple when zone has > 100 records The _get_records function currently returns the first 100 records. As our TXT is added most recently, if you have > 100 records it will not be returned. I've changed the function to sort by ID DESC, so it will always return the latest 100 records. --- dnsapi/dns_dnsimple.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_dnsimple.sh b/dnsapi/dns_dnsimple.sh index 0dd3918a..b2cba584 100644 --- a/dnsapi/dns_dnsimple.sh +++ b/dnsapi/dns_dnsimple.sh @@ -152,7 +152,7 @@ _get_records() { sub_domain=$3 _debug "fetching txt records" - _dnsimple_rest GET "$account_id/zones/$domain/records?per_page=100" + _dnsimple_rest GET "$account_id/zones/$domain/records?per_page=100&sort=id:desc" if ! _contains "$response" "\"id\":"; then _err "failed to retrieve records" From 5b7cac100220f4d6354d400d655c2e87d9023999 Mon Sep 17 00:00:00 2001 From: Tom Blauwendraat Date: Wed, 12 Sep 2018 05:34:56 +0200 Subject: [PATCH 02/61] [FIX] Delete all occurrences of TXT key, dont fail if there is more than one, [FIX] Respect pagination on domain listing, before only the first page was loaded --- dnsapi/dns_dgon.sh | 159 ++++++++++++++++++++++++++------------------- 1 file changed, 92 insertions(+), 67 deletions(-) diff --git a/dnsapi/dns_dgon.sh b/dnsapi/dns_dgon.sh index 5d38ef76..e92c7809 100755 --- a/dnsapi/dns_dgon.sh +++ b/dnsapi/dns_dgon.sh @@ -104,48 +104,60 @@ dns_dgon_rm() { ## may get: "links":{"pages":{"last":".../v2/domains/DOM/records?page=2","next":".../v2/domains/DOM/records?page=2"}} GURL="https://api.digitalocean.com/v2/domains/$_domain/records" - ## while we dont have a record ID we keep going - while [ -z "$record" ]; do + ## Get all the matching records + while [ true ]; do ## 1) get the URL ## the create request - get ## args: URL, [onlyheader, timeout] domain_list="$(_get "$GURL")" - ## 2) find record - ## check for what we are looing for: "type":"A","name":"$_sub_domain" - record="$(echo "$domain_list" | _egrep_o "\"id\"\s*\:\s*\"*[0-9]+\"*[^}]*\"name\"\s*\:\s*\"$_sub_domain\"[^}]*\"data\"\s*\:\s*\"$txtvalue\"")" - ## 3) check record and get next page - if [ -z "$record" ]; then - ## find the next page if we dont have a match - nextpage="$(echo "$domain_list" | _egrep_o "\"links\".*" | _egrep_o "\"next\".*" | _egrep_o "http.*page\=[0-9]+")" - if [ -z "$nextpage" ]; then - _err "no record and no nextpage in digital ocean DNS removal" - return 1 - fi - _debug2 nextpage "$nextpage" - GURL="$nextpage" + + ## check response + if [ "$?" != "0" ]; then + _err "error in domain_list response: $domain_list" + return 1 fi - ## we break out of the loop when we have a record + _debug2 domain_list "$domain_list" + + ## 2) find records + ## check for what we are looking for: "type":"A","name":"$_sub_domain" + record="$(echo "$domain_list" | _egrep_o "\"id\"\s*\:\s*\"*[0-9]+\"*[^}]*\"name\"\s*\:\s*\"$_sub_domain\"[^}]*\"data\"\s*\:\s*\"$txtvalue\"")" + + if [ ! -z "$record" ]; then + + ## we found records + rec_ids="$(echo "$record" | _egrep_o "id\"\s*\:\s*\"*[0-9]+" | _egrep_o "[0-9]+")" + _debug rec_ids "$rec_ids" + if [ ! -z "$rec_ids" ]; then + echo "$rec_ids" | while IFS= read -r rec_id ; do + ## delete the record + ## delete URL for removing the one we dont want + DURL="https://api.digitalocean.com/v2/domains/$_domain/records/$rec_id" + + ## the create request - delete + ## args: BODY, URL, [need64, httpmethod] + response="$(_post "" "$DURL" "" "DELETE")" + + ## check response (sort of) + if [ "$?" != "0" ]; then + _err "error in remove response: $response" + return 1 + fi + _debug2 response "$response" + + done + fi + fi + + ## 3) find the next page + nextpage="$(echo "$domain_list" | _egrep_o "\"links\".*" | _egrep_o "\"next\".*" | _egrep_o "http.*page\=[0-9]+")" + if [ -z "$nextpage" ]; then + break + fi + _debug2 nextpage "$nextpage" + GURL="$nextpage" + done - ## we found the record - rec_id="$(echo "$record" | _egrep_o "id\"\s*\:\s*\"*[0-9]+" | _egrep_o "[0-9]+")" - _debug rec_id "$rec_id" - - ## delete the record - ## delete URL for removing the one we dont want - DURL="https://api.digitalocean.com/v2/domains/$_domain/records/$rec_id" - - ## the create request - delete - ## args: BODY, URL, [need64, httpmethod] - response="$(_post "" "$DURL" "" "DELETE")" - - ## check response (sort of) - if [ "$?" != "0" ]; then - _err "error in remove response: $response" - return 1 - fi - _debug2 response "$response" - ## finished correctly return 0 } @@ -178,44 +190,57 @@ _get_base_domain() { export _H2="Authorization: Bearer $DO_API_KEY" _debug DO_API_KEY "$DO_API_KEY" ## get URL for the list of domains - ## havent seen this request paginated, tested with 18 domains (more requires manual requests with DO) + ## may get: "links":{"pages":{"last":".../v2/domains/DOM/records?page=2","next":".../v2/domains/DOM/records?page=2"}} DOMURL="https://api.digitalocean.com/v2/domains" - ## get the domain list (DO gives basically a full XFER!) - domain_list="$(_get "$DOMURL")" + ## while we dont have a matching domain we keep going + while [ -z "$found" ]; do + ## get the domain list (current page) + domain_list="$(_get "$DOMURL")" - ## check response - if [ "$?" != "0" ]; then - _err "error in domain_list response: $domain_list" - return 1 - fi - _debug2 domain_list "$domain_list" - - ## for each shortening of our $fulldomain, check if it exists in the $domain_list - ## can never start on 1 (aka whole $fulldomain) as $fulldomain starts with "_acme-challenge" - i=2 - while [ $i -gt 0 ]; do - ## get next longest domain - _domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-"$MAX_DOM") - ## check we got something back from our cut (or are we at the end) - if [ -z "$_domain" ]; then - ## we got to the end of the domain - invalid domain - _err "domain not found in DigitalOcean account" + ## check response + if [ "$?" != "0" ]; then + _err "error in domain_list response: $domain_list" return 1 fi - ## we got part of a domain back - grep it out - found="$(echo "$domain_list" | _egrep_o "\"name\"\s*\:\s*\"$_domain\"")" - ## check if it exists - if [ ! -z "$found" ]; then - ## exists - exit loop returning the parts - sub_point=$(_math $i - 1) - _sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-"$sub_point") - _debug _domain "$_domain" - _debug _sub_domain "$_sub_domain" - return 0 + _debug2 domain_list "$domain_list" + + ## for each shortening of our $fulldomain, check if it exists in the $domain_list + ## can never start on 1 (aka whole $fulldomain) as $fulldomain starts with "_acme-challenge" + i=2 + while [ $i -gt 0 ]; do + ## get next longest domain + _domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-"$MAX_DOM") + ## check we got something back from our cut (or are we at the end) + if [ -z "$_domain" ]; then + break + fi + ## we got part of a domain back - grep it out + found="$(echo "$domain_list" | _egrep_o "\"name\"\s*\:\s*\"$_domain\"")" + ## check if it exists + if [ ! -z "$found" ]; then + ## exists - exit loop returning the parts + sub_point=$(_math $i - 1) + _sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-"$sub_point") + _debug _domain "$_domain" + _debug _sub_domain "$_sub_domain" + return 0 + fi + ## increment cut point $i + i=$(_math $i + 1) + done + + if [ -z "$found" ]; then + ## find the next page if we dont have a match + nextpage="$(echo "$domain_list" | _egrep_o "\"links\".*" | _egrep_o "\"next\".*" | _egrep_o "http.*page\=[0-9]+")" + if [ -z "$nextpage" ]; then + _err "no record and no nextpage in digital ocean DNS removal" + return 1 + fi + _debug2 nextpage "$nextpage" + DOMURL="$nextpage" fi - ## increment cut point $i - i=$(_math $i + 1) + done ## we went through the entire domain zone list and dint find one that matched From 4a18c45e4f34bcc05ecc3891af9ac72f5df2b68f Mon Sep 17 00:00:00 2001 From: Tom Blauwendraat Date: Wed, 12 Sep 2018 05:46:51 +0200 Subject: [PATCH 03/61] fixup! [FIX] Delete all occurrences of TXT key, dont fail if there is more than one, [FIX] Respect pagination on domain listing, before only the first page was loaded --- dnsapi/dns_dgon.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_dgon.sh b/dnsapi/dns_dgon.sh index e92c7809..24e1a9f2 100755 --- a/dnsapi/dns_dgon.sh +++ b/dnsapi/dns_dgon.sh @@ -105,7 +105,7 @@ dns_dgon_rm() { GURL="https://api.digitalocean.com/v2/domains/$_domain/records" ## Get all the matching records - while [ true ]; do + while true; do ## 1) get the URL ## the create request - get ## args: URL, [onlyheader, timeout] @@ -128,7 +128,7 @@ dns_dgon_rm() { rec_ids="$(echo "$record" | _egrep_o "id\"\s*\:\s*\"*[0-9]+" | _egrep_o "[0-9]+")" _debug rec_ids "$rec_ids" if [ ! -z "$rec_ids" ]; then - echo "$rec_ids" | while IFS= read -r rec_id ; do + echo "$rec_ids" | while IFS= read -r rec_id; do ## delete the record ## delete URL for removing the one we dont want DURL="https://api.digitalocean.com/v2/domains/$_domain/records/$rec_id" From 26421684dc0c7c0cc79ea36f728d44de2fa382f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Thu, 26 Jul 2018 19:59:15 +0200 Subject: [PATCH 04/61] Fix inwx account without Mobile TAN --- dnsapi/dns_inwx.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_inwx.sh b/dnsapi/dns_inwx.sh index cd5af91b..f4590cf8 100755 --- a/dnsapi/dns_inwx.sh +++ b/dnsapi/dns_inwx.sh @@ -158,7 +158,8 @@ _inwx_login() { export _H1 #https://github.com/inwx/php-client/blob/master/INWX/Domrobot.php#L71 - if _contains "$response" "tfa"; then + if _contains "$response" "code1000" \ + && _contains "$response" "tfaGOOGLE-AUTH"; then if [ -z "$INWX_Shared_Secret" ]; then _err "Mobile TAN detected." _err "Please define a shared secret." From 46b3a9158c80ab5f1c76437ed1fb9fad2c13e96a Mon Sep 17 00:00:00 2001 From: LLeny <5269958+LLeny@users.noreply.github.com> Date: Sun, 21 Oct 2018 18:17:23 +0800 Subject: [PATCH 05/61] Fixes Neilpang/acme.sh#1888 --- dnsapi/dns_namecheap.sh | 64 +++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index 7089c2d0..a6651be6 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -199,9 +199,12 @@ _namecheap_check_config() { _set_namecheap_TXT() { subdomain=$2 txt=$3 - tld=$(echo "$1" | cut -d '.' -f 2) - sld=$(echo "$1" | cut -d '.' -f 1) - request="namecheap.domains.dns.getHosts&SLD=$sld&TLD=$tld" + + if ! _namecheap_set_tld_sld "$1"; then + return 1 + fi + + request="namecheap.domains.dns.getHosts&SLD=${_sld}&TLD=${_tld}" if ! _namecheap_post "$request"; then _err "$error" @@ -231,7 +234,7 @@ EOT _debug hostrequestfinal "$_hostrequest" - request="namecheap.domains.dns.setHosts&SLD=${sld}&TLD=${tld}${_hostrequest}" + request="namecheap.domains.dns.setHosts&SLD=${_sld}&TLD=${_tld}${_hostrequest}" if ! _namecheap_post "$request"; then _err "$error" @@ -244,9 +247,12 @@ EOT _del_namecheap_TXT() { subdomain=$2 txt=$3 - tld=$(echo "$1" | cut -d '.' -f 2) - sld=$(echo "$1" | cut -d '.' -f 1) - request="namecheap.domains.dns.getHosts&SLD=$sld&TLD=$tld" + + if ! _namecheap_set_tld_sld "$1"; then + return 1 + fi + + request="namecheap.domains.dns.getHosts&SLD=${_sld}&TLD=${_tld}" if ! _namecheap_post "$request"; then _err "$error" @@ -286,7 +292,7 @@ EOT _debug hostrequestfinal "$_hostrequest" - request="namecheap.domains.dns.setHosts&SLD=${sld}&TLD=${tld}${_hostrequest}" + request="namecheap.domains.dns.setHosts&SLD=${_sld}&TLD=${_tld}${_hostrequest}" if ! _namecheap_post "$request"; then _err "$error" @@ -306,3 +312,45 @@ _namecheap_add_host() { _hostindex=$(_math "$_hostindex" + 1) _hostrequest=$(printf '%s&HostName%d=%s&RecordType%d=%s&Address%d=%s&MXPref%d=%d&TTL%d=%d' "$_hostrequest" "$_hostindex" "$1" "$_hostindex" "$2" "$_hostindex" "$3" "$_hostindex" "$4" "$_hostindex" "$5") } + +_namecheap_set_tld_sld() { + domain=$1 + _tld="" + _sld="" + + i=2 + + while true; do + + _tld=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug tld "$_tld" + + if [ -z "$_tld" ]; then + _debug "invalid tld" + return 1 + fi + + j=$(_math "$i" - 1) + + _sld=$(printf "%s" "$domain" | cut -d . -f 1-"$j") + _debug sld "$_sld" + + if [ -z "$_sld" ]; then + _debug "invalid sld" + return 1 + fi + + request="namecheap.domains.dns.getHosts&SLD=$_sld&TLD=$_tld" + + if ! _namecheap_post "$request"; then + _debug "sld($_sld)/tld($_tld) not found" + else + _debug "sld($_sld)/tld($_tld) found" + return 0 + fi + + i=$(_math "$i" + 1) + + done + +} From 2671af13cdfb592f56c5de1ffdbe438f79db72d8 Mon Sep 17 00:00:00 2001 From: Ketil Date: Thu, 27 Dec 2018 15:17:19 +0100 Subject: [PATCH 06/61] Bugfix for allowing '+' character in CloudFlare email --- dnsapi/dns_cf.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_cf.sh b/dnsapi/dns_cf.sh index f50ab498..021094d8 100755 --- a/dnsapi/dns_cf.sh +++ b/dnsapi/dns_cf.sh @@ -34,7 +34,7 @@ dns_cf_add() { _saveaccountconf_mutable CF_Key "$CF_Key" _saveaccountconf_mutable CF_Email "$CF_Email" - _DOMAIN_CF_ZONES_CACHE_NAME_="$(echo "${CF_Email}_CF_ZONES_" | tr '@.' '__')" + _DOMAIN_CF_ZONES_CACHE_NAME_="$(echo "${CF_Email}_CF_ZONES_" | tr '+@.' '___')" _cleardomainconf "$_DOMAIN_CF_ZONES_CACHE_NAME_" _debug "First detect the root zone" @@ -105,7 +105,7 @@ dns_cf_rm() { return 1 fi - _DOMAIN_CF_ZONES_CACHE_NAME_="$(echo "${CF_Email}_CF_ZONES_" | tr '@.' '__')" + _DOMAIN_CF_ZONES_CACHE_NAME_="$(echo "${CF_Email}_CF_ZONES_" | tr '+@.' '___')" _debug "First detect the root zone" if ! _get_root "$fulldomain"; then From 9756adb9336daf7fdfd63ce83dde75aa269708d8 Mon Sep 17 00:00:00 2001 From: Ketil Date: Thu, 27 Dec 2018 15:45:19 +0100 Subject: [PATCH 07/61] Fixed spelling of 'tigger' to 'Trigger'. --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index acda4bee..c80d8aa3 100755 --- a/acme.sh +++ b/acme.sh @@ -3443,7 +3443,7 @@ __get_domain_new_authz() { #uri keyAuthorization __trigger_validation() { - _debug2 "tigger domain validation." + _debug2 "Trigger domain validation." _t_url="$1" _debug2 _t_url "$_t_url" _t_key_authz="$2" From 920cab6f1206abde5e8ced352bdd3908a2950534 Mon Sep 17 00:00:00 2001 From: Ketil Date: Thu, 27 Dec 2018 16:06:41 +0100 Subject: [PATCH 08/61] Added fixes to also use BuyPass Go ACME server --- acme.sh | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/acme.sh b/acme.sh index acda4bee..aa2adc6c 100755 --- a/acme.sh +++ b/acme.sh @@ -13,6 +13,8 @@ _SCRIPT_="$0" _SUB_FOLDERS="dnsapi deploy" +BUYPASS_CA="https://api.buypass.no/acme/directory" + LETSENCRYPT_CA_V1="https://acme-v01.api.letsencrypt.org/directory" LETSENCRYPT_STAGING_CA_V1="https://acme-staging.api.letsencrypt.org/directory" @@ -1820,9 +1822,12 @@ _send_signed_request() { _debug3 _request_retry_times "$_request_retry_times" if [ -z "$_CACHED_NONCE" ]; then _headers="" - if [ "$ACME_NEW_NONCE" ]; then - _debug2 "Get nonce with HEAD. ACME_NEW_NONCE" "$ACME_NEW_NONCE" + if [ "$ACME_NEW_NONCE" ] || [ "$BUYPASS" ]; then nonceurl="$ACME_NEW_NONCE" + if [ "$BUYPASS" ]; then + nonceurl=$url + fi + _debug2 "Get nonce with HEAD. ACME_NEW_NONCE" "$nonceurl" if _post "" "$nonceurl" "" "HEAD" "$__request_conent_type"; then _headers="$(cat "$HTTP_HEADER")" fi @@ -1875,7 +1880,7 @@ _send_signed_request() { sig="$(printf "%s" "$_sig_t" | _url_replace)" _debug3 sig "$sig" - if [ "$ACME_VERSION" = "2" ]; then + if [ "$ACME_VERSION" = "2" ] || [ "$BUYPASS" ]; then body="{\"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}" else body="{\"header\": $JWK_HEADER, \"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}" @@ -2330,6 +2335,13 @@ _initAPI() { fi export ACME_AGREEMENT + BUYPASS=$(echo "$_api_server" | _egrep_o 'buypass') + if [ "$BUYPASS" ]; then + BUYPASS=1 + fi + export BUYPASS + _debug "BUYPASS" "$BUYPASS" + _debug "ACME_KEY_CHANGE" "$ACME_KEY_CHANGE" _debug "ACME_NEW_AUTHZ" "$ACME_NEW_AUTHZ" _debug "ACME_NEW_ORDER" "$ACME_NEW_ORDER" @@ -3448,10 +3460,16 @@ __trigger_validation() { _debug2 _t_url "$_t_url" _t_key_authz="$2" _debug2 _t_key_authz "$_t_key_authz" + _t_vtype="$3" + _debug2 _t_vtype "$_t_vtype" if [ "$ACME_VERSION" = "2" ]; then _send_signed_request "$_t_url" "{\"keyAuthorization\": \"$_t_key_authz\"}" else - _send_signed_request "$_t_url" "{\"resource\": \"challenge\", \"keyAuthorization\": \"$_t_key_authz\"}" + if [ "$BUYPASS" ]; then + _send_signed_request "$_t_url" "{\"resource\": \"challenge\", \"type\": \"$_t_vtype\", \"keyAuthorization\": \"$_t_key_authz\"}" + else + _send_signed_request "$_t_url" "{\"resource\": \"challenge\", \"keyAuthorization\": \"$_t_key_authz\"}" + fi fi } @@ -4038,7 +4056,7 @@ $_authorizations_map" fi fi - if ! __trigger_validation "$uri" "$keyauthorization"; then + if ! __trigger_validation "$uri" "$keyauthorization" "$vtype"; then _err "$d:Can not get challenge: $response" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearup @@ -4047,14 +4065,18 @@ $_authorizations_map" fi if [ "$code" ] && [ "$code" != '202' ]; then - if [ "$ACME_VERSION" = "2" ] && [ "$code" = '200' ]; then + if [ "$BUYPASS" ] && [ "$code" = '200' ]; then _debug "trigger validation code: $code" else - _err "$d:Challenge error: $response" - _clearupwebbroot "$_currentRoot" "$removelevel" "$token" - _clearup - _on_issue_err "$_post_hook" "$vlist" - return 1 + if [ "$ACME_VERSION" = "2" ] && [ "$code" = '200' ]; then + _debug "trigger validation code: $code" + else + _err "$d:Challenge error: $response" + _clearupwebbroot "$_currentRoot" "$removelevel" "$token" + _clearup + _on_issue_err "$_post_hook" "$vlist" + return 1 + fi fi fi From 8bd12ed040c65fcc5b4919c1f81835c579da6314 Mon Sep 17 00:00:00 2001 From: Ketil Date: Fri, 28 Dec 2018 09:22:31 +0100 Subject: [PATCH 09/61] Rewrite to remove BuyPass spesific fixes and adapt ACME v1 --- acme.sh | 44 +++++++++++--------------------------------- 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/acme.sh b/acme.sh index aa2adc6c..0ec08511 100755 --- a/acme.sh +++ b/acme.sh @@ -1822,12 +1822,9 @@ _send_signed_request() { _debug3 _request_retry_times "$_request_retry_times" if [ -z "$_CACHED_NONCE" ]; then _headers="" - if [ "$ACME_NEW_NONCE" ] || [ "$BUYPASS" ]; then + if [ "$ACME_NEW_NONCE" ]; then + _debug2 "Get nonce with HEAD. ACME_NEW_NONCE" "$ACME_NEW_NONCE" nonceurl="$ACME_NEW_NONCE" - if [ "$BUYPASS" ]; then - nonceurl=$url - fi - _debug2 "Get nonce with HEAD. ACME_NEW_NONCE" "$nonceurl" if _post "" "$nonceurl" "" "HEAD" "$__request_conent_type"; then _headers="$(cat "$HTTP_HEADER")" fi @@ -1880,11 +1877,7 @@ _send_signed_request() { sig="$(printf "%s" "$_sig_t" | _url_replace)" _debug3 sig "$sig" - if [ "$ACME_VERSION" = "2" ] || [ "$BUYPASS" ]; then - body="{\"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}" - else - body="{\"header\": $JWK_HEADER, \"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}" - fi + body="{\"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}" _debug3 body "$body" response="$(_post "$body" "$url" "$needbase64" "POST" "$__request_conent_type")" @@ -2335,13 +2328,6 @@ _initAPI() { fi export ACME_AGREEMENT - BUYPASS=$(echo "$_api_server" | _egrep_o 'buypass') - if [ "$BUYPASS" ]; then - BUYPASS=1 - fi - export BUYPASS - _debug "BUYPASS" "$BUYPASS" - _debug "ACME_KEY_CHANGE" "$ACME_KEY_CHANGE" _debug "ACME_NEW_AUTHZ" "$ACME_NEW_AUTHZ" _debug "ACME_NEW_ORDER" "$ACME_NEW_ORDER" @@ -3455,7 +3441,7 @@ __get_domain_new_authz() { #uri keyAuthorization __trigger_validation() { - _debug2 "tigger domain validation." + _debug2 "Trigger domain validation." _t_url="$1" _debug2 _t_url "$_t_url" _t_key_authz="$2" @@ -3465,11 +3451,7 @@ __trigger_validation() { if [ "$ACME_VERSION" = "2" ]; then _send_signed_request "$_t_url" "{\"keyAuthorization\": \"$_t_key_authz\"}" else - if [ "$BUYPASS" ]; then - _send_signed_request "$_t_url" "{\"resource\": \"challenge\", \"type\": \"$_t_vtype\", \"keyAuthorization\": \"$_t_key_authz\"}" - else - _send_signed_request "$_t_url" "{\"resource\": \"challenge\", \"keyAuthorization\": \"$_t_key_authz\"}" - fi + _send_signed_request "$_t_url" "{\"resource\": \"challenge\", \"type\": \"$_t_vtype\", \"keyAuthorization\": \"$_t_key_authz\"}" fi } @@ -4065,18 +4047,14 @@ $_authorizations_map" fi if [ "$code" ] && [ "$code" != '202' ]; then - if [ "$BUYPASS" ] && [ "$code" = '200' ]; then + if [ "$code" = '200' ]; then _debug "trigger validation code: $code" else - if [ "$ACME_VERSION" = "2" ] && [ "$code" = '200' ]; then - _debug "trigger validation code: $code" - else - _err "$d:Challenge error: $response" - _clearupwebbroot "$_currentRoot" "$removelevel" "$token" - _clearup - _on_issue_err "$_post_hook" "$vlist" - return 1 - fi + _err "$d:Challenge error: $response" + _clearupwebbroot "$_currentRoot" "$removelevel" "$token" + _clearup + _on_issue_err "$_post_hook" "$vlist" + return 1 fi fi From 65a2f789dc415c518d16d5c50e9d0d28919eb5ff Mon Sep 17 00:00:00 2001 From: Ketil Date: Fri, 28 Dec 2018 13:26:20 +0100 Subject: [PATCH 10/61] Removing BUYPASS_CA variable --- acme.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/acme.sh b/acme.sh index 0ec08511..422383b6 100755 --- a/acme.sh +++ b/acme.sh @@ -13,8 +13,6 @@ _SCRIPT_="$0" _SUB_FOLDERS="dnsapi deploy" -BUYPASS_CA="https://api.buypass.no/acme/directory" - LETSENCRYPT_CA_V1="https://acme-v01.api.letsencrypt.org/directory" LETSENCRYPT_STAGING_CA_V1="https://acme-staging.api.letsencrypt.org/directory" From b32071ad049e3235adebd87f64b1899bbc3d21f2 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 28 Dec 2018 22:12:54 +0800 Subject: [PATCH 11/61] remove unused code --- acme.sh | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/acme.sh b/acme.sh index 422383b6..dd718352 100755 --- a/acme.sh +++ b/acme.sh @@ -36,7 +36,6 @@ _OLD_STAGE_CA_HOST="https://acme-staging.api.letsencrypt.org" VTYPE_HTTP="http-01" VTYPE_DNS="dns-01" VTYPE_TLS="tls-sni-01" -VTYPE_TLS2="tls-sni-02" VTYPE_ALPN="tls-alpn-01" LOCAL_ANY_ADDRESS="0.0.0.0" @@ -3700,11 +3699,7 @@ $_authorizations_map" fi if [ "$_currentRoot" = "$W_TLS" ]; then - if [ "$ACME_VERSION" = "2" ]; then - vtype="$VTYPE_TLS2" - else - vtype="$VTYPE_TLS" - fi + vtype="$VTYPE_TLS" fi if [ "$_currentRoot" = "$W_ALPN" ]; then From 7ba9a5972dd904b1b5834e7ef1a6a3323d1e29aa Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 28 Dec 2018 22:45:40 +0800 Subject: [PATCH 12/61] revert fix for https://github.com/Neilpang/acme.sh/issues/1941 1. fix https://github.com/Neilpang/acme.sh/issues/1977 2. The cache is too long to as a line to save in the conf --- dnsapi/dns_cf.sh | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/dnsapi/dns_cf.sh b/dnsapi/dns_cf.sh index 021094d8..202385fe 100755 --- a/dnsapi/dns_cf.sh +++ b/dnsapi/dns_cf.sh @@ -34,9 +34,6 @@ dns_cf_add() { _saveaccountconf_mutable CF_Key "$CF_Key" _saveaccountconf_mutable CF_Email "$CF_Email" - _DOMAIN_CF_ZONES_CACHE_NAME_="$(echo "${CF_Email}_CF_ZONES_" | tr '+@.' '___')" - _cleardomainconf "$_DOMAIN_CF_ZONES_CACHE_NAME_" - _debug "First detect the root zone" if ! _get_root "$fulldomain"; then _err "invalid domain" @@ -105,16 +102,11 @@ dns_cf_rm() { return 1 fi - _DOMAIN_CF_ZONES_CACHE_NAME_="$(echo "${CF_Email}_CF_ZONES_" | tr '+@.' '___')" - _debug "First detect the root zone" if ! _get_root "$fulldomain"; then - _cleardomainconf "$_DOMAIN_CF_ZONES_CACHE_NAME_" _err "invalid domain" return 1 fi - _cleardomainconf "$_DOMAIN_CF_ZONES_CACHE_NAME_" - _debug _domain_id "$_domain_id" _debug _sub_domain "$_sub_domain" _debug _domain "$_domain" @@ -154,21 +146,6 @@ dns_cf_rm() { # _domain=domain.com # _domain_id=sdjkglgdfewsdfg _get_root() { - - _cf_zones="$(_readdomainconf "$_DOMAIN_CF_ZONES_CACHE_NAME_")" - _debug2 "_cf_zones" "$_cf_zones" - if [ -z "$_cf_zones" ]; then - _debug "$_DOMAIN_CF_ZONES_CACHE_NAME_ is none, so get it." - if ! _cf_rest GET "zones"; then - return 1 - fi - _cf_zones="$response" - _savedomainconf "$_DOMAIN_CF_ZONES_CACHE_NAME_" "$(echo "$_cf_zones" | _base64)" - else - _debug "$_DOMAIN_CF_ZONES_CACHE_NAME_ found" - _cf_zones="$(echo "$_cf_zones" | _dbase64)" - fi - domain=$1 i=2 p=1 @@ -180,8 +157,12 @@ _get_root() { return 1 fi - if _contains "$_cf_zones" "\"name\":\"$h\"" >/dev/null; then - _domain_id=$(echo "$_cf_zones" | tr '{' "\n" | grep "\"name\":\"$h\"" | _egrep_o "^\"id\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") + if ! _cf_rest GET "zones?name=$h"; then + return 1 + fi + + if _contains "$response" "\"name\":\"$h\"" >/dev/null; then + _domain_id=$(echo "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") if [ "$_domain_id" ]; then _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _domain=$h From ec67a1b2c12c4fa1bdb28feb870853652b7bbe07 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 28 Dec 2018 22:52:40 +0800 Subject: [PATCH 13/61] Do not limit the renew days to 60, it's just a default value. buypass support 180 days. --- acme.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/acme.sh b/acme.sh index dd718352..aae16f07 100755 --- a/acme.sh +++ b/acme.sh @@ -40,7 +40,7 @@ VTYPE_ALPN="tls-alpn-01" LOCAL_ANY_ADDRESS="0.0.0.0" -MAX_RENEW=60 +DEFAULT_RENEW=60 DEFAULT_DNS_SLEEP=120 @@ -4267,8 +4267,8 @@ $_authorizations_map" Le_CertCreateTimeStr=$(date -u) _savedomainconf "Le_CertCreateTimeStr" "$Le_CertCreateTimeStr" - if [ -z "$Le_RenewalDays" ] || [ "$Le_RenewalDays" -lt "0" ] || [ "$Le_RenewalDays" -gt "$MAX_RENEW" ]; then - Le_RenewalDays="$MAX_RENEW" + if [ -z "$Le_RenewalDays" ] || [ "$Le_RenewalDays" -lt "0" ]; then + Le_RenewalDays="$DEFAULT_RENEW" else _savedomainconf "Le_RenewalDays" "$Le_RenewalDays" fi @@ -5520,7 +5520,7 @@ Parameters: --useragent Specifies the user agent string. it will be saved for future use too. --accountemail Specifies the account email, only valid for the '--install' and '--update-account' command. --accountkey Specifies the account key path, only valid for the '--install' command. - --days Specifies the days to renew the cert when using '--issue' command. The max value is $MAX_RENEW days. + --days Specifies the days to renew the cert when using '--issue' command. The default value is $DEFAULT_RENEW days. --httpport Specifies the standalone listening port. Only valid if the server is behind a reverse proxy or load balancer. --tlsport Specifies the standalone tls listening port. Only valid if the server is behind a reverse proxy or load balancer. --local-address Specifies the standalone/tls server listening address, in case you have multiple ip addresses. From c4094c68ee44cd9651fb1effe38ce4a1c97b1cee Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 28 Dec 2018 23:04:40 +0800 Subject: [PATCH 14/61] Support BuyPass.com CA --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 6a1cf3a4..50d2cfbe 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,10 @@ For all build statuses, check our [weekly build project](https://github.com/Neil https://github.com/Neilpang/acmetest +# Supported CA + +- Letsencrypt.org CA(default) +- [BuyPass.com CA](https://github.com/Neilpang/acme.sh/wiki/BuyPass.com-CA) # Supported modes From c9baca79109de3d55a6ced143b01e4ef7a07729a Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 28 Dec 2018 23:12:16 +0800 Subject: [PATCH 15/61] add tls-alpn mode --- README.md | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 50d2cfbe..2d31c678 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ https://github.com/Neilpang/acmetest - Webroot mode - Standalone mode +- Standalone tls-alpn mode - Apache mode - Nginx mode - DNS mode @@ -225,8 +226,20 @@ acme.sh --issue --standalone -d example.com -d www.example.com -d cp.example.com More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert +# 5. Use Standalone ssl server to issue cert -# 5. Use Apache mode +**(requires you to be root/sudoer or have permission to listen on port 443 (TCP))** + +Port `443` (TCP) **MUST** be free to listen on, otherwise you will be prompted to free it and try again. + +```bash +acme.sh --issue --alpn -d example.com -d www.example.com -d cp.example.com +``` + +More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert + + +# 6. Use Apache mode **(requires you to be root/sudoer, since it is required to interact with Apache server)** @@ -246,7 +259,7 @@ We don't want to mess your apache server, don't worry.** More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert -# 6. Use Nginx mode +# 7. Use Nginx mode **(requires you to be root/sudoer, since it is required to interact with Nginx server)** @@ -270,7 +283,7 @@ We don't want to mess your nginx server, don't worry.** More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert -# 7. Automatic DNS API integration +# 8. Automatic DNS API integration If your DNS provider supports API access, we can use that API to automatically issue the certs. @@ -348,7 +361,7 @@ If your DNS provider is not on the supported list above, you can write your own For more details: [How to use DNS API](dnsapi) -# 8. Use DNS manual mode: +# 9. Use DNS manual mode: See: https://github.com/Neilpang/acme.sh/wiki/dns-manual-mode first. @@ -384,7 +397,7 @@ Ok, it's done. **Please use dns api mode instead.** -# 9. Issue ECC certificates +# 10. Issue ECC certificates `Let's Encrypt` can now issue **ECDSA** certificates. @@ -416,7 +429,7 @@ Valid values are: -# 10. Issue Wildcard certificates +# 11. Issue Wildcard certificates It's simple, just give a wildcard domain as the `-d` parameter. @@ -426,7 +439,7 @@ acme.sh --issue -d example.com -d '*.example.com' --dns dns_cf -# 11. How to renew the certs +# 12. How to renew the certs No, you don't need to renew the certs manually. All the certs will be renewed automatically every **60** days. @@ -443,7 +456,7 @@ acme.sh --renew -d example.com --force --ecc ``` -# 12. How to stop cert renewal +# 13. How to stop cert renewal To stop renewal of a cert, you can execute the following to remove the cert from the renewal list: @@ -456,7 +469,7 @@ The cert/key file is not removed from the disk. You can remove the respective directory (e.g. `~/.acme.sh/example.com`) by yourself. -# 13. How to upgrade `acme.sh` +# 14. How to upgrade `acme.sh` acme.sh is in constant development, so it's strongly recommended to use the latest code. @@ -481,25 +494,25 @@ acme.sh --upgrade --auto-upgrade 0 ``` -# 14. Issue a cert from an existing CSR +# 15. Issue a cert from an existing CSR https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR -# 15. Under the Hood +# 16. Under the Hood Speak ACME language using shell, directly to "Let's Encrypt". TODO: -# 16. Acknowledgments +# 17. Acknowledgments 1. Acme-tiny: https://github.com/diafygi/acme-tiny 2. ACME protocol: https://github.com/ietf-wg-acme/acme -# 17. License & Others +# 18. License & Others License is GPLv3 @@ -508,7 +521,7 @@ Please Star and Fork me. [Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcome. -# 18. Donate +# 19. Donate Your donation makes **acme.sh** better: 1. PayPal/Alipay(支付宝)/Wechat(微信): [https://donate.acme.sh/](https://donate.acme.sh/) From 29a5311ae0cb82799d404efb8dc1b4c3cc7ff14d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20R=C3=B6ttsches?= Date: Fri, 28 Dec 2018 00:45:51 +0200 Subject: [PATCH 16/61] [dnsapi] Support adding / removing multiple TXT values for Gandi Gandi supports setting multiple entries by setting multiple array items for the rrset_values field in their API. Modify the dns_gandi_livedns.sh script so that it checks for existing entries, appends new ones if needed, and removes existing ones individually. This enabled wildcard certificate support on Gandi. Fixes the dns_gandi_livedns part of #1261. Tested for creating a multidomain, multiple wild-card certificate on Gandi and using a test script executing only the dns_gandi_livedns_add and dns_gandi_livedns_rm functions. --- dnsapi/dns_gandi_livedns.sh | 60 ++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 4 deletions(-) mode change 100755 => 100644 dnsapi/dns_gandi_livedns.sh diff --git a/dnsapi/dns_gandi_livedns.sh b/dnsapi/dns_gandi_livedns.sh old mode 100755 new mode 100644 index 7a21aba6..cdda4775 --- a/dnsapi/dns_gandi_livedns.sh +++ b/dnsapi/dns_gandi_livedns.sh @@ -7,6 +7,7 @@ # Requires GANDI API KEY set in GANDI_LIVEDNS_KEY set as environment variable # #Author: Frédéric Crozat +# Dominik Röttsches #Report Bugs here: https://github.com/fcrozat/acme.sh # ######## Public functions ##################### @@ -36,9 +37,7 @@ dns_gandi_livedns_add() { _debug domain "$_domain" _debug sub_domain "$_sub_domain" - _gandi_livedns_rest PUT "domains/$_domain/records/$_sub_domain/TXT" "{\"rrset_ttl\": 300, \"rrset_values\":[\"$txtvalue\"]}" \ - && _contains "$response" '{"message": "DNS Record Created"}' \ - && _info "Add $(__green "success")" + _dns_gandi_append_record "$_domain" "$_sub_domain" "$txtvalue" } #Usage: fulldomain txtvalue @@ -56,9 +55,23 @@ dns_gandi_livedns_rm() { _debug fulldomain "$fulldomain" _debug domain "$_domain" _debug sub_domain "$_sub_domain" + _debug txtvalue "$txtvalue" - _gandi_livedns_rest DELETE "domains/$_domain/records/$_sub_domain/TXT" "" + if ! _dns_gandi_existing_rrset_values "$_domain" "$_sub_domain"; then + return 1 + fi + _new_rrset_values=$(echo "$_rrset_values" | sed "s/...$txtvalue...//g") + # Cleanup dangling commata. + _new_rrset_values=$(echo "$_new_rrset_values" | sed "s/, ,/ ,/g") + _new_rrset_values=$(echo "$_new_rrset_values" | sed "s/, *\]/\]/g") + _new_rrset_values=$(echo "$_new_rrset_values" | sed "s/\[ *,/\[/g") + _debug "New rrset_values" "$_new_rrset_values" + _gandi_livedns_rest PUT \ + "domains/$_domain/records/$_sub_domain/TXT" \ + "{\"rrset_ttl\": 300, \"rrset_values\": $_new_rrset_values}" \ + && _contains "$response" '{"message": "DNS Record Created"}' \ + && _info "Removing record $(__green "success")" } #################### Private functions below ################################## @@ -98,6 +111,45 @@ _get_root() { return 1 } +_dns_gandi_append_record() { + domain=$1 + sub_domain=$2 + txtvalue=$3 + + if _dns_gandi_existing_rrset_values "$domain" "$sub_domain"; then + _debug "Appending new value" + _rrset_values=$(echo "$_rrset_values" | sed "s/\"]/\",\"$txtvalue\"]/") + else + _debug "Creating new record" "$_rrset_values" + _rrset_values="[\"$txtvalue\"]" + fi + _debug new_rrset_values "$_rrset_values" + _gandi_livedns_rest PUT "domains/$_domain/records/$sub_domain/TXT" \ + "{\"rrset_ttl\": 300, \"rrset_values\": $_rrset_values}" \ + && _contains "$response" '{"message": "DNS Record Created"}' \ + && _info "Adding record $(__green "success")" +} + +_dns_gandi_existing_rrset_values() { + domain=$1 + sub_domain=$2 + if ! _gandi_livedns_rest GET "domains/$domain/records/$sub_domain"; then + return 1 + fi + if ! _contains "$response" '"rrset_type": "TXT"'; then + _debug "Does not have a _acme-challenge TXT record yet." + return 1 + fi + if _contains "$response" '"rrset_values": \[\]'; then + _debug "Empty rrset_values for TXT record, no previous TXT record." + return 1 + fi + _debug "Already has TXT record." + _rrset_values=$(echo "$response" | _egrep_o 'rrset_values.*\[.*\]' \ + | _egrep_o '\[".*\"]') + return 0 +} + _gandi_livedns_rest() { m=$1 ep="$2" From 68c5c366f4bc0ab421bd2004e40718b7561c984f Mon Sep 17 00:00:00 2001 From: Ben Edmunds Date: Sun, 30 Dec 2018 03:13:23 +0000 Subject: [PATCH 17/61] dnsapi update dynu for api v2 --- dnsapi/dns_dynu.sh | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/dnsapi/dns_dynu.sh b/dnsapi/dns_dynu.sh index 17a1cdb0..506ef53e 100644 --- a/dnsapi/dns_dynu.sh +++ b/dnsapi/dns_dynu.sh @@ -10,7 +10,7 @@ Dynu_Token="" # #Endpoint -Dynu_EndPoint="https://api.dynu.com/v1" +Dynu_EndPoint="https://api.dynu.com/v2" # #Author: Dynu Systems, Inc. #Report Bugs here: https://github.com/shar0119/acme.sh @@ -51,11 +51,11 @@ dns_dynu_add() { _debug _domain_name "$_domain_name" _info "Creating TXT record." - if ! _dynu_rest POST "dns/record/add" "{\"domain_name\":\"$_domain_name\",\"node_name\":\"$_node\",\"record_type\":\"TXT\",\"text_data\":\"$txtvalue\",\"state\":true,\"ttl\":90}"; then + if ! _dynu_rest POST "dns/$dnsId/record" "{\"domainId\":\"$dnsId\",\"nodeName\":\"$_node\",\"recordType\":\"TXT\",\"textData\":\"$txtvalue\",\"state\":true,\"ttl\":90}"; then return 1 fi - if ! _contains "$response" "text_data"; then + if ! _contains "$response" "200"; then _err "Could not add TXT record." return 1 fi @@ -132,11 +132,12 @@ _get_root() { return 1 fi - if ! _dynu_rest GET "dns/get/$h"; then + if ! _dynu_rest GET "dns/getroot/$h"; then return 1 fi - if _contains "$response" "\"name\":\"$h\"" >/dev/null; then + if _contains "$response" "\"domainName\":\"$h\"" >/dev/null; then + dnsId=$(printf "%s" "$response" | tr -d "{}" | cut -d , -f 2 | cut -d : -f 2) _domain_name=$h _node=$(printf "%s" "$domain" | cut -d . -f 1-$p) return 0 @@ -152,7 +153,7 @@ _get_recordid() { fulldomain=$1 txtvalue=$2 - if ! _dynu_rest GET "dns/record/get?hostname=$fulldomain&rrtype=TXT"; then + if ! _dynu_rest GET "dns/$dnsId/record"; then return 1 fi @@ -161,19 +162,18 @@ _get_recordid() { return 0 fi - _dns_record_id=$(printf "%s" "$response" | _egrep_o "{[^}]*}" | grep "\"text_data\":\"$txtvalue\"" | _egrep_o ",[^,]*," | grep ',"id":' | tr -d ",," | cut -d : -f 2) - + _dns_record_id=$(printf "%s" "$response" | sed -e 's/[^{]*\({[^}]*}\)[^{]*/\1\n/g' | grep "\"textData\":\"$txtvalue\"" | sed -e 's/.*"id":\([^,]*\).*/\1/') return 0 } _delete_txt_record() { _dns_record_id=$1 - if ! _dynu_rest GET "dns/record/delete/$_dns_record_id"; then + if ! _dynu_rest DELETE "dns/$dnsId/record/$_dns_record_id"; then return 1 fi - if ! _contains "$response" "true"; then + if ! _contains "$response" "200"; then return 1 fi @@ -189,7 +189,7 @@ _dynu_rest() { export _H1="Authorization: Bearer $Dynu_Token" export _H2="Content-Type: application/json" - if [ "$data" ]; then + if [ "$data" ] || [ "$m" = "DELETE" ]; then _debug data "$data" response="$(_post "$data" "$Dynu_EndPoint/$ep" "" "$m")" else @@ -216,8 +216,8 @@ _dynu_authentication() { _err "Authentication failed." return 1 fi - if _contains "$response" "accessToken"; then - Dynu_Token=$(printf "%s" "$response" | tr -d "[]" | cut -d , -f 2 | cut -d : -f 2 | cut -d '"' -f 2) + if _contains "$response" "access_token"; then + Dynu_Token=$(printf "%s" "$response" | tr -d "{}" | cut -d , -f 1 | cut -d : -f 2 | cut -d '"' -f 2) fi if _contains "$Dynu_Token" "null"; then Dynu_Token="" From cd4f29135b8f66d5dc8a34833712ad90eceefe9f Mon Sep 17 00:00:00 2001 From: Oliver Dick Date: Wed, 2 Jan 2019 16:44:11 +0100 Subject: [PATCH 18/61] waiting for API zoneStatus active --- dnsapi/dns_hostingde.sh | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/dnsapi/dns_hostingde.sh b/dnsapi/dns_hostingde.sh index 39bcfb63..317ebeda 100644 --- a/dnsapi/dns_hostingde.sh +++ b/dnsapi/dns_hostingde.sh @@ -74,8 +74,26 @@ _hostingde_getZoneConfig() { return $returnCode } +_hostingde_getZoneStatus() { + _debug "Checking Zone status" + curData="{\"filter\":{\"field\":\"zoneConfigId\",\"value\":\"${zoneConfigId}\"},\"limit\":1,\"authToken\":\"${HOSTINGDE_APIKEY}\"}" + curResult="$(_post "${curData}" "${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zonesFind")" + _debug "Calling zonesFind '${curData}' '${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zonesFind'" + _debug "Result of zonesFind '$curResult'" + zoneStatus=$(echo "${curResult}" | grep -v success | _egrep_o '"status":.*' | cut -d ':' -f 2 | cut -d '"' -f 2) + _debug "zoneStatus '${zoneStatus}'" + return 0 +} + _hostingde_addRecord() { _info "Adding record to zone" + _hostingde_getZoneStatus + _debug "Result of zoneStatus: '${zoneStatus}'" + while [ "${zoneStatus}" != "active" ]; do + sleep 5 + _hostingde_getZoneStatus + _debug "Result of zoneStatus: '${zoneStatus}'" + done curData="{\"authToken\":\"${HOSTINGDE_APIKEY}\",\"zoneConfig\":{\"id\":\"${zoneConfigId}\"},\"recordsToAdd\":[{\"name\":\"${fulldomain}\",\"type\":\"TXT\",\"content\":\"\\\"${txtvalue}\\\"\",\"ttl\":3600}]}" curResult="$(_post "${curData}" "${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zoneUpdate")" _debug "Calling zoneUpdate: '${curData}' '${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zoneUpdate'" @@ -93,6 +111,13 @@ _hostingde_addRecord() { _hostingde_removeRecord() { _info "Removing record from zone" + _hostingde_getZoneStatus + _debug "Result of zoneStatus: '$zoneStatus'" + while [ "$zoneStatus" != "active" ]; do + sleep 5 + _hostingde_getZoneStatus + _debug "Result of zoneStatus: '$zoneStatus'" + done curData="{\"authToken\":\"${HOSTINGDE_APIKEY}\",\"zoneConfig\":{\"id\":\"${zoneConfigId}\"},\"recordsToDelete\":[{\"name\":\"${fulldomain}\",\"type\":\"TXT\",\"content\":\"\\\"${txtvalue}\\\"\"}]}" curResult="$(_post "${curData}" "${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zoneUpdate")" _debug "Calling zoneUpdate: '${curData}' '${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zoneUpdate'" From ecf7dded07144d81aba47addee52eae0c072dbd0 Mon Sep 17 00:00:00 2001 From: Ivru Date: Thu, 3 Jan 2019 08:39:51 +0100 Subject: [PATCH 19/61] Fix typo --- dnsapi/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/README.md b/dnsapi/README.md index 201deeec..9358eb4b 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -1122,7 +1122,7 @@ export EXOSCALE_SECRET_KEY='xxx' Now, let's issue a cert: ``` -acme.sh --issue --dns dns_netcup -d example.com -d www.example.com +acme.sh --issue --dns dns_exoscale -d example.com -d www.example.com ``` The `EXOSCALE_API_KEY` and `EXOSCALE_SECRET_KEY` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. From 089823785e1aa4b1cb4d3b4725bab2920a97ff02 Mon Sep 17 00:00:00 2001 From: Oliver Dick Date: Thu, 3 Jan 2019 10:32:59 +0100 Subject: [PATCH 20/61] Using _sleep() instead of sleep --- dnsapi/dns_hostingde.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_hostingde.sh b/dnsapi/dns_hostingde.sh index 317ebeda..74a472d2 100644 --- a/dnsapi/dns_hostingde.sh +++ b/dnsapi/dns_hostingde.sh @@ -90,7 +90,7 @@ _hostingde_addRecord() { _hostingde_getZoneStatus _debug "Result of zoneStatus: '${zoneStatus}'" while [ "${zoneStatus}" != "active" ]; do - sleep 5 + _sleep 5 _hostingde_getZoneStatus _debug "Result of zoneStatus: '${zoneStatus}'" done @@ -114,7 +114,7 @@ _hostingde_removeRecord() { _hostingde_getZoneStatus _debug "Result of zoneStatus: '$zoneStatus'" while [ "$zoneStatus" != "active" ]; do - sleep 5 + _sleep 5 _hostingde_getZoneStatus _debug "Result of zoneStatus: '$zoneStatus'" done From 40f0238bb79a14ed884a520b24cb5cbcdbd3aa08 Mon Sep 17 00:00:00 2001 From: Marton Szucs Date: Thu, 3 Jan 2019 11:32:43 +0100 Subject: [PATCH 21/61] fix dns_loopia wildcard certificate Checks if a subdomain already exists before creating one. The loopia API clears all records for a subdomain when adding it again. Adding TXT-records instead of updating the existing record when using the add method. Wildcard certificates require multiple TXT-records for the same subdomain. Now you can create wildcard certificates using: `acme.sh --issue -d example.com -d '*.example.com' --dns dns_loopia` Double quoting variables --- dnsapi/dns_loopia.sh | 77 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 68 insertions(+), 9 deletions(-) diff --git a/dnsapi/dns_loopia.sh b/dnsapi/dns_loopia.sh index 5d761187..ece5ef8c 100644 --- a/dnsapi/dns_loopia.sh +++ b/dnsapi/dns_loopia.sh @@ -38,8 +38,8 @@ dns_loopia_add() { _info "Adding record" - _loopia_add_record "$_domain" "$_sub_domain" - _loopia_update_record "$_domain" "$_sub_domain" "$txtvalue" + _loopia_add_sub_domain "$_domain" "$_sub_domain" + _loopia_add_record "$_domain" "$_sub_domain" "$txtvalue" } @@ -96,6 +96,37 @@ dns_loopia_rm() { #################### Private functions below ################################## +_loopia_get_records() { + domain=$1 + sub_domain=$2 + + xml_content=$(printf ' + + getZoneRecords + + + %s + + + %s + + + %s + + + %s + + + ' $LOOPIA_User $LOOPIA_Password "$domain" "$sub_domain") + + response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")" + if ! _contains "$response" ""; then + _err "Error" + return 1 + fi + return 0 +} + _get_root() { domain=$1 _debug "get root" @@ -137,14 +168,14 @@ _get_root() { } -_loopia_update_record() { +_loopia_add_record() { domain=$1 sub_domain=$2 txtval=$3 xml_content=$(printf ' - updateZoneRecord + addZoneRecord %s @@ -176,10 +207,6 @@ _loopia_update_record() { rdata %s - - record_id - 0 - @@ -194,10 +221,42 @@ _loopia_update_record() { return 0 } -_loopia_add_record() { +_sub_domain_exists() { domain=$1 sub_domain=$2 + xml_content=$(printf ' + + getSubdomains + + + %s + + + %s + + + %s + + + ' $LOOPIA_User $LOOPIA_Password "$domain") + + response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")" + + if _contains "$response" "$sub_domain"; then + return 0 + fi + return 1 +} + +_loopia_add_sub_domain() { + domain=$1 + sub_domain=$2 + + if _sub_domain_exists "$domain" "$sub_domain"; then + return 0 + fi + xml_content=$(printf ' addSubdomain From 68d9aad3a26eacb0d57d9c5fe66f59571bddab69 Mon Sep 17 00:00:00 2001 From: hebbet Date: Thu, 3 Jan 2019 14:19:55 +0100 Subject: [PATCH 22/61] add link to profile of Cloudflare follow-up for #1893 --- dnsapi/dns_cf.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_cf.sh b/dnsapi/dns_cf.sh index 202385fe..532199f3 100755 --- a/dnsapi/dns_cf.sh +++ b/dnsapi/dns_cf.sh @@ -19,8 +19,8 @@ dns_cf_add() { if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then CF_Key="" CF_Email="" - _err "You didn't specify a cloudflare api key and email yet." - _err "Please create the key and try again." + _err "You didn't specify a Cloudflare api key and email yet." + _err "You can get yours from here https://dash.cloudflare.com/profile." return 1 fi @@ -97,8 +97,8 @@ dns_cf_rm() { if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then CF_Key="" CF_Email="" - _err "You didn't specify a cloudflare api key and email yet." - _err "Please create the key and try again." + _err "You didn't specify a Cloudflare api key and email yet." + _err "You can get yours from here https://dash.cloudflare.com/profile." return 1 fi From ad613e2437f0cb4cb476af6c61c5975cf1212db8 Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 4 Jan 2019 22:40:59 +0800 Subject: [PATCH 23/61] fix alpn oid. https://github.com/Neilpang/acme.sh/issues/2005 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index aae16f07..8b7fa70b 100755 --- a/acme.sh +++ b/acme.sh @@ -1089,7 +1089,7 @@ _createcsr() { fi if [ "$acmeValidationv1" ]; then - printf "\n1.3.6.1.5.5.7.1.30.1=critical,DER:04:20:${acmeValidationv1}" >>"${csrconf}" + printf "\n1.3.6.1.5.5.7.1.31=critical,DER:04:20:${acmeValidationv1}" >>"${csrconf}" fi _csr_cn="$(_idn "$domain")" From 0483d841e385626e6dc45bc24c8d88a3d5277b62 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 6 Jan 2019 21:05:33 +0800 Subject: [PATCH 24/61] Support Post as Get (#2009) * Support POST as GET https://community.letsencrypt.org/t/acme-v2-scheduled-deprecation-of-unauthenticated-resource-gets/74380 * fix PAG, The newline '\n' in response is removed by _send_signed_request(), to keep it, we just use needbase64 * fix PAG, the cert is muti line * fix format * PAG is only for v2 --- acme.sh | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/acme.sh b/acme.sh index 8b7fa70b..872529f7 100755 --- a/acme.sh +++ b/acme.sh @@ -3651,7 +3651,7 @@ issue() { _authorizations_map="" for _authz_url in $(echo "$_authorizations_seg" | tr ',' ' '); do _debug2 "_authz_url" "$_authz_url" - if ! response="$(_get "$_authz_url")"; then + if ! _send_signed_request "$_authz_url"; then _err "get to authz error." _err "_authorizations_seg" "$_authorizations_seg" _err "_authz_url" "$_authz_url" @@ -4069,7 +4069,11 @@ $_authorizations_map" _debug "sleep 2 secs to verify" sleep 2 _debug "checking" - response="$(_get "$uri")" + if [ "$ACME_VERSION" = "2" ]; then + _send_signed_request "$uri" + else + response="$(_get "$uri")" + fi if [ "$?" != "0" ]; then _err "$d:Verify error:$response" _clearupwebbroot "$_currentRoot" "$removelevel" "$token" @@ -4145,13 +4149,16 @@ $_authorizations_map" fi Le_LinkCert="$(echo "$response" | tr -d '\r\n' | _egrep_o '"certificate" *: *"[^"]*"' | cut -d '"' -f 4)" - if ! _get "$Le_LinkCert" >"$CERT_PATH"; then + _tempSignedResponse="$response" + if ! _send_signed_request "$Le_LinkCert" "" "needbase64"; then _err "Sign failed, can not download cert:$Le_LinkCert." _err "$response" _on_issue_err "$_post_hook" return 1 fi + echo "$response" | _dbase64 "multiline" >"$CERT_PATH" + if [ "$(grep -- "$BEGIN_CERT" "$CERT_PATH" | wc -l)" -gt "1" ]; then _debug "Found cert chain" cat "$CERT_PATH" >"$CERT_FULLCHAIN_PATH" @@ -4161,6 +4168,7 @@ $_authorizations_map" _end_n="$(_math $_end_n + 1)" sed -n "${_end_n},9999p" "$CERT_FULLCHAIN_PATH" >"$CA_CERT_PATH" fi + response="$_tempSignedResponse" else if ! _send_signed_request "${ACME_NEW_ORDER}" "{\"resource\": \"$ACME_NEW_ORDER_RES\", \"csr\": \"$der\"}" "needbase64"; then _err "Sign failed. $response" @@ -4231,7 +4239,8 @@ $_authorizations_map" while [ "$_link_issuer_retry" -lt "$_MAX_ISSUER_RETRY" ]; do _debug _link_issuer_retry "$_link_issuer_retry" if [ "$ACME_VERSION" = "2" ]; then - if _get "$Le_LinkIssuer" >"$CA_CERT_PATH"; then + if _send_signed_request "$Le_LinkIssuer"; then + echo "$response" >"$CA_CERT_PATH" break fi else @@ -4957,7 +4966,7 @@ _deactivate() { authzUri="$_authorizations_seg" _debug2 "authzUri" "$authzUri" - if ! response="$(_get "$authzUri")"; then + if ! _send_signed_request "$authzUri"; then _err "get to authz error." _err "_authorizations_seg" "$_authorizations_seg" _err "authzUri" "$authzUri" From 72ce37704bbaa04d71623c50b545ef1357e981b3 Mon Sep 17 00:00:00 2001 From: Mike Barnes Date: Tue, 8 Jan 2019 15:49:09 +1100 Subject: [PATCH 25/61] Native PointHQ support --- dnsapi/README.md | 19 ++++- dnsapi/dns_pointhq.sh | 164 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 dnsapi/dns_pointhq.sh diff --git a/dnsapi/README.md b/dnsapi/README.md index 9358eb4b..f1bf05e4 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -1,12 +1,12 @@ # How to use DNS API -If your dns provider doesn't provide api access, you can use our dns alias mode: +If your dns provider doesn't provide api access, you can use our dns alias mode: https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode ## 1. Use CloudFlare domain API to automatically issue cert -First you need to login to your CloudFlare account to get your [API key](https://dash.cloudflare.com/profile). +First you need to login to your CloudFlare account to get your [API key](https://dash.cloudflare.com/profile). ``` export CF_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" @@ -891,7 +891,7 @@ acme.sh --issue --dns dns_loopia -d example.com -d *.example.com The username and password will be saved in `~/.acme.sh/account.conf` and will be reused when needed. ## 45. Use ACME DNS API -ACME DNS is a limited DNS server with RESTful HTTP API to handle ACME DNS challenges easily and securely. +ACME DNS is a limited DNS server with RESTful HTTP API to handle ACME DNS challenges easily and securely. https://github.com/joohoi/acme-dns ``` @@ -1056,6 +1056,7 @@ Now you can issue a certificate. acme.sh --issue --dns dns_namecheap -d example.com -d *.example.com ``` +<<<<<<< HEAD ## 54. Use MyDNS.JP API First, register to MyDNS.JP and get MasterID and Password. @@ -1127,6 +1128,18 @@ acme.sh --issue --dns dns_exoscale -d example.com -d www.example.com The `EXOSCALE_API_KEY` and `EXOSCALE_SECRET_KEY` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. +## 58. Using PointHQ API to issue certs + +Log into [PointHQ account management](https://app.pointhq.com/profile) and copy the API key from the page there. + +```export PointHQ_Key="apikeystringgoeshere" +exportPointHQ_Email="accountemail@yourdomain.com" +``` + +You can then issue certs by using: +```acme.sh --issue --dns dns_pointhq -d example.com -d www.example.com +``` + # Use custom API If your API is not supported yet, you can write your own DNS API. diff --git a/dnsapi/dns_pointhq.sh b/dnsapi/dns_pointhq.sh new file mode 100644 index 00000000..62313109 --- /dev/null +++ b/dnsapi/dns_pointhq.sh @@ -0,0 +1,164 @@ +#!/usr/bin/env sh + +# +#PointHQ_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" +# +#PointHQ_Email="xxxx@sss.com" + +PointHQ_Api="https://api.pointhq.com" + +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_pointhq_add() { + fulldomain=$1 + txtvalue=$2 + + PointHQ_Key="${PointHQ_Key:-$(_readaccountconf_mutable PointHQ_Key)}" + PointHQ_Email="${PointHQ_Email:-$(_readaccountconf_mutable PointHQ_Email)}" + if [ -z "$PointHQ_Key" ] || [ -z "$PointHQ_Email" ]; then + PointHQ_Key="" + PointHQ_Email="" + _err "You didn't specify a PointHQ API key and email yet." + _err "Please create the key and try again." + return 1 + fi + + if ! _contains "$PointHQ_Email" "@"; then + _err "It seems that the PointHQ_Email=$PointHQ_Email is not a valid email address." + _err "Please check and retry." + return 1 + fi + + #save the api key and email to the account conf file. + _saveaccountconf_mutable PointHQ_Key "$PointHQ_Key" + _saveaccountconf_mutable PointHQ_Email "$PointHQ_Email" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _info "Adding record" + if _pointhq_rest POST "zones/$_domain/records" "{\"zone_record\": {\"name\":\"$_sub_domain\",\"record_type\":\"TXT\",\"data\":\"$txtvalue\",\"ttl\":3600}}"; then + if printf -- "%s" "$response" | grep "$fulldomain" >/dev/null; then + _info "Added, OK" + return 0 + else + _err "Add txt record error." + return 1 + fi + fi + _err "Add txt record error." + return 1 +} + +#fulldomain txtvalue +dns_pointhq_rm() { + fulldomain=$1 + txtvalue=$2 + + PointHQ_Key="${PointHQ_Key:-$(_readaccountconf_mutable PointHQ_Key)}" + PointHQ_Email="${PointHQ_Email:-$(_readaccountconf_mutable PointHQ_Email)}" + if [ -z "$PointHQ_Key" ] || [ -z "$PointHQ_Email" ]; then + PointHQ_Key="" + PointHQ_Email="" + _err "You didn't specify a PointHQ API key and email yet." + _err "Please create the key and try again." + return 1 + fi + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _debug "Getting txt records" + _pointhq_rest GET "zones/${_domain}/records?record_type=TXT&name=$_sub_domain" + + if ! printf "%s" "$response" | grep "^\[" >/dev/null; then + _err "Error" + return 1 + fi + + if [ "$response" = "[]" ]; then + _info "No records to remove." + else + record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*" | cut -d : -f 2 | tr -d \" | head -n 1) + _debug "record_id" "$record_id" + if [ -z "$record_id" ]; then + _err "Can not get record id to remove." + return 1 + fi + if ! _pointhq_rest DELETE "zones/$_domain/records/$record_id"; then + _err "Delete record error." + return 1 + fi + _contains "$response" '"status":"OK"' + fi +} + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +_get_root() { + domain=$1 + i=2 + p=1 + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug h "$h" + if [ -z "$h" ]; then + #not valid + return 1 + fi + + if ! _pointhq_rest GET "zones"; then + return 1 + fi + + if _contains "$response" "\"name\":\"$h\"" >/dev/null; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain=$h + return 0 + fi + p=$i + i=$(_math "$i" + 1) + done + return 1 +} + +_pointhq_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + + _pointhq_auth=$(printf "%s:%s" "$PointHQ_Email" "$PointHQ_Key" | _base64) + + export _H1="Authorization: Basic $_pointhq_auth" + export _H2="Content-Type: application/json" + export _H3="Accept: application/json" + + if [ "$m" != "GET" ]; then + _debug data "$data" + response="$(_post "$data" "$PointHQ_Api/$ep" "" "$m")" + else + response="$(_get "$PointHQ_Api/$ep")" + fi + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + return 0 +} From cd3ef8fa5ac946975704d6bb910b2ddf07314377 Mon Sep 17 00:00:00 2001 From: Mike Barnes Date: Tue, 8 Jan 2019 15:53:53 +1100 Subject: [PATCH 26/61] Correct edits to README.md this time --- dnsapi/README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dnsapi/README.md b/dnsapi/README.md index f1bf05e4..fc65748e 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -1,12 +1,12 @@ # How to use DNS API -If your dns provider doesn't provide api access, you can use our dns alias mode: +If your dns provider doesn't provide api access, you can use our dns alias mode: https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode ## 1. Use CloudFlare domain API to automatically issue cert -First you need to login to your CloudFlare account to get your [API key](https://dash.cloudflare.com/profile). +First you need to login to your CloudFlare account to get your [API key](https://dash.cloudflare.com/profile). ``` export CF_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" @@ -891,7 +891,7 @@ acme.sh --issue --dns dns_loopia -d example.com -d *.example.com The username and password will be saved in `~/.acme.sh/account.conf` and will be reused when needed. ## 45. Use ACME DNS API -ACME DNS is a limited DNS server with RESTful HTTP API to handle ACME DNS challenges easily and securely. +ACME DNS is a limited DNS server with RESTful HTTP API to handle ACME DNS challenges easily and securely. https://github.com/joohoi/acme-dns ``` @@ -1056,7 +1056,6 @@ Now you can issue a certificate. acme.sh --issue --dns dns_namecheap -d example.com -d *.example.com ``` -<<<<<<< HEAD ## 54. Use MyDNS.JP API First, register to MyDNS.JP and get MasterID and Password. From 3099c799b25b4eca5de668326b3be297eed12903 Mon Sep 17 00:00:00 2001 From: Mike Barnes Date: Wed, 9 Jan 2019 10:24:28 +1100 Subject: [PATCH 27/61] Added PointHQ to supported API list --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2d31c678..41ffb694 100644 --- a/README.md +++ b/README.md @@ -348,6 +348,7 @@ You don't have to do anything manually! 1. hosting.de (https://www.hosting.de) 1. Neodigit.net API (https://www.neodigit.net) 1. Exoscale.com API (https://www.exoscale.com/) +1. PointDNS API (https://pointhq.com/) And: From dd068467def09b070dc2e7dcf158cf69d52c5d74 Mon Sep 17 00:00:00 2001 From: Fabio Kruger Date: Thu, 10 Jan 2019 19:33:25 +0100 Subject: [PATCH 28/61] 2020 Added a space to improve log readability --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 872529f7..ff472867 100755 --- a/acme.sh +++ b/acme.sh @@ -3901,7 +3901,7 @@ $_authorizations_map" continue fi - _info "Verifying:$d" + _info "Verifying: $d" _debug "d" "$d" _debug "keyauthorization" "$keyauthorization" _debug "uri" "$uri" From e19809d5b510ebd466f1abfd9f8ec4feadae3d92 Mon Sep 17 00:00:00 2001 From: shonenada Date: Fri, 11 Jan 2019 18:17:38 +0800 Subject: [PATCH 29/61] Add deployment for qiniu cdn Upload certificate and privkey to Qiniu's CDN service with https://developer.qiniu.com/fusion/api/4248/certificate --- acme.sh | 2 +- deploy/qiniu.sh | 73 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 deploy/qiniu.sh diff --git a/acme.sh b/acme.sh index 872529f7..86b555a3 100755 --- a/acme.sh +++ b/acme.sh @@ -1580,7 +1580,7 @@ _inithttp() { fi if [ -z "$_ACME_CURL" ] && _exists "curl"; then - _ACME_CURL="curl -L --silent --dump-header $HTTP_HEADER " + _ACME_CURL="curl -L --dump-header $HTTP_HEADER " if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then _CURL_DUMP="$(_mktemp)" _ACME_CURL="$_ACME_CURL --trace-ascii $_CURL_DUMP " diff --git a/deploy/qiniu.sh b/deploy/qiniu.sh new file mode 100644 index 00000000..4fa66ee6 --- /dev/null +++ b/deploy/qiniu.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env sh + +# Script to create certificate to qiniu.com +# +# This deployment required following variables +# export QINIU_AK="QINIUACCESSKEY" +# export QINIU_SK="QINIUSECRETKEY" + +QINIU_API_BASE="https://api.qiniu.com" + +qiniu_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 [ -z "$QINIU_AK" ]; then + if [ -z "$Le_Deploy_Qiniu_AK" ]; then + _err "QINIU_AK is not defined." + return 1 + fi + else + Le_Deploy_Qiniu_AK="$QINIU_AK" + _savedomainconf Le_Deploy_Qiniu_AK "$Le_Deploy_Qiniu_AK" + fi + + if [ -z "$QINIU_SK" ]; then + if [ -z "$Le_Deploy_Qiniu_SK" ]; then + _err "QINIU_SK is not defined." + return 1 + fi + else + Le_Deploy_Qiniu_SK="$QINIU_SK" + _savedomainconf Le_Deploy_Qiniu_SK "$Le_Deploy_Qiniu_SK" + fi + + string_fullchain=$(awk '{printf "%s\\n", $0}' "$_cfullchain") + string_key=$(awk '{printf "%s\\n", $0}' "$_ckey") + + body="{\"name\":\"$_cdomain\",\"common_name\":\"$_cdomain\",\"ca\":\""$string_fullchain"\",\"pri\":\"$string_key\"}" + + create_ssl_url="$QINIU_API_BASE/sslcert" + + ACCESSTOKEN="$(_make_sslcreate_access_token)" + export _H1="Authorization: QBox $ACCESSTOKEN" + + _response=$(_post "$body" "$create_ssl_url" 0 "POST" "application/json" | _dbase64 "multiline") + + success_response="certID" + if test "${_response#*$success_response}" == "$_response"; then + _err "Error in deploying certificate:" + _err "$_response" + return 1 + fi + + _debug response "$_response" + _info "Certificate successfully deployed" + + return 0 +} + +_make_sslcreate_access_token() { + _data="/sslcert\\n" + _token="$(printf "$_data" | openssl sha1 -hmac $Le_Deploy_Qiniu_SK -binary | openssl base64 -e)" + echo "$Le_Deploy_Qiniu_AK:$_token" +} From 3bc6628227dcebc1b788ed0676d51b992ee202cc Mon Sep 17 00:00:00 2001 From: shonenada Date: Fri, 11 Jan 2019 19:19:07 +0800 Subject: [PATCH 30/61] Update Qiniu's domain settings after uploading certificate --- acme.sh | 2 +- deploy/qiniu.sh | 41 ++++++++++++++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/acme.sh b/acme.sh index 86b555a3..872529f7 100755 --- a/acme.sh +++ b/acme.sh @@ -1580,7 +1580,7 @@ _inithttp() { fi if [ -z "$_ACME_CURL" ] && _exists "curl"; then - _ACME_CURL="curl -L --dump-header $HTTP_HEADER " + _ACME_CURL="curl -L --silent --dump-header $HTTP_HEADER " if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then _CURL_DUMP="$(_mktemp)" _ACME_CURL="$_ACME_CURL --trace-ascii $_CURL_DUMP " diff --git a/deploy/qiniu.sh b/deploy/qiniu.sh index 4fa66ee6..070b7f69 100644 --- a/deploy/qiniu.sh +++ b/deploy/qiniu.sh @@ -44,30 +44,53 @@ qiniu_deploy() { string_fullchain=$(awk '{printf "%s\\n", $0}' "$_cfullchain") string_key=$(awk '{printf "%s\\n", $0}' "$_ckey") - body="{\"name\":\"$_cdomain\",\"common_name\":\"$_cdomain\",\"ca\":\""$string_fullchain"\",\"pri\":\"$string_key\"}" + sslcerl_body="{\"name\":\"$_cdomain\",\"common_name\":\"$_cdomain\",\"ca\":\""$string_fullchain"\",\"pri\":\"$string_key\"}" create_ssl_url="$QINIU_API_BASE/sslcert" - ACCESSTOKEN="$(_make_sslcreate_access_token)" - export _H1="Authorization: QBox $ACCESSTOKEN" + sslcert_access_token="$(_make_sslcreate_access_token "/sslcert\\n")" + _debug sslcert_access_token "$sslcert_access_token" + export _H1="Authorization: QBox $sslcert_access_token" - _response=$(_post "$body" "$create_ssl_url" 0 "POST" "application/json" | _dbase64 "multiline") + sslcert_response=$(_post "$sslcerl_body" "$create_ssl_url" 0 "POST" "application/json" | _dbase64 "multiline") success_response="certID" - if test "${_response#*$success_response}" == "$_response"; then - _err "Error in deploying certificate:" - _err "$_response" + if test "${sslcert_response#*$success_response}" == "$sslcert_response"; then + _err "Error in creating certificate:" + _err "$sslcert_response" return 1 fi - _debug response "$_response" + _debug sslcert_response "$sslcert_response" + _info "Certificate successfully uploaded, updating domain $_cdomain" + + _certId=$(printf "%s" $sslcert_response | sed -e "s/^.*certID\":\"//" -e "s/\"\}$//") + _debug certId "$_certId" + + update_path="/domain/$_cdomain/httpsconf" + update_url="$QINIU_API_BASE$update_path" + update_body="{\"certid\":\""$_certId"\",\"forceHttps\":true}" + + update_access_token="$(_make_sslcreate_access_token "$update_path\\n")" + _debug update_access_token "$update_access_token" + export _H1="Authorization: QBox $update_access_token" + update_response=$(_post "$update_body" "$update_url" 0 "PUT" "application/json" | _dbase64 "multiline") + + err_response="error" + if test "${update_response#*$err_response}" != "$update_response"; then + _err "Error in updating domain:" + _err "$update_response" + return 1 + fi + + _debug update_response "$update_response" _info "Certificate successfully deployed" return 0 } _make_sslcreate_access_token() { - _data="/sslcert\\n" + _data="$1" _token="$(printf "$_data" | openssl sha1 -hmac $Le_Deploy_Qiniu_SK -binary | openssl base64 -e)" echo "$Le_Deploy_Qiniu_AK:$_token" } From d2a60f3ca42aead53dedbb7afa841919ac75fc83 Mon Sep 17 00:00:00 2001 From: shonenada Date: Sat, 12 Jan 2019 15:54:42 +0800 Subject: [PATCH 31/61] lint code --- deploy/qiniu.sh | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/deploy/qiniu.sh b/deploy/qiniu.sh index 070b7f69..4f578b27 100644 --- a/deploy/qiniu.sh +++ b/deploy/qiniu.sh @@ -41,18 +41,16 @@ qiniu_deploy() { _savedomainconf Le_Deploy_Qiniu_SK "$Le_Deploy_Qiniu_SK" fi + ## upload certificate string_fullchain=$(awk '{printf "%s\\n", $0}' "$_cfullchain") string_key=$(awk '{printf "%s\\n", $0}' "$_ckey") - sslcerl_body="{\"name\":\"$_cdomain\",\"common_name\":\"$_cdomain\",\"ca\":\""$string_fullchain"\",\"pri\":\"$string_key\"}" - - create_ssl_url="$QINIU_API_BASE/sslcert" - - sslcert_access_token="$(_make_sslcreate_access_token "/sslcert\\n")" + sslcert_path="/sslcert" + sslcerl_body="{\"name\":\"$_cdomain\",\"common_name\":\"$_cdomain\",\"ca\":\"$string_fullchain\",\"pri\":\"$string_key\"}" + sslcert_access_token="$(_make_sslcreate_access_token "$sslcert_path")" _debug sslcert_access_token "$sslcert_access_token" export _H1="Authorization: QBox $sslcert_access_token" - - sslcert_response=$(_post "$sslcerl_body" "$create_ssl_url" 0 "POST" "application/json" | _dbase64 "multiline") + sslcert_response=$(_post "$sslcerl_body" "$QINIU_API_BASE$sslcert_path" 0 "POST" "application/json" | _dbase64 "multiline") success_response="certID" if test "${sslcert_response#*$success_response}" == "$sslcert_response"; then @@ -64,21 +62,21 @@ qiniu_deploy() { _debug sslcert_response "$sslcert_response" _info "Certificate successfully uploaded, updating domain $_cdomain" - _certId=$(printf "%s" $sslcert_response | sed -e "s/^.*certID\":\"//" -e "s/\"\}$//") + ## extract certId + _certId=$(printf "%s" "$sslcert_response" | sed -e "s/^.*certID\":\"//" -e "s/\"\}$//") _debug certId "$_certId" + ## update domain ssl config update_path="/domain/$_cdomain/httpsconf" - update_url="$QINIU_API_BASE$update_path" - update_body="{\"certid\":\""$_certId"\",\"forceHttps\":true}" - - update_access_token="$(_make_sslcreate_access_token "$update_path\\n")" + update_body="{\"certid\":\"$_certId\",\"forceHttps\":true}" + update_access_token="$(_make_sslcreate_access_token "$update_path")" _debug update_access_token "$update_access_token" export _H1="Authorization: QBox $update_access_token" - update_response=$(_post "$update_body" "$update_url" 0 "PUT" "application/json" | _dbase64 "multiline") + update_response=$(_post "$update_body" "$QINIU_API_BASE$update_body" 0 "PUT" "application/json" | _dbase64 "multiline") err_response="error" if test "${update_response#*$err_response}" != "$update_response"; then - _err "Error in updating domain:" + _err "Error in updating domain httpsconf:" _err "$update_response" return 1 fi @@ -90,7 +88,7 @@ qiniu_deploy() { } _make_sslcreate_access_token() { - _data="$1" - _token="$(printf "$_data" | openssl sha1 -hmac $Le_Deploy_Qiniu_SK -binary | openssl base64 -e)" + _data="$1\\n" + _token="$(printf "%s" "$_data" | openssl sha1 -hmac "$Le_Deploy_Qiniu_SK" -binary | openssl base64 -e)" echo "$Le_Deploy_Qiniu_AK:$_token" } From 4ec39ab707069e8fe87eccffc289dc0432afcc53 Mon Sep 17 00:00:00 2001 From: shonenada Date: Sat, 12 Jan 2019 19:58:57 +0800 Subject: [PATCH 32/61] replace with functions defined in acme.sh --- deploy/qiniu.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/deploy/qiniu.sh b/deploy/qiniu.sh index 4f578b27..c2306c51 100644 --- a/deploy/qiniu.sh +++ b/deploy/qiniu.sh @@ -72,7 +72,7 @@ qiniu_deploy() { update_access_token="$(_make_sslcreate_access_token "$update_path")" _debug update_access_token "$update_access_token" export _H1="Authorization: QBox $update_access_token" - update_response=$(_post "$update_body" "$QINIU_API_BASE$update_body" 0 "PUT" "application/json" | _dbase64 "multiline") + update_response=$(_post "$update_body" "$QINIU_API_BASE$update_path" 0 "PUT" "application/json" | _dbase64 "multiline") err_response="error" if test "${update_response#*$err_response}" != "$update_response"; then @@ -88,7 +88,6 @@ qiniu_deploy() { } _make_sslcreate_access_token() { - _data="$1\\n" - _token="$(printf "%s" "$_data" | openssl sha1 -hmac "$Le_Deploy_Qiniu_SK" -binary | openssl base64 -e)" + _token="$(printf "%s\\n" "$1" | _hmac "sha1" "$(printf "%s" "$Le_Deploy_Qiniu_SK" | _hex_dump | tr -d " ")" | _base64)" echo "$Le_Deploy_Qiniu_AK:$_token" } From 82b11da4caf356f418e12ca5c5fd047bbe21d37e Mon Sep 17 00:00:00 2001 From: shonenada Date: Sat, 12 Jan 2019 21:07:22 +0800 Subject: [PATCH 33/61] replace `awk` with `sed` and `tr` --- deploy/qiniu.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deploy/qiniu.sh b/deploy/qiniu.sh index c2306c51..559e59cf 100644 --- a/deploy/qiniu.sh +++ b/deploy/qiniu.sh @@ -42,8 +42,8 @@ qiniu_deploy() { fi ## upload certificate - string_fullchain=$(awk '{printf "%s\\n", $0}' "$_cfullchain") - string_key=$(awk '{printf "%s\\n", $0}' "$_ckey") + string_fullchain=$(sed 's/$/\\n/' "$_cfullchain" | tr -d '\n') + string_key=$(sed 's/$/\\n/' "$_ckey" | tr -d '\n') sslcert_path="/sslcert" sslcerl_body="{\"name\":\"$_cdomain\",\"common_name\":\"$_cdomain\",\"ca\":\"$string_fullchain\",\"pri\":\"$string_key\"}" @@ -63,12 +63,12 @@ qiniu_deploy() { _info "Certificate successfully uploaded, updating domain $_cdomain" ## extract certId - _certId=$(printf "%s" "$sslcert_response" | sed -e "s/^.*certID\":\"//" -e "s/\"\}$//") + _certId="$(printf "%s" "$sslcert_response" | _normalizeJson | _egrep_o "certID\":\s*\"[^\"]*\"" | cut -d : -f 2)" _debug certId "$_certId" ## update domain ssl config update_path="/domain/$_cdomain/httpsconf" - update_body="{\"certid\":\"$_certId\",\"forceHttps\":true}" + update_body="{\"certid\":$_certId,\"forceHttps\":true}" update_access_token="$(_make_sslcreate_access_token "$update_path")" _debug update_access_token "$update_access_token" export _H1="Authorization: QBox $update_access_token" From 0cd6afde6f586a3791952f07a3fe99c5f7e45ed3 Mon Sep 17 00:00:00 2001 From: shonenada Date: Sat, 12 Jan 2019 21:15:16 +0800 Subject: [PATCH 34/61] Add guidance to deploying cert to qiniu.com --- deploy/README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/deploy/README.md b/deploy/README.md index cec7d773..68c1a272 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -332,3 +332,19 @@ variable to anything (ex: "1") before running `acme.sh`: ```sh export FABIO="1" ``` + +## 13. Deploy your certificate to Qiniu.com + +You should create AccessKey/SecretKey pair in https://portal.qiniu.com/user/key before deploying +your certificate. + +```sh +$ export QINIU_AK="foo" +$ export QINIU_SK="bar" +``` + +then you can deploy certificate by following command: + +```sh +$ acme.sh --deploy -d example.com --deploy-hook qiniu +``` From 96efc8c7f025b6b862c9502abf44434fcd6b0693 Mon Sep 17 00:00:00 2001 From: shonenada Date: Sat, 12 Jan 2019 23:11:19 +0800 Subject: [PATCH 35/61] lint codes --- deploy/qiniu.sh | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/deploy/qiniu.sh b/deploy/qiniu.sh index 559e59cf..e0be60fe 100644 --- a/deploy/qiniu.sh +++ b/deploy/qiniu.sh @@ -52,8 +52,7 @@ qiniu_deploy() { export _H1="Authorization: QBox $sslcert_access_token" sslcert_response=$(_post "$sslcerl_body" "$QINIU_API_BASE$sslcert_path" 0 "POST" "application/json" | _dbase64 "multiline") - success_response="certID" - if test "${sslcert_response#*$success_response}" == "$sslcert_response"; then + if ! _contains "$sslcert_response" "certID"; then _err "Error in creating certificate:" _err "$sslcert_response" return 1 @@ -63,7 +62,7 @@ qiniu_deploy() { _info "Certificate successfully uploaded, updating domain $_cdomain" ## extract certId - _certId="$(printf "%s" "$sslcert_response" | _normalizeJson | _egrep_o "certID\":\s*\"[^\"]*\"" | cut -d : -f 2)" + _certId="$(printf "%s" "$sslcert_response" | _normalizeJson | _egrep_o "certID\": *\"[^\"]*\"" | cut -d : -f 2)" _debug certId "$_certId" ## update domain ssl config @@ -74,8 +73,7 @@ qiniu_deploy() { export _H1="Authorization: QBox $update_access_token" update_response=$(_post "$update_body" "$QINIU_API_BASE$update_path" 0 "PUT" "application/json" | _dbase64 "multiline") - err_response="error" - if test "${update_response#*$err_response}" != "$update_response"; then + if _contains "$update_response" "error"; then _err "Error in updating domain httpsconf:" _err "$update_response" return 1 @@ -88,6 +86,6 @@ qiniu_deploy() { } _make_sslcreate_access_token() { - _token="$(printf "%s\\n" "$1" | _hmac "sha1" "$(printf "%s" "$Le_Deploy_Qiniu_SK" | _hex_dump | tr -d " ")" | _base64)" + _token="$(printf "%s\n" "$1" | _hmac "sha1" "$(printf "%s" "$Le_Deploy_Qiniu_SK" | _hex_dump | tr -d " ")" | _base64)" echo "$Le_Deploy_Qiniu_AK:$_token" } From 3c6b707353007d476e758932dfca1e7125e534b1 Mon Sep 17 00:00:00 2001 From: shonenada Date: Sun, 13 Jan 2019 12:23:15 +0800 Subject: [PATCH 36/61] add `QINIU_CDN_DOMAIN` for wildcard certificate --- deploy/README.md | 14 ++++++++++++-- deploy/qiniu.sh | 6 ++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/deploy/README.md b/deploy/README.md index 68c1a272..fa2d7189 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -335,8 +335,9 @@ export FABIO="1" ## 13. Deploy your certificate to Qiniu.com -You should create AccessKey/SecretKey pair in https://portal.qiniu.com/user/key before deploying -your certificate. +You should create AccessKey/SecretKey pair in https://portal.qiniu.com/user/key +before deploying your certificate, and please ensure you have enabled HTTPS for +your domain name. You can enable it in https://portal.qiniu.com/cdn/domain. ```sh $ export QINIU_AK="foo" @@ -348,3 +349,12 @@ then you can deploy certificate by following command: ```sh $ acme.sh --deploy -d example.com --deploy-hook qiniu ``` + +(Optional), If you are using wildcard certificate, +you may need export `QINIU_CDN_DOMAIN` to specify which domain +you want to update: + +```sh +$ export QINIU_CDN_DOMAIN="cdn.example.com" +$ acme.sh --deploy -d example.com --deploy-hook qiniu +``` diff --git a/deploy/qiniu.sh b/deploy/qiniu.sh index e0be60fe..dac1866d 100644 --- a/deploy/qiniu.sh +++ b/deploy/qiniu.sh @@ -5,6 +5,7 @@ # This deployment required following variables # export QINIU_AK="QINIUACCESSKEY" # export QINIU_SK="QINIUSECRETKEY" +# export QINIU_CDN_DOMAIN="cdn.example.com" QINIU_API_BASE="https://api.qiniu.com" @@ -14,6 +15,7 @@ qiniu_deploy() { _ccert="$3" _cca="$4" _cfullchain="$5" + _cdndomain="${QINIU_CDN_DOMAIN:-$_cdomain}" _debug _cdomain "$_cdomain" _debug _ckey "$_ckey" @@ -46,7 +48,7 @@ qiniu_deploy() { string_key=$(sed 's/$/\\n/' "$_ckey" | tr -d '\n') sslcert_path="/sslcert" - sslcerl_body="{\"name\":\"$_cdomain\",\"common_name\":\"$_cdomain\",\"ca\":\"$string_fullchain\",\"pri\":\"$string_key\"}" + sslcerl_body="{\"name\":\"$_cdomain\",\"common_name\":\"$_cdndomain\",\"ca\":\"$string_fullchain\",\"pri\":\"$string_key\"}" sslcert_access_token="$(_make_sslcreate_access_token "$sslcert_path")" _debug sslcert_access_token "$sslcert_access_token" export _H1="Authorization: QBox $sslcert_access_token" @@ -66,7 +68,7 @@ qiniu_deploy() { _debug certId "$_certId" ## update domain ssl config - update_path="/domain/$_cdomain/httpsconf" + update_path="/domain/$_cdndomain/httpsconf" update_body="{\"certid\":$_certId,\"forceHttps\":true}" update_access_token="$(_make_sslcreate_access_token "$update_path")" _debug update_access_token "$update_access_token" From 4c1fa9c2422143b164448b6e7c327bb293f808a8 Mon Sep 17 00:00:00 2001 From: shonenada Date: Mon, 14 Jan 2019 22:19:00 +0800 Subject: [PATCH 37/61] save CDN Domain with `_savedomainconf` --- deploy/qiniu.sh | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/deploy/qiniu.sh b/deploy/qiniu.sh index dac1866d..a97dfbbf 100644 --- a/deploy/qiniu.sh +++ b/deploy/qiniu.sh @@ -15,7 +15,6 @@ qiniu_deploy() { _ccert="$3" _cca="$4" _cfullchain="$5" - _cdndomain="${QINIU_CDN_DOMAIN:-$_cdomain}" _debug _cdomain "$_cdomain" _debug _ckey "$_ckey" @@ -43,13 +42,20 @@ qiniu_deploy() { _savedomainconf Le_Deploy_Qiniu_SK "$Le_Deploy_Qiniu_SK" fi + Le_Deploy_Qiniu_Cdn_Domain="${QINIU_CDN_DOMAIN:-$(_readdomainconf Le_Deploy_Qiniu_Cdn_Domain)}" + if [ -z "$Le_Deploy_Qiniu_Cdn_Domain" ]; then + Le_Deploy_Qiniu_Cdn_Domain="$_cdomain" + fi + + _savedomainconf Le_Deploy_Qiniu_Cdn_Domain "$Le_Deploy_Qiniu_Cdn_Domain" + ## upload certificate string_fullchain=$(sed 's/$/\\n/' "$_cfullchain" | tr -d '\n') string_key=$(sed 's/$/\\n/' "$_ckey" | tr -d '\n') sslcert_path="/sslcert" - sslcerl_body="{\"name\":\"$_cdomain\",\"common_name\":\"$_cdndomain\",\"ca\":\"$string_fullchain\",\"pri\":\"$string_key\"}" - sslcert_access_token="$(_make_sslcreate_access_token "$sslcert_path")" + sslcerl_body="{\"name\":\"$_cdomain\",\"common_name\":\"$Le_Deploy_Qiniu_Cdn_Domain\",\"ca\":\"$string_fullchain\",\"pri\":\"$string_key\"}" + sslcert_access_token="$(_make_access_token "$sslcert_path")" _debug sslcert_access_token "$sslcert_access_token" export _H1="Authorization: QBox $sslcert_access_token" sslcert_response=$(_post "$sslcerl_body" "$QINIU_API_BASE$sslcert_path" 0 "POST" "application/json" | _dbase64 "multiline") @@ -68,9 +74,9 @@ qiniu_deploy() { _debug certId "$_certId" ## update domain ssl config - update_path="/domain/$_cdndomain/httpsconf" - update_body="{\"certid\":$_certId,\"forceHttps\":true}" - update_access_token="$(_make_sslcreate_access_token "$update_path")" + update_path="/domain/$Le_Deploy_Qiniu_Cdn_Domain/httpsconf" + update_body="{\"certid\":$_certId,\"forceHttps\":false}" + update_access_token="$(_make_access_token "$update_path")" _debug update_access_token "$update_access_token" export _H1="Authorization: QBox $update_access_token" update_response=$(_post "$update_body" "$QINIU_API_BASE$update_path" 0 "PUT" "application/json" | _dbase64 "multiline") @@ -87,7 +93,7 @@ qiniu_deploy() { return 0 } -_make_sslcreate_access_token() { +_make_access_token() { _token="$(printf "%s\n" "$1" | _hmac "sha1" "$(printf "%s" "$Le_Deploy_Qiniu_SK" | _hex_dump | tr -d " ")" | _base64)" echo "$Le_Deploy_Qiniu_AK:$_token" } From 10ba2cd312fb346a9af32a808ddbfa1d55b83879 Mon Sep 17 00:00:00 2001 From: jim-p Date: Thu, 10 Jan 2019 16:06:46 -0500 Subject: [PATCH 38/61] Use a literal space instead of an escaped space. Fixes #2022 --- dnsapi/dns_namecheap.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index a6651be6..2f401bd9 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -161,12 +161,12 @@ _namecheap_parse_host() { _host=$1 _debug _host "$_host" - _hostid=$(echo "$_host" | _egrep_o '\sHostId="[^"]*' | cut -d '"' -f 2) - _hostname=$(echo "$_host" | _egrep_o '\sName="[^"]*' | cut -d '"' -f 2) - _hosttype=$(echo "$_host" | _egrep_o '\sType="[^"]*' | cut -d '"' -f 2) - _hostaddress=$(echo "$_host" | _egrep_o '\sAddress="[^"]*' | cut -d '"' -f 2) - _hostmxpref=$(echo "$_host" | _egrep_o '\sMXPref="[^"]*' | cut -d '"' -f 2) - _hostttl=$(echo "$_host" | _egrep_o '\sTTL="[^"]*' | cut -d '"' -f 2) + _hostid=$(echo "$_host" | _egrep_o ' HostId="[^"]*' | cut -d '"' -f 2) + _hostname=$(echo "$_host" | _egrep_o ' Name="[^"]*' | cut -d '"' -f 2) + _hosttype=$(echo "$_host" | _egrep_o ' Type="[^"]*' | cut -d '"' -f 2) + _hostaddress=$(echo "$_host" | _egrep_o ' Address="[^"]*' | cut -d '"' -f 2) + _hostmxpref=$(echo "$_host" | _egrep_o ' MXPref="[^"]*' | cut -d '"' -f 2) + _hostttl=$(echo "$_host" | _egrep_o ' TTL="[^"]*' | cut -d '"' -f 2) _debug hostid "$_hostid" _debug hostname "$_hostname" From afdb9a63ffa4540dd8d3097492b8940b21b50907 Mon Sep 17 00:00:00 2001 From: shonenada Date: Sat, 19 Jan 2019 23:58:55 +0800 Subject: [PATCH 39/61] chore: replece `Le_Deploy_Qiniu_*` with `QINIU_*` --- deploy/qiniu.sh | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/deploy/qiniu.sh b/deploy/qiniu.sh index a97dfbbf..aadda53b 100644 --- a/deploy/qiniu.sh +++ b/deploy/qiniu.sh @@ -23,38 +23,31 @@ qiniu_deploy() { _debug _cfullchain "$_cfullchain" if [ -z "$QINIU_AK" ]; then - if [ -z "$Le_Deploy_Qiniu_AK" ]; then - _err "QINIU_AK is not defined." - return 1 - fi + _err "QINIU_AK is not defined." + return 1 else - Le_Deploy_Qiniu_AK="$QINIU_AK" - _savedomainconf Le_Deploy_Qiniu_AK "$Le_Deploy_Qiniu_AK" + _savedomainconf QINIU_AK "$QINIU_AK" fi if [ -z "$QINIU_SK" ]; then - if [ -z "$Le_Deploy_Qiniu_SK" ]; then - _err "QINIU_SK is not defined." - return 1 - fi + _err "QINIU_SK is not defined." + return 1 else - Le_Deploy_Qiniu_SK="$QINIU_SK" - _savedomainconf Le_Deploy_Qiniu_SK "$Le_Deploy_Qiniu_SK" + _savedomainconf QINIU_SK "$QINIU_SK" fi - Le_Deploy_Qiniu_Cdn_Domain="${QINIU_CDN_DOMAIN:-$(_readdomainconf Le_Deploy_Qiniu_Cdn_Domain)}" - if [ -z "$Le_Deploy_Qiniu_Cdn_Domain" ]; then - Le_Deploy_Qiniu_Cdn_Domain="$_cdomain" + if [ -z "$QINIU_CDN_DOMAIN" ]; then + QINIU_CDN_DOMAIN="$_cdomain" fi - _savedomainconf Le_Deploy_Qiniu_Cdn_Domain "$Le_Deploy_Qiniu_Cdn_Domain" + _savedomainconf QINIU_CDN_DOMAIN "$QINIU_CDN_DOMAIN" ## upload certificate string_fullchain=$(sed 's/$/\\n/' "$_cfullchain" | tr -d '\n') string_key=$(sed 's/$/\\n/' "$_ckey" | tr -d '\n') sslcert_path="/sslcert" - sslcerl_body="{\"name\":\"$_cdomain\",\"common_name\":\"$Le_Deploy_Qiniu_Cdn_Domain\",\"ca\":\"$string_fullchain\",\"pri\":\"$string_key\"}" + sslcerl_body="{\"name\":\"$_cdomain\",\"common_name\":\"$QINIU_CDN_DOMAIN\",\"ca\":\"$string_fullchain\",\"pri\":\"$string_key\"}" sslcert_access_token="$(_make_access_token "$sslcert_path")" _debug sslcert_access_token "$sslcert_access_token" export _H1="Authorization: QBox $sslcert_access_token" @@ -74,7 +67,7 @@ qiniu_deploy() { _debug certId "$_certId" ## update domain ssl config - update_path="/domain/$Le_Deploy_Qiniu_Cdn_Domain/httpsconf" + update_path="/domain/$QINIU_CDN_DOMAIN/httpsconf" update_body="{\"certid\":$_certId,\"forceHttps\":false}" update_access_token="$(_make_access_token "$update_path")" _debug update_access_token "$update_access_token" @@ -94,6 +87,6 @@ qiniu_deploy() { } _make_access_token() { - _token="$(printf "%s\n" "$1" | _hmac "sha1" "$(printf "%s" "$Le_Deploy_Qiniu_SK" | _hex_dump | tr -d " ")" | _base64)" - echo "$Le_Deploy_Qiniu_AK:$_token" + _token="$(printf "%s\n" "$1" | _hmac "sha1" "$(printf "%s" "$QINIU_SK" | _hex_dump | tr -d " ")" | _base64)" + echo "$QINIU_AK:$_token" } From dd6fa4af0075248585202eab93ac89f51b652c0e Mon Sep 17 00:00:00 2001 From: shonenada Date: Sun, 20 Jan 2019 23:58:10 +0800 Subject: [PATCH 40/61] Save `QINIU_CDN_DOMAIN` only when defined --- deploy/qiniu.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deploy/qiniu.sh b/deploy/qiniu.sh index aadda53b..8410caa9 100644 --- a/deploy/qiniu.sh +++ b/deploy/qiniu.sh @@ -36,12 +36,12 @@ qiniu_deploy() { _savedomainconf QINIU_SK "$QINIU_SK" fi - if [ -z "$QINIU_CDN_DOMAIN" ]; then - QINIU_CDN_DOMAIN="$_cdomain" + if [ "$QINIU_CDN_DOMAIN" ]; then + _savedomainconf QINIU_CDN_DOMAIN "$QINIU_CDN_DOMAIN" + else + QINIU_CDN_DOMAIN="$_cdomain" fi - _savedomainconf QINIU_CDN_DOMAIN "$QINIU_CDN_DOMAIN" - ## upload certificate string_fullchain=$(sed 's/$/\\n/' "$_cfullchain" | tr -d '\n') string_key=$(sed 's/$/\\n/' "$_ckey" | tr -d '\n') From e8eec2cb41b34bf52fff36647a4861bec23fa653 Mon Sep 17 00:00:00 2001 From: shonenada Date: Mon, 21 Jan 2019 00:08:23 +0800 Subject: [PATCH 41/61] add chinese readme --- deploy/README.md | 2 ++ deploy/README_zh.md | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 deploy/README_zh.md diff --git a/deploy/README.md b/deploy/README.md index fa2d7189..a9e28e9e 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -335,6 +335,8 @@ export FABIO="1" ## 13. Deploy your certificate to Qiniu.com +[中文文档](https://github.com/Neilpang/acme.sh/blob/master/deploy/README_zh.md#13-%E9%83%A8%E7%BD%B2%E5%88%B0%E4%B8%83%E7%89%9B%E5%9F%9F%E5%90%8D%E8%AF%81%E4%B9%A6%E6%9C%8D%E5%8A%A1) + You should create AccessKey/SecretKey pair in https://portal.qiniu.com/user/key before deploying your certificate, and please ensure you have enabled HTTPS for your domain name. You can enable it in https://portal.qiniu.com/cdn/domain. diff --git a/deploy/README_zh.md b/deploy/README_zh.md new file mode 100644 index 00000000..4132dcea --- /dev/null +++ b/deploy/README_zh.md @@ -0,0 +1,24 @@ +# Deploy 使用文档 + +## 13. 部署到七牛域名证书服务 + +使用 acme.sh 部署到七牛之前,需要确保部署的域名已打开 HTTPS 功能,您可以访问[融合 CDN - 域名管理](https://portal.qiniu.com/cdn/domain) 设置。 +另外还需要先导出 AK/SK 环境变量,您可以访问[密钥管理](https://portal.qiniu.com/user/key) 获得。 + +```sh +$ export QINIU_AK="foo" +$ export QINIU_SK="bar" +``` + +完成准备工作之后,您就可以通过下面的命令开始部署 SSL 证书到七牛上: + +```sh +$ acme.sh --deploy -d example.com --deploy-hook qiniu +``` + +假如您部署的证书为泛域名证书,您还需要设置 `QINIU_CDN_DOMAIN` 变量,指定实际需要部署的域名: + +```sh +$ export QINIU_CDN_DOMAIN="cdn.example.com" +$ acme.sh --deploy -d example.com --deploy-hook qiniu +``` From c445e70cffe326219b8d597867ba28ae85523ba1 Mon Sep 17 00:00:00 2001 From: shonenada Date: Mon, 21 Jan 2019 14:33:15 +0800 Subject: [PATCH 42/61] fix indent --- deploy/qiniu.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/qiniu.sh b/deploy/qiniu.sh index 8410caa9..158b8dbf 100644 --- a/deploy/qiniu.sh +++ b/deploy/qiniu.sh @@ -37,9 +37,9 @@ qiniu_deploy() { fi if [ "$QINIU_CDN_DOMAIN" ]; then - _savedomainconf QINIU_CDN_DOMAIN "$QINIU_CDN_DOMAIN" + _savedomainconf QINIU_CDN_DOMAIN "$QINIU_CDN_DOMAIN" else - QINIU_CDN_DOMAIN="$_cdomain" + QINIU_CDN_DOMAIN="$_cdomain" fi ## upload certificate From a4a53e1355503efa8a550f954f59cc3a2b763935 Mon Sep 17 00:00:00 2001 From: shonenada Date: Mon, 21 Jan 2019 17:31:21 +0800 Subject: [PATCH 43/61] Move docs into README.md from README_zh.md --- deploy/README.md | 23 ++++++++++++++++++++++- deploy/README_zh.md | 24 ------------------------ 2 files changed, 22 insertions(+), 25 deletions(-) delete mode 100644 deploy/README_zh.md diff --git a/deploy/README.md b/deploy/README.md index a9e28e9e..091e9feb 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -335,7 +335,28 @@ export FABIO="1" ## 13. Deploy your certificate to Qiniu.com -[中文文档](https://github.com/Neilpang/acme.sh/blob/master/deploy/README_zh.md#13-%E9%83%A8%E7%BD%B2%E5%88%B0%E4%B8%83%E7%89%9B%E5%9F%9F%E5%90%8D%E8%AF%81%E4%B9%A6%E6%9C%8D%E5%8A%A1) +使用 acme.sh 部署到七牛之前,需要确保部署的域名已打开 HTTPS 功能,您可以访问[融合 CDN - 域名管理](https://portal.qiniu.com/cdn/domain) 设置。 +另外还需要先导出 AK/SK 环境变量,您可以访问[密钥管理](https://portal.qiniu.com/user/key) 获得。 + +```sh +$ export QINIU_AK="foo" +$ export QINIU_SK="bar" +``` + +完成准备工作之后,您就可以通过下面的命令开始部署 SSL 证书到七牛上: + +```sh +$ acme.sh --deploy -d example.com --deploy-hook qiniu +``` + +假如您部署的证书为泛域名证书,您还需要设置 `QINIU_CDN_DOMAIN` 变量,指定实际需要部署的域名: + +```sh +$ export QINIU_CDN_DOMAIN="cdn.example.com" +$ acme.sh --deploy -d example.com --deploy-hook qiniu +``` + +### English version You should create AccessKey/SecretKey pair in https://portal.qiniu.com/user/key before deploying your certificate, and please ensure you have enabled HTTPS for diff --git a/deploy/README_zh.md b/deploy/README_zh.md deleted file mode 100644 index 4132dcea..00000000 --- a/deploy/README_zh.md +++ /dev/null @@ -1,24 +0,0 @@ -# Deploy 使用文档 - -## 13. 部署到七牛域名证书服务 - -使用 acme.sh 部署到七牛之前,需要确保部署的域名已打开 HTTPS 功能,您可以访问[融合 CDN - 域名管理](https://portal.qiniu.com/cdn/domain) 设置。 -另外还需要先导出 AK/SK 环境变量,您可以访问[密钥管理](https://portal.qiniu.com/user/key) 获得。 - -```sh -$ export QINIU_AK="foo" -$ export QINIU_SK="bar" -``` - -完成准备工作之后,您就可以通过下面的命令开始部署 SSL 证书到七牛上: - -```sh -$ acme.sh --deploy -d example.com --deploy-hook qiniu -``` - -假如您部署的证书为泛域名证书,您还需要设置 `QINIU_CDN_DOMAIN` 变量,指定实际需要部署的域名: - -```sh -$ export QINIU_CDN_DOMAIN="cdn.example.com" -$ acme.sh --deploy -d example.com --deploy-hook qiniu -``` From 56d70e4ea74d2c1274326ec0ac9c93657d9b4e94 Mon Sep 17 00:00:00 2001 From: Oliver Dick Date: Mon, 21 Jan 2019 15:02:09 +0100 Subject: [PATCH 44/61] Update to latest API Changes --- dnsapi/dns_hostingde.sh | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/dnsapi/dns_hostingde.sh b/dnsapi/dns_hostingde.sh index 74a472d2..7c185119 100644 --- a/dnsapi/dns_hostingde.sh +++ b/dnsapi/dns_hostingde.sh @@ -59,9 +59,22 @@ _hostingde_getZoneConfig() { if _contains "${curResult}" '"totalEntries": 1'; then _info "Retrieved zone data." _debug "Zone data: '${curResult}'" - - # read ZoneConfigId for later update zoneConfigId=$(echo "${curResult}" | _egrep_o '"id":.*' | cut -d ':' -f 2 | cut -d '"' -f 2) + zoneConfigName=$(echo "${curResult}" | _egrep_o '"name":.*' | cut -d ':' -f 2 | cut -d '"' -f 2) + zoneConfigType=$(echo "${curResult}" | grep -v "FindZoneConfigsResult" | _egrep_o '"type":.*' | cut -d ':' -f 2 | cut -d '"' -f 2) + zoneConfigExpire=$(echo "${curResult}" | _egrep_o '"expire":.*' | cut -d ':' -f 2 | cut -d '"' -f 2 | cut -d ',' -f 1) + zoneConfigNegativeTtl=$(echo "${curResult}" | _egrep_o '"negativeTtl":.*' | cut -d ':' -f 2 | cut -d '"' -f 2 | cut -d ',' -f 1) + zoneConfigRefresh=$(echo "${curResult}" | _egrep_o '"refresh":.*' | cut -d ':' -f 2 | cut -d '"' -f 2| cut -d ',' -f 1) + zoneConfigRetry=$(echo "${curResult}" | _egrep_o '"retry":.*' | cut -d ':' -f 2 | cut -d '"' -f 2| cut -d ',' -f 1) + zoneConfigTtl=$(echo "${curResult}" | _egrep_o '"ttl":.*' | cut -d ':' -f 2 | cut -d '"' -f 2| cut -d ',' -f 1) + zoneConfigDnsServerGroupId=$(echo "${curResult}" | _egrep_o '"dnsServerGroupId":.*' | cut -d ':' -f 2 | cut -d '"' -f 2) + zoneConfigEmailAddress=$(echo "${curResult}" | _egrep_o '"emailAddress":.*' | cut -d ':' -f 2 | cut -d '"' -f 2) + zoneConfigDnsSecMode=$(echo "${curResult}" | _egrep_o '"dnsSecMode":.*' | cut -d ':' -f 2 | cut -d '"' -f 2) + if [ $zoneConfigType != "NATIVE" ]; then + _err "Zone is not native" + returnCode=1 + break + fi _debug "zoneConfigId '${zoneConfigId}'" returnCode=0 break @@ -94,7 +107,7 @@ _hostingde_addRecord() { _hostingde_getZoneStatus _debug "Result of zoneStatus: '${zoneStatus}'" done - curData="{\"authToken\":\"${HOSTINGDE_APIKEY}\",\"zoneConfig\":{\"id\":\"${zoneConfigId}\"},\"recordsToAdd\":[{\"name\":\"${fulldomain}\",\"type\":\"TXT\",\"content\":\"\\\"${txtvalue}\\\"\",\"ttl\":3600}]}" + curData="{\"authToken\":\"${HOSTINGDE_APIKEY}\",\"zoneConfig\":{\"id\":\"${zoneConfigId}\",\"name\":\"${zoneConfigName}\",\"type\":\"${zoneConfigType}\",\"dnsServerGroupId\":\"${zoneConfigDnsServerGroupId}\",\"dnsSecMode\":\"${zoneConfigDnsSecMode}\",\"emailAddress\":\"${zoneConfigEmailAddress}\",\"soaValues\":{\"expire\":${zoneConfigExpire},\"negativeTtl\":${zoneConfigNegativeTtl},\"refresh\":${zoneConfigRefresh},\"retry\":${zoneConfigRetry},\"ttl\":${zoneConfigTtl}}},\"recordsToAdd\":[{\"name\":\"${fulldomain}\",\"type\":\"TXT\",\"content\":\"\\\"${txtvalue}\\\"\",\"ttl\":3600}]}" curResult="$(_post "${curData}" "${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zoneUpdate")" _debug "Calling zoneUpdate: '${curData}' '${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zoneUpdate'" _debug "Result of zoneUpdate: '$curResult'" @@ -118,7 +131,7 @@ _hostingde_removeRecord() { _hostingde_getZoneStatus _debug "Result of zoneStatus: '$zoneStatus'" done - curData="{\"authToken\":\"${HOSTINGDE_APIKEY}\",\"zoneConfig\":{\"id\":\"${zoneConfigId}\"},\"recordsToDelete\":[{\"name\":\"${fulldomain}\",\"type\":\"TXT\",\"content\":\"\\\"${txtvalue}\\\"\"}]}" + curData="{\"authToken\":\"${HOSTINGDE_APIKEY}\",\"zoneConfig\":{\"id\":\"${zoneConfigId}\",\"name\":\"${zoneConfigName}\",\"type\":\"${zoneConfigType}\",\"dnsServerGroupId\":\"${zoneConfigDnsServerGroupId}\",\"dnsSecMode\":\"${zoneConfigDnsSecMode}\",\"emailAddress\":\"${zoneConfigEmailAddress}\",\"soaValues\":{\"expire\":${zoneConfigExpire},\"negativeTtl\":${zoneConfigNegativeTtl},\"refresh\":${zoneConfigRefresh},\"retry\":${zoneConfigRetry},\"ttl\":${zoneConfigTtl}}},\"recordsToDelete\":[{\"name\":\"${fulldomain}\",\"type\":\"TXT\",\"content\":\"\\\"${txtvalue}\\\"\"}]}" curResult="$(_post "${curData}" "${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zoneUpdate")" _debug "Calling zoneUpdate: '${curData}' '${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zoneUpdate'" _debug "Result of zoneUpdate: '$curResult'" From b15c1ffedcd1d627e6339396179e7691ca83938e Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 21 Jan 2019 22:09:13 +0800 Subject: [PATCH 45/61] clean TXT records when error happens. https://github.com/Neilpang/acme.sh/issues/2037 --- acme.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index ff472867..697a14a4 100755 --- a/acme.sh +++ b/acme.sh @@ -2921,7 +2921,10 @@ _clearup() { _clearupdns() { _debug "_clearupdns" - if [ "$dnsadded" != 1 ] || [ -z "$vlist" ]; then + _debug "dnsadded" "$dnsadded" + _debug "vlist" "$vlist" + #dnsadded is "0" or "1" means dns-01 method was used for at least one domain + if [ -z "$dnsadded" ] || [ -z "$vlist" ]; then _debug "skip dns." return fi From 545f23551f09082799f02a159ed6ade2aa4eb36f Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 21 Jan 2019 22:25:23 +0800 Subject: [PATCH 46/61] trigger validation before cleanup fix https://github.com/Neilpang/acme.sh/issues/2037 --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 697a14a4..d651c4f5 100755 --- a/acme.sh +++ b/acme.sh @@ -3857,8 +3857,8 @@ $_authorizations_map" ) if [ "$?" != "0" ]; then - _clearup _on_issue_err "$_post_hook" "$vlist" + _clearup return 1 fi dnsadded='1' @@ -3869,8 +3869,8 @@ $_authorizations_map" _savedomainconf "Le_Vlist" "$vlist" _debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit." _err "Please add the TXT records to the domains, and re-run with --renew." - _clearup _on_issue_err "$_post_hook" + _clearup return 1 fi From 2dc50e66330c291fafee95d1b8d7183e413df647 Mon Sep 17 00:00:00 2001 From: Oliver Dick Date: Mon, 21 Jan 2019 15:45:32 +0100 Subject: [PATCH 47/61] making shfmt happy --- dnsapi/dns_hostingde.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_hostingde.sh b/dnsapi/dns_hostingde.sh index 7c185119..7f29d629 100644 --- a/dnsapi/dns_hostingde.sh +++ b/dnsapi/dns_hostingde.sh @@ -64,9 +64,9 @@ _hostingde_getZoneConfig() { zoneConfigType=$(echo "${curResult}" | grep -v "FindZoneConfigsResult" | _egrep_o '"type":.*' | cut -d ':' -f 2 | cut -d '"' -f 2) zoneConfigExpire=$(echo "${curResult}" | _egrep_o '"expire":.*' | cut -d ':' -f 2 | cut -d '"' -f 2 | cut -d ',' -f 1) zoneConfigNegativeTtl=$(echo "${curResult}" | _egrep_o '"negativeTtl":.*' | cut -d ':' -f 2 | cut -d '"' -f 2 | cut -d ',' -f 1) - zoneConfigRefresh=$(echo "${curResult}" | _egrep_o '"refresh":.*' | cut -d ':' -f 2 | cut -d '"' -f 2| cut -d ',' -f 1) - zoneConfigRetry=$(echo "${curResult}" | _egrep_o '"retry":.*' | cut -d ':' -f 2 | cut -d '"' -f 2| cut -d ',' -f 1) - zoneConfigTtl=$(echo "${curResult}" | _egrep_o '"ttl":.*' | cut -d ':' -f 2 | cut -d '"' -f 2| cut -d ',' -f 1) + zoneConfigRefresh=$(echo "${curResult}" | _egrep_o '"refresh":.*' | cut -d ':' -f 2 | cut -d '"' -f 2 | cut -d ',' -f 1) + zoneConfigRetry=$(echo "${curResult}" | _egrep_o '"retry":.*' | cut -d ':' -f 2 | cut -d '"' -f 2 | cut -d ',' -f 1) + zoneConfigTtl=$(echo "${curResult}" | _egrep_o '"ttl":.*' | cut -d ':' -f 2 | cut -d '"' -f 2 | cut -d ',' -f 1) zoneConfigDnsServerGroupId=$(echo "${curResult}" | _egrep_o '"dnsServerGroupId":.*' | cut -d ':' -f 2 | cut -d '"' -f 2) zoneConfigEmailAddress=$(echo "${curResult}" | _egrep_o '"emailAddress":.*' | cut -d ':' -f 2 | cut -d '"' -f 2) zoneConfigDnsSecMode=$(echo "${curResult}" | _egrep_o '"dnsSecMode":.*' | cut -d ':' -f 2 | cut -d '"' -f 2) From b0775f7a580ac534ad2443cd9308fab5b339749f Mon Sep 17 00:00:00 2001 From: Oliver Dick Date: Mon, 21 Jan 2019 16:32:45 +0100 Subject: [PATCH 48/61] making shftm really happy --- dnsapi/dns_hostingde.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_hostingde.sh b/dnsapi/dns_hostingde.sh index 7f29d629..b61acb7a 100644 --- a/dnsapi/dns_hostingde.sh +++ b/dnsapi/dns_hostingde.sh @@ -70,7 +70,7 @@ _hostingde_getZoneConfig() { zoneConfigDnsServerGroupId=$(echo "${curResult}" | _egrep_o '"dnsServerGroupId":.*' | cut -d ':' -f 2 | cut -d '"' -f 2) zoneConfigEmailAddress=$(echo "${curResult}" | _egrep_o '"emailAddress":.*' | cut -d ':' -f 2 | cut -d '"' -f 2) zoneConfigDnsSecMode=$(echo "${curResult}" | _egrep_o '"dnsSecMode":.*' | cut -d ':' -f 2 | cut -d '"' -f 2) - if [ $zoneConfigType != "NATIVE" ]; then + if [ "${zoneConfigType}" != "NATIVE" ]; then _err "Zone is not native" returnCode=1 break From 572adbaad2c8531870753c18c2b313c70faa9a16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20P=C3=A1la?= Date: Mon, 31 Dec 2018 20:05:08 +0100 Subject: [PATCH 49/61] Add support for Active24.cz --- README.md | 1 + dnsapi/README.md | 18 ++++++ dnsapi/dns_active24.sh | 141 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100755 dnsapi/dns_active24.sh diff --git a/README.md b/README.md index 41ffb694..70abcc6c 100644 --- a/README.md +++ b/README.md @@ -349,6 +349,7 @@ You don't have to do anything manually! 1. Neodigit.net API (https://www.neodigit.net) 1. Exoscale.com API (https://www.exoscale.com/) 1. PointDNS API (https://pointhq.com/) +1. Active24.cz API (https://www.active24.cz/) And: diff --git a/dnsapi/README.md b/dnsapi/README.md index fc65748e..0a9c4925 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -1139,6 +1139,24 @@ You can then issue certs by using: ```acme.sh --issue --dns dns_pointhq -d example.com -d www.example.com ``` +## 59. Use Active24 API + +Create an API token in the Active24 account section, documentation on https://faq.active24.com/cz/790131-REST-API-rozhran%C3%AD. + +Set your API token: + +``` +export ACTIVE24_Token='xxx' +``` + +Now, let's issue a cert, set `dnssleep` for propagation new DNS record: +``` +acme.sh --issue --dns dns_active24 -d example.com -d www.example.com --dnssleep 1000 +``` + +The `ACTIVE24_Token` 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_active24.sh b/dnsapi/dns_active24.sh new file mode 100755 index 00000000..90ffaf68 --- /dev/null +++ b/dnsapi/dns_active24.sh @@ -0,0 +1,141 @@ +#!/usr/bin/env sh + +#ACTIVE24_Token="sdfsdfsdfljlbjkljlkjsdfoiwje" + +ACTIVE24_Api="https://api.active24.com" + +######## Public functions ##################### + +# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +# Used to add txt record +dns_active24_add() { + fulldomain=$1 + txtvalue=$2 + + _active24_init + + _info "Adding txt record" + if _active24_rest POST "dns/$_domain/txt/v1" "{\"name\":\"$_sub_domain\",\"text\":\"$txtvalue\",\"ttl\":0}"; then + if _contains "$response" "errors"; then + _err "Add txt record error." + return 1 + else + _info "Added, OK" + return 0 + fi + fi + _err "Add txt record error." + return 1 +} + +# Usage: fulldomain txtvalue +# Used to remove the txt record after validation +dns_active24_rm() { + fulldomain=$1 + txtvalue=$2 + + _active24_init + + _debug "Getting txt records" + _active24_rest GET "dns/$_domain/records/v1" + + if _contains "$response" "errors"; then + _err "Error" + return 1 + fi + + hash_ids=$(echo "$response" | _egrep_o "[^{]+${txtvalue}[^}]+" | _egrep_o "hashId\":\"[^\"]+" | cut -c10-) + + for hash_id in $hash_ids; do + _debug "Removing hash_id" "$hash_id" + if _active24_rest DELETE "dns/$_domain/$hash_id/v1" ""; then + if _contains "$response" "errors"; then + _err "Unable to remove txt record." + return 1 + else + _info "Removed txt record." + return 0 + fi + fi + done + + _err "No txt records found." + return 1 +} + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +# _domain_id=sdjkglgdfewsdfg +_get_root() { + domain=$1 + + if ! _active24_rest GET "dns/domains/v1"; then + return 1 + fi + + i=2 + p=1 + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug "h" "$h" + if [ -z "$h" ]; then + #not valid + return 1 + fi + + if _contains "$response" "\"$h\"" >/dev/null; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain=$h + return 0 + fi + p=$i + i=$(_math "$i" + 1) + done + return 1 +} + +_active24_rest() { + m=$1 + ep="$2" + data="$3" + _debug "$ep" + + export _H1="Authorization: Bearer $ACTIVE24_Token" + + if [ "$m" != "GET" ]; then + _debug "data" "$data" + response="$(_post "$data" "$ACTIVE24_Api/$ep" "" "$m" "application/json")" + else + response="$(_get "$ACTIVE24_Api/$ep")" + fi + + if [ "$?" != "0" ]; then + _err "error $ep" + return 1 + fi + _debug2 response "$response" + return 0 +} + +_active24_init() { + ACTIVE24_Token="${ACTIVE24_Token:-$(_readaccountconf_mutable ACTIVE24_Token)}" + if [ -z "$ACTIVE24_Token" ]; then + ACTIVE24_Token="" + _err "You didn't specify a Active24 api token yet." + _err "Please create the token and try again." + return 1 + fi + + _saveaccountconf_mutable ACTIVE24_Token "ACTIVE24_Token" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" +} From 127532c226149b991814bd696b1362b079fa8c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20M=C3=A4del?= Date: Thu, 24 Jan 2019 16:53:03 +0100 Subject: [PATCH 50/61] Added dns_doapi.sh --- dnsapi/dns_doapi.sh | 59 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100755 dnsapi/dns_doapi.sh diff --git a/dnsapi/dns_doapi.sh b/dnsapi/dns_doapi.sh new file mode 100755 index 00000000..f3d56b68 --- /dev/null +++ b/dnsapi/dns_doapi.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env sh + +# Official Let's Encrypt API for do.de / Domain-Offensive +# +# This is different from the dns_do adapter, because dns_do is only usable for enterprise customers +# This API is also available to private customers/individuals +# +# Provide the required LetsEncrypt token like this: +# DO_LETOKEN="FmD408PdqT1E269gUK57" + +DO_API="https://www.do.de/api/letsencrypt" + +######## Public functions ##################### + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_doapi_add() { + fulldomain=$1 + txtvalue=$2 + + DO_LETOKEN="${DO_LETOKEN:-$(_readaccountconf_mutable DO_LETOKEN)}" + if [ -z "$DO_LETOKEN" ]; then + DO_LETOKEN="" + _err "You didn't configure a do.de API token yet." + _err "Please set DO_LETOKEN and try again." + return 1 + fi + _saveaccountconf_mutable DO_LETOKEN "$DO_LETOKEN" + + _info "Adding TXT record to ${_domain} as ${fulldomain}" + response="$(_get "$DO_API?token=$DO_LETOKEN&domain=${fulldomain}&value=${txtvalue}")" + if _contains "${response}" 'success'; then + return 0 + fi + _err "Could not create resource record, check logs" + _err $response + return 1 +} + +dns_doapi_rm() { + fulldomain=$1 + + DO_LETOKEN="${DO_LETOKEN:-$(_readaccountconf_mutable DO_LETOKEN)}" + if [ -z "$DO_LETOKEN" ]; then + DO_LETOKEN="" + _err "You didn't configure a do.de API token yet." + _err "Please set DO_LETOKEN and try again." + return 1 + fi + _saveaccountconf_mutable DO_LETOKEN "$DO_LETOKEN" + + _info "Deleting resource record $fulldomain" + response="$(_get "$DO_API?token=$DO_LETOKEN&domain=${fulldomain}&action=delete")" + if _contains "${response}" 'success'; then + return 0 + fi + _err "Could not delete resource record, check logs" + _err $response + return 1 +} From ddf77f10e95e6daf22b99a7e5986912d58ff4b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20M=C3=A4del?= Date: Thu, 24 Jan 2019 16:59:36 +0100 Subject: [PATCH 51/61] Cleaned up dns_doapi.sh --- dnsapi/dns_doapi.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_doapi.sh b/dnsapi/dns_doapi.sh index f3d56b68..fa2b7d33 100755 --- a/dnsapi/dns_doapi.sh +++ b/dnsapi/dns_doapi.sh @@ -26,13 +26,13 @@ dns_doapi_add() { fi _saveaccountconf_mutable DO_LETOKEN "$DO_LETOKEN" - _info "Adding TXT record to ${_domain} as ${fulldomain}" + _info "Adding TXT record to ${fulldomain}" response="$(_get "$DO_API?token=$DO_LETOKEN&domain=${fulldomain}&value=${txtvalue}")" if _contains "${response}" 'success'; then return 0 fi _err "Could not create resource record, check logs" - _err $response + _err "${response}" return 1 } @@ -54,6 +54,6 @@ dns_doapi_rm() { return 0 fi _err "Could not delete resource record, check logs" - _err $response + _err "${response}" return 1 } From 5f9b57d3004831cbd0e4455c0676633c56b5f708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20M=C3=A4del?= Date: Thu, 24 Jan 2019 17:00:37 +0100 Subject: [PATCH 52/61] Cleaned up dns_doapi.sh --- dnsapi/dns_doapi.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_doapi.sh b/dnsapi/dns_doapi.sh index fa2b7d33..135f0b03 100755 --- a/dnsapi/dns_doapi.sh +++ b/dnsapi/dns_doapi.sh @@ -24,7 +24,7 @@ dns_doapi_add() { _err "Please set DO_LETOKEN and try again." return 1 fi - _saveaccountconf_mutable DO_LETOKEN "$DO_LETOKEN" + _saveaccountconf_mutable DO_LETOKEN "$DO_LETOKEN" _info "Adding TXT record to ${fulldomain}" response="$(_get "$DO_API?token=$DO_LETOKEN&domain=${fulldomain}&value=${txtvalue}")" @@ -46,7 +46,7 @@ dns_doapi_rm() { _err "Please set DO_LETOKEN and try again." return 1 fi - _saveaccountconf_mutable DO_LETOKEN "$DO_LETOKEN" + _saveaccountconf_mutable DO_LETOKEN "$DO_LETOKEN" _info "Deleting resource record $fulldomain" response="$(_get "$DO_API?token=$DO_LETOKEN&domain=${fulldomain}&action=delete")" From e2f1338f941dfca192ebc51c1cb65bb09bf8f6d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20M=C3=A4del?= Date: Thu, 24 Jan 2019 17:05:01 +0100 Subject: [PATCH 53/61] Added documentation --- dnsapi/README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/dnsapi/README.md b/dnsapi/README.md index fc65748e..e0532bcd 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -1139,6 +1139,22 @@ You can then issue certs by using: ```acme.sh --issue --dns dns_pointhq -d example.com -d www.example.com ``` +## 59. Use do.de API + +Create an API token in your do.de account. + +Set your API token: +``` +export DO_LETOKEN='FmD408PdqT1E269gUK57' +``` + +To issue a certificate run: +``` +acme.sh --issue --dns dns_doapi -d example.com -d *.example.com +``` + +The API token 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. From c1ec2afeca11ad8afdb8feec5e6e3bba1bf113da Mon Sep 17 00:00:00 2001 From: Grant Millar Date: Fri, 25 Jan 2019 09:27:30 +0000 Subject: [PATCH 54/61] Changed records per page to 5000 --- dnsapi/dns_dnsimple.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_dnsimple.sh b/dnsapi/dns_dnsimple.sh index b2cba584..d831eb2b 100644 --- a/dnsapi/dns_dnsimple.sh +++ b/dnsapi/dns_dnsimple.sh @@ -152,7 +152,7 @@ _get_records() { sub_domain=$3 _debug "fetching txt records" - _dnsimple_rest GET "$account_id/zones/$domain/records?per_page=100&sort=id:desc" + _dnsimple_rest GET "$account_id/zones/$domain/records?per_page=5000&sort=id:desc" if ! _contains "$response" "\"id\":"; then _err "failed to retrieve records" From 75fe022f96dce0baeaef6f8fe9c206f8ab094d9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20M=C3=A4del?= Date: Fri, 25 Jan 2019 15:26:41 +0100 Subject: [PATCH 55/61] Changed order in readme, added do.de --- README.md | 1 + dnsapi/README.md | 34 +++++++++++++++++----------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 70abcc6c..90a648d5 100644 --- a/README.md +++ b/README.md @@ -350,6 +350,7 @@ You don't have to do anything manually! 1. Exoscale.com API (https://www.exoscale.com/) 1. PointDNS API (https://pointhq.com/) 1. Active24.cz API (https://www.active24.cz/) +1. do.de API (https://www.do.de/) And: diff --git a/dnsapi/README.md b/dnsapi/README.md index dc20ac9c..4f9b4100 100644 --- a/dnsapi/README.md +++ b/dnsapi/README.md @@ -1139,23 +1139,7 @@ You can then issue certs by using: ```acme.sh --issue --dns dns_pointhq -d example.com -d www.example.com ``` -## 59. Use do.de API - -Create an API token in your do.de account. - -Set your API token: -``` -export DO_LETOKEN='FmD408PdqT1E269gUK57' -``` - -To issue a certificate run: -``` -acme.sh --issue --dns dns_doapi -d example.com -d *.example.com -``` - -The API token will be saved in `~/.acme.sh/account.conf` and will be reused when needed. - -## 60. Use Active24 API +## 59. Use Active24 API Create an API token in the Active24 account section, documentation on https://faq.active24.com/cz/790131-REST-API-rozhran%C3%AD. @@ -1172,6 +1156,22 @@ acme.sh --issue --dns dns_active24 -d example.com -d www.example.com --dnssleep The `ACTIVE24_Token` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. +## 60. Use do.de API + +Create an API token in your do.de account. + +Set your API token: +``` +export DO_LETOKEN='FmD408PdqT1E269gUK57' +``` + +To issue a certificate run: +``` +acme.sh --issue --dns dns_doapi -d example.com -d *.example.com +``` + +The API token 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. From 36335984629d07d7c048981cea921bce60e37dbf Mon Sep 17 00:00:00 2001 From: neilpang Date: Fri, 25 Jan 2019 22:39:22 +0800 Subject: [PATCH 56/61] Lets start 2.8.1 --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index d651c4f5..85c17f16 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=2.8.0 +VER=2.8.1 PROJECT_NAME="acme.sh" From 43ff787b04b56fb1b8cf73857351c8fbad1c382e Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 26 Jan 2019 18:32:11 +0800 Subject: [PATCH 57/61] remove tls-sni --- acme.sh | 44 ++------------------------------------------ 1 file changed, 2 insertions(+), 42 deletions(-) diff --git a/acme.sh b/acme.sh index 85c17f16..cfdf5714 100755 --- a/acme.sh +++ b/acme.sh @@ -35,7 +35,6 @@ _OLD_STAGE_CA_HOST="https://acme-staging.api.letsencrypt.org" VTYPE_HTTP="http-01" VTYPE_DNS="dns-01" -VTYPE_TLS="tls-sni-01" VTYPE_ALPN="tls-alpn-01" LOCAL_ANY_ADDRESS="0.0.0.0" @@ -46,7 +45,6 @@ DEFAULT_DNS_SLEEP=120 NO_VALUE="no" -W_TLS="tls" W_DNS="dns" W_ALPN="alpn" DNS_ALIAS_PREFIX="=" @@ -3080,8 +3078,8 @@ _on_before_issue() { _savedomainconf "Le_HTTPPort" "$Le_HTTPPort" fi _checkport="$Le_HTTPPort" - elif [ "$_currentRoot" = "$W_TLS" ] || [ "$_currentRoot" = "$W_ALPN" ]; then - _info "Standalone tls/alpn mode." + elif [ "$_currentRoot" = "$W_ALPN" ]; then + _info "Standalone alpn mode." if [ -z "$Le_TLSPort" ]; then Le_TLSPort=443 else @@ -3701,10 +3699,6 @@ $_authorizations_map" vtype="$VTYPE_DNS" fi - if [ "$_currentRoot" = "$W_TLS" ]; then - vtype="$VTYPE_TLS" - fi - if [ "$_currentRoot" = "$W_ALPN" ]; then vtype="$VTYPE_ALPN" fi @@ -3988,40 +3982,6 @@ $_authorizations_map" fi fi - - elif [ "$vtype" = "$VTYPE_TLS" ]; then - #create A - #_hash_A="$(printf "%s" $token | _digest "sha256" "hex" )" - #_debug2 _hash_A "$_hash_A" - #_x="$(echo $_hash_A | cut -c 1-32)" - #_debug2 _x "$_x" - #_y="$(echo $_hash_A | cut -c 33-64)" - #_debug2 _y "$_y" - #_SAN_A="$_x.$_y.token.acme.invalid" - #_debug2 _SAN_A "$_SAN_A" - - #create B - _hash_B="$(printf "%s" "$keyauthorization" | _digest "sha256" "hex")" - _debug2 _hash_B "$_hash_B" - _x="$(echo "$_hash_B" | cut -c 1-32)" - _debug2 _x "$_x" - _y="$(echo "$_hash_B" | cut -c 33-64)" - _debug2 _y "$_y" - - #_SAN_B="$_x.$_y.ka.acme.invalid" - - _SAN_B="$_x.$_y.acme.invalid" - _debug2 _SAN_B "$_SAN_B" - - _ncaddr="$(_getfield "$_local_addr" "$_ncIndex")" - _ncIndex="$(_math "$_ncIndex" + 1)" - if ! _starttlsserver "$_SAN_B" "$_SAN_A" "$Le_TLSPort" "$keyauthorization" "$_ncaddr"; then - _err "Start tls server error." - _clearupwebbroot "$_currentRoot" "$removelevel" "$token" - _clearup - _on_issue_err "$_post_hook" "$vlist" - return 1 - fi elif [ "$vtype" = "$VTYPE_ALPN" ]; then acmevalidationv1="$(printf "%s" "$keyauthorization" | _digest "sha256" "hex")" _debug acmevalidationv1 "$acmevalidationv1" From cc6159b39b5305778e1f437fcbe2673a3012cb13 Mon Sep 17 00:00:00 2001 From: neilpang Date: Sat, 26 Jan 2019 19:15:13 +0800 Subject: [PATCH 58/61] urlencode the existing txt record value fix https://github.com/Neilpang/acme.sh/issues/2052 --- dnsapi/dns_namecheap.sh | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index 2f401bd9..27eda3ad 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -3,16 +3,15 @@ # Namecheap API # https://www.namecheap.com/support/api/intro.aspx # -# Requires Namecheap API key set in NAMECHEAP_API_KEY, NAMECHEAP_SOURCEIP and NAMECHEAP_USERNAME set as environment variable +# Requires Namecheap API key set in +#NAMECHEAP_API_KEY, +#NAMECHEAP_USERNAME, +#NAMECHEAP_SOURCEIP # Due to Namecheap's API limitation all the records of your domain will be read and re applied, make sure to have a backup of your records you could apply if any issue would arise. ######## Public functions ##################### -if [ "$STAGE" -eq 1 ]; then - NAMECHEAP_API="https://api.sandbox.namecheap.com/xml.response" -else - NAMECHEAP_API="https://api.namecheap.com/xml.response" -fi +NAMECHEAP_API="https://api.namecheap.com/xml.response" #Usage: dns_namecheap_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_namecheap_add() { @@ -144,7 +143,7 @@ _namecheap_set_publicip() { _namecheap_post() { command=$1 data="ApiUser=${NAMECHEAP_USERNAME}&ApiKey=${NAMECHEAP_API_KEY}&ClientIp=${_publicip}&UserName=${NAMECHEAP_USERNAME}&Command=${command}" - + _debug2 "_namecheap_post data" "$data" response="$(_post "$data" "$NAMECHEAP_API" "" "POST")" _debug2 response "$response" @@ -224,6 +223,12 @@ _set_namecheap_TXT() { while read -r host; do if _contains "$host" " Date: Sat, 26 Jan 2019 20:27:53 +0800 Subject: [PATCH 59/61] fix rm method to urlencode the existing txt records. fix https://github.com/Neilpang/acme.sh/issues/2052 --- dnsapi/dns_namecheap.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/dnsapi/dns_namecheap.sh b/dnsapi/dns_namecheap.sh index 27eda3ad..fbf93c32 100755 --- a/dnsapi/dns_namecheap.sh +++ b/dnsapi/dns_namecheap.sh @@ -283,6 +283,7 @@ _del_namecheap_TXT() { _debug "TXT entry found" found=1 else + _hostaddress="$(printf "%s" "$_hostaddress" | _url_encode)" _namecheap_add_host "$_hostname" "$_hosttype" "$_hostaddress" "$_hostmxpref" "$_hostttl" fi fi From a96464680361dde97e1388b81de275756612ba83 Mon Sep 17 00:00:00 2001 From: neilpang Date: Mon, 28 Jan 2019 19:11:45 +0800 Subject: [PATCH 60/61] fix https://github.com/Neilpang/acme.sh/issues/1364#issuecomment-458035330 --- dnsapi/dns_dp.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_dp.sh b/dnsapi/dns_dp.sh index 3cc720aa..6bbf149e 100755 --- a/dnsapi/dns_dp.sh +++ b/dnsapi/dns_dp.sh @@ -63,7 +63,7 @@ dns_dp_rm() { return 0 fi - record_id=$(echo "$response" | _egrep_o '{[^{]*"value":"'"$txtvalue"'"' | cut -d , -f 1 | cut -d : -f 2 | tr -d \") + record_id=$(echo "$response" | tr "{" "\n" | grep "$txtvalue" | grep '^"id"' | cut -d : -f 2 | cut -d '"' -f 2) _debug record_id "$record_id" if [ -z "$record_id" ]; then _err "Can not get record id." From 227547f8263a87d9241a8f0a5de84ded1c6aa3d3 Mon Sep 17 00:00:00 2001 From: neilpang Date: Wed, 30 Jan 2019 20:13:23 +0800 Subject: [PATCH 61/61] fix https://github.com/Neilpang/acme.sh/pull/1979 --- dnsapi/dns_linode_v4.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dnsapi/dns_linode_v4.sh b/dnsapi/dns_linode_v4.sh index dfa1a651..c9a83c77 100755 --- a/dnsapi/dns_linode_v4.sh +++ b/dnsapi/dns_linode_v4.sh @@ -8,7 +8,7 @@ LINODE_V4_API_URL="https://api.linode.com/v4/domains" ######## Public functions ##################### #Usage: dns_linode_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" -dns_linode_add() { +dns_linode_v4_add() { fulldomain="${1}" txtvalue="${2}" @@ -51,7 +51,7 @@ dns_linode_add() { } #Usage: dns_linode_rm _acme-challenge.www.domain.com -dns_linode_rm() { +dns_linode_v4_rm() { fulldomain="${1}" if ! _Linode_API; then