]> git.proxmox.com Git - mirror_acme.sh.git/blob - dnsapi/dns_servercow.sh
Merge pull request #4547 from eastonman/master
[mirror_acme.sh.git] / dnsapi / dns_servercow.sh
1 #!/usr/bin/env sh
2
3 ##########
4 # Custom servercow.de DNS API v1 for use with [acme.sh](https://github.com/acmesh-official/acme.sh)
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() {
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"
51
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%%\"*}
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."
69 return 1
70 fi
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."
82 return 1
83 fi
84 fi
85 _err "add txt record error."
86 return 1
87 fi
88
89 return 1
90 }
91
92 # Usage fulldomain txtvalue
93 # Remove the txt record after validation
94 dns_servercow_rm() {
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
121 if _servercow_api DELETE "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\"}"; then
122 if printf -- "%s" "$response" | grep "ok" >/dev/null; then
123 _info "Deleted, OK"
124 _contains "$response" '"message":"ok"'
125 else
126 _err "delete txt record error."
127 return 1
128 fi
129 fi
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() {
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
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
160 # not valid
161 return 1
162 fi
163
164 return 0
165 fi
166
167 p=$i
168 i=$(_math "$i" + 1)
169 done
170
171 return 1
172 }
173
174 _servercow_api() {
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
196 }