diff --git a/acme.sh b/acme.sh index 5d73cdb6..d5caee4d 100755 --- a/acme.sh +++ b/acme.sh @@ -2229,15 +2229,19 @@ _send_signed_request() { _debug3 _body "$_body" fi - _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *:" | cut -d : -f 2 | tr -d ' ' | tr -d '\r') - if [ "$code" = '503' ] || [ "$_retryafter" ]; then + _retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *: *[0-9]\+ *" | cut -d : -f 2 | tr -d ' ' | tr -d '\r') + if [ "$code" = '503' ]; then _sleep_overload_retry_sec=$_retryafter if [ -z "$_sleep_overload_retry_sec" ]; then _sleep_overload_retry_sec=5 fi - _info "It seems the CA server is currently overloaded, let's wait and retry. Sleeping $_sleep_overload_retry_sec seconds." - _sleep $_sleep_overload_retry_sec - continue + if [ $_sleep_overload_retry_sec -le 600 ]; then + _info "It seems the CA server is currently overloaded, let's wait and retry. Sleeping $_sleep_overload_retry_sec seconds." + _sleep $_sleep_overload_retry_sec + continue + else + _info "The retryafter=$_retryafter is too large > 600, not retry anymore." + fi fi if _contains "$_body" "JWS has invalid anti-replay nonce" || _contains "$_body" "JWS has an invalid anti-replay nonce"; then _info "It seems the CA server is busy now, let's wait and retry. Sleeping $_sleep_retry_sec seconds." @@ -2408,7 +2412,7 @@ _getdeployconf() { return 0 # do nothing fi _saved="$(_readdomainconf "SAVED_$_rac_key")" - eval $_rac_key="$_saved" + eval $_rac_key=\$_saved export $_rac_key } @@ -5782,6 +5786,7 @@ deploy() { return 1 fi + _debug2 DOMAIN_CONF "$DOMAIN_CONF" . "$DOMAIN_CONF" _savedomainconf Le_DeployHook "$_hooks" @@ -6141,8 +6146,22 @@ revoke() { uri="${ACME_REVOKE_CERT}" + _info "Try account key first." + if _send_signed_request "$uri" "$data" "" "$ACCOUNT_KEY_PATH"; then + if [ -z "$response" ]; then + _info "Revoke success." + rm -f "$CERT_PATH" + cat "$CERT_KEY_PATH" >"$CERT_KEY_PATH.revoked" + cat "$CSR_PATH" >"$CSR_PATH.revoked" + return 0 + else + _err "Revoke error." + _debug "$response" + fi + fi + if [ -f "$CERT_KEY_PATH" ]; then - _info "Try domain key first." + _info "Try domain key." if _send_signed_request "$uri" "$data" "" "$CERT_KEY_PATH"; then if [ -z "$response" ]; then _info "Revoke success." @@ -6158,21 +6177,6 @@ revoke() { else _info "Domain key file doesn't exist." fi - - _info "Try account key." - - if _send_signed_request "$uri" "$data" "" "$ACCOUNT_KEY_PATH"; then - if [ -z "$response" ]; then - _info "Revoke success." - rm -f "$CERT_PATH" - cat "$CERT_KEY_PATH" >"$CERT_KEY_PATH.revoked" - cat "$CSR_PATH" >"$CSR_PATH.revoked" - return 0 - else - _err "Revoke error." - _debug "$response" - fi - fi return 1 } diff --git a/dnsapi/dns_cloudns.sh b/dnsapi/dns_cloudns.sh index b03fd579..8d7fd437 100755 --- a/dnsapi/dns_cloudns.sh +++ b/dnsapi/dns_cloudns.sh @@ -78,7 +78,7 @@ dns_cloudns_rm() { return 1 fi - for i in $(echo "$response" | tr '{' "\n" | grep "$record"); do + for i in $(echo "$response" | tr '{' "\n" | grep -- "$record"); do record_id=$(echo "$i" | tr ',' "\n" | grep -E '^"id"' | sed -re 's/^\"id\"\:\"([0-9]+)\"$/\1/g') if [ -n "$record_id" ]; then diff --git a/dnsapi/dns_googledomains.sh b/dnsapi/dns_googledomains.sh new file mode 100755 index 00000000..63e3073b --- /dev/null +++ b/dnsapi/dns_googledomains.sh @@ -0,0 +1,173 @@ +#!/usr/bin/env sh + +# Author: Alex Leigh +# Created: 2023-03-02 + +#GOOGLEDOMAINS_ACCESS_TOKEN="xxxx" +#GOOGLEDOMAINS_ZONE="xxxx" +GOOGLEDOMAINS_API="https://acmedns.googleapis.com/v1/acmeChallengeSets" + +######## Public functions ######## + +#Usage: dns_googledomains_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_googledomains_add() { + fulldomain=$1 + txtvalue=$2 + + _info "Invoking Google Domains ACME DNS API." + + if ! _dns_googledomains_setup; then + return 1 + fi + + zone="$(_dns_googledomains_get_zone "$fulldomain")" + if [ -z "$zone" ]; then + _err "Could not find a Google Domains-managed zone containing the requested domain." + return 1 + fi + + _debug zone "$zone" + _debug txtvalue "$txtvalue" + + _info "Adding TXT record for $fulldomain." + if _dns_googledomains_api "$zone" ":rotateChallenges" "{\"accessToken\":\"$GOOGLEDOMAINS_ACCESS_TOKEN\",\"recordsToAdd\":[{\"fqdn\":\"$fulldomain\",\"digest\":\"$txtvalue\"}],\"keepExpiredRecords\":true}"; then + if _contains "$response" "$txtvalue"; then + _info "TXT record added." + return 0 + else + _err "Error adding TXT record." + return 1 + fi + fi + + _err "Error adding TXT record." + return 1 +} + +#Usage: dns_googledomains_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_googledomains_rm() { + fulldomain=$1 + txtvalue=$2 + + _info "Invoking Google Domains ACME DNS API." + + if ! _dns_googledomains_setup; then + return 1 + fi + + zone="$(_dns_googledomains_get_zone "$fulldomain")" + if [ -z "$zone" ]; then + _err "Could not find a Google Domains-managed domain based on request." + return 1 + fi + + _debug zone "$zone" + _debug txtvalue "$txtvalue" + + _info "Removing TXT record for $fulldomain." + if _dns_googledomains_api "$zone" ":rotateChallenges" "{\"accessToken\":\"$GOOGLEDOMAINS_ACCESS_TOKEN\",\"recordsToRemove\":[{\"fqdn\":\"$fulldomain\",\"digest\":\"$txtvalue\"}],\"keepExpiredRecords\":true}"; then + if _contains "$response" "$txtvalue"; then + _err "Error removing TXT record." + return 1 + else + _info "TXT record removed." + return 0 + fi + fi + + _err "Error removing TXT record." + return 1 +} + +######## Private functions ######## + +_dns_googledomains_setup() { + if [ -n "$GOOGLEDOMAINS_SETUP_COMPLETED" ]; then + return 0 + fi + + GOOGLEDOMAINS_ACCESS_TOKEN="${GOOGLEDOMAINS_ACCESS_TOKEN:-$(_readaccountconf_mutable GOOGLEDOMAINS_ACCESS_TOKEN)}" + GOOGLEDOMAINS_ZONE="${GOOGLEDOMAINS_ZONE:-$(_readaccountconf_mutable GOOGLEDOMAINS_ZONE)}" + + if [ -z "$GOOGLEDOMAINS_ACCESS_TOKEN" ]; then + GOOGLEDOMAINS_ACCESS_TOKEN="" + _err "Google Domains access token was not specified." + _err "Please visit Google Domains Security settings to provision an ACME DNS API access token." + return 1 + fi + + if [ "$GOOGLEDOMAINS_ZONE" ]; then + _savedomainconf GOOGLEDOMAINS_ACCESS_TOKEN "$GOOGLEDOMAINS_ACCESS_TOKEN" + _savedomainconf GOOGLEDOMAINS_ZONE "$GOOGLEDOMAINS_ZONE" + else + _saveaccountconf_mutable GOOGLEDOMAINS_ACCESS_TOKEN "$GOOGLEDOMAINS_ACCESS_TOKEN" + _clearaccountconf_mutable GOOGLEDOMAINS_ZONE + _clearaccountconf GOOGLEDOMAINS_ZONE + fi + + _debug GOOGLEDOMAINS_ACCESS_TOKEN "$GOOGLEDOMAINS_ACCESS_TOKEN" + _debug GOOGLEDOMAINS_ZONE "$GOOGLEDOMAINS_ZONE" + + GOOGLEDOMAINS_SETUP_COMPLETED=1 + return 0 +} + +_dns_googledomains_get_zone() { + domain=$1 + + # Use zone directly if provided + if [ "$GOOGLEDOMAINS_ZONE" ]; then + if ! _dns_googledomains_api "$GOOGLEDOMAINS_ZONE"; then + return 1 + fi + + echo "$GOOGLEDOMAINS_ZONE" + return 0 + fi + + i=2 + while true; do + curr=$(printf "%s" "$domain" | cut -d . -f $i-100) + _debug curr "$curr" + + if [ -z "$curr" ]; then + return 1 + fi + + if _dns_googledomains_api "$curr"; then + echo "$curr" + return 0 + fi + + i=$(_math "$i" + 1) + done + + return 1 +} + +_dns_googledomains_api() { + zone=$1 + apimethod=$2 + data="$3" + + if [ -z "$data" ]; then + response="$(_get "$GOOGLEDOMAINS_API/$zone$apimethod")" + else + _debug data "$data" + export _H1="Content-Type: application/json" + response="$(_post "$data" "$GOOGLEDOMAINS_API/$zone$apimethod")" + fi + + _debug response "$response" + + if [ "$?" != "0" ]; then + _err "Error" + return 1 + fi + + if _contains "$response" "\"error\": {"; then + return 1 + fi + + return 0 +} diff --git a/dnsapi/dns_kas.sh b/dnsapi/dns_kas.sh index 053abd21..1253cf27 100755 --- a/dnsapi/dns_kas.sh +++ b/dnsapi/dns_kas.sh @@ -215,7 +215,7 @@ _get_record_id() { return 1 fi - _record_id="$(echo "$response" | tr -d '\n\r' | sed "s//\n/g" | grep -i "$_record_name" | grep -i ">TXT<" | sed "s/record_id<\/key>/=>/g" | sed "s/<\/value><\/item>/\n/g" | grep "=>" | sed "s/=>//g")" + _record_id="$(echo "$response" | tr -d '\n\r' | sed "s//\n/g" | grep -i "$_record_name" | grep -i ">TXT<" | sed "s/record_id<\/key>/=>/g" | grep -i "$_txtvalue" | sed "s/<\/value><\/item>/\n/g" | grep "=>" | sed "s/=>//g")" _debug "[KAS] -> Record Id: " "$_record_id" return 0 } diff --git a/dnsapi/dns_leaseweb.sh b/dnsapi/dns_leaseweb.sh index 63f81869..4cd3a8f8 100644 --- a/dnsapi/dns_leaseweb.sh +++ b/dnsapi/dns_leaseweb.sh @@ -6,7 +6,7 @@ #See https://developer.leaseweb.com for more information. ######## Public functions ##################### -LSW_API="https://api.leaseweb.com/hosting/v2/domains/" +LSW_API="https://api.leaseweb.com/hosting/v2/domains" #Usage: dns_leaseweb_add _acme-challenge.www.domain.com dns_leaseweb_add() {