]>
Commit | Line | Data |
---|---|---|
3870bab0 | 1 | #!/bin/sh |
f60f554e ER |
2 | # based on https://github.com/lukas2511/dehydrated/wiki/example-dns-01-nsupdate-script |
3 | ||
deb84dd0 | 4 | set -e |
3870bab0 ER |
5 | |
6 | # concat file atomic way | |
7 | atomic_concat() { | |
8 | local file=$1; shift | |
9 | > $file.new | |
10 | chmod 600 $file.new | |
11 | cat "$@" > $file.new | |
12 | cp -f $file $file.dehydrated~ | |
13 | mv -f $file.new $file | |
14 | } | |
15 | ||
16 | lighttpd_reload() { | |
17 | if [ ! -x /usr/sbin/lighttpd ] || [ ! -f /etc/lighttpd/server.pem ]; then | |
18 | return | |
19 | fi | |
20 | ||
21 | echo " + Hook: Overwritting /etc/lighttpd/server.pem and reloading lighttpd..." | |
6c474061 | 22 | atomic_concat /etc/lighttpd/server.pem "$FULLCHAINFILE" "$KEYFILE" |
3870bab0 ER |
23 | /sbin/service lighttpd reload |
24 | } | |
25 | ||
26 | haproxy_reload() { | |
27 | if [ ! -x /usr/sbin/haproxy ] || [ ! -f /etc/haproxy/server.pem ]; then | |
28 | return | |
29 | fi | |
30 | ||
31 | echo " + Hook: Overwritting /etc/haproxy/server.pem and restarting haproxy..." | |
6c474061 | 32 | atomic_concat /etc/haproxy/server.pem "$FULLCHAINFILE" "$KEYFILE" |
3870bab0 ER |
33 | /sbin/service haproxy reload |
34 | } | |
35 | ||
36 | nginx_reload() { | |
37 | if [ ! -f /etc/nginx/server.crt ] || [ ! -f /etc/nginx/server.key ]; then | |
38 | return | |
39 | fi | |
40 | ||
41 | echo " + Hook: Overwritting /etc/nginx/server.{crt,key} and reloading nginx..." | |
6c474061 ER |
42 | atomic_concat /etc/nginx/server.crt "$FULLCHAINFILE" |
43 | atomic_concat /etc/nginx/server.key "$KEYFILE" | |
3870bab0 ER |
44 | /sbin/service nginx reload |
45 | } | |
46 | ||
47 | httpd_reload() { | |
48 | if [ ! -x /etc/rc.d/init.d/httpd ]; then | |
49 | return | |
50 | fi | |
51 | ||
30b951d8 | 52 | echo " + Hook: Reloading Apache 2..." |
6c474061 ER |
53 | atomic_concat /etc/httpd/ssl/server.crt "$FULLCHAINFILE" |
54 | atomic_concat /etc/httpd/ssl/server.key "$KEYFILE" | |
3870bab0 ER |
55 | /sbin/service httpd graceful |
56 | } | |
f60f554e | 57 | |
6c474061 ER |
58 | deploy_challenge() { |
59 | local DOMAIN="${1}" TOKEN_FILENAME="${2}" TOKEN_VALUE="${3}" | |
60 | ||
61 | # This hook is called once for every domain that needs to be | |
62 | # validated, including any alternative names you may have listed. | |
63 | # | |
64 | # Parameters: | |
65 | # - DOMAIN | |
66 | # The domain name (CN or subject alternative name) being | |
67 | # validated. | |
68 | # - TOKEN_FILENAME | |
69 | # The name of the file containing the token to be served for HTTP | |
70 | # validation. Should be served by your web server as | |
71 | # /.well-known/acme-challenge/${TOKEN_FILENAME}. | |
72 | # - TOKEN_VALUE | |
73 | # The token value that needs to be served for validation. For DNS | |
74 | # validation, this is what you want to put in the _acme-challenge | |
75 | # TXT record. For HTTP validation it is the value that is expected | |
76 | # be found in the $TOKEN_FILENAME file. | |
77 | ||
78 | # Simple example: Use nsupdate with local named | |
79 | # printf 'server 127.0.0.1\nupdate add _acme-challenge.%s 300 IN TXT "%s"\nsend\n' "${DOMAIN}" "${TOKEN_VALUE}" | nsupdate -k /var/run/named/session.key | |
80 | ||
81 | echo "" | |
82 | echo "Add the following to the zone definition of ${DOMAIN}:" | |
83 | echo "'_acme-challenge.${DOMAIN}:${TOKEN_VALUE}:300" | |
84 | echo "" | |
85 | echo -n "Press enter to continue..." | |
86 | read tmp | |
87 | echo "" | |
88 | } | |
89 | ||
90 | clean_challenge() { | |
91 | local DOMAIN="${1}" TOKEN_FILENAME="${2}" TOKEN_VALUE="${3}" | |
92 | ||
93 | # This hook is called after attempting to validate each domain, | |
94 | # whether or not validation was successful. Here you can delete | |
95 | # files or DNS records that are no longer needed. | |
96 | # | |
97 | # The parameters are the same as for deploy_challenge. | |
98 | ||
99 | # Simple example: Use nsupdate with local named | |
100 | # printf 'server 127.0.0.1\nupdate delete _acme-challenge.%s TXT "%s"\nsend\n' "${DOMAIN}" "${TOKEN_VALUE}" | nsupdate -k /var/run/named/session.key | |
101 | ||
102 | echo "" | |
103 | echo "Now you can remove the following from the zone definition of ${DOMAIN}:" | |
104 | echo "'_acme-challenge.${DOMAIN}:${TOKEN_VALUE}:300" | |
105 | echo "" | |
106 | echo -n "Press enter to continue..." | |
107 | read tmp | |
108 | echo "" | |
109 | } | |
110 | ||
111 | deploy_cert() { | |
112 | local DOMAIN="${1}" KEYFILE="${2}" CERTFILE="${3}" FULLCHAINFILE="${4}" CHAINFILE="${5}" TIMESTAMP="${6}" | |
113 | ||
114 | # This hook is called once for each certificate that has been | |
115 | # produced. Here you might, for instance, copy your new certificates | |
116 | # to service-specific locations and reload the service. | |
117 | # | |
118 | # Parameters: | |
119 | # - DOMAIN | |
120 | # The primary domain name, i.e. the certificate common | |
121 | # name (CN). | |
122 | # - KEYFILE | |
123 | # The path of the file containing the private key. | |
124 | # - CERTFILE | |
125 | # The path of the file containing the signed certificate. | |
126 | # - FULLCHAINFILE | |
127 | # The path of the file containing the full certificate chain. | |
128 | # - CHAINFILE | |
129 | # The path of the file containing the intermediate certificate(s). | |
130 | # - TIMESTAMP | |
131 | # Timestamp when the specified certificate was created. | |
132 | ||
133 | # Simple example: Copy file to nginx config | |
134 | # cp "${KEYFILE}" "${FULLCHAINFILE}" /etc/nginx/ssl/; chown -R nginx: /etc/nginx/ssl | |
135 | # systemctl reload nginx | |
136 | ||
137 | lighttpd_reload | |
138 | nginx_reload | |
139 | httpd_reload | |
140 | haproxy_reload | |
141 | } | |
142 | ||
143 | deploy_ocsp() { | |
144 | local DOMAIN="${1}" OCSPFILE="${2}" TIMESTAMP="${3}" | |
145 | ||
146 | # This hook is called once for each updated ocsp stapling file that has | |
147 | # been produced. Here you might, for instance, copy your new ocsp stapling | |
148 | # files to service-specific locations and reload the service. | |
149 | # | |
150 | # Parameters: | |
151 | # - DOMAIN | |
152 | # The primary domain name, i.e. the certificate common | |
153 | # name (CN). | |
154 | # - OCSPFILE | |
155 | # The path of the ocsp stapling file | |
156 | # - TIMESTAMP | |
157 | # Timestamp when the specified ocsp stapling file was created. | |
158 | ||
159 | # Simple example: Copy file to nginx config | |
160 | # cp "${OCSPFILE}" /etc/nginx/ssl/; chown -R nginx: /etc/nginx/ssl | |
161 | # systemctl reload nginx | |
162 | } | |
163 | ||
164 | unchanged_cert() { | |
165 | local DOMAIN="${1}" KEYFILE="${2}" CERTFILE="${3}" FULLCHAINFILE="${4}" CHAINFILE="${5}" | |
166 | ||
167 | # This hook is called once for each certificate that is still | |
168 | # valid and therefore wasn't reissued. | |
169 | # | |
170 | # Parameters: | |
171 | # - DOMAIN | |
172 | # The primary domain name, i.e. the certificate common | |
173 | # name (CN). | |
174 | # - KEYFILE | |
175 | # The path of the file containing the private key. | |
176 | # - CERTFILE | |
177 | # The path of the file containing the signed certificate. | |
178 | # - FULLCHAINFILE | |
179 | # The path of the file containing the full certificate chain. | |
180 | # - CHAINFILE | |
181 | # The path of the file containing the intermediate certificate(s). | |
182 | } | |
183 | ||
184 | invalid_challenge() { | |
185 | local DOMAIN="${1}" RESPONSE="${2}" | |
186 | ||
187 | # This hook is called if the challenge response has failed, so domain | |
188 | # owners can be aware and act accordingly. | |
189 | # | |
190 | # Parameters: | |
191 | # - DOMAIN | |
192 | # The primary domain name, i.e. the certificate common | |
193 | # name (CN). | |
194 | # - RESPONSE | |
195 | # The response that the verification server returned | |
196 | ||
197 | # Simple example: Send mail to root | |
198 | # printf "Subject: Validation of ${DOMAIN} failed!\n\nOh noez!" | sendmail root | |
199 | } | |
200 | ||
201 | request_failure() { | |
202 | local STATUSCODE="${1}" REASON="${2}" REQTYPE="${3}" HEADERS="${4}" | |
203 | ||
204 | # This hook is called when an HTTP request fails (e.g., when the ACME | |
205 | # server is busy, returns an error, etc). It will be called upon any | |
206 | # response code that does not start with '2'. Useful to alert admins | |
207 | # about problems with requests. | |
208 | # | |
209 | # Parameters: | |
210 | # - STATUSCODE | |
211 | # The HTML status code that originated the error. | |
212 | # - REASON | |
213 | # The specified reason for the error. | |
214 | # - REQTYPE | |
215 | # The kind of request that was made (GET, POST...) | |
216 | # - HEADERS | |
217 | # HTTP headers returned by the CA | |
218 | ||
219 | # Simple example: Send mail to root | |
220 | # printf "Subject: HTTP request failed failed!\n\nA http request failed with status ${STATUSCODE}!" | sendmail root | |
221 | } | |
222 | ||
223 | generate_csr() { | |
224 | local DOMAIN="${1}" CERTDIR="${2}" ALTNAMES="${3}" | |
225 | ||
226 | # This hook is called before any certificate signing operation takes place. | |
227 | # It can be used to generate or fetch a certificate signing request with external | |
228 | # tools. | |
229 | # The output should be just the cerificate signing request formatted as PEM. | |
230 | # | |
231 | # Parameters: | |
232 | # - DOMAIN | |
233 | # The primary domain as specified in domains.txt. This does not need to | |
234 | # match with the domains in the CSR, it's basically just the directory name. | |
235 | # - CERTDIR | |
236 | # Certificate output directory for this particular certificate. Can be used | |
237 | # for storing additional files. | |
238 | # - ALTNAMES | |
239 | # All domain names for the current certificate as specified in domains.txt. | |
240 | # Again, this doesn't need to match with the CSR, it's just there for convenience. | |
241 | ||
242 | # Simple example: Look for pre-generated CSRs | |
243 | # if [ -e "${CERTDIR}/pre-generated.csr" ]; then | |
244 | # cat "${CERTDIR}/pre-generated.csr" | |
245 | # fi | |
246 | } | |
247 | ||
248 | startup_hook() { | |
249 | # This hook is called before the cron command to do some initial tasks | |
250 | # (e.g. starting a webserver). | |
251 | ||
252 | : | |
253 | } | |
254 | ||
255 | exit_hook() { | |
256 | # This hook is called at the end of the cron command and can be used to | |
257 | # do some final (cleanup or other) tasks. | |
258 | ||
259 | : | |
260 | } | |
261 | ||
262 | HANDLER="$1"; shift | |
263 | ||
264 | case "$HANDLER" in | |
265 | deploy_challenge|clean_challenge|deploy_cert|deploy_ocsp|unchanged_cert|invalid_challenge|request_failure|generate_csr|startup_hook|exit_hook) | |
266 | "$HANDLER" "$@" | |
f60f554e | 267 | ;; |
6c474061 ER |
268 | *) |
269 | echo " + Hook: $HANDLER: Nothing to do..." | |
f60f554e ER |
270 | ;; |
271 | esac | |
272 | ||
273 | exit 0 |