acme.sh/dnsapi/dns_clouddns.sh

203 lines
6.5 KiB
Bash
Raw Normal View History

2020-01-21 06:36:31 +01:00
#!/usr/bin/env sh
# shellcheck disable=SC2034
dns_clouddns_info='vshosting.cz CloudDNS
Site: github.com/vshosting/clouddns
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_clouddns
Options:
CLOUDDNS_EMAIL Email
CLOUDDNS_PASSWORD Password
CLOUDDNS_CLIENT_ID Client ID
Issues: github.com/acmesh-official/acme.sh/issues/2699
Author: Radek Sprta <sprta@vshosting.cz>
'
2020-01-21 06:36:31 +01:00
CLOUDDNS_API='https://admin.vshosting.cloud/clouddns'
CLOUDDNS_LOGIN_API='https://admin.vshosting.cloud/api/public/auth/login'
######## Public functions #####################
2020-01-22 01:59:40 +01:00
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
2020-01-21 06:36:31 +01:00
dns_clouddns_add() {
fulldomain=$1
txtvalue=$2
2020-01-22 01:59:40 +01:00
_debug "fulldomain" "$fulldomain"
2020-01-21 06:36:31 +01:00
CLOUDDNS_CLIENT_ID="${CLOUDDNS_CLIENT_ID:-$(_readaccountconf_mutable CLOUDDNS_CLIENT_ID)}"
CLOUDDNS_EMAIL="${CLOUDDNS_EMAIL:-$(_readaccountconf_mutable CLOUDDNS_EMAIL)}"
CLOUDDNS_PASSWORD="${CLOUDDNS_PASSWORD:-$(_readaccountconf_mutable CLOUDDNS_PASSWORD)}"
if [ -z "$CLOUDDNS_PASSWORD" ] || [ -z "$CLOUDDNS_EMAIL" ] || [ -z "$CLOUDDNS_CLIENT_ID" ]; then
CLOUDDNS_CLIENT_ID=""
CLOUDDNS_EMAIL=""
CLOUDDNS_PASSWORD=""
2020-01-22 01:59:40 +01:00
_err "You didn't specify a CloudDNS password, email and client ID yet."
2020-01-21 06:36:31 +01:00
return 1
fi
if ! _contains "$CLOUDDNS_EMAIL" "@"; then
_err "It seems that the CLOUDDNS_EMAIL=$CLOUDDNS_EMAIL is not a valid email address."
_err "Please check and retry."
return 1
fi
# Save CloudDNS client id, email and password to config file
_saveaccountconf_mutable CLOUDDNS_CLIENT_ID "$CLOUDDNS_CLIENT_ID"
_saveaccountconf_mutable CLOUDDNS_EMAIL "$CLOUDDNS_EMAIL"
_saveaccountconf_mutable CLOUDDNS_PASSWORD "$CLOUDDNS_PASSWORD"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "Invalid domain"
return 1
fi
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
2020-01-22 02:53:50 +01:00
# Add TXT record
data="{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"value\":\"$txtvalue\",\"domainId\":\"$_domain_id\"}"
if _clouddns_api POST "record-txt" "$data"; then
2020-01-21 06:36:31 +01:00
if _contains "$response" "$txtvalue"; then
_info "Added, OK"
elif _contains "$response" '"code":4136'; then
_info "Already exists, OK"
else
2020-01-22 01:59:40 +01:00
_err "Add TXT record error."
2020-01-21 06:36:31 +01:00
return 1
fi
fi
_debug "Publishing record changes"
_clouddns_api PUT "domain/$_domain_id/publish" "{\"soaTtl\":300}"
}
2020-01-22 01:59:40 +01:00
# Usage: rm _acme-challenge.www.domain.com
2020-01-21 06:36:31 +01:00
dns_clouddns_rm() {
fulldomain=$1
2020-01-22 01:59:40 +01:00
_debug "fulldomain" "$fulldomain"
2020-01-21 06:36:31 +01:00
CLOUDDNS_CLIENT_ID="${CLOUDDNS_CLIENT_ID:-$(_readaccountconf_mutable CLOUDDNS_CLIENT_ID)}"
CLOUDDNS_EMAIL="${CLOUDDNS_EMAIL:-$(_readaccountconf_mutable CLOUDDNS_EMAIL)}"
CLOUDDNS_PASSWORD="${CLOUDDNS_PASSWORD:-$(_readaccountconf_mutable CLOUDDNS_PASSWORD)}"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
2020-01-22 01:59:40 +01:00
_err "Invalid domain"
2020-01-21 06:36:31 +01:00
return 1
fi
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
2020-01-22 01:59:40 +01:00
# Get record ID
2020-01-22 02:53:50 +01:00
_clouddns_api GET "domain/$_domain_id"
2020-01-21 06:36:31 +01:00
if _contains "$response" "lastDomainRecordList"; then
2020-01-22 05:33:46 +01:00
re="\"lastDomainRecordList\".*\"id\":\"([^\"}]*)\"[^}]*\"name\":\"$fulldomain.\","
2020-01-21 06:36:31 +01:00
_last_domains=$(echo "$response" | _egrep_o "$re")
re2="\"id\":\"([^\"}]*)\"[^}]*\"name\":\"$fulldomain.\","
_record_id=$(echo "$_last_domains" | _egrep_o "$re2" | _head_n 1 | cut -d : -f 2 | cut -d , -f 1 | tr -d "\"")
_debug _record_id "$_record_id"
else
2020-01-22 01:59:40 +01:00
_err "Could not retrieve record ID"
2020-01-21 06:36:31 +01:00
return 1
fi
2020-01-22 05:33:46 +01:00
2020-01-21 06:36:31 +01:00
_info "Removing record"
if _clouddns_api DELETE "record/$_record_id"; then
if _contains "$response" "\"error\":"; then
_err "Could not remove record"
return 1
fi
fi
_debug "Publishing record changes"
_clouddns_api PUT "domain/$_domain_id/publish" "{\"soaTtl\":300}"
}
#################### Private functions below ##################################
2020-01-22 01:59:40 +01:00
# Usage: _get_root _acme-challenge.www.domain.com
# Returns:
2020-01-21 06:36:31 +01:00
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() {
domain=$1
2020-01-22 01:33:15 +01:00
# Get domain root
data="{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$CLOUDDNS_CLIENT_ID\"}]}"
2020-01-22 05:33:46 +01:00
_clouddns_api "POST" "domain/search" "$data"
2020-01-22 01:33:15 +01:00
domain_slice="$domain"
while [ -z "$domain_root" ]; do
if _contains "$response" "\"domainName\":\"$domain_slice\.\""; then
domain_root="$domain_slice"
_debug domain_root "$domain_root"
fi
domain_slice="$(echo "$domain_slice" | cut -d . -f 2-)"
done
2020-01-21 06:36:31 +01:00
# Get domain id
data="{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$CLOUDDNS_CLIENT_ID\"}, \
2020-01-22 01:59:40 +01:00
{\"name\": \"domainName\", \"operator\": \"eq\", \"value\": \"$domain_root.\"}]}"
2020-01-22 02:53:50 +01:00
_clouddns_api "POST" "domain/search" "$data"
2020-01-21 06:36:31 +01:00
if _contains "$response" "\"id\":\""; then
re='domainType\":\"[^\"]*\",\"id\":\"([^\"]*)\",' # Match domain id
_domain_id=$(echo "$response" | _egrep_o "$re" | _head_n 1 | cut -d : -f 3 | tr -d "\",")
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | sed "s/.$domain_root//")
_domain="$domain_root"
return 0
fi
_err 'Domain name not found on your CloudDNS account'
return 1
fi
return 1
}
2020-01-22 01:59:40 +01:00
# Usage: _clouddns_api GET domain/search '{"data": "value"}'
# Returns:
# response='{"message": "api response"}'
2020-01-21 06:36:31 +01:00
_clouddns_api() {
method=$1
endpoint="$2"
data="$3"
_debug endpoint "$endpoint"
if [ -z "$CLOUDDNS_TOKEN" ]; then
_clouddns_login
fi
_debug CLOUDDNS_TOKEN "$CLOUDDNS_TOKEN"
export _H1="Content-Type: application/json"
export _H2="Authorization: Bearer $CLOUDDNS_TOKEN"
if [ "$method" != "GET" ]; then
_debug data "$data"
2020-01-22 02:53:50 +01:00
response="$(_post "$data" "$CLOUDDNS_API/$endpoint" "" "$method" | tr -d '\t\r\n ')"
2020-01-21 06:36:31 +01:00
else
2020-01-22 02:53:50 +01:00
response="$(_get "$CLOUDDNS_API/$endpoint" | tr -d '\t\r\n ')"
2020-01-21 06:36:31 +01:00
fi
2020-01-22 02:03:11 +01:00
# shellcheck disable=SC2181
2020-01-21 06:36:31 +01:00
if [ "$?" != "0" ]; then
2020-01-22 01:59:40 +01:00
_err "Error $endpoint"
2020-01-21 06:36:31 +01:00
return 1
fi
2020-01-22 02:53:50 +01:00
_debug2 response "$response"
2020-01-21 06:36:31 +01:00
return 0
}
2020-01-22 01:59:40 +01:00
# Returns:
# CLOUDDNS_TOKEN=dslfje2rj23l
2020-01-21 06:36:31 +01:00
_clouddns_login() {
login_data="{\"email\": \"$CLOUDDNS_EMAIL\", \"password\": \"$CLOUDDNS_PASSWORD\"}"
response="$(_post "$login_data" "$CLOUDDNS_LOGIN_API" "" "POST" "Content-Type: application/json")"
if _contains "$response" "\"accessToken\":\""; then
CLOUDDNS_TOKEN=$(echo "$response" | _egrep_o "\"accessToken\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")
export CLOUDDNS_TOKEN
else
echo 'Could not get CloudDNS access token; check your credentials'
return 1
fi
return 0
}