diff --git a/dnsapi/dns_baidu.sh b/dnsapi/dns_baidu.sh index 8651deab..dfad8eeb 100644 --- a/dnsapi/dns_baidu.sh +++ b/dnsapi/dns_baidu.sh @@ -49,26 +49,95 @@ Options: Baidu_SK SecretAccessKey OptionsAlt: Baidu_BCD_Host API host, default: bcd.baidubce.com + Baidu_DNS_Host New DNS API host, default: dns.baidubce.com + Baidu_API_Preference Engine preference, default: auto Baidu_BCD_Version API version number, default: 1 Baidu_BCD_Expire Signature expiration seconds, default: 3600 Baidu_View Resolve view, default: DEFAULT + Baidu_Line New DNS line, default: default Baidu_TTL Resolve ttl seconds, default: 300 Baidu_RM_Max Max records to delete in one run, default: 20 ' BAIDU_BCD_DEFAULT_HOST="bcd.baidubce.com" +BAIDU_DNS_DEFAULT_HOST="dns.baidubce.com" # --- Public API --- dns_baidu_add() { fulldomain=$(_idn "$1") txtvalue=$2 - if ! _baidu_prepare_record "$fulldomain"; then - _baidu_err "baidu_prepare_record failed for add: $fulldomain" + if ! _baidu_run_with_fallback "add" "$fulldomain" "$txtvalue"; then + _baidu_err "all baidu api engines failed for add: $fulldomain" return 1 fi - if ! _baidu_find_record_ids "$_zone_name" "$_record_domain" "TXT" "$txtvalue"; then + return 0 +} + +dns_baidu_rm() { + fulldomain=$(_idn "$1") + txtvalue=$2 + + if ! _baidu_run_with_fallback "rm" "$fulldomain" "$txtvalue"; then + _baidu_err "all baidu api engines failed for delete: $fulldomain" + return 1 + fi + + return 0 +} + +_baidu_run_with_fallback() { + _action="$1" + _fulldomain="$2" + _txtvalue="$3" + + if ! _baidu_load_credentials; then + _baidu_err "baidu_load_credentials failed" + return 1 + fi + + for _baidu_api_engine in $(_baidu_engine_order); do + if ! _baidu_prepare_record "$_fulldomain"; then + _baidu_info "prepare failed for engine: $_baidu_api_engine" + continue + fi + + if [ "$_action" = "add" ]; then + if _baidu_add_record "$_txtvalue"; then + return 0 + fi + else + if _baidu_rm_record "$_txtvalue"; then + return 0 + fi + fi + + _baidu_info "engine failed, try next if available: $_baidu_api_engine" + done + + return 1 +} + +_baidu_engine_order() { + _pref="$(_lower_case "$(_baidu_trim_ws "${Baidu_API_Preference:-auto}")")" + case "$_pref" in + legacy) + printf "%s" "legacy new" + ;; + new) + printf "%s" "new legacy" + ;; + *) + printf "%s" "new legacy" + ;; + esac +} + +_baidu_add_record() { + _txtvalue="$1" + + if ! _baidu_find_record_ids_current "$_zone_name" "$_record_domain" "TXT" "$_txtvalue"; then _baidu_err "baidu_find_record_ids failed for add: $_record_domain.$_zone_name" return 1 fi @@ -85,16 +154,28 @@ dns_baidu_add() { _ttl="300" ;; esac - _view="$(_baidu_trim_ws "${Baidu_View:-DEFAULT}")" - txtvalue="$(_baidu_trim_ws "$txtvalue")" + + txtvalue="$(_baidu_trim_ws "$_txtvalue")" _record_domain="$(_baidu_trim_ws "$_record_domain")" _zone_name="$(_baidu_trim_ws "$_zone_name")" - _body="$(_baidu_payload_add_txt "$_zone_name" "$_record_domain" "$txtvalue" "$_ttl" "$_view")" - - if ! _baidu_bcd_post "/domain/resolve/add" "$_body"; then - _baidu_err "baidu_bcd_post failed: add record" - return 1 + if [ "$_baidu_api_engine" = "new" ]; then + _line="$(_baidu_trim_ws "${Baidu_Line:-default}")" + if [ -z "$_line" ]; then + _line="default" + fi + _body="$(_baidu_payload_add_txt_dns "$_record_domain" "$txtvalue" "$_ttl" "$_line")" + if ! _baidu_dns_call "POST" "/v1/dns/zone/${_zone_name}/record" "$_body"; then + _baidu_err "baidu_dns_call failed: add record" + return 1 + fi + else + _view="$(_baidu_trim_ws "${Baidu_View:-DEFAULT}")" + _body="$(_baidu_payload_add_txt "$_zone_name" "$_record_domain" "$txtvalue" "$_ttl" "$_view")" + if ! _baidu_bcd_post "/domain/resolve/add" "$_body"; then + _baidu_err "baidu_bcd_post failed: add record" + return 1 + fi fi if _baidu_is_api_error "$response"; then @@ -105,16 +186,10 @@ dns_baidu_add() { return 0 } -dns_baidu_rm() { - fulldomain=$(_idn "$1") - txtvalue=$2 +_baidu_rm_record() { + _txtvalue="$1" - if ! _baidu_prepare_record "$fulldomain"; then - _baidu_err "baidu_prepare_record failed for delete: $fulldomain" - return 1 - fi - - if ! _baidu_find_record_ids "$_zone_name" "$_record_domain" "TXT" "$txtvalue"; then + if ! _baidu_find_record_ids_current "$_zone_name" "$_record_domain" "TXT" "$_txtvalue"; then _baidu_err "baidu_find_record_ids failed for delete: $_record_domain.$_zone_name" return 1 fi @@ -138,28 +213,37 @@ dns_baidu_rm() { fi for _rid in $_ids; do - _body="$(_baidu_payload_delete "$_zone_name" "$_rid")" - if ! _baidu_bcd_post "/domain/resolve/delete" "$_body"; then - _baidu_err "baidu_bcd_post failed: delete recordId=$_rid" - return 1 - fi - if _baidu_is_api_error "$response"; then - _baidu_err "$response" - return 1 + if [ "$_baidu_api_engine" = "new" ]; then + if ! _baidu_dns_call "DELETE" "/v1/dns/zone/${_zone_name}/record/${_rid}" ""; then + _baidu_err "baidu_dns_call failed: delete recordId=$_rid" + return 1 + fi + else + _body="$(_baidu_payload_delete "$_zone_name" "$_rid")" + if ! _baidu_bcd_post "/domain/resolve/delete" "$_body"; then + _baidu_err "baidu_bcd_post failed: delete recordId=$_rid" + return 1 + fi + if _baidu_is_api_error "$response"; then + _baidu_err "$response" + return 1 + fi fi done - if ! _baidu_find_record_ids "$_zone_name" "$_record_domain" "TXT" "$txtvalue"; then - _baidu_err "baidu_find_record_ids failed for delete verify: $_record_domain.$_zone_name" - return 1 - fi - _left_ids="$_BAIDU_FIND_RESULT" - if [ -z "$_left_ids" ]; then - return 0 - fi - if [ -n "$_left_ids" ]; then - _baidu_err "delete verification failed: $_record_domain.$_zone_name still has TXT records" - return 1 + if [ "$_baidu_api_engine" = "legacy" ]; then + if ! _baidu_find_record_ids "$_zone_name" "$_record_domain" "TXT" "$_txtvalue"; then + _baidu_err "baidu_find_record_ids failed for delete verify: $_record_domain.$_zone_name" + return 1 + fi + _left_ids="$_BAIDU_FIND_RESULT" + if [ -z "$_left_ids" ]; then + return 0 + fi + if [ -n "$_left_ids" ]; then + _baidu_err "delete verification failed: $_record_domain.$_zone_name still has TXT records" + return 1 + fi fi return 0 @@ -182,6 +266,7 @@ _baidu_load_credentials() { _saveaccountconf_mutable Baidu_SK "$Baidu_SK" BAIDU_BCD_HOST="${Baidu_BCD_Host:-$BAIDU_BCD_DEFAULT_HOST}" + BAIDU_DNS_HOST="${Baidu_DNS_Host:-$BAIDU_DNS_DEFAULT_HOST}" BAIDU_BCD_VERSION="${Baidu_BCD_Version:-1}" return 0 @@ -189,13 +274,16 @@ _baidu_load_credentials() { _baidu_prepare_record() { _fulldomain="$1" - if ! _baidu_load_credentials; then - _baidu_err "baidu_load_credentials failed" - return 1 - fi - if ! _baidu_get_root "$_fulldomain"; then - _baidu_err "Could not find zone for $_fulldomain" - return 1 + if [ "$_baidu_api_engine" = "new" ]; then + if ! _baidu_get_root_dns "$_fulldomain"; then + _baidu_err "Could not find zone by new dns api for $_fulldomain" + return 1 + fi + else + if ! _baidu_get_root "$_fulldomain"; then + _baidu_err "Could not find zone by legacy bcd api for $_fulldomain" + return 1 + fi fi _record_domain="$_sub_domain" _zone_name="$_domain" @@ -234,6 +322,43 @@ _baidu_get_root() { done } +_baidu_get_root_dns() { + domain=$1 + i=1 + p=1 + + while true; do + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) + if [ -z "$h" ]; then + _baidu_err "invalid domain: $domain" + return 1 + fi + + if ! _baidu_dns_call "GET" "/v1/dns/zone/${h}/record" ""; then + _baidu_info "baidu_dns_call failed: list zones" + elif ! _baidu_is_api_error "$response" && (_contains "$response" "\"records\"" || _contains "$response" "\"maxKeys\""); then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") + _domain=$h + if [ "$_sub_domain" = "$_domain" ]; then + _sub_domain="@" + fi + _baidu_info "zone matched by dns api: $_domain (host: $_sub_domain)" + return 0 + fi + + p=$i + i=$(_math "$i" + 1) + done +} + +_baidu_find_record_ids_current() { + if [ "$_baidu_api_engine" = "new" ]; then + _baidu_find_record_ids_dns "$@" + else + _baidu_find_record_ids "$@" + fi +} + _baidu_find_record_ids() { _zone_name="$1" _record_domain="$2" @@ -293,6 +418,39 @@ EOF _BAIDU_FIND_RESULT="$_ids" } +_baidu_find_record_ids_dns() { + _zone_name="$1" + _record_domain="$2" + _rdtype="$3" + _rdata="$4" + _BAIDU_FIND_RESULT="" + + if ! _baidu_dns_call "GET" "/v1/dns/zone/${_zone_name}/record" ""; then + _baidu_err "baidu_dns_call failed: list records" + return 1 + fi + + if _baidu_is_api_error "$response"; then + _baidu_err "baidu_dns error: $(_baidu_json_get_str "$response" "code") $(_baidu_json_get_str "$response" "message")" + return 1 + fi + + _normalized="$(printf "%s" "$response" | _normalizeJson)" + _records=$(printf "%s" "$_normalized" | sed 's/},{/}\n{/g') + _ids="" + + while IFS= read -r _line; do + _id="$(_baidu_match_record_id_dns "$_line" "$_record_domain" "$_rdtype" "$_rdata")" + if [ "$_id" ]; then + _ids="$_ids $_id" + fi + done <