forked from srvrco/getssl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdns_add_cloudflare
executable file
·135 lines (121 loc) · 3.82 KB
/
dns_add_cloudflare
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
#!/usr/bin/env bash
# either configure here or export environment variables in getssl.cfg
email=${CF_EMAIL:-''}
key=${CF_KEY:-''}
api_token=${CF_API_TOKEN:-''}
zone_id=${CF_ZONE_ID:-''}
# This script adds a TXT record to cloudflare DNS for the ACME challenge
# usage dns_add_cloudflare "domain name" "token"
# return codes are;
# 0 - success
# 1 - error in input
# 2 - error within internal processing
# 3 - error in result ( domain not found in cloudflare etc)
fulldomain="${1}"
token="${2}"
API='https://api.cloudflare.com/client/v4/zones'
if [[ -z "$api_token" ]]; then
curl_params=( -H "X-Auth-Email: $email" -H "X-Auth-Key: $key" -H 'Content-Type: application/json' )
else
curl_params=( -H "Authorization: Bearer $api_token" -H 'Content-Type: application/json' )
fi
# check initial parameters
if [[ -z "$fulldomain" ]]; then
echo "DNS script requires full domain name as first parameter"
exit 1
fi
if [[ -z "$token" ]]; then
echo "DNS script requires challenge token as second parameter"
exit 1
fi
if [[ -z "$api_token" ]]; then
if [[ -z "$email" ]]; then
echo "CF_EMAIL (email) parameter not set"
exit 1
fi
if [[ -z "$key" ]]; then
echo "CF_KEY (key) parameter not set"
exit 1
fi
fi
if [[ -z "$zone_id" ]]; then
# get a list of all domain names from cloudflare
# If you have a lot, you may need add "&page=1&per_page=1000" and/or "&status=active"
resp=$(curl --silent "${curl_params[@]}" -X GET "$API")
re='"result":\[(([^][]*\[[^][]*])*[^][]*)]' # find result section
if [[ "${resp// }" =~ $re ]]; then
resp="${BASH_REMATCH[1]}"
fi
# iterate through all sections to obtain a list of domains
while [[ "$resp" ]]; do
re='[^}{]*\{(([^}{]*\{[^}{]*})*[^}{]*)}(.*)'
if [[ "$resp" =~ $re ]]; then
first="${BASH_REMATCH[1]}"
resp="${BASH_REMATCH[3]}"
fi
# remove subsections - leave only domain level
while [[ "$first" =~ (.*)[\[\{][^]\{\}[]*[\]\}](.*) ]]; do
first="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
done
re='"name":"([^"]*)"'
if [[ "$first" =~ $re ]]; then
domains=( "${domains[@]}" "${BASH_REMATCH[1]}" )
else
echo "Error getting domain name"
exit 2
fi
re='"id":"([^"]*)"'
if [[ "$first" =~ $re ]]; then
ids=( "${ids[@]}" "${BASH_REMATCH[1]}" )
else
echo "Error getting domain id"
exit 2
fi
done
# split required domain name into an array
dnarray=(${fulldomain//./ })
# get number of parts in required domain name
NumParts=${#dnarray[@]}
# build a test domain name, starting with the largest, and reduce it
# until a match is found, set domain = first ( longest) match.
domain=""
i=1
while [ $i -lt "$NumParts" ]; do
testdomain="${dnarray[i-1]}"
for ((j=i; j<NumParts; j++)); do
testdomain+=".${dnarray[j]}"
done
# loop through domains at cloudflare
for k in "${!domains[@]}"; do
# if match found, then set domain and zone_id
if [[ "$testdomain" == "${domains[k]}" ]]; then
domain="$testdomain"
zone_id=${ids[k]}
i="$NumParts"
fi
done
((i++))
done
if [[ -z "$domain" ]]; then
echo 'domain name not found on your cloudflare account'
exit 3
fi
fi
txt_record="_acme-challenge.${fulldomain%.$domain}"
resp=$(curl --silent "${curl_params[@]}" -X POST "$API/$zone_id/dns_records" \
--data "{\"type\":\"TXT\",\"name\":\"${txt_record}\",\"content\":\"$token\",\"ttl\":300}")
# if it failed (success:false) then give error message
if [[ "${resp// }" == *'"success":false'* ]]; then
if [[ "${resp// }" == *'"code":81057'[^0-9]* ]]; then
echo "DNS challenge token already exists"
exit
fi
re='"message":"([^"]+)"'
if [[ "$resp" =~ $re ]]; then
echo "Error: DNS challenge not added: ${BASH_REMATCH[1]}"
exit 3
else
echo "Error: DNS challenge not added: unknown error - ${resp}"
exit 3
fi
fi