_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."
return 0 # do nothing
fi
_saved="$(_readdomainconf "SAVED_$_rac_key")"
- eval $_rac_key="$_saved"
+ eval $_rac_key=\$_saved
export $_rac_key
}
return 1
fi
+ _debug2 DOMAIN_CONF "$DOMAIN_CONF"
. "$DOMAIN_CONF"
_savedomainconf Le_DeployHook "$_hooks"
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."
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
}
--- /dev/null
+#!/usr/bin/env sh
+
+# Author: Alex Leigh <leigh at alexleigh dot me>
+# 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
+}