committed by
neil
1 changed files with 211 additions and 0 deletions
@ -0,0 +1,211 @@ |
|||
#!/usr/bin/env sh |
|||
# shellcheck disable=SC2034 |
|||
dns_sitehost_info='SiteHost |
|||
Site: sitehost.nz |
|||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_sitehost |
|||
Options: |
|||
SITEHOST_API_KEY API Key |
|||
SITEHOST_CLIENT_ID Client ID. The numeric client ID for your SiteHost account. |
|||
Issues: github.com/acmesh-official/acme.sh/issues/6892 |
|||
Author: Jordan Russell <jordanbrussell@gmail.com> |
|||
' |
|||
|
|||
SITEHOST_API="https://api.sitehost.nz/1.5" |
|||
|
|||
######## Public functions ##################### |
|||
|
|||
#Usage: dns_sitehost_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" |
|||
dns_sitehost_add() { |
|||
fulldomain=$1 |
|||
txtvalue=$2 |
|||
|
|||
if ! _sitehost_load_creds; then |
|||
return 1 |
|||
fi |
|||
|
|||
_debug "First detect the root zone" |
|||
if ! _get_root "$fulldomain"; then |
|||
_err "invalid domain" |
|||
return 1 |
|||
fi |
|||
|
|||
_debug _sub_domain "$_sub_domain" |
|||
_debug _domain "$_domain" |
|||
|
|||
# SiteHost expects the full record name as the name parameter |
|||
_info "Adding TXT record for ${fulldomain}" |
|||
if _sitehost_rest POST "dns/add_record.json" "client_id=${SITEHOST_CLIENT_ID}&domain=${_domain}&type=TXT&name=${fulldomain}&content=${txtvalue}"; then |
|||
if _contains "$response" '"Successful"'; then |
|||
_info "TXT record added successfully." |
|||
return 0 |
|||
fi |
|||
fi |
|||
|
|||
_err "Could not add TXT record for ${fulldomain}" |
|||
_err "$response" |
|||
return 1 |
|||
} |
|||
|
|||
#Usage: dns_sitehost_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" |
|||
#Remove the txt record after validation. |
|||
dns_sitehost_rm() { |
|||
fulldomain=$1 |
|||
txtvalue=$2 |
|||
|
|||
if ! _sitehost_load_creds; then |
|||
return 1 |
|||
fi |
|||
|
|||
_debug "First detect the root zone" |
|||
if ! _get_root "$fulldomain"; then |
|||
_err "invalid domain" |
|||
return 1 |
|||
fi |
|||
|
|||
_debug _sub_domain "$_sub_domain" |
|||
_debug _domain "$_domain" |
|||
|
|||
_debug "Getting TXT records for ${_domain}" |
|||
if ! _sitehost_rest GET "dns/list_records.json" "client_id=${SITEHOST_CLIENT_ID}&domain=${_domain}"; then |
|||
_err "Could not list DNS records" |
|||
_err "$response" |
|||
return 1 |
|||
fi |
|||
|
|||
# Extract record ID matching our fulldomain, type TXT, and txtvalue |
|||
# Response format: {"return":[{"id":"123","name":"...","type":"TXT","content":"..."},...]} |
|||
# SiteHost returns flat single-line JSON objects in the records array |
|||
# Use field-specific matching to avoid false positives from substring matches |
|||
_record_id="$(echo "$response" | _egrep_o '\{[^}]*\}' | grep '"name" *: *"'"${fulldomain}"'"' | grep '"type" *: *"TXT"' | grep '"content" *: *"'"${txtvalue}"'"' | _head_n 1 | _egrep_o '"id" *: *"?[0-9]+"?' | _egrep_o '[0-9]+')" |
|||
|
|||
if [ -z "$_record_id" ]; then |
|||
_info "TXT record not found, nothing to remove." |
|||
return 0 |
|||
fi |
|||
|
|||
_debug _record_id "$_record_id" |
|||
|
|||
_info "Deleting TXT record ${_record_id} for ${fulldomain}" |
|||
if _sitehost_rest POST "dns/delete_record.json" "client_id=${SITEHOST_CLIENT_ID}&domain=${_domain}&record_id=${_record_id}"; then |
|||
if _contains "$response" '"Successful"'; then |
|||
_info "TXT record deleted successfully." |
|||
return 0 |
|||
fi |
|||
fi |
|||
|
|||
_err "Could not delete TXT record for ${fulldomain}" |
|||
_err "$response" |
|||
return 1 |
|||
} |
|||
|
|||
#################### Private functions below ################################## |
|||
|
|||
_sitehost_load_creds() { |
|||
SITEHOST_API_KEY="${SITEHOST_API_KEY:-$(_readaccountconf_mutable SITEHOST_API_KEY)}" |
|||
SITEHOST_CLIENT_ID="${SITEHOST_CLIENT_ID:-$(_readaccountconf_mutable SITEHOST_CLIENT_ID)}" |
|||
|
|||
if [ -z "$SITEHOST_API_KEY" ] || [ -z "$SITEHOST_CLIENT_ID" ]; then |
|||
SITEHOST_API_KEY="" |
|||
SITEHOST_CLIENT_ID="" |
|||
_err "You didn't specify SITEHOST_API_KEY and/or SITEHOST_CLIENT_ID." |
|||
_err "Please export them and try again." |
|||
return 1 |
|||
fi |
|||
|
|||
_saveaccountconf_mutable SITEHOST_API_KEY "$SITEHOST_API_KEY" |
|||
_saveaccountconf_mutable SITEHOST_CLIENT_ID "$SITEHOST_CLIENT_ID" |
|||
return 0 |
|||
} |
|||
|
|||
#_acme-challenge.www.domain.com |
|||
#returns |
|||
# _sub_domain=_acme-challenge.www |
|||
# _domain=domain.com |
|||
_get_root() { |
|||
domain=$1 |
|||
|
|||
_debug "Getting domain list" |
|||
|
|||
# Fetch ALL pages of domains first so we can match the most specific zone |
|||
# (a more specific zone on a later page must take precedence over a broader match) |
|||
_all_domains="" |
|||
_page=1 |
|||
|
|||
while true; do |
|||
if ! _sitehost_rest GET "dns/list_domains.json" "client_id=${SITEHOST_CLIENT_ID}&filters%5Bpage_number%5D=${_page}"; then |
|||
_err "Could not list domains" |
|||
return 1 |
|||
fi |
|||
|
|||
if ! _contains "$response" '"Successful"'; then |
|||
_err "Error listing domains" |
|||
_err "$response" |
|||
return 1 |
|||
fi |
|||
|
|||
_all_domains="${_all_domains} ${response}" |
|||
|
|||
_total_pages=$(echo "$response" | _egrep_o '"total_pages" *: *[0-9]+' | _egrep_o '[0-9]+') |
|||
if [ -z "$_total_pages" ] || [ "$_page" -ge "$_total_pages" ]; then |
|||
break |
|||
fi |
|||
|
|||
_page=$(_math "$_page" + 1) |
|||
done |
|||
|
|||
# Try each subdomain level, most specific first |
|||
_i=1 |
|||
_p=1 |
|||
while true; do |
|||
h=$(printf "%s" "$domain" | cut -d . -f "${_i}"-100) |
|||
_debug h "$h" |
|||
if [ -z "$h" ]; then |
|||
return 1 |
|||
fi |
|||
|
|||
if echo "$_all_domains" | grep -F "\"${h}\"" >/dev/null 2>&1; then |
|||
if [ "$_i" = "1" ]; then |
|||
# DNS alias mode - fulldomain is the zone itself |
|||
_sub_domain="" |
|||
else |
|||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"${_p}") |
|||
fi |
|||
_domain="${h}" |
|||
return 0 |
|||
fi |
|||
|
|||
_p="${_i}" |
|||
_i=$(_math "$_i" + 1) |
|||
done |
|||
|
|||
return 1 |
|||
} |
|||
|
|||
#Usage: _sitehost_rest method endpoint data |
|||
_sitehost_rest() { |
|||
m="$1" |
|||
ep="$2" |
|||
data="$3" |
|||
url="${SITEHOST_API}/${ep}" |
|||
|
|||
_debug url "$url" |
|||
|
|||
_apikey="$(printf "%s" "${SITEHOST_API_KEY}" | _url_encode)" |
|||
|
|||
if [ "$m" = "GET" ]; then |
|||
response="$(_get "${url}?apikey=${_apikey}&${data}")" |
|||
else |
|||
_debug2 data "$data" |
|||
response="$(_post "apikey=${_apikey}&${data}" "$url")" |
|||
fi |
|||
|
|||
if [ "$?" != "0" ]; then |
|||
_err "error ${ep}" |
|||
return 1 |
|||
fi |
|||
|
|||
response="$(echo "$response" | tr -d '\r')" |
|||
|
|||
_debug2 response "$response" |
|||
return 0 |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue