]>
Commit | Line | Data |
---|---|---|
3bb97b81 JQ |
1 | #!/usr/bin/env sh |
2 | # | |
3 | # deSEC.io Domain API | |
4 | # | |
5 | # Author: Zheng Qian | |
6 | # | |
7 | # deSEC API doc | |
8 | # https://desec.readthedocs.io/en/latest/ | |
9 | ||
10 | REST_API="https://desec.io/api/v1/domains" | |
11 | ||
12 | ######## Public functions ##################### | |
13 | ||
14 | #Usage: dns_desec_add _acme-challenge.foobar.dedyn.io "d41d8cd98f00b204e9800998ecf8427e" | |
15 | dns_desec_add() { | |
16 | fulldomain=$1 | |
17 | txtvalue=$2 | |
18 | _info "Using desec.io api" | |
19 | _debug fulldomain "$fulldomain" | |
20 | _debug txtvalue "$txtvalue" | |
21 | ||
22 | DEDYN_TOKEN="${DEDYN_TOKEN:-$(_readaccountconf_mutable DEDYN_TOKEN)}" | |
3bb97b81 | 23 | |
c5557fc4 | 24 | if [ -z "$DEDYN_TOKEN" ]; then |
3bb97b81 | 25 | DEDYN_TOKEN="" |
c5557fc4 | 26 | _err "You did not specify DEDYN_TOKEN yet." |
d42cf6da | 27 | _err "Please create your key and try again." |
3bb97b81 JQ |
28 | _err "e.g." |
29 | _err "export DEDYN_TOKEN=d41d8cd98f00b204e9800998ecf8427e" | |
3bb97b81 JQ |
30 | return 1 |
31 | fi | |
c5557fc4 | 32 | #save the api token to the account conf file. |
3bb97b81 | 33 | _saveaccountconf_mutable DEDYN_TOKEN "$DEDYN_TOKEN" |
3bb97b81 JQ |
34 | |
35 | _debug "First detect the root zone" | |
36 | if ! _get_root "$fulldomain" "$REST_API/"; then | |
37 | _err "invalid domain" | |
38 | return 1 | |
39 | fi | |
40 | _debug _sub_domain "$_sub_domain" | |
41 | _debug _domain "$_domain" | |
42 | ||
43 | # Get existing TXT record | |
44 | _debug "Getting txt records" | |
45 | txtvalues="\"\\\"$txtvalue\\\"\"" | |
c5557fc4 | 46 | _desec_rest GET "$REST_API/$_domain/rrsets/$_sub_domain/TXT/" |
3bb97b81 JQ |
47 | |
48 | if [ "$_code" = "200" ]; then | |
49 | oldtxtvalues="$(echo "$response" | _egrep_o "\"records\":\\[\"\\S*\"\\]" | cut -d : -f 2 | tr -d "[]\\\\\"" | sed "s/,/ /g")" | |
50 | _debug "existing TXT found" | |
51 | _debug oldtxtvalues "$oldtxtvalues" | |
52 | if [ -n "$oldtxtvalues" ]; then | |
53 | for oldtxtvalue in $oldtxtvalues; do | |
54 | txtvalues="$txtvalues, \"\\\"$oldtxtvalue\\\"\"" | |
55 | done | |
56 | fi | |
57 | fi | |
58 | _debug txtvalues "$txtvalues" | |
59 | _info "Adding record" | |
a077132d | 60 | body="[{\"subname\":\"$_sub_domain\", \"type\":\"TXT\", \"records\":[$txtvalues], \"ttl\":3600}]" |
3bb97b81 | 61 | |
c5557fc4 | 62 | if _desec_rest PUT "$REST_API/$_domain/rrsets/" "$body"; then |
3bb97b81 JQ |
63 | if _contains "$response" "$txtvalue"; then |
64 | _info "Added, OK" | |
65 | return 0 | |
66 | else | |
67 | _err "Add txt record error." | |
68 | return 1 | |
69 | fi | |
70 | fi | |
71 | ||
72 | _err "Add txt record error." | |
73 | return 1 | |
74 | } | |
75 | ||
76 | #Usage: fulldomain txtvalue | |
77 | #Remove the txt record after validation. | |
78 | dns_desec_rm() { | |
79 | fulldomain=$1 | |
80 | txtvalue=$2 | |
81 | _info "Using desec.io api" | |
82 | _debug fulldomain "$fulldomain" | |
83 | _debug txtvalue "$txtvalue" | |
84 | ||
85 | DEDYN_TOKEN="${DEDYN_TOKEN:-$(_readaccountconf_mutable DEDYN_TOKEN)}" | |
3bb97b81 | 86 | |
c5557fc4 | 87 | if [ -z "$DEDYN_TOKEN" ]; then |
3bb97b81 | 88 | DEDYN_TOKEN="" |
c5557fc4 | 89 | _err "You did not specify DEDYN_TOKEN yet." |
d42cf6da | 90 | _err "Please create your key and try again." |
3bb97b81 JQ |
91 | _err "e.g." |
92 | _err "export DEDYN_TOKEN=d41d8cd98f00b204e9800998ecf8427e" | |
3bb97b81 JQ |
93 | return 1 |
94 | fi | |
95 | ||
96 | _debug "First detect the root zone" | |
97 | if ! _get_root "$fulldomain" "$REST_API/"; then | |
98 | _err "invalid domain" | |
99 | return 1 | |
100 | fi | |
101 | ||
102 | _debug _sub_domain "$_sub_domain" | |
103 | _debug _domain "$_domain" | |
104 | ||
105 | # Get existing TXT record | |
106 | _debug "Getting txt records" | |
107 | txtvalues="" | |
c5557fc4 | 108 | _desec_rest GET "$REST_API/$_domain/rrsets/$_sub_domain/TXT/" |
3bb97b81 JQ |
109 | |
110 | if [ "$_code" = "200" ]; then | |
111 | oldtxtvalues="$(echo "$response" | _egrep_o "\"records\":\\[\"\\S*\"\\]" | cut -d : -f 2 | tr -d "[]\\\\\"" | sed "s/,/ /g")" | |
112 | _debug "existing TXT found" | |
113 | _debug oldtxtvalues "$oldtxtvalues" | |
114 | if [ -n "$oldtxtvalues" ]; then | |
115 | for oldtxtvalue in $oldtxtvalues; do | |
116 | if [ "$txtvalue" != "$oldtxtvalue" ]; then | |
117 | txtvalues="$txtvalues, \"\\\"$oldtxtvalue\\\"\"" | |
118 | fi | |
119 | done | |
120 | fi | |
121 | fi | |
122 | txtvalues="$(echo "$txtvalues" | cut -c3-)" | |
123 | _debug txtvalues "$txtvalues" | |
124 | ||
125 | _info "Deleting record" | |
7dfc5a78 | 126 | body="[{\"subname\":\"$_sub_domain\", \"type\":\"TXT\", \"records\":[$txtvalues], \"ttl\":3600}]" |
c5557fc4 | 127 | _desec_rest PUT "$REST_API/$_domain/rrsets/" "$body" |
3bb97b81 JQ |
128 | if [ "$_code" = "200" ]; then |
129 | _info "Deleted, OK" | |
130 | return 0 | |
131 | fi | |
132 | ||
133 | _err "Delete txt record error." | |
134 | return 1 | |
135 | } | |
136 | ||
137 | #################### Private functions below ################################## | |
138 | ||
139 | _desec_rest() { | |
140 | m="$1" | |
141 | ep="$2" | |
142 | data="$3" | |
143 | ||
144 | export _H1="Authorization: Token $DEDYN_TOKEN" | |
145 | export _H2="Accept: application/json" | |
146 | export _H3="Content-Type: application/json" | |
147 | ||
148 | if [ "$m" != "GET" ]; then | |
149 | _secure_debug2 data "$data" | |
150 | response="$(_post "$data" "$ep" "" "$m")" | |
151 | else | |
152 | response="$(_get "$ep")" | |
153 | fi | |
154 | _ret="$?" | |
155 | _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" | |
156 | _debug "http response code $_code" | |
157 | _secure_debug2 response "$response" | |
158 | if [ "$_ret" != "0" ]; then | |
159 | _err "error $ep" | |
160 | return 1 | |
161 | fi | |
162 | ||
163 | response="$(printf "%s" "$response" | _normalizeJson)" | |
164 | return 0 | |
165 | } | |
166 | ||
167 | #_acme-challenge.www.domain.com | |
168 | #returns | |
169 | # _sub_domain=_acme-challenge.www | |
170 | # _domain=domain.com | |
171 | _get_root() { | |
172 | domain="$1" | |
173 | ep="$2" | |
174 | i=2 | |
175 | p=1 | |
176 | while true; do | |
177 | h=$(printf "%s" "$domain" | cut -d . -f $i-100) | |
178 | _debug h "$h" | |
179 | if [ -z "$h" ]; then | |
180 | #not valid | |
181 | return 1 | |
182 | fi | |
183 | ||
184 | if ! _desec_rest GET "$ep"; then | |
185 | return 1 | |
186 | fi | |
187 | ||
188 | if _contains "$response" "\"name\":\"$h\"" >/dev/null; then | |
189 | _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) | |
190 | _domain=$h | |
191 | return 0 | |
192 | fi | |
193 | p=$i | |
194 | i=$(_math "$i" + 1) | |
195 | done | |
196 | return 1 | |
197 | } |