From 11af6f49c6d8c3d1a9670d232ca2aebadbd46239 Mon Sep 17 00:00:00 2001 From: Anton Avramov Date: Thu, 5 Dec 2024 22:12:04 -0500 Subject: [PATCH] Add support for ZoneEdit.com --- dnsapi/dns_zoneedit.sh | 145 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 dnsapi/dns_zoneedit.sh diff --git a/dnsapi/dns_zoneedit.sh b/dnsapi/dns_zoneedit.sh new file mode 100644 index 00000000..7ea16f75 --- /dev/null +++ b/dnsapi/dns_zoneedit.sh @@ -0,0 +1,145 @@ +#!/usr/bin/env sh + +# https://github.com/blueslow/sslcertzoneedit + +# Only need to export the credentials once, acme.sh will save for automatic renewal. +# export ZONEEDIT_ID="Your id" +# export ZONEEDIT_Token="Your token" +# acme.sh --issue --dns dns_zoneedit -d example.com -d www.example.com + +######## Public functions ##################### + +# Usage: dns_zoneedit_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_zoneedit_add() { + fulldomain=$1 + txtvalue=$2 + _info "Using Zoneedit" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + # Load the credentials from the account conf file + ZONEEDIT_ID="${ZONEEDIT_ID:-$(_readaccountconf_mutable ZONEEDIT_ID)}" + ZONEEDIT_Token="${ZONEEDIT_Token:-$(_readaccountconf_mutable ZONEEDIT_Token)}" + if [ -z "$ZONEEDIT_ID" ] || [ -z "$ZONEEDIT_Token" ]; then + ZONEEDIT_ID="" + ZONEEDIT_Token="" + _err "Please specify ZONEEDIT_ID and _Token." + _err "Please export as ZONEEDIT_ID and ZONEEDIT_Token then try again." + return 1 + fi + + # Save the credentials to the account conf file + _saveaccountconf_mutable ZONEEDIT_ID "$ZONEEDIT_ID" + _saveaccountconf_mutable ZONEEDIT_Token "$ZONEEDIT_Token" + + if _zoneedit_api "CREATE" "$fulldomain" "$txtvalue"; then + _info "Added, OK" + return 0 + else + _err "Add txt record error." + return 1 + fi +} + +# Usage: dns_zoneedit_rm fulldomain txtvalue +dns_zoneedit_rm() { + fulldomain=$1 + txtvalue=$2 + _info "Using Zoneedit" + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + # Load the credentials from the account conf file + ZONEEDIT_ID="${ZONEEDIT_ID:-$(_readaccountconf_mutable ZONEEDIT_ID)}" + ZONEEDIT_Token="${ZONEEDIT_Token:-$(_readaccountconf_mutable ZONEEDIT_Token)}" + if [ -z "$ZONEEDIT_ID" ] || [ -z "$ZONEEDIT_Token" ]; then + ZONEEDIT_ID="" + ZONEEDIT_Token="" + _err "Please specify ZONEEDIT_ID and _Token." + _err "Please export as ZONEEDIT_ID and ZONEEDIT_Token then try again." + return 1 + fi + + if _zoneedit_api "DELETE" "$fulldomain" "$txtvalue"; then + _info "Deleted, OK" + return 0 + else + _err "Delete txt record error." + return 1 + fi +} + +#################### Private functions below ################################## + +#Usage: _zoneedit_api fulldomain txtvalue +_zoneedit_api() { + cmd=$1 + fulldomain=$2 + txtvalue=$3 + + # Construct basic authorization header + credentials=$(printf "%s:%s" "$ZONEEDIT_ID" "$ZONEEDIT_Token" | _base64) + export _H1="Authorization: Basic ${credentials}" + + # Generate request URL + case "$cmd" in + "CREATE") + # https://dynamic.zoneedit.com/txt-create.php?host=_acme-challenge.example.com&rdata=depE1VF_xshMm1IVY1Y56Kk9Zb_7jA2VFkP65WuNgu8W + geturl="https://dynamic.zoneedit.com/txt-create.php?host=${fulldomain}&rdata=${txtvalue}" + ;; + "DELETE") + # https://dynamic.zoneedit.com/txt-delete.php?host=_acme-challenge.example.com&rdata=depE1VF_xshMm1IVY1Y56Kk9Zb_7jA2VFkP65WuNgu8W + geturl="https://dynamic.zoneedit.com/txt-delete.php?host=${fulldomain}&rdata=${txtvalue}" + ze_sleep=2 + ;; + *) + _err "Unknown parameter : $cmd" + return 1 + ;; + esac + + # Execute request + i=3 # Tries + while [ $i -gt 0 ]; do + i=$(_math "$i" - 1) + + if ! response=$(_get "$geturl"); then + _err "_get() failed ($response)" + return 1 + fi + _debug2 response "$response" + if _contains "$response" "SUCCESS.*200"; then + # Sleep (when needed) to work around a Zonedit API bug + # https://forum.zoneedit.com/threads/automating-changes-of-txt-records-in-dns.7394/page-2#post-23855 + if [ "$ze_sleep" ]; then _sleep "$ze_sleep"; fi + return 0 + elif _contains "$response" "ERROR.*Minimum.*seconds"; then + _info "Zoneedit responded with a rate limit of..." + ze_ratelimit=$(echo "$response" | sed -n 's/.*Minimum \([0-9]\+\) seconds.*/\1/p') + if [ "$ze_ratelimit" ] && [ ! "$(echo "$ze_ratelimit" | tr -d '0-9')" ]; then + _info "$ze_ratelimit seconds." + else + _err "$response" + _err "not a number, or blank ($ze_ratelimit), API change?" + unset ze_ratelimit + fi + else + _err "$response" + _err "Unknown response, API change?" + fi + + # Retry + if [ "$i" -lt 1 ]; then + _err "Tries exceeded, giving up." + return 1 + fi + if [ "$ze_ratelimit" ]; then + _info "Waiting $ze_ratelimit seconds..." + _sleep "$ze_ratelimit" + else + _err "Going to retry after 10 seconds..." + _sleep 10 + fi + done + return 1 +}