4 # Custom servercow.de DNS API v1 for use with [acme.sh](https://github.com/acmesh-official/acme.sh)
7 # export SERVERCOW_API_Username=username
8 # export SERVERCOW_API_Password=password
9 # acme.sh --issue -d example.com --dns dns_servercow
12 # Any issues / questions / suggestions can be posted here:
13 # https://github.com/jhartlep/servercow-dns-api/issues
15 # Author: Jens Hartlep
18 SERVERCOW_API
="https://api.servercow.de/dns/v1/domains"
20 # Usage dns_servercow_add _acme-challenge.www.domain.com "abcdefghijklmnopqrstuvwxyz"
25 _info
"Using servercow"
26 _debug fulldomain
"$fulldomain"
27 _debug txtvalue
"$txtvalue"
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."
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"
43 _debug
"First detect the root zone"
44 if ! _get_root
"$fulldomain"; then
49 _debug _sub_domain
"$_sub_domain"
50 _debug _domain
"$_domain"
52 # check whether a txt record already exists for the subdomain
53 if printf -- "%s" "$response" |
grep "{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\"" >/dev
/null
; then
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%%\"*}
60 _debug txtvalue_old
"$txtvalue_old"
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"
68 _err
"add txt record error."
72 _err
"add txt record error."
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
81 _err
"add txt record error."
85 _err
"add txt record error."
92 # Usage fulldomain txtvalue
93 # Remove the txt record after validation
98 _info
"Using servercow"
99 _debug fulldomain
"$fulldomain"
100 _debug txtvalue
"$fulldomain"
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."
112 _debug
"First detect the root zone"
113 if ! _get_root
"$fulldomain"; then
114 _err
"invalid domain"
118 _debug _sub_domain
"$_sub_domain"
119 _debug _domain
"$_domain"
121 if _servercow_api DELETE
"$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\"}"; then
122 if printf -- "%s" "$response" |
grep "ok" >/dev
/null
; then
124 _contains
"$response" '"message":"ok"'
126 _err
"delete txt record error."
133 #################### Private functions below ##################################
135 # _acme-challenge.www.domain.com
137 # _sub_domain=_acme-challenge.www
145 _domain
=$
(printf "%s" "$fulldomain" | cut
-d .
-f $i-100)
147 _debug _domain
"$_domain"
148 if [ -z "$_domain" ]; then
153 if ! _servercow_api GET
"$_domain"; then
157 if ! _contains
"$response" '"error":"no such domain in user context"' >/dev
/null
; then
158 _sub_domain
=$
(printf "%s" "$fulldomain" | cut
-d .
-f 1-$p)
159 if [ -z "$_sub_domain" ]; then
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"
183 if [ "$method" != "GET" ]; then
185 response
="$(_post "$data" "$SERVERCOW_API/$domain" "" "$method")"
187 response
="$(_get "$SERVERCOW_API/$domain")"
190 if [ "$?" != "0" ]; then
194 _debug2 response
"$response"