]>
Commit | Line | Data |
---|---|---|
84d80e93 FL |
1 | #!/usr/bin/env sh |
2 | ######################################################################## | |
3 | # NocWorx script for acme.sh | |
4 | # | |
5 | # Handles DNS Updates for the Following vendors: | |
6 | # - Nexcess.net | |
7 | # - Thermo.io | |
8 | # - Futurehosting.com | |
9 | # | |
10 | # Environment variables: | |
11 | # | |
12 | # - NW_API_TOKEN (Your API Token) | |
13 | # - NW_API_ENDPOINT (One of the following listed below) | |
14 | # | |
15 | # Endpoints: | |
16 | # - https://portal.nexcess.net (default) | |
17 | # - https://core.thermo.io | |
18 | # - https://my.futurehosting.com | |
19 | # | |
20 | # Note: If you do not have an API token, one can be generated at one | |
21 | # of the following URLs: | |
22 | # - https://portal.nexcess.net/api-token | |
23 | # - https://core.thermo.io/api-token | |
24 | # - https://my.futurehosting.com/api-token | |
25 | # | |
26 | # Author: Frank Laszlo <flaszlo@nexcess.net> | |
27 | ||
28 | NW_API_VERSION="0" | |
29 | ||
30 | # dns_nw_add() - Add TXT record | |
31 | # Usage: dns_nw_add _acme-challenge.subdomain.domain.com "XyZ123..." | |
32 | dns_nw_add() { | |
33 | host="${1}" | |
34 | txtvalue="${2}" | |
35 | ||
36 | _debug host "${host}" | |
37 | _debug txtvalue "${txtvalue}" | |
38 | ||
39 | if ! _check_nw_api_creds; then | |
40 | return 1 | |
41 | fi | |
42 | ||
43 | _info "Using NocWorx (${NW_API_ENDPOINT})" | |
44 | _debug "Calling: dns_nw_add() '${host}' '${txtvalue}'" | |
45 | ||
46 | _debug "Detecting root zone" | |
47 | if ! _get_root "${host}"; then | |
48 | _err "Zone for domain does not exist." | |
49 | return 1 | |
50 | fi | |
51 | _debug _zone_id "${_zone_id}" | |
52 | _debug _sub_domain "${_sub_domain}" | |
53 | _debug _domain "${_domain}" | |
54 | ||
55 | _post_data="{\"zone_id\": \"${_zone_id}\", \"type\": \"TXT\", \"host\": \"${host}\", \"target\": \"${txtvalue}\", \"ttl\": \"300\"}" | |
56 | ||
57 | if _rest POST "dns-record" "${_post_data}" && [ -n "${response}" ]; then | |
58 | _record_id=$(printf "%s\n" "${response}" | _egrep_o "\"record_id\": *[0-9]+" | cut -d : -f 2 | tr -d " " | _head_n 1) | |
59 | _debug _record_id "${_record_id}" | |
60 | ||
61 | if [ -z "$_record_id" ]; then | |
62 | _err "Error adding the TXT record." | |
63 | return 1 | |
64 | fi | |
65 | ||
66 | _info "TXT record successfully added." | |
67 | return 0 | |
68 | fi | |
69 | ||
70 | return 1 | |
71 | } | |
72 | ||
73 | # dns_nw_rm() - Remove TXT record | |
74 | # Usage: dns_nw_rm _acme-challenge.subdomain.domain.com "XyZ123..." | |
75 | dns_nw_rm() { | |
76 | host="${1}" | |
77 | txtvalue="${2}" | |
78 | ||
79 | _debug host "${host}" | |
80 | _debug txtvalue "${txtvalue}" | |
81 | ||
82 | if ! _check_nw_api_creds; then | |
83 | return 1 | |
84 | fi | |
85 | ||
86 | _info "Using NocWorx (${NW_API_ENDPOINT})" | |
87 | _debug "Calling: dns_nw_rm() '${host}'" | |
88 | ||
89 | _debug "Detecting root zone" | |
90 | if ! _get_root "${host}"; then | |
91 | _err "Zone for domain does not exist." | |
92 | return 1 | |
93 | fi | |
94 | _debug _zone_id "${_zone_id}" | |
95 | _debug _sub_domain "${_sub_domain}" | |
96 | _debug _domain "${_domain}" | |
97 | ||
98 | _parameters="?zone_id=${_zone_id}" | |
99 | ||
100 | if _rest GET "dns-record" "${_parameters}" && [ -n "${response}" ]; then | |
101 | response="$(echo "${response}" | tr -d "\n" | sed 's/^\[\(.*\)\]$/\1/' | sed -e 's/{"record_id":/|"record_id":/g' | sed 's/|/&{/g' | tr "|" "\n")" | |
102 | _debug response "${response}" | |
103 | ||
104 | record="$(echo "${response}" | _egrep_o "{.*\"host\": *\"${_sub_domain}\", *\"target\": *\"${txtvalue}\".*}")" | |
105 | _debug record "${record}" | |
106 | ||
107 | if [ "${record}" ]; then | |
108 | _record_id=$(printf "%s\n" "${record}" | _egrep_o "\"record_id\": *[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ ) | |
109 | if [ "${_record_id}" ]; then | |
110 | _debug _record_id "${_record_id}" | |
111 | ||
112 | _rest DELETE "dns-record/${_record_id}" | |
113 | ||
114 | _info "TXT record successfully deleted." | |
115 | return 0 | |
116 | fi | |
117 | ||
118 | return 1 | |
119 | fi | |
120 | ||
121 | return 0 | |
122 | fi | |
123 | ||
124 | return 1 | |
125 | } | |
126 | ||
127 | _check_nw_api_creds() { | |
128 | NW_API_TOKEN="${NW_API_TOKEN:-$(_readaccountconf_mutable NW_API_TOKEN)}" | |
129 | NW_API_ENDPOINT="${NW_API_ENDPOINT:-$(_readaccountconf_mutable NW_API_ENDPOINT)}" | |
130 | ||
131 | if [ -z "${NW_API_ENDPOINT}" ]; then | |
132 | NW_API_ENDPOINT="https://portal.nexcess.net" | |
133 | fi | |
134 | ||
135 | if [ -z "${NW_API_TOKEN}" ]; then | |
136 | _err "You have not defined your NW_API_TOKEN." | |
137 | _err "Please create your token and try again." | |
138 | _err "If you need to generate a new token, please visit one of the following URLs:" | |
139 | _err " - https://portal.nexcess.net/api-token" | |
140 | _err " - https://core.thermo.io/api-token" | |
141 | _err " - https://my.futurehosting.com/api-token" | |
142 | ||
143 | return 1 | |
144 | fi | |
145 | ||
146 | _saveaccountconf_mutable NW_API_TOKEN "${NW_API_TOKEN}" | |
147 | _saveaccountconf_mutable NW_API_ENDPOINT "${NW_API_ENDPOINT}" | |
148 | } | |
149 | ||
150 | _get_root() { | |
151 | domain="${1}" | |
152 | i=2 | |
153 | p=1 | |
154 | ||
155 | if _rest GET "dns-zone"; then | |
156 | response="$(echo "${response}" | tr -d "\n" | sed 's/^\[\(.*\)\]$/\1/' | sed -e 's/{"zone_id":/|"zone_id":/g' | sed 's/|/&{/g' | tr "|" "\n")" | |
157 | ||
158 | _debug response "${response}" | |
159 | while true; do | |
160 | h=$(printf "%s" "${domain}" | cut -d . -f $i-100) | |
161 | _debug h "${h}" | |
162 | if [ -z "${h}" ]; then | |
163 | #not valid | |
164 | return 1 | |
165 | fi | |
166 | ||
167 | hostedzone="$(echo "${response}" | _egrep_o "{.*\"domain\": *\"${h}\".*}")" | |
168 | if [ "${hostedzone}" ]; then | |
169 | _zone_id=$(printf "%s\n" "${hostedzone}" | _egrep_o "\"zone_id\": *[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ ) | |
170 | if [ "${_zone_id}" ]; then | |
171 | _sub_domain=$(printf "%s" "${domain}" | cut -d . -f 1-${p}) | |
172 | _domain="${h}" | |
173 | return 0 | |
174 | fi | |
175 | return 1 | |
176 | fi | |
177 | p=$i | |
178 | i=$(_math "${i}" + 1) | |
179 | done | |
180 | fi | |
181 | return 1 | |
182 | } | |
183 | ||
184 | _rest() { | |
185 | method="${1}" | |
186 | ep="/${2}" | |
187 | data="${3}" | |
188 | ||
189 | _debug method "${method}" | |
190 | _debug ep "${ep}" | |
191 | ||
192 | export _H1="Accept: application/json" | |
193 | export _H2="Content-Type: application/json" | |
194 | export _H3="Api-Version: ${NW_API_VERSION}" | |
195 | export _H4="User-Agent: NW-ACME-CLIENT" | |
196 | export _H5="Authorization: Bearer ${NW_API_TOKEN}" | |
197 | ||
198 | if [ "${method}" != "GET" ]; then | |
199 | _debug data "${data}" | |
200 | response="$(_post "${data}" "${NW_API_ENDPOINT}${ep}" "" "${method}")" | |
201 | else | |
202 | response="$(_get "${NW_API_ENDPOINT}${ep}${data}")" | |
203 | fi | |
204 | ||
205 | if [ "${?}" != "0" ]; then | |
206 | _err "error ${ep}" | |
207 | return 1 | |
208 | fi | |
209 | _debug2 response "${response}" | |
210 | return 0 | |
211 | } |