From 3abcfd8fa926fb1ee03b45826f8a12644e63ff05 Mon Sep 17 00:00:00 2001 From: KincaidYang <91786638+KincaidYang@users.noreply.github.com> Date: Sat, 2 Sep 2023 18:47:59 +0800 Subject: [PATCH 1/5] Add dns_tencent.sh Adapt to Tencent Cloud (DNSPod) API 3.0 --- dnsapi/dns_tencent.sh | 210 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 dnsapi/dns_tencent.sh diff --git a/dnsapi/dns_tencent.sh b/dnsapi/dns_tencent.sh new file mode 100644 index 00000000..b4b4cb24 --- /dev/null +++ b/dnsapi/dns_tencent.sh @@ -0,0 +1,210 @@ +#!/usr/bin/env sh +Tencent_API="https://dnspod.tencentcloudapi.com" + +#Tencent_SecretId="AKIDz81d2cd22cdcdc2dcd1cc1d1A" +#Tencent_SecretKey="Gu5t9abcabcaabcbabcbbbcbcbbccbbcb" + +#Usage: dns_tencent_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_tencent_add() { + fulldomain=$1 + txtvalue=$2 + + Tencent_SecretId="${Tencent_SecretId:-$(_readaccountconf_mutable Tencent_SecretId)}" + Tencent_SecretKey="${Tencent_SecretKey:-$(_readaccountconf_mutable Tencent_SecretKey)}" + if [ -z "$Tencent_SecretId" ] || [ -z "$Tencent_SecretKey" ]; then + Tencent_SecretId="" + Tencent_SecretKey="" + _err "You don't specify tencent api SecretId and SecretKey yet." + return 1 + fi + + #save the api SecretId and SecretKey to the account conf file. + _saveaccountconf_mutable Tencent_SecretId "$Tencent_SecretId" + _saveaccountconf_mutable Tencent_SecretKey "$Tencent_SecretKey" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + return 1 + fi + + _debug "Add record" + _add_record_query "$_domain" "$_sub_domain" "$txtvalue" && _tencent_rest "CreateRecord" +} + +dns_tencent_rm() { + fulldomain=$1 + txtvalue=$2 + Tencent_SecretId="${Tencent_SecretId:-$(_readaccountconf_mutable Tencent_SecretId)}" + Tencent_SecretKey="${Tencent_SecretKey:-$(_readaccountconf_mutable Tencent_SecretKey)}" + + _debug "First detect the root zone" + if ! _get_root "$fulldomain"; then + return 1 + fi + + _debug "Get record list" + attempt=1 + max_attempts=5 + while [ -z "$record_id" ] && [ $attempt -le $max_attempts ]; do + _check_exist_query "$_domain" "$_sub_domain" "$txtvalue" && _tencent_rest "DescribeRecordFilterList" + record_id="$(echo "$response" | _egrep_o "\"RecordId\":\s*[0-9]+" | _egrep_o "[0-9]+")" + _debug2 record_id "$record_id" + if [ -z "$record_id" ]; then + _debug "Due to TencentCloud API synchronization delay, record not found, waiting 10 seconds and retrying" + sleep 10 + attempt=$((attempt + 1)) + fi + done + + record_id="$(echo "$response" | _egrep_o "\"RecordId\":\s*[0-9]+" | _egrep_o "[0-9]+")" + _debug2 record_id "$record_id" + + if [ -z "$record_id" ]; then + _debug "record not found after $max_attempts attempts, skip" + else + _debug "Delete record" + _delete_record_query "$record_id" && _tencent_rest "DeleteRecord" + fi +} + +#################### Private functions below ################################## + +_get_root() { + domain=$1 + i=2 + p=1 + while true; do + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) + if [ -z "$h" ]; then + #not valid + return 1 + fi + + _describe_records_query "$h" "@" + if ! _tencent_rest "DescribeRecordList" "ignore"; then + return 1 + fi + + if _contains "$response" "\"TotalCount\":"; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") + _debug _sub_domain "$_sub_domain" + _domain="$h" + _debug _domain "$_domain" + return 0 + fi + p="$i" + i=$(_math "$i" + 1) + done + return 1 +} + +_tencent_rest() { + action=$1 + service="dnspod" + payload="${query}" + timestamp=$(date -u +%s) + + token=$(tencent_signature_v3 $service "$action" "$payload" "$timestamp") + version="2021-03-23" + + if ! response="$(tencent_api_request $service $version "$action" "$payload" "$timestamp")"; then + _err "Error <$1>" + return 1 + fi + + _debug2 response "$response" + if [ -z "$2" ]; then + message="$(echo "$response" | _egrep_o "\"Message\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")" + if [ "$message" ]; then + _err "$message" + return 1 + fi + fi +} + +_add_record_query() { + query="{\"Domain\":\"$1\",\"SubDomain\":\"$2\",\"RecordType\":\"TXT\",\"RecordLineId\":\"0\",\"RecordLine\":\"0\",\"Value\":\"$3\",\"TTL\":600}" +} + +_describe_records_query() { + query="{\"Domain\":\"$1\",\"Limit\":3000}" +} + +_delete_record_query() { + query="{\"Domain\":\"$_domain\",\"RecordId\":$1}" +} + +_check_exist_query() { + _domain="$1" + _subdomain="$2" + _value="$3" + query="{\"Domain\":\"$_domain\",\"SubDomain\":\"$_subdomain\",\"RecordValue\":\"$_value\"}" +} + +# shell client for tencent cloud api v3 | @author: rehiy + +tencent_sha256() { + printf %b "$@" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -hex | sed 's/^.* //' +} + +tencent_hmac_sha256() { + k=$1 + shift + printf %b "$@" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -hmac "$k" | sed 's/^.* //' +} + +tencent_hmac_sha256_hexkey() { + k=$1 + shift + printf %b "$@" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -mac HMAC -macopt "hexkey:$k" | sed 's/^.* //' +} + +tencent_signature_v3() { + service=$1 + action=$(echo "$2" | tr '[:upper:]' '[:lower:]') + payload=${3:-'{}'} + timestamp=${4:-$(date +%s)} + + domain="$service.tencentcloudapi.com" + secretId=${Tencent_SecretId:-'tencent-cloud-secret-id'} + secretKey=${Tencent_SecretKey:-'tencent-cloud-secret-key'} + + algorithm='TC3-HMAC-SHA256' + date=$(date -u -d "@$timestamp" +%Y-%m-%d 2>/dev/null) + [ -z "$date" ] && date=$(date -u -r "$timestamp" +%Y-%m-%d) + + canonicalUri='/' + canonicalQuery='' + canonicalHeaders="content-type:application/json\nhost:$domain\nx-tc-action:$action\n" + + signedHeaders='content-type;host;x-tc-action' + canonicalRequest="POST\n$canonicalUri\n$canonicalQuery\n$canonicalHeaders\n$signedHeaders\n$(tencent_sha256 "$payload")" + + credentialScope="$date/$service/tc3_request" + stringToSign="$algorithm\n$timestamp\n$credentialScope\n$(tencent_sha256 "$canonicalRequest")" + + secretDate=$(tencent_hmac_sha256 "TC3$secretKey" "$date") + secretService=$(tencent_hmac_sha256_hexkey "$secretDate" "$service") + secretSigning=$(tencent_hmac_sha256_hexkey "$secretService" 'tc3_request') + signature=$(tencent_hmac_sha256_hexkey "$secretSigning" "$stringToSign") + + echo "$algorithm Credential=$secretId/$credentialScope, SignedHeaders=$signedHeaders, Signature=$signature" +} + +tencent_api_request() { + service=$1 + version=$2 + action=$3 + payload=${4:-'{}'} + timestamp=${5:-$(date +%s)} + + token=$(tencent_signature_v3 "$service" "$action" "$payload" "$timestamp") + + _H1="Content-Type: application/json" + _H2="Authorization: $token" + _H3="X-TC-Version: $version" + _H4="X-TC-Timestamp: $timestamp" + _H5="X-TC-Action: $action" + + _post "$payload" "$Tencent_API" "" "POST" "application/json" +} From b3f8612e6128d186359d0b0b91dcb8ee2683dc8f Mon Sep 17 00:00:00 2001 From: KincaidYang <91786638+KincaidYang@users.noreply.github.com> Date: Sun, 3 Sep 2023 01:31:57 +0800 Subject: [PATCH 2/5] Following Neilpang's suggestions and project standards, replace some functions. --- dnsapi/dns_tencent.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/dnsapi/dns_tencent.sh b/dnsapi/dns_tencent.sh index b4b4cb24..746f00f0 100644 --- a/dnsapi/dns_tencent.sh +++ b/dnsapi/dns_tencent.sh @@ -51,7 +51,7 @@ dns_tencent_rm() { _debug2 record_id "$record_id" if [ -z "$record_id" ]; then _debug "Due to TencentCloud API synchronization delay, record not found, waiting 10 seconds and retrying" - sleep 10 + _sleep 10 attempt=$((attempt + 1)) fi done @@ -71,7 +71,7 @@ dns_tencent_rm() { _get_root() { domain=$1 - i=2 + i=1 p=1 while true; do h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) @@ -144,19 +144,20 @@ _check_exist_query() { # shell client for tencent cloud api v3 | @author: rehiy tencent_sha256() { - printf %b "$@" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -hex | sed 's/^.* //' + printf %b "$@" | _digest sha256 hex } tencent_hmac_sha256() { k=$1 shift - printf %b "$@" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -hmac "$k" | sed 's/^.* //' + hex_key=$(_ascii_hex "$k" | tr -d ' ') + printf %b "$@" | _hmac sha256 "$hex_key" hex } tencent_hmac_sha256_hexkey() { k=$1 shift - printf %b "$@" | ${ACME_OPENSSL_BIN:-openssl} dgst -sha256 -mac HMAC -macopt "hexkey:$k" | sed 's/^.* //' + printf %b "$@" | _hmac sha256 "$k" hex } tencent_signature_v3() { From e3c4c9265dfe2d2816e68dfe310d5f6fcda4f25b Mon Sep 17 00:00:00 2001 From: KincaidYang <91786638+KincaidYang@users.noreply.github.com> Date: Sun, 3 Sep 2023 21:21:05 +0800 Subject: [PATCH 3/5] Replace some functions. --- dnsapi/dns_tencent.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dnsapi/dns_tencent.sh b/dnsapi/dns_tencent.sh index 746f00f0..5cce4aeb 100644 --- a/dnsapi/dns_tencent.sh +++ b/dnsapi/dns_tencent.sh @@ -45,14 +45,14 @@ dns_tencent_rm() { _debug "Get record list" attempt=1 max_attempts=5 - while [ -z "$record_id" ] && [ $attempt -le $max_attempts ]; do + while [ -z "$record_id" ] && [ "$attempt" -le $max_attempts ]; do _check_exist_query "$_domain" "$_sub_domain" "$txtvalue" && _tencent_rest "DescribeRecordFilterList" record_id="$(echo "$response" | _egrep_o "\"RecordId\":\s*[0-9]+" | _egrep_o "[0-9]+")" _debug2 record_id "$record_id" if [ -z "$record_id" ]; then _debug "Due to TencentCloud API synchronization delay, record not found, waiting 10 seconds and retrying" _sleep 10 - attempt=$((attempt + 1)) + attempt=$(_math "$attempt + 1") fi done @@ -162,7 +162,7 @@ tencent_hmac_sha256_hexkey() { tencent_signature_v3() { service=$1 - action=$(echo "$2" | tr '[:upper:]' '[:lower:]') + action=$(echo "$2" | _lower_case) payload=${3:-'{}'} timestamp=${4:-$(date +%s)} From 772bbdc862777cf06c649271c9319f45b9075313 Mon Sep 17 00:00:00 2001 From: KincaidYang <91786638+KincaidYang@users.noreply.github.com> Date: Wed, 6 Sep 2023 12:57:19 +0800 Subject: [PATCH 4/5] Replace some functions --- dnsapi/dns_tencent.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dnsapi/dns_tencent.sh b/dnsapi/dns_tencent.sh index 5cce4aeb..b926225b 100644 --- a/dnsapi/dns_tencent.sh +++ b/dnsapi/dns_tencent.sh @@ -150,7 +150,7 @@ tencent_sha256() { tencent_hmac_sha256() { k=$1 shift - hex_key=$(_ascii_hex "$k" | tr -d ' ') + hex_key=$(printf %b "$k" | _hex_dump | tr -d ' ') printf %b "$@" | _hmac sha256 "$hex_key" hex } @@ -183,6 +183,7 @@ tencent_signature_v3() { credentialScope="$date/$service/tc3_request" stringToSign="$algorithm\n$timestamp\n$credentialScope\n$(tencent_sha256 "$canonicalRequest")" + _debug "stringToSign: $stringToSign" secretDate=$(tencent_hmac_sha256 "TC3$secretKey" "$date") secretService=$(tencent_hmac_sha256_hexkey "$secretDate" "$service") From af534a73fc75cddf5a60f0ec1b13f79056b51940 Mon Sep 17 00:00:00 2001 From: KincaidYang <91786638+KincaidYang@users.noreply.github.com> Date: Wed, 6 Sep 2023 13:09:52 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E9=83=A8=E5=88=86?= =?UTF-8?q?=E6=95=8F=E6=84=9Fdebug=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dnsapi/dns_tencent.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dnsapi/dns_tencent.sh b/dnsapi/dns_tencent.sh index b926225b..2f8d3b67 100644 --- a/dnsapi/dns_tencent.sh +++ b/dnsapi/dns_tencent.sh @@ -183,7 +183,6 @@ tencent_signature_v3() { credentialScope="$date/$service/tc3_request" stringToSign="$algorithm\n$timestamp\n$credentialScope\n$(tencent_sha256 "$canonicalRequest")" - _debug "stringToSign: $stringToSign" secretDate=$(tencent_hmac_sha256 "TC3$secretKey" "$date") secretService=$(tencent_hmac_sha256_hexkey "$secretDate" "$service")