]>
Commit | Line | Data |
---|---|---|
ae299297 JH |
1 | #!/usr/bin/env sh |
2 | ||
3 | ########## | |
d795fac3 | 4 | # Custom servercow.de DNS API v1 for use with [acme.sh](https://github.com/acmesh-official/acme.sh) |
ae299297 JH |
5 | # |
6 | # Usage: | |
7 | # export SERVERCOW_API_Username=username | |
8 | # export SERVERCOW_API_Password=password | |
9 | # acme.sh --issue -d example.com --dns dns_servercow | |
10 | # | |
11 | # Issues: | |
12 | # Any issues / questions / suggestions can be posted here: | |
13 | # https://github.com/jhartlep/servercow-dns-api/issues | |
14 | # | |
15 | # Author: Jens Hartlep | |
16 | ########## | |
17 | ||
18 | SERVERCOW_API="https://api.servercow.de/dns/v1/domains" | |
19 | ||
20 | # Usage dns_servercow_add _acme-challenge.www.domain.com "abcdefghijklmnopqrstuvwxyz" | |
21 | dns_servercow_add() { | |
1c9b1983 J |
22 | fulldomain=$1 |
23 | txtvalue=$2 | |
24 | ||
25 | _info "Using servercow" | |
26 | _debug fulldomain "$fulldomain" | |
27 | _debug txtvalue "$txtvalue" | |
28 | ||
29 | SERVERCOW_API_Username="${SERVERCOW_API_Username:-$(_readaccountconf_mutable SERVERCOW_API_Username)}" | |
30 | SERVERCOW_API_Password="${SERVERCOW_API_Password:-$(_readaccountconf_mutable SERVERCOW_API_Password)}" | |
31 | if [ -z "$SERVERCOW_API_Username" ] || [ -z "$SERVERCOW_API_Password" ]; then | |
32 | SERVERCOW_API_Username="" | |
33 | SERVERCOW_API_Password="" | |
34 | _err "You don't specify servercow api username and password yet." | |
35 | _err "Please create your username and password and try again." | |
36 | return 1 | |
37 | fi | |
38 | ||
39 | # save the credentials to the account conf file | |
40 | _saveaccountconf_mutable SERVERCOW_API_Username "$SERVERCOW_API_Username" | |
41 | _saveaccountconf_mutable SERVERCOW_API_Password "$SERVERCOW_API_Password" | |
42 | ||
43 | _debug "First detect the root zone" | |
44 | if ! _get_root "$fulldomain"; then | |
45 | _err "invalid domain" | |
46 | return 1 | |
47 | fi | |
48 | ||
49 | _debug _sub_domain "$_sub_domain" | |
50 | _debug _domain "$_domain" | |
5c4bfbbd | 51 | |
52 | # check whether a txt record already exists for the subdomain | |
87336356 | 53 | if printf -- "%s" "$response" | grep "{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\"" >/dev/null; then |
5c4bfbbd | 54 | _info "A txt record with the same name already exists." |
55 | # trim the string on the left | |
56 | txtvalue_old=${response#*{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"} | |
57 | # trim the string on the right | |
58 | txtvalue_old=${txtvalue_old%%\"*} | |
59 | ||
60 | _debug txtvalue_old "$txtvalue_old" | |
61 | ||
62 | _info "Add the new txtvalue to the existing txt record." | |
63 | if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":[\"$txtvalue\",\"$txtvalue_old\"],\"ttl\":20}"; then | |
64 | if printf -- "%s" "$response" | grep "ok" >/dev/null; then | |
65 | _info "Added additional txtvalue, OK" | |
66 | return 0 | |
67 | else | |
68 | _err "add txt record error." | |
87336356 | 69 | return 1 |
87336356 | 70 | fi |
5c4bfbbd | 71 | fi |
72 | _err "add txt record error." | |
73 | return 1 | |
74 | else | |
75 | _info "There is no txt record with the name yet." | |
76 | if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then | |
77 | if printf -- "%s" "$response" | grep "ok" >/dev/null; then | |
78 | _info "Added, OK" | |
79 | return 0 | |
80 | else | |
81 | _err "add txt record error." | |
87336356 | 82 | return 1 |
87336356 | 83 | fi |
5c4bfbbd | 84 | fi |
85 | _err "add txt record error." | |
86 | return 1 | |
1c9b1983 | 87 | fi |
5c4bfbbd | 88 | |
1c9b1983 | 89 | return 1 |
ae299297 JH |
90 | } |
91 | ||
92 | # Usage fulldomain txtvalue | |
93 | # Remove the txt record after validation | |
94 | dns_servercow_rm() { | |
1c9b1983 J |
95 | fulldomain=$1 |
96 | txtvalue=$2 | |
97 | ||
98 | _info "Using servercow" | |
99 | _debug fulldomain "$fulldomain" | |
100 | _debug txtvalue "$fulldomain" | |
101 | ||
102 | SERVERCOW_API_Username="${SERVERCOW_API_Username:-$(_readaccountconf_mutable SERVERCOW_API_Username)}" | |
103 | SERVERCOW_API_Password="${SERVERCOW_API_Password:-$(_readaccountconf_mutable SERVERCOW_API_Password)}" | |
104 | if [ -z "$SERVERCOW_API_Username" ] || [ -z "$SERVERCOW_API_Password" ]; then | |
105 | SERVERCOW_API_Username="" | |
106 | SERVERCOW_API_Password="" | |
107 | _err "You don't specify servercow api username and password yet." | |
108 | _err "Please create your username and password and try again." | |
109 | return 1 | |
110 | fi | |
111 | ||
112 | _debug "First detect the root zone" | |
113 | if ! _get_root "$fulldomain"; then | |
114 | _err "invalid domain" | |
115 | return 1 | |
116 | fi | |
117 | ||
118 | _debug _sub_domain "$_sub_domain" | |
119 | _debug _domain "$_domain" | |
120 | ||
8101acea J |
121 | if _servercow_api DELETE "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\"}"; then |
122 | if printf -- "%s" "$response" | grep "ok" >/dev/null; then | |
1c9b1983 J |
123 | _info "Deleted, OK" |
124 | _contains "$response" '"message":"ok"' | |
125 | else | |
126 | _err "delete txt record error." | |
127 | return 1 | |
128 | fi | |
129 | fi | |
ae299297 JH |
130 | |
131 | } | |
132 | ||
133 | #################### Private functions below ################################## | |
134 | ||
135 | # _acme-challenge.www.domain.com | |
136 | # returns | |
137 | # _sub_domain=_acme-challenge.www | |
138 | # _domain=domain.com | |
139 | _get_root() { | |
1c9b1983 J |
140 | fulldomain=$1 |
141 | i=2 | |
142 | p=1 | |
143 | ||
144 | while true; do | |
145 | _domain=$(printf "%s" "$fulldomain" | cut -d . -f $i-100) | |
146 | ||
147 | _debug _domain "$_domain" | |
148 | if [ -z "$_domain" ]; then | |
149 | # not valid | |
150 | return 1 | |
151 | fi | |
152 | ||
153 | if ! _servercow_api GET "$_domain"; then | |
154 | return 1 | |
155 | fi | |
156 | ||
a95ccc7e | 157 | if ! _contains "$response" '"error":"no such domain in user context"' >/dev/null; then |
1c9b1983 J |
158 | _sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-$p) |
159 | if [ -z "$_sub_domain" ]; then | |
160 | # not valid | |
161 | return 1 | |
162 | fi | |
163 | ||
164 | return 0 | |
165 | fi | |
166 | ||
167 | p=$i | |
168 | i=$(_math "$i" + 1) | |
8101acea | 169 | done |
1c9b1983 J |
170 | |
171 | return 1 | |
ae299297 JH |
172 | } |
173 | ||
174 | _servercow_api() { | |
1c9b1983 J |
175 | method=$1 |
176 | domain=$2 | |
177 | data="$3" | |
178 | ||
179 | export _H1="Content-Type: application/json" | |
180 | export _H2="X-Auth-Username: $SERVERCOW_API_Username" | |
181 | export _H3="X-Auth-Password: $SERVERCOW_API_Password" | |
182 | ||
183 | if [ "$method" != "GET" ]; then | |
184 | _debug data "$data" | |
185 | response="$(_post "$data" "$SERVERCOW_API/$domain" "" "$method")" | |
186 | else | |
187 | response="$(_get "$SERVERCOW_API/$domain")" | |
188 | fi | |
189 | ||
190 | if [ "$?" != "0" ]; then | |
191 | _err "error $domain" | |
192 | return 1 | |
193 | fi | |
194 | _debug2 response "$response" | |
195 | return 0 | |
ae299297 | 196 | } |