-
-
Notifications
You must be signed in to change notification settings - Fork 5k
/
dns_cf.sh
executable file
·249 lines (217 loc) · 6.9 KB
/
dns_cf.sh
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
#!/usr/bin/env sh
#
#CF_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
#
#CF_Email="xxxx@sss.com"
#CF_Token="xxxx"
#CF_Account_ID="xxxx"
#CF_Zone_ID="xxxx"
CF_Api="https://api.cloudflare.com/client/v4"
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_cf_add() {
fulldomain=$1
txtvalue=$2
CF_Token="${CF_Token:-$(_readaccountconf_mutable CF_Token)}"
CF_Account_ID="${CF_Account_ID:-$(_readaccountconf_mutable CF_Account_ID)}"
CF_Zone_ID="${CF_Zone_ID:-$(_readaccountconf_mutable CF_Zone_ID)}"
CF_Key="${CF_Key:-$(_readaccountconf_mutable CF_Key)}"
CF_Email="${CF_Email:-$(_readaccountconf_mutable CF_Email)}"
if [ "$CF_Token" ]; then
if [ "$CF_Zone_ID" ]; then
_savedomainconf CF_Token "$CF_Token"
_savedomainconf CF_Account_ID "$CF_Account_ID"
_savedomainconf CF_Zone_ID "$CF_Zone_ID"
else
_saveaccountconf_mutable CF_Token "$CF_Token"
_saveaccountconf_mutable CF_Account_ID "$CF_Account_ID"
_clearaccountconf_mutable CF_Zone_ID
_clearaccountconf CF_Zone_ID
fi
else
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
CF_Key=""
CF_Email=""
_err "You didn't specify a Cloudflare api key and email yet."
_err "You can get yours from here https://dash.cloudflare.com/profile."
return 1
fi
if ! _contains "$CF_Email" "@"; then
_err "It seems that the CF_Email=$CF_Email is not a valid email address."
_err "Please check and retry."
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf_mutable CF_Key "$CF_Key"
_saveaccountconf_mutable CF_Email "$CF_Email"
_clearaccountconf_mutable CF_Token
_clearaccountconf_mutable CF_Account_ID
_clearaccountconf_mutable CF_Zone_ID
_clearaccountconf CF_Token
_clearaccountconf CF_Account_ID
_clearaccountconf CF_Zone_ID
fi
_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 txt records"
_cf_rest GET "zones/${_domain_id}/dns_records?type=TXT&name=$fulldomain"
if ! echo "$response" | tr -d " " | grep \"success\":true >/dev/null; then
_err "Error"
return 1
fi
# 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 _cf_rest POST "zones/$_domain_id/dns_records" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"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
}
#fulldomain txtvalue
dns_cf_rm() {
fulldomain=$1
txtvalue=$2
CF_Token="${CF_Token:-$(_readaccountconf_mutable CF_Token)}"
CF_Account_ID="${CF_Account_ID:-$(_readaccountconf_mutable CF_Account_ID)}"
CF_Zone_ID="${CF_Zone_ID:-$(_readaccountconf_mutable CF_Zone_ID)}"
CF_Key="${CF_Key:-$(_readaccountconf_mutable CF_Key)}"
CF_Email="${CF_Email:-$(_readaccountconf_mutable CF_Email)}"
_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 txt records"
_cf_rest GET "zones/${_domain_id}/dns_records?type=TXT&name=$fulldomain&content=$txtvalue"
if ! echo "$response" | tr -d " " | grep \"success\":true >/dev/null; then
_err "Error: $response"
return 1
fi
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" | _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 ! _cf_rest DELETE "zones/$_domain_id/dns_records/$record_id"; then
_err "Delete record error."
return 1
fi
echo "$response" | tr -d " " | grep \"success\":true >/dev/null
fi
}
#################### 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
# Use Zone ID directly if provided
if [ "$CF_Zone_ID" ]; then
if ! _cf_rest GET "zones/$CF_Zone_ID"; then
return 1
else
if echo "$response" | tr -d " " | grep \"success\":true >/dev/null; then
_domain=$(echo "$response" | _egrep_o "\"name\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | _head_n 1 | tr -d " ")
if [ "$_domain" ]; then
_cutlength=$((${#domain} - ${#_domain} - 1))
_sub_domain=$(printf "%s" "$domain" | cut -c "1-$_cutlength")
_domain_id=$CF_Zone_ID
return 0
else
return 1
fi
else
return 1
fi
fi
fi
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 [ "$CF_Account_ID" ]; then
if ! _cf_rest GET "zones?name=$h&account.id=$CF_Account_ID"; then
return 1
fi
else
if ! _cf_rest GET "zones?name=$h"; then
return 1
fi
fi
if _contains "$response" "\"name\":\"$h\"" || _contains "$response" '"total_count":1'; 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
}
_cf_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
email_trimmed=$(echo "$CF_Email" | tr -d '"')
key_trimmed=$(echo "$CF_Key" | tr -d '"')
token_trimmed=$(echo "$CF_Token" | tr -d '"')
export _H1="Content-Type: application/json"
if [ "$token_trimmed" ]; then
export _H2="Authorization: Bearer $token_trimmed"
else
export _H2="X-Auth-Email: $email_trimmed"
export _H3="X-Auth-Key: $key_trimmed"
fi
if [ "$m" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$CF_Api/$ep" "" "$m")"
else
response="$(_get "$CF_Api/$ep")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}