flywithu
4 years ago
37 changed files with 2255 additions and 323 deletions
-
4.github/workflows/DNS.yml
-
4.github/workflows/LetsEncrypt.yml
-
10.github/workflows/dockerhub.yml
-
1Dockerfile
-
7README.md
-
257acme.sh
-
30deploy/cleverreach.sh
-
1deploy/docker.sh
-
13deploy/gcore_cdn.sh
-
123deploy/peplink.sh
-
34deploy/synology_dsm.sh
-
220deploy/unifi.sh
-
10deploy/vault_cli.sh
-
47dnsapi/dns_arvan.sh
-
171dnsapi/dns_aurora.sh
-
61dnsapi/dns_constellix.sh
-
25dnsapi/dns_desec.sh
-
2dnsapi/dns_dp.sh
-
10dnsapi/dns_dpi.sh
-
8dnsapi/dns_duckdns.sh
-
36dnsapi/dns_huaweicloud.sh
-
162dnsapi/dns_ionos.sh
-
26dnsapi/dns_ispconfig.sh
-
3dnsapi/dns_linode_v4.sh
-
10dnsapi/dns_namecheap.sh
-
56dnsapi/dns_one.sh
-
4dnsapi/dns_pdns.sh
-
157dnsapi/dns_porkbun.sh
-
156dnsapi/dns_rackcorp.sh
-
176dnsapi/dns_scaleway.sh
-
42dnsapi/dns_servercow.sh
-
18dnsapi/dns_simply.sh
-
207dnsapi/dns_websupport.sh
-
31dnsapi/dns_world4you.sh
-
2notify/mail.sh
-
402notify/smtp.sh
-
52notify/telegram.sh
@ -0,0 +1,123 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
# Script to deploy cert to Peplink Routers |
||||
|
# |
||||
|
# The following environment variables must be set: |
||||
|
# |
||||
|
# PEPLINK_Hostname - Peplink hostname |
||||
|
# PEPLINK_Username - Peplink username to login |
||||
|
# PEPLINK_Password - Peplink password to login |
||||
|
# |
||||
|
# The following environmental variables may be set if you don't like their |
||||
|
# default values: |
||||
|
# |
||||
|
# PEPLINK_Certtype - Certificate type to target for replacement |
||||
|
# defaults to "webadmin", can be one of: |
||||
|
# * "chub" (ContentHub) |
||||
|
# * "openvpn" (OpenVPN CA) |
||||
|
# * "portal" (Captive Portal SSL) |
||||
|
# * "webadmin" (Web Admin SSL) |
||||
|
# * "webproxy" (Proxy Root CA) |
||||
|
# * "wwan_ca" (Wi-Fi WAN CA) |
||||
|
# * "wwan_client" (Wi-Fi WAN Client) |
||||
|
# PEPLINK_Scheme - defaults to "https" |
||||
|
# PEPLINK_Port - defaults to "443" |
||||
|
# |
||||
|
#returns 0 means success, otherwise error. |
||||
|
|
||||
|
######## Public functions ##################### |
||||
|
|
||||
|
_peplink_get_cookie_data() { |
||||
|
grep -i "\W$1=" | grep -i "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';' |
||||
|
} |
||||
|
|
||||
|
#domain keyfile certfile cafile fullchain |
||||
|
peplink_deploy() { |
||||
|
|
||||
|
_cdomain="$1" |
||||
|
_ckey="$2" |
||||
|
_cfullchain="$5" |
||||
|
|
||||
|
_debug _cdomain "$_cdomain" |
||||
|
_debug _cfullchain "$_cfullchain" |
||||
|
_debug _ckey "$_ckey" |
||||
|
|
||||
|
# Get Hostname, Username and Password, but don't save until we successfully authenticate |
||||
|
_getdeployconf PEPLINK_Hostname |
||||
|
_getdeployconf PEPLINK_Username |
||||
|
_getdeployconf PEPLINK_Password |
||||
|
if [ -z "${PEPLINK_Hostname:-}" ] || [ -z "${PEPLINK_Username:-}" ] || [ -z "${PEPLINK_Password:-}" ]; then |
||||
|
_err "PEPLINK_Hostname & PEPLINK_Username & PEPLINK_Password must be set" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug2 PEPLINK_Hostname "$PEPLINK_Hostname" |
||||
|
_debug2 PEPLINK_Username "$PEPLINK_Username" |
||||
|
_secure_debug2 PEPLINK_Password "$PEPLINK_Password" |
||||
|
|
||||
|
# Optional certificate type, scheme, and port for Peplink |
||||
|
_getdeployconf PEPLINK_Certtype |
||||
|
_getdeployconf PEPLINK_Scheme |
||||
|
_getdeployconf PEPLINK_Port |
||||
|
|
||||
|
# Don't save the certificate type until we verify it exists and is supported |
||||
|
_savedeployconf PEPLINK_Scheme "$PEPLINK_Scheme" |
||||
|
_savedeployconf PEPLINK_Port "$PEPLINK_Port" |
||||
|
|
||||
|
# Default vaules for certificate type, scheme, and port |
||||
|
[ -n "${PEPLINK_Certtype}" ] || PEPLINK_Certtype="webadmin" |
||||
|
[ -n "${PEPLINK_Scheme}" ] || PEPLINK_Scheme="https" |
||||
|
[ -n "${PEPLINK_Port}" ] || PEPLINK_Port="443" |
||||
|
|
||||
|
_debug2 PEPLINK_Certtype "$PEPLINK_Certtype" |
||||
|
_debug2 PEPLINK_Scheme "$PEPLINK_Scheme" |
||||
|
_debug2 PEPLINK_Port "$PEPLINK_Port" |
||||
|
|
||||
|
_base_url="$PEPLINK_Scheme://$PEPLINK_Hostname:$PEPLINK_Port" |
||||
|
_debug _base_url "$_base_url" |
||||
|
|
||||
|
# Login, get the auth token from the cookie |
||||
|
_info "Logging into $PEPLINK_Hostname:$PEPLINK_Port" |
||||
|
encoded_username="$(printf "%s" "$PEPLINK_Username" | _url_encode)" |
||||
|
encoded_password="$(printf "%s" "$PEPLINK_Password" | _url_encode)" |
||||
|
response=$(_post "func=login&username=$encoded_username&password=$encoded_password" "$_base_url/cgi-bin/MANGA/api.cgi") |
||||
|
auth_token=$(_peplink_get_cookie_data "bauth" <"$HTTP_HEADER") |
||||
|
_debug3 response "$response" |
||||
|
_debug auth_token "$auth_token" |
||||
|
|
||||
|
if [ -z "$auth_token" ]; then |
||||
|
_err "Unable to authenticate to $PEPLINK_Hostname:$PEPLINK_Port using $PEPLINK_Scheme." |
||||
|
_err "Check your username and password." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_H1="Cookie: $auth_token" |
||||
|
export _H1 |
||||
|
_debug2 H1 "${_H1}" |
||||
|
|
||||
|
# Now that we know the hostnameusername and password are good, save them |
||||
|
_savedeployconf PEPLINK_Hostname "$PEPLINK_Hostname" |
||||
|
_savedeployconf PEPLINK_Username "$PEPLINK_Username" |
||||
|
_savedeployconf PEPLINK_Password "$PEPLINK_Password" |
||||
|
|
||||
|
_info "Generate form POST request" |
||||
|
|
||||
|
encoded_key="$(_url_encode <"$_ckey")" |
||||
|
encoded_fullchain="$(_url_encode <"$_cfullchain")" |
||||
|
body="cert_type=$PEPLINK_Certtype&cert_uid=§ion=CERT_modify&key_pem=$encoded_key&key_pem_passphrase=&key_pem_passphrase_confirm=&cert_pem=$encoded_fullchain" |
||||
|
_debug3 body "$body" |
||||
|
|
||||
|
_info "Upload $PEPLINK_Certtype certificate to the Peplink" |
||||
|
|
||||
|
response=$(_post "$body" "$_base_url/cgi-bin/MANGA/admin.cgi") |
||||
|
_debug3 response "$response" |
||||
|
|
||||
|
if echo "$response" | grep 'Success' >/dev/null; then |
||||
|
# We've verified this certificate type is valid, so save it |
||||
|
_savedeployconf PEPLINK_Certtype "$PEPLINK_Certtype" |
||||
|
_info "Certificate was updated" |
||||
|
return 0 |
||||
|
else |
||||
|
_err "Unable to update certificate, error code $response" |
||||
|
return 1 |
||||
|
fi |
||||
|
} |
@ -0,0 +1,171 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
# |
||||
|
#AURORA_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" |
||||
|
# |
||||
|
#AURORA_Secret="sdfsdfsdfljlbjkljlkjsdfoiwje" |
||||
|
|
||||
|
AURORA_Api="https://api.auroradns.eu" |
||||
|
|
||||
|
######## Public functions ##################### |
||||
|
|
||||
|
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" |
||||
|
dns_aurora_add() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
AURORA_Key="${AURORA_Key:-$(_readaccountconf_mutable AURORA_Key)}" |
||||
|
AURORA_Secret="${AURORA_Secret:-$(_readaccountconf_mutable AURORA_Secret)}" |
||||
|
|
||||
|
if [ -z "$AURORA_Key" ] || [ -z "$AURORA_Secret" ]; then |
||||
|
AURORA_Key="" |
||||
|
AURORA_Secret="" |
||||
|
_err "You didn't specify an Aurora api key and secret yet." |
||||
|
_err "You can get yours from here https://cp.pcextreme.nl/auroradns/users." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
#save the api key and secret to the account conf file. |
||||
|
_saveaccountconf_mutable AURORA_Key "$AURORA_Key" |
||||
|
_saveaccountconf_mutable AURORA_Secret "$AURORA_Secret" |
||||
|
|
||||
|
_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" |
||||
|
|
||||
|
_info "Adding record" |
||||
|
if _aurora_rest POST "zones/$_domain_id/records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":300}"; then |
||||
|
if _contains "$response" "$txtvalue"; then |
||||
|
_info "Added, OK" |
||||
|
return 0 |
||||
|
elif _contains "$response" "RecordExistsError"; then |
||||
|
_info "Already exists, OK" |
||||
|
return 0 |
||||
|
else |
||||
|
_err "Add txt record error." |
||||
|
return 1 |
||||
|
fi |
||||
|
fi |
||||
|
_err "Add txt record error." |
||||
|
return 1 |
||||
|
|
||||
|
} |
||||
|
|
||||
|
#fulldomain txtvalue |
||||
|
dns_aurora_rm() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
AURORA_Key="${AURORA_Key:-$(_readaccountconf_mutable AURORA_Key)}" |
||||
|
AURORA_Secret="${AURORA_Secret:-$(_readaccountconf_mutable AURORA_Secret)}" |
||||
|
|
||||
|
_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" |
||||
|
|
||||
|
_debug "Getting records" |
||||
|
_aurora_rest GET "zones/${_domain_id}/records" |
||||
|
|
||||
|
if ! _contains "$response" "$txtvalue"; then |
||||
|
_info "Don't need to remove." |
||||
|
else |
||||
|
records=$(echo "$response" | _normalizeJson | tr -d "[]" | sed "s/},{/}|{/g" | tr "|" "\n") |
||||
|
if [ "$(echo "$records" | wc -l)" -le 2 ]; then |
||||
|
_err "Can not parse records." |
||||
|
return 1 |
||||
|
fi |
||||
|
record_id=$(echo "$records" | grep "\"type\": *\"TXT\"" | grep "\"name\": *\"$_sub_domain\"" | grep "\"content\": *\"$txtvalue\"" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | _head_n 1 | tr -d " ") |
||||
|
_debug "record_id" "$record_id" |
||||
|
if [ -z "$record_id" ]; then |
||||
|
_err "Can not get record id to remove." |
||||
|
return 1 |
||||
|
fi |
||||
|
if ! _aurora_rest DELETE "zones/$_domain_id/records/$record_id"; then |
||||
|
_err "Delete record error." |
||||
|
return 1 |
||||
|
fi |
||||
|
fi |
||||
|
return 0 |
||||
|
|
||||
|
} |
||||
|
|
||||
|
#################### Private functions below ################################## |
||||
|
#_acme-challenge.www.domain.com |
||||
|
#returns |
||||
|
# _sub_domain=_acme-challenge.www |
||||
|
# _domain=domain.com |
||||
|
# _domain_id=sdjkglgdfewsdfg |
||||
|
_get_root() { |
||||
|
domain=$1 |
||||
|
i=1 |
||||
|
p=1 |
||||
|
|
||||
|
while true; do |
||||
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100) |
||||
|
_debug h "$h" |
||||
|
if [ -z "$h" ]; then |
||||
|
#not valid |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if ! _aurora_rest GET "zones/$h"; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if _contains "$response" "\"name\": \"$h\""; then |
||||
|
_domain_id=$(echo "$response" | _normalizeJson | tr -d "{}" | tr "," "\n" | grep "\"id\": *\"" | cut -d : -f 2 | tr -d \" | _head_n 1 | tr -d " ") |
||||
|
_debug _domain_id "$_domain_id" |
||||
|
if [ "$_domain_id" ]; then |
||||
|
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) |
||||
|
_domain=$h |
||||
|
return 0 |
||||
|
fi |
||||
|
return 1 |
||||
|
fi |
||||
|
p=$i |
||||
|
i=$(_math "$i" + 1) |
||||
|
done |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
_aurora_rest() { |
||||
|
m=$1 |
||||
|
ep="$2" |
||||
|
data="$3" |
||||
|
_debug "$ep" |
||||
|
|
||||
|
key_trimmed=$(echo "$AURORA_Key" | tr -d '"') |
||||
|
secret_trimmed=$(echo "$AURORA_Secret" | tr -d '"') |
||||
|
|
||||
|
timestamp=$(date -u +"%Y%m%dT%H%M%SZ") |
||||
|
signature=$(printf "%s/%s%s" "$m" "$ep" "$timestamp" | _hmac sha256 "$(printf "%s" "$secret_trimmed" | _hex_dump | tr -d " ")" | _base64) |
||||
|
authorization=$(printf "AuroraDNSv1 %s" "$(printf "%s:%s" "$key_trimmed" "$signature" | _base64)") |
||||
|
|
||||
|
export _H1="Content-Type: application/json; charset=UTF-8" |
||||
|
export _H2="X-AuroraDNS-Date: $timestamp" |
||||
|
export _H3="Authorization: $authorization" |
||||
|
|
||||
|
if [ "$m" != "GET" ]; then |
||||
|
_debug data "$data" |
||||
|
response="$(_post "$data" "$AURORA_Api/$ep" "" "$m")" |
||||
|
else |
||||
|
response="$(_get "$AURORA_Api/$ep")" |
||||
|
fi |
||||
|
|
||||
|
if [ "$?" != "0" ]; then |
||||
|
_err "error $ep" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug2 response "$response" |
||||
|
return 0 |
||||
|
} |
@ -0,0 +1,162 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
# Supports IONOS DNS API Beta v1.0.0 |
||||
|
# |
||||
|
# Usage: |
||||
|
# Export IONOS_PREFIX and IONOS_SECRET before calling acme.sh: |
||||
|
# |
||||
|
# $ export IONOS_PREFIX="..." |
||||
|
# $ export IONOS_SECRET="..." |
||||
|
# |
||||
|
# $ acme.sh --issue --dns dns_ionos ... |
||||
|
|
||||
|
IONOS_API="https://api.hosting.ionos.com/dns" |
||||
|
IONOS_ROUTE_ZONES="/v1/zones" |
||||
|
|
||||
|
IONOS_TXT_TTL=60 # minimum accepted by API |
||||
|
IONOS_TXT_PRIO=10 |
||||
|
|
||||
|
dns_ionos_add() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
if ! _ionos_init; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_body="[{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}]" |
||||
|
|
||||
|
if _ionos_rest POST "$IONOS_ROUTE_ZONES/$_zone_id/records" "$_body" && [ -z "$response" ]; then |
||||
|
_info "TXT record has been created successfully." |
||||
|
return 0 |
||||
|
fi |
||||
|
|
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
dns_ionos_rm() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
if ! _ionos_init; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if ! _ionos_get_record "$fulldomain" "$_zone_id" "$txtvalue"; then |
||||
|
_err "Could not find _acme-challenge TXT record." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if _ionos_rest DELETE "$IONOS_ROUTE_ZONES/$_zone_id/records/$_record_id" && [ -z "$response" ]; then |
||||
|
_info "TXT record has been deleted successfully." |
||||
|
return 0 |
||||
|
fi |
||||
|
|
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
_ionos_init() { |
||||
|
IONOS_PREFIX="${IONOS_PREFIX:-$(_readaccountconf_mutable IONOS_PREFIX)}" |
||||
|
IONOS_SECRET="${IONOS_SECRET:-$(_readaccountconf_mutable IONOS_SECRET)}" |
||||
|
|
||||
|
if [ -z "$IONOS_PREFIX" ] || [ -z "$IONOS_SECRET" ]; then |
||||
|
_err "You didn't specify an IONOS api prefix and secret yet." |
||||
|
_err "Read https://beta.developer.hosting.ionos.de/docs/getstarted to learn how to get a prefix and secret." |
||||
|
_err "" |
||||
|
_err "Then set them before calling acme.sh:" |
||||
|
_err "\$ export IONOS_PREFIX=\"...\"" |
||||
|
_err "\$ export IONOS_SECRET=\"...\"" |
||||
|
_err "\$ acme.sh --issue -d ... --dns dns_ionos" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_saveaccountconf_mutable IONOS_PREFIX "$IONOS_PREFIX" |
||||
|
_saveaccountconf_mutable IONOS_SECRET "$IONOS_SECRET" |
||||
|
|
||||
|
if ! _get_root "$fulldomain"; then |
||||
|
_err "Cannot find this domain in your IONOS account." |
||||
|
return 1 |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
_get_root() { |
||||
|
domain=$1 |
||||
|
i=1 |
||||
|
p=1 |
||||
|
|
||||
|
if _ionos_rest GET "$IONOS_ROUTE_ZONES"; then |
||||
|
response="$(echo "$response" | tr -d "\n")" |
||||
|
|
||||
|
while true; do |
||||
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100) |
||||
|
if [ -z "$h" ]; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_zone="$(echo "$response" | _egrep_o "\"name\":\"$h\".*\}")" |
||||
|
if [ "$_zone" ]; then |
||||
|
_zone_id=$(printf "%s\n" "$_zone" | _egrep_o "\"id\":\"[a-fA-F0-9\-]*\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') |
||||
|
if [ "$_zone_id" ]; then |
||||
|
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) |
||||
|
_domain=$h |
||||
|
|
||||
|
return 0 |
||||
|
fi |
||||
|
|
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
p=$i |
||||
|
i=$(_math "$i" + 1) |
||||
|
done |
||||
|
fi |
||||
|
|
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
_ionos_get_record() { |
||||
|
fulldomain=$1 |
||||
|
zone_id=$2 |
||||
|
txtrecord=$3 |
||||
|
|
||||
|
if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then |
||||
|
response="$(echo "$response" | tr -d "\n")" |
||||
|
|
||||
|
_record="$(echo "$response" | _egrep_o "\"name\":\"$fulldomain\"[^\}]*\"type\":\"TXT\"[^\}]*\"content\":\"\\\\\"$txtrecord\\\\\"\".*\}")" |
||||
|
if [ "$_record" ]; then |
||||
|
_record_id=$(printf "%s\n" "$_record" | _egrep_o "\"id\":\"[a-fA-F0-9\-]*\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"') |
||||
|
|
||||
|
return 0 |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
_ionos_rest() { |
||||
|
method="$1" |
||||
|
route="$2" |
||||
|
data="$3" |
||||
|
|
||||
|
IONOS_API_KEY="$(printf "%s.%s" "$IONOS_PREFIX" "$IONOS_SECRET")" |
||||
|
|
||||
|
export _H1="X-API-Key: $IONOS_API_KEY" |
||||
|
|
||||
|
if [ "$method" != "GET" ]; then |
||||
|
export _H2="Accept: application/json" |
||||
|
export _H3="Content-Type: application/json" |
||||
|
|
||||
|
response="$(_post "$data" "$IONOS_API$route" "" "$method" "application/json")" |
||||
|
else |
||||
|
export _H2="Accept: */*" |
||||
|
|
||||
|
response="$(_get "$IONOS_API$route")" |
||||
|
fi |
||||
|
|
||||
|
if [ "$?" != "0" ]; then |
||||
|
_err "Error $route" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
return 0 |
||||
|
} |
@ -0,0 +1,157 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
# |
||||
|
#PORKBUN_API_KEY="pk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" |
||||
|
#PORKBUN_SECRET_API_KEY="sk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" |
||||
|
|
||||
|
PORKBUN_Api="https://porkbun.com/api/json/v3" |
||||
|
|
||||
|
######## Public functions ##################### |
||||
|
|
||||
|
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" |
||||
|
dns_porkbun_add() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}" |
||||
|
PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}" |
||||
|
|
||||
|
if [ -z "$PORKBUN_API_KEY" ] || [ -z "$PORKBUN_SECRET_API_KEY" ]; then |
||||
|
PORKBUN_API_KEY='' |
||||
|
PORKBUN_SECRET_API_KEY='' |
||||
|
_err "You didn't specify a Porkbun api key and secret api key yet." |
||||
|
_err "You can get yours from here https://porkbun.com/account/api." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
#save the credentials to the account conf file. |
||||
|
_saveaccountconf_mutable PORKBUN_API_KEY "$PORKBUN_API_KEY" |
||||
|
_saveaccountconf_mutable PORKBUN_SECRET_API_KEY "$PORKBUN_SECRET_API_KEY" |
||||
|
|
||||
|
_debug 'First detect the root zone' |
||||
|
if ! _get_root "$fulldomain"; then |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug _sub_domain "$_sub_domain" |
||||
|
_debug _domain "$_domain" |
||||
|
|
||||
|
# For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so |
||||
|
# we can not use updating anymore. |
||||
|
# count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2) |
||||
|
# _debug count "$count" |
||||
|
# if [ "$count" = "0" ]; then |
||||
|
_info "Adding record" |
||||
|
if _porkbun_rest POST "dns/create/$_domain" "{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":120}"; then |
||||
|
if _contains "$response" '\"status\":"SUCCESS"'; then |
||||
|
_info "Added, OK" |
||||
|
return 0 |
||||
|
elif _contains "$response" "The record already exists"; then |
||||
|
_info "Already exists, OK" |
||||
|
return 0 |
||||
|
else |
||||
|
_err "Add txt record error. ($response)" |
||||
|
return 1 |
||||
|
fi |
||||
|
fi |
||||
|
_err "Add txt record error." |
||||
|
return 1 |
||||
|
|
||||
|
} |
||||
|
|
||||
|
#fulldomain txtvalue |
||||
|
dns_porkbun_rm() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}" |
||||
|
PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}" |
||||
|
|
||||
|
_debug 'First detect the root zone' |
||||
|
if ! _get_root "$fulldomain"; then |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug _sub_domain "$_sub_domain" |
||||
|
_debug _domain "$_domain" |
||||
|
|
||||
|
count=$(echo "$response" | _egrep_o "\"count\": *[^,]*" | cut -d : -f 2 | tr -d " ") |
||||
|
_debug count "$count" |
||||
|
if [ "$count" = "0" ]; then |
||||
|
_info "Don't need to remove." |
||||
|
else |
||||
|
record_id=$(echo "$response" | tr '{' '\n' | grep -- "$txtvalue" | cut -d, -f1 | cut -d: -f2 | tr -d \") |
||||
|
_debug "record_id" "$record_id" |
||||
|
if [ -z "$record_id" ]; then |
||||
|
_err "Can not get record id to remove." |
||||
|
return 1 |
||||
|
fi |
||||
|
if ! _porkbun_rest POST "dns/delete/$_domain/$record_id"; then |
||||
|
_err "Delete record error." |
||||
|
return 1 |
||||
|
fi |
||||
|
echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null |
||||
|
fi |
||||
|
|
||||
|
} |
||||
|
|
||||
|
#################### Private functions below ################################## |
||||
|
#_acme-challenge.www.domain.com |
||||
|
#returns |
||||
|
# _sub_domain=_acme-challenge.www |
||||
|
# _domain=domain.com |
||||
|
_get_root() { |
||||
|
domain=$1 |
||||
|
i=1 |
||||
|
while true; do |
||||
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100) |
||||
|
_debug h "$h" |
||||
|
if [ -z "$h" ]; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if _porkbun_rest POST "dns/retrieve/$h"; then |
||||
|
if _contains "$response" "\"status\":\"SUCCESS\""; then |
||||
|
_sub_domain="$(echo "$fulldomain" | sed "s/\\.$_domain\$//")" |
||||
|
_domain=$h |
||||
|
return 0 |
||||
|
else |
||||
|
_debug "Go to next level of $_domain" |
||||
|
fi |
||||
|
else |
||||
|
_debug "Go to next level of $_domain" |
||||
|
fi |
||||
|
i=$(_math "$i" + 1) |
||||
|
done |
||||
|
|
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
_porkbun_rest() { |
||||
|
m=$1 |
||||
|
ep="$2" |
||||
|
data="$3" |
||||
|
_debug "$ep" |
||||
|
|
||||
|
api_key_trimmed=$(echo "$PORKBUN_API_KEY" | tr -d '"') |
||||
|
secret_api_key_trimmed=$(echo "$PORKBUN_SECRET_API_KEY" | tr -d '"') |
||||
|
|
||||
|
test -z "$data" && data="{" || data="$(echo $data | cut -d'}' -f1)," |
||||
|
data="$data\"apikey\":\"$api_key_trimmed\",\"secretapikey\":\"$secret_api_key_trimmed\"}" |
||||
|
|
||||
|
export _H1="Content-Type: application/json" |
||||
|
|
||||
|
if [ "$m" != "GET" ]; then |
||||
|
_debug data "$data" |
||||
|
response="$(_post "$data" "$PORKBUN_Api/$ep" "" "$m")" |
||||
|
else |
||||
|
response="$(_get "$PORKBUN_Api/$ep")" |
||||
|
fi |
||||
|
|
||||
|
_sleep 3 # prevent rate limit |
||||
|
|
||||
|
if [ "$?" != "0" ]; then |
||||
|
_err "error $ep" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug2 response "$response" |
||||
|
return 0 |
||||
|
} |
@ -0,0 +1,156 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
# Provider: RackCorp (www.rackcorp.com) |
||||
|
# Author: Stephen Dendtler (sdendtler@rackcorp.com) |
||||
|
# Report Bugs here: https://github.com/senjoo/acme.sh |
||||
|
# Alternate email contact: support@rackcorp.com |
||||
|
# |
||||
|
# You'll need an API key (Portal: ADMINISTRATION -> API) |
||||
|
# Set the environment variables as below: |
||||
|
# |
||||
|
# export RACKCORP_APIUUID="UUIDHERE" |
||||
|
# export RACKCORP_APISECRET="SECRETHERE" |
||||
|
# |
||||
|
|
||||
|
RACKCORP_API_ENDPOINT="https://api.rackcorp.net/api/rest/v2.4/json.php" |
||||
|
|
||||
|
######## Public functions ##################### |
||||
|
|
||||
|
dns_rackcorp_add() { |
||||
|
fulldomain="$1" |
||||
|
txtvalue="$2" |
||||
|
|
||||
|
_debug fulldomain="$fulldomain" |
||||
|
_debug txtvalue="$txtvalue" |
||||
|
|
||||
|
if ! _rackcorp_validate; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_debug "Searching for root zone" |
||||
|
if ! _get_root "$fulldomain"; then |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug _lookup "$_lookup" |
||||
|
_debug _domain "$_domain" |
||||
|
|
||||
|
_info "Creating TXT record." |
||||
|
|
||||
|
if ! _rackcorp_api dns.record.create "\"name\":\"$_domain\",\"type\":\"TXT\",\"lookup\":\"$_lookup\",\"data\":\"$txtvalue\",\"ttl\":300"; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
#Usage: fulldomain txtvalue |
||||
|
#Remove the txt record after validation. |
||||
|
dns_rackcorp_rm() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
_debug fulldomain="$fulldomain" |
||||
|
_debug txtvalue="$txtvalue" |
||||
|
|
||||
|
if ! _rackcorp_validate; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_debug "Searching for root zone" |
||||
|
if ! _get_root "$fulldomain"; then |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug _lookup "$_lookup" |
||||
|
_debug _domain "$_domain" |
||||
|
|
||||
|
_info "Creating TXT record." |
||||
|
|
||||
|
if ! _rackcorp_api dns.record.delete "\"name\":\"$_domain\",\"type\":\"TXT\",\"lookup\":\"$_lookup\",\"data\":\"$txtvalue\""; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
#################### Private functions below ################################## |
||||
|
#_acme-challenge.domain.com |
||||
|
#returns |
||||
|
# _lookup=_acme-challenge |
||||
|
# _domain=domain.com |
||||
|
_get_root() { |
||||
|
domain=$1 |
||||
|
i=1 |
||||
|
p=1 |
||||
|
if ! _rackcorp_api dns.domain.getall "\"name\":\"$domain\""; then |
||||
|
return 1 |
||||
|
fi |
||||
|
while true; do |
||||
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100) |
||||
|
_debug searchhost "$h" |
||||
|
if [ -z "$h" ]; then |
||||
|
_err "Could not find domain for record $domain in RackCorp using the provided credentials" |
||||
|
#not valid |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_rackcorp_api dns.domain.getall "\"exactName\":\"$h\"" |
||||
|
|
||||
|
if _contains "$response" "\"matches\":1"; then |
||||
|
if _contains "$response" "\"name\":\"$h\""; then |
||||
|
_lookup=$(printf "%s" "$domain" | cut -d . -f 1-$p) |
||||
|
_domain="$h" |
||||
|
return 0 |
||||
|
fi |
||||
|
fi |
||||
|
p=$i |
||||
|
i=$(_math "$i" + 1) |
||||
|
done |
||||
|
|
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
_rackcorp_validate() { |
||||
|
RACKCORP_APIUUID="${RACKCORP_APIUUID:-$(_readaccountconf_mutable RACKCORP_APIUUID)}" |
||||
|
if [ -z "$RACKCORP_APIUUID" ]; then |
||||
|
RACKCORP_APIUUID="" |
||||
|
_err "You require a RackCorp API UUID (export RACKCORP_APIUUID=\"<api uuid>\")" |
||||
|
_err "Please login to the portal and create an API key and try again." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_saveaccountconf_mutable RACKCORP_APIUUID "$RACKCORP_APIUUID" |
||||
|
|
||||
|
RACKCORP_APISECRET="${RACKCORP_APISECRET:-$(_readaccountconf_mutable RACKCORP_APISECRET)}" |
||||
|
if [ -z "$RACKCORP_APISECRET" ]; then |
||||
|
RACKCORP_APISECRET="" |
||||
|
_err "You require a RackCorp API secret (export RACKCORP_APISECRET=\"<api secret>\")" |
||||
|
_err "Please login to the portal and create an API key and try again." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_saveaccountconf_mutable RACKCORP_APISECRET "$RACKCORP_APISECRET" |
||||
|
|
||||
|
return 0 |
||||
|
} |
||||
|
_rackcorp_api() { |
||||
|
_rackcorpcmd=$1 |
||||
|
_rackcorpinputdata=$2 |
||||
|
_debug cmd "$_rackcorpcmd $_rackcorpinputdata" |
||||
|
|
||||
|
export _H1="Accept: application/json" |
||||
|
response="$(_post "{\"APIUUID\":\"$RACKCORP_APIUUID\",\"APISECRET\":\"$RACKCORP_APISECRET\",\"cmd\":\"$_rackcorpcmd\",$_rackcorpinputdata}" "$RACKCORP_API_ENDPOINT" "" "POST")" |
||||
|
|
||||
|
if [ "$?" != "0" ]; then |
||||
|
_err "error $response" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug2 response "$response" |
||||
|
if _contains "$response" "\"code\":\"OK\""; then |
||||
|
_debug code "OK" |
||||
|
else |
||||
|
_debug code "FAILED" |
||||
|
response="" |
||||
|
return 1 |
||||
|
fi |
||||
|
return 0 |
||||
|
} |
@ -0,0 +1,176 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
# Scaleway API |
||||
|
# https://developers.scaleway.com/en/products/domain/dns/api/ |
||||
|
# |
||||
|
# Requires Scaleway API token set in SCALEWAY_API_TOKEN |
||||
|
|
||||
|
######## Public functions ##################### |
||||
|
|
||||
|
SCALEWAY_API="https://api.scaleway.com/domain/v2beta1" |
||||
|
|
||||
|
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" |
||||
|
dns_scaleway_add() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
if ! _scaleway_check_config; 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" |
||||
|
|
||||
|
_info "Adding record" |
||||
|
_scaleway_create_TXT_record "$_domain" "$_sub_domain" "$txtvalue" |
||||
|
if _contains "$response" "records"; then |
||||
|
return 0 |
||||
|
else |
||||
|
_err error "$response" |
||||
|
return 1 |
||||
|
fi |
||||
|
_info "Record added." |
||||
|
|
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
dns_scaleway_rm() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
if ! _scaleway_check_config; 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" |
||||
|
|
||||
|
_info "Deleting record" |
||||
|
_scaleway_delete_TXT_record "$_domain" "$_sub_domain" "$txtvalue" |
||||
|
if _contains "$response" "records"; then |
||||
|
return 0 |
||||
|
else |
||||
|
_err error "$response" |
||||
|
return 1 |
||||
|
fi |
||||
|
_info "Record deleted." |
||||
|
|
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
#################### Private functions below ################################## |
||||
|
|
||||
|
_scaleway_check_config() { |
||||
|
SCALEWAY_API_TOKEN="${SCALEWAY_API_TOKEN:-$(_readaccountconf_mutable SCALEWAY_API_TOKEN)}" |
||||
|
if [ -z "$SCALEWAY_API_TOKEN" ]; then |
||||
|
_err "No API key specified for Scaleway API." |
||||
|
_err "Create your key and export it as SCALEWAY_API_TOKEN" |
||||
|
return 1 |
||||
|
fi |
||||
|
if ! _scaleway_rest GET "dns-zones"; then |
||||
|
_err "Invalid API key specified for Scaleway API." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_saveaccountconf_mutable SCALEWAY_API_TOKEN "$SCALEWAY_API_TOKEN" |
||||
|
|
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
#_acme-challenge.www.domain.com |
||||
|
#returns |
||||
|
# _sub_domain=_acme-challenge.www |
||||
|
# _domain=domain.com |
||||
|
_get_root() { |
||||
|
domain=$1 |
||||
|
i=1 |
||||
|
p=1 |
||||
|
while true; do |
||||
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100) |
||||
|
if [ -z "$h" ]; then |
||||
|
#not valid |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_scaleway_rest GET "dns-zones/$h/records" |
||||
|
|
||||
|
if ! _contains "$response" "subdomain not found" >/dev/null; then |
||||
|
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) |
||||
|
_domain="$h" |
||||
|
return 0 |
||||
|
fi |
||||
|
p=$i |
||||
|
i=$(_math "$i" + 1) |
||||
|
done |
||||
|
_err "Unable to retrive DNS zone matching this domain" |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
# this function add a TXT record |
||||
|
_scaleway_create_TXT_record() { |
||||
|
txt_zone=$1 |
||||
|
txt_name=$2 |
||||
|
txt_value=$3 |
||||
|
|
||||
|
_scaleway_rest PATCH "dns-zones/$txt_zone/records" "{\"return_all_records\":false,\"changes\":[{\"add\":{\"records\":[{\"name\":\"$txt_name\",\"data\":\"$txt_value\",\"type\":\"TXT\",\"ttl\":60}]}}]}" |
||||
|
|
||||
|
if _contains "$response" "records"; then |
||||
|
return 0 |
||||
|
else |
||||
|
_err "error1 $response" |
||||
|
return 1 |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
# this function delete a TXT record based on name and content |
||||
|
_scaleway_delete_TXT_record() { |
||||
|
txt_zone=$1 |
||||
|
txt_name=$2 |
||||
|
txt_value=$3 |
||||
|
|
||||
|
_scaleway_rest PATCH "dns-zones/$txt_zone/records" "{\"return_all_records\":false,\"changes\":[{\"delete\":{\"id_fields\":{\"name\":\"$txt_name\",\"data\":\"$txt_value\",\"type\":\"TXT\"}}}]}" |
||||
|
|
||||
|
if _contains "$response" "records"; then |
||||
|
return 0 |
||||
|
else |
||||
|
_err "error2 $response" |
||||
|
return 1 |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
_scaleway_rest() { |
||||
|
m=$1 |
||||
|
ep="$2" |
||||
|
data="$3" |
||||
|
_debug "$ep" |
||||
|
_scaleway_url="$SCALEWAY_API/$ep" |
||||
|
_debug2 _scaleway_url "$_scaleway_url" |
||||
|
export _H1="x-auth-token: $SCALEWAY_API_TOKEN" |
||||
|
export _H2="Accept: application/json" |
||||
|
export _H3="Content-Type: application/json" |
||||
|
|
||||
|
if [ "$data" ] || [ "$m" != "GET" ]; then |
||||
|
_debug data "$data" |
||||
|
response="$(_post "$data" "$_scaleway_url" "" "$m")" |
||||
|
else |
||||
|
response="$(_get "$_scaleway_url")" |
||||
|
fi |
||||
|
if [ "$?" != "0" ] || _contains "$response" "denied_authentication" || _contains "$response" "Method not allowed" || _contains "$response" "json parse error: unexpected EOF"; then |
||||
|
_err "error $response" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug2 response "$response" |
||||
|
return 0 |
||||
|
} |
@ -0,0 +1,207 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
# Acme.sh DNS API wrapper for websupport.sk |
||||
|
# |
||||
|
# Original author: trgo.sk (https://github.com/trgosk) |
||||
|
# Tweaks by: akulumbeg (https://github.com/akulumbeg) |
||||
|
# Report Bugs here: https://github.com/akulumbeg/acme.sh |
||||
|
|
||||
|
# Requirements: API Key and Secret from https://admin.websupport.sk/en/auth/apiKey |
||||
|
# |
||||
|
# WS_ApiKey="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" |
||||
|
# (called "Identifier" in the WS Admin) |
||||
|
# |
||||
|
# WS_ApiSecret="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" |
||||
|
# (called "Secret key" in the WS Admin) |
||||
|
|
||||
|
WS_Api="https://rest.websupport.sk" |
||||
|
|
||||
|
######## Public functions ##################### |
||||
|
|
||||
|
dns_websupport_add() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
WS_ApiKey="${WS_ApiKey:-$(_readaccountconf_mutable WS_ApiKey)}" |
||||
|
WS_ApiSecret="${WS_ApiSecret:-$(_readaccountconf_mutable WS_ApiSecret)}" |
||||
|
|
||||
|
if [ "$WS_ApiKey" ] && [ "$WS_ApiSecret" ]; then |
||||
|
_saveaccountconf_mutable WS_ApiKey "$WS_ApiKey" |
||||
|
_saveaccountconf_mutable WS_ApiSecret "$WS_ApiSecret" |
||||
|
else |
||||
|
WS_ApiKey="" |
||||
|
WS_ApiSecret="" |
||||
|
_err "You did not specify the API Key and/or API Secret" |
||||
|
_err "You can get the API login credentials from https://admin.websupport.sk/en/auth/apiKey" |
||||
|
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" |
||||
|
|
||||
|
# For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so |
||||
|
# we can not use updating anymore. |
||||
|
# count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2) |
||||
|
# _debug count "$count" |
||||
|
# if [ "$count" = "0" ]; then |
||||
|
_info "Adding record" |
||||
|
if _ws_rest POST "/v1/user/self/zone/$_domain/record" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then |
||||
|
if _contains "$response" "$txtvalue"; then |
||||
|
_info "Added, OK" |
||||
|
return 0 |
||||
|
elif _contains "$response" "The record already exists"; then |
||||
|
_info "Already exists, OK" |
||||
|
return 0 |
||||
|
else |
||||
|
_err "Add txt record error." |
||||
|
return 1 |
||||
|
fi |
||||
|
fi |
||||
|
_err "Add txt record error." |
||||
|
return 1 |
||||
|
|
||||
|
} |
||||
|
|
||||
|
dns_websupport_rm() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
_debug2 fulldomain "$fulldomain" |
||||
|
_debug2 txtvalue "$txtvalue" |
||||
|
|
||||
|
_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" |
||||
|
_ws_rest GET "/v1/user/self/zone/$_domain/record" |
||||
|
|
||||
|
if [ "$(printf "%s" "$response" | tr -d " " | grep -c \"items\")" -lt "1" ]; then |
||||
|
_err "Error: $response" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
record_line="$(_get_from_array "$response" "$txtvalue")" |
||||
|
_debug record_line "$record_line" |
||||
|
if [ -z "$record_line" ]; then |
||||
|
_info "Don't need to remove." |
||||
|
else |
||||
|
record_id=$(echo "$record_line" | _egrep_o "\"id\": *[^,]*" | _head_n 1 | cut -d : -f 2 | tr -d \" | tr -d " ") |
||||
|
_debug "record_id" "$record_id" |
||||
|
if [ -z "$record_id" ]; then |
||||
|
_err "Can not get record id to remove." |
||||
|
return 1 |
||||
|
fi |
||||
|
if ! _ws_rest DELETE "/v1/user/self/zone/$_domain/record/$record_id"; then |
||||
|
_err "Delete record error." |
||||
|
return 1 |
||||
|
fi |
||||
|
if [ "$(printf "%s" "$response" | tr -d " " | grep -c \"success\")" -lt "1" ]; then |
||||
|
return 1 |
||||
|
else |
||||
|
return 0 |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
} |
||||
|
|
||||
|
#################### Private Functions ################################## |
||||
|
|
||||
|
_get_root() { |
||||
|
domain=$1 |
||||
|
i=1 |
||||
|
p=1 |
||||
|
|
||||
|
while true; do |
||||
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100) |
||||
|
_debug h "$h" |
||||
|
if [ -z "$h" ]; then |
||||
|
#not valid |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if ! _ws_rest GET "/v1/user/self/zone"; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if _contains "$response" "\"name\":\"$h\""; then |
||||
|
_domain_id=$(echo "$response" | _egrep_o "\[.\"id\": *[^,]*" | _head_n 1 | cut -d : -f 2 | tr -d \" | tr -d " ") |
||||
|
if [ "$_domain_id" ]; then |
||||
|
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) |
||||
|
_domain=$h |
||||
|
return 0 |
||||
|
fi |
||||
|
return 1 |
||||
|
fi |
||||
|
p=$i |
||||
|
i=$(_math "$i" + 1) |
||||
|
done |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
_ws_rest() { |
||||
|
me=$1 |
||||
|
pa="$2" |
||||
|
da="$3" |
||||
|
|
||||
|
_debug2 api_key "$WS_ApiKey" |
||||
|
_debug2 api_secret "$WS_ApiSecret" |
||||
|
|
||||
|
timestamp=$(_time) |
||||
|
datez="$(_utc_date | sed "s/ /T/" | sed "s/$/+0000/")" |
||||
|
canonical_request="${me} ${pa} ${timestamp}" |
||||
|
signature_hash=$(printf "%s" "$canonical_request" | _hmac sha1 "$(printf "%s" "$WS_ApiSecret" | _hex_dump | tr -d " ")" hex) |
||||
|
basicauth="$(printf "%s:%s" "$WS_ApiKey" "$signature_hash" | _base64)" |
||||
|
|
||||
|
_debug2 method "$me" |
||||
|
_debug2 path "$pa" |
||||
|
_debug2 data "$da" |
||||
|
_debug2 timestamp "$timestamp" |
||||
|
_debug2 datez "$datez" |
||||
|
_debug2 canonical_request "$canonical_request" |
||||
|
_debug2 signature_hash "$signature_hash" |
||||
|
_debug2 basicauth "$basicauth" |
||||
|
|
||||
|
export _H1="Accept: application/json" |
||||
|
export _H2="Content-Type: application/json" |
||||
|
export _H3="Authorization: Basic ${basicauth}" |
||||
|
export _H4="Date: ${datez}" |
||||
|
|
||||
|
_debug2 H1 "$_H1" |
||||
|
_debug2 H2 "$_H2" |
||||
|
_debug2 H3 "$_H3" |
||||
|
_debug2 H4 "$_H4" |
||||
|
|
||||
|
if [ "$me" != "GET" ]; then |
||||
|
_debug2 "${me} $WS_Api${pa}" |
||||
|
_debug data "$da" |
||||
|
response="$(_post "$da" "${WS_Api}${pa}" "" "$me")" |
||||
|
else |
||||
|
_debug2 "GET $WS_Api${pa}" |
||||
|
response="$(_get "$WS_Api${pa}")" |
||||
|
fi |
||||
|
|
||||
|
_debug2 response "$response" |
||||
|
return "$?" |
||||
|
} |
||||
|
|
||||
|
_get_from_array() { |
||||
|
va="$1" |
||||
|
fi="$2" |
||||
|
for i in $(echo "$va" | sed "s/{/ /g"); do |
||||
|
if _contains "$i" "$fi"; then |
||||
|
echo "$i" |
||||
|
break |
||||
|
fi |
||||
|
done |
||||
|
} |
@ -0,0 +1,52 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
#Support Telegram Bots |
||||
|
|
||||
|
#TELEGRAM_BOT_APITOKEN="" |
||||
|
#TELEGRAM_BOT_CHATID="" |
||||
|
|
||||
|
telegram_send() { |
||||
|
_subject="$1" |
||||
|
_content="$2" |
||||
|
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped |
||||
|
_debug "_statusCode" "$_statusCode" |
||||
|
|
||||
|
TELEGRAM_BOT_APITOKEN="${TELEGRAM_BOT_APITOKEN:-$(_readaccountconf_mutable TELEGRAM_BOT_APITOKEN)}" |
||||
|
if [ -z "$TELEGRAM_BOT_APITOKEN" ]; then |
||||
|
TELEGRAM_BOT_APITOKEN="" |
||||
|
_err "You didn't specify a Telegram BOT API Token TELEGRAM_BOT_APITOKEN yet." |
||||
|
return 1 |
||||
|
fi |
||||
|
_saveaccountconf_mutable TELEGRAM_BOT_APITOKEN "$TELEGRAM_BOT_APITOKEN" |
||||
|
|
||||
|
TELEGRAM_BOT_CHATID="${TELEGRAM_BOT_CHATID:-$(_readaccountconf_mutable TELEGRAM_BOT_CHATID)}" |
||||
|
if [ -z "$TELEGRAM_BOT_CHATID" ]; then |
||||
|
TELEGRAM_BOT_CHATID="" |
||||
|
_err "You didn't specify a Telegram Chat id TELEGRAM_BOT_CHATID yet." |
||||
|
return 1 |
||||
|
fi |
||||
|
_saveaccountconf_mutable TELEGRAM_BOT_CHATID "$TELEGRAM_BOT_CHATID" |
||||
|
|
||||
|
_content="$(printf "%s" "$_content" | sed -e 's/*/\\\\*/')" |
||||
|
_content="$(printf "*%s*\n%s" "$_subject" "$_content" | _json_encode)" |
||||
|
_data="{\"text\": \"$_content\", " |
||||
|
_data="$_data\"chat_id\": \"$TELEGRAM_BOT_CHATID\", " |
||||
|
_data="$_data\"parse_mode\": \"markdown\", " |
||||
|
_data="$_data\"disable_web_page_preview\": \"1\"}" |
||||
|
|
||||
|
_debug "$_data" |
||||
|
|
||||
|
export _H1="Content-Type: application/json" |
||||
|
_telegram_bot_url="https://api.telegram.org/bot${TELEGRAM_BOT_APITOKEN}/sendMessage" |
||||
|
if _post "$_data" "$_telegram_bot_url" >/dev/null; then |
||||
|
# shellcheck disable=SC2154 |
||||
|
_message=$(printf "%s\n" "$response" | sed -n 's/.*"ok":\([^,]*\).*/\1/p') |
||||
|
if [ "$_message" = "true" ]; then |
||||
|
_info "telegram send success." |
||||
|
return 0 |
||||
|
fi |
||||
|
fi |
||||
|
_err "telegram send error." |
||||
|
_err "$response" |
||||
|
return 1 |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue