|
|
@@ -0,0 +1,163 @@
|
|
|
+#!/usr/bin/env sh
|
|
|
+# shellcheck disable=SC2034
|
|
|
+
|
|
|
+# EdgeCenter DNS API integration for acme.sh
|
|
|
+# Author: Konstantin Ruchev <[email protected]>
|
|
|
+dns_edgecenter_info='edgecenter DNS API
|
|
|
+Site: https://edgecenter.ru
|
|
|
+Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_edgecenter
|
|
|
+Options:
|
|
|
+ EDGECENTER_API_KEY auth APIKey'
|
|
|
+
|
|
|
+EDGECENTER_API="https://api.edgecenter.ru"
|
|
|
+DOMAIN_TYPE=
|
|
|
+DOMAIN_MASTER=
|
|
|
+
|
|
|
+######## Public functions #####################
|
|
|
+
|
|
|
+#Usage: dns_edgecenter_add _acme-challenge.www.domain.com "TXT_RECORD_VALUE"
|
|
|
+dns_edgecenter_add() {
|
|
|
+ fulldomain="$1"
|
|
|
+ txtvalue="$2"
|
|
|
+
|
|
|
+ _info "Using EdgeCenter DNS API"
|
|
|
+
|
|
|
+ if ! _dns_edgecenter_init_check; then
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+
|
|
|
+ _debug "Detecting root zone for $fulldomain"
|
|
|
+ if ! _get_root "$fulldomain"; then
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+
|
|
|
+ subdomain="${fulldomain%."$_zone"}"
|
|
|
+ subdomain=${subdomain%.}
|
|
|
+
|
|
|
+ _debug "Zone: $_zone"
|
|
|
+ _debug "Subdomain: $subdomain"
|
|
|
+ _debug "TXT value: $txtvalue"
|
|
|
+
|
|
|
+ payload='{"resource_records": [ { "content": ["'"$txtvalue"'"] } ], "ttl": 60 }'
|
|
|
+ _dns_edgecenter_http_api_call "post" "dns/v2/zones/$_zone/$subdomain.$_zone/txt" "$payload"
|
|
|
+
|
|
|
+ if _contains "$response" '"error":"rrset is already exists"'; then
|
|
|
+ _debug "RRSet exists, merging values"
|
|
|
+ _dns_edgecenter_http_api_call "get" "dns/v2/zones/$_zone/$subdomain.$_zone/txt"
|
|
|
+ current="$response"
|
|
|
+ newlist=""
|
|
|
+ for v in $(echo "$current" | sed -n 's/.*"content":\["\([^"]*\)"\].*/\1/p'); do
|
|
|
+ newlist="$newlist {\"content\":[\"$v\"]},"
|
|
|
+ done
|
|
|
+ newlist="$newlist{\"content\":[\"$txtvalue\"]}"
|
|
|
+ putdata="{\"resource_records\":[${newlist}]}
|
|
|
+"
|
|
|
+ _dns_edgecenter_http_api_call "put" "dns/v2/zones/$_zone/$subdomain.$_zone/txt" "$putdata"
|
|
|
+ _info "Updated existing RRSet with new TXT value."
|
|
|
+ return 0
|
|
|
+ fi
|
|
|
+
|
|
|
+ if _contains "$response" '"exception":'; then
|
|
|
+ _err "Record cannot be added."
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+
|
|
|
+ _info "TXT record added successfully."
|
|
|
+ return 0
|
|
|
+}
|
|
|
+
|
|
|
+#Usage: dns_edgecenter_rm _acme-challenge.www.domain.com "TXT_RECORD_VALUE"
|
|
|
+dns_edgecenter_rm() {
|
|
|
+ fulldomain="$1"
|
|
|
+ txtvalue="$2"
|
|
|
+
|
|
|
+ _info "Removing TXT record for $fulldomain"
|
|
|
+
|
|
|
+ if ! _dns_edgecenter_init_check; then
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+
|
|
|
+ if ! _get_root "$fulldomain"; then
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+
|
|
|
+ subdomain="${fulldomain%."$_zone"}"
|
|
|
+ subdomain=${subdomain%.}
|
|
|
+
|
|
|
+ _dns_edgecenter_http_api_call "delete" "dns/v2/zones/$_zone/$subdomain.$_zone/txt"
|
|
|
+
|
|
|
+ if [ -z "$response" ]; then
|
|
|
+ _info "TXT record deleted successfully."
|
|
|
+ else
|
|
|
+ _info "TXT record may not have been deleted: $response"
|
|
|
+ fi
|
|
|
+ return 0
|
|
|
+}
|
|
|
+
|
|
|
+#################### Private functions below ##################################
|
|
|
+
|
|
|
+_dns_edgecenter_init_check() {
|
|
|
+ EDGECENTER_API_KEY="${EDGECENTER_API_KEY:-$(_readaccountconf_mutable EDGECENTER_API_KEY)}"
|
|
|
+ if [ -z "$EDGECENTER_API_KEY" ]; then
|
|
|
+ _err "EDGECENTER_API_KEY was not exported."
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+
|
|
|
+ _saveaccountconf_mutable EDGECENTER_API_KEY "$EDGECENTER_API_KEY"
|
|
|
+ export _H1="Authorization: APIKey $EDGECENTER_API_KEY"
|
|
|
+
|
|
|
+ _dns_edgecenter_http_api_call "get" "dns/v2/clients/me/features"
|
|
|
+ if ! _contains "$response" '"id":'; then
|
|
|
+ _err "Invalid API key."
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+ return 0
|
|
|
+}
|
|
|
+
|
|
|
+_get_root() {
|
|
|
+ domain="$1"
|
|
|
+ i=1
|
|
|
+ while true; do
|
|
|
+ h=$(printf "%s" "$domain" | cut -d . -f "$i"-)
|
|
|
+ if [ -z "$h" ]; then
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+ _dns_edgecenter_http_api_call "get" "dns/v2/zones/$h"
|
|
|
+ if ! _contains "$response" 'zone is not found'; then
|
|
|
+ _zone="$h"
|
|
|
+ return 0
|
|
|
+ fi
|
|
|
+ i=$((i + 1))
|
|
|
+ done
|
|
|
+ return 1
|
|
|
+}
|
|
|
+
|
|
|
+_dns_edgecenter_http_api_call() {
|
|
|
+ mtd="$1"
|
|
|
+ endpoint="$2"
|
|
|
+ data="$3"
|
|
|
+
|
|
|
+ export _H1="Authorization: APIKey $EDGECENTER_API_KEY"
|
|
|
+
|
|
|
+ case "$mtd" in
|
|
|
+ get)
|
|
|
+ response="$(_get "$EDGECENTER_API/$endpoint")"
|
|
|
+ ;;
|
|
|
+ post)
|
|
|
+ response="$(_post "$data" "$EDGECENTER_API/$endpoint")"
|
|
|
+ ;;
|
|
|
+ delete)
|
|
|
+ response="$(_post "" "$EDGECENTER_API/$endpoint" "" "DELETE")"
|
|
|
+ ;;
|
|
|
+ put)
|
|
|
+ response="$(_post "$data" "$EDGECENTER_API/$endpoint" "" "PUT")"
|
|
|
+ ;;
|
|
|
+ *)
|
|
|
+ _err "Unknown HTTP method $mtd"
|
|
|
+ return 1
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+
|
|
|
+ _debug "HTTP $mtd response: $response"
|
|
|
+ return 0
|
|
|
+}
|