|
@@ -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 <CREATE|DELETE> 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
|
|
|
+}
|