blob: 32c09ed4365e0a162c56802d7ea6431e34f77e38 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
#!/bin/sh
#
# script for sending updates to huaweicloud.com
# 2023-2024 sxlehua <sxlehua at qq dot com>
# API documentation at https://support.huaweicloud.com/api-dns/dns_api_62003.html
# API signature documentation at https://support.huaweicloud.com/api-dns/dns_api_30003.html
#
# This script is parsed by dynamic_dns_functions.sh inside send_update() function
#
# useage:
# using following options from /etc/config/ddns
# option username - huaweicloud Access Key Id
# option password - huaweicloud Secret Access Key,AK、SK documentation from https://support.huaweicloud.com/devg-apisign/api-sign-provide-aksk.html
# option domain - "hostname@yourdomain.TLD"
#
# Check inputs
[ -z "$username" ] && write_log 14 "Configuration error! [username] cannot be empty"
[ -z "$password" ] && write_log 14 "Configuration error! [password] cannot be empty"
[ -z "$CURL" ] && [ -z "$CURL_SSL" ] && write_log 14 "huaweicloud API require cURL with SSL support. Please install"
command -v openssl >/dev/null 2>&1 || write_log 14 "huaweicloud API require openssl-util support. Please install"
# public variable
local __HOST __DOMAIN __TYPE __ZONE_ID __RECORD_ID
local __ENDPOINT="dns.cn-north-1.myhuaweicloud.com"
local __TTL=120
[ $use_ipv6 -eq 0 ] && __TYPE="A" || __TYPE="AAAA"
# Get host and domain from $domain
[ "${domain:0:2}" == "@." ] && domain="${domain/./}" # host
[ "$domain" == "${domain/@/}" ] && domain="${domain/./@}" # host with no sperator
__HOST="${domain%%@*}"
__DOMAIN="${domain#*@}"
[ -z "$__HOST" -o "$__HOST" == "$__DOMAIN" ] && __HOST="@"
hcloud_transfer() {
local method=$1
local path=$2
local query=$3
local body=$4
local timestamp=$(date -u +'%Y%m%dT%H%M%SZ')
local contentType=""
if [ ! "$method" = "GET" ]; then
contentType="application/json"
fi
local _H_Content_Type=""
local canonicalUri="${path}"
# add / if need
echo $canonicalUri | grep -qE "/$" || canonicalUri="$canonicalUri/"
local canonicalQuery="$query" # for extend
local canonicalHeaders="host:$__ENDPOINT\nx-sdk-date:$timestamp\n"
local signedHeaders="host;x-sdk-date"
if [ ! "$contentType" = "" ]; then
canonicalHeaders="content-type:$contentType\n${canonicalHeaders}"
signedHeaders="content-type;$signedHeaders"
_H_Content_Type="Content-Type: ${contentType}"
fi
local hexencode=$(printf "%s" "$body" | openssl dgst -sha256 -hex 2>/dev/null | sed 's/^.* //')
local canonicalRequest="$method\n$canonicalUri\n$canonicalQuery\n$canonicalHeaders\n$signedHeaders\n$hexencode"
canonicalRequest="$(printf "$canonicalRequest%s")"
local stringToSign="SDK-HMAC-SHA256\n$timestamp\n$(printf "%s" "$canonicalRequest" | openssl dgst -sha256 -hex 2>/dev/null | sed 's/^.* //')"
stringToSign="$(printf "$stringToSign%s")"
local signature=$(printf "%s" "$stringToSign" | openssl dgst -sha256 -hmac "$password" 2>/dev/null | sed 's/^.* //')
authorization="SDK-HMAC-SHA256 Access=$username, SignedHeaders=$signedHeaders, Signature=$signature"
reqUrl="$__ENDPOINT$path"
if [ ! -z "$query" ]; then
reqUrl="$reqUrl""?$query"
fi
curl -s -X "${method}" \
-H "Host: $__ENDPOINT" \
-H "$_H_Content_Type" \
-H "Authorization: $authorization" \
-H "X-Sdk-Date: $timestamp" \
-d "${body}" \
"https://$reqUrl"
if [ $? -ne 0 ]; then
write_log 4 "rest api error"
fi
}
get_zone() {
local resp=`hcloud_transfer GET /v2/zones "name=$__DOMAIN.&search_mode=equal" ""`
__ZONE_ID=`printf "%s" $resp | grep -Eo '"id":"[a-z0-9]+"' | cut -d':' -f2 | tr -d '"'`
if [ "$__ZONE_ID" = "" ]; then
write_log 4 "query zone error [$resp]"
return 1
fi
return 0
}
upd_record() {
local body="{\"name\":\"$__HOST.$__DOMAIN.\",\"type\":\"$__TYPE\",\"records\":[\"$__IP\"],\"ttl\":$__TTL}"
local resp=`hcloud_transfer PUT /v2/zones/"$__ZONE_ID"/recordsets/$__RECORD_ID "" "$body"`
local recordId=`printf "%s" $resp | grep -Eo '"id":"[a-z0-9]+"' | cut -d':' -f2 | tr -d '"'`
if [ ! "$recordId" = "" ]; then
write_log 7 "upd [$recordId] success [$__TYPE] [$__IP]"
else
write_log 4 "upd ecord error [$resp]"
return 1
fi
return 0
}
add_record() {
local body="{\"name\":\"$__HOST.$__DOMAIN.\",\"type\":\"$__TYPE\",\"records\":[\"$__IP\"],\"ttl\":$__TTL}"
local resp=`hcloud_transfer POST /v2/zones/"$__ZONE_ID"/recordsets "" "$body"`
local recordId=`printf "%s" $resp | grep -Eo '"id":"[a-z0-9]+"' | cut -d':' -f2 | tr -d '"'`
if [ ! "$recordId" = "" ]; then
write_log 7 "add [$recordId] success [$__TYPE] [$__IP]"
else
write_log 4 "add record error [$resp]"
return 1
fi
return 0
}
# Get DNS record
get_record() {
local ret=0
local resp=`hcloud_transfer GET /v2/zones/$__ZONE_ID/recordsets "name=$__HOST.$__DOMAIN.&search_mode=equal" ""`
__RECORD_ID=`printf "%s" $resp | grep -Eo '"id":"[a-z0-9]+"' | cut -d':' -f2 | tr -d '"' | head -1`
if [ "$__RECORD_ID" = "" ]; then
# Record needs to be add
ret=1
else
local remoteIp=`printf "%s" $resp | grep -Eo '"records":\[[^]]+]' | cut -d ':' -f 2-10 | tr -d '[' | tr -d ']' | tr -d '"' | head -1`
if [ ! "$remoteIp" = "$__IP" ]; then
# Record needs to be updated
ret=2
fi
fi
return $ret
}
get_zone || return 1
get_record
ret=$?
if [ $ret -eq 0 ]; then
write_log 7 "nochg [$__IP]"
fi
if [ $ret -eq 1 ]; then
add_record
fi
if [ $ret -eq 2 ]; then
upd_record
fi
|