]> git.madduck.net Git - puppet/acmessl.git/blob - templates/dehydrated-hook.epp

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

initial checkin
[puppet/acmessl.git] / templates / dehydrated-hook.epp
1 #!/bin/bash
2 set -eu
3
4 NSUPDATE="${0%/*}/nsupdate-wrapper"
5 TTL=120
6 ZONE="<%= $dnszone %>"
7 SERVER="<%= $dnsserver %>"
8 DEPLOYDIR="<%= $deploydir %>"
9
10 deploy_challenge() {
11     local DOMAIN="${1}" TOKEN_FILENAME="${2}" TOKEN_VALUE="${3}"
12
13     # This hook is called once for every domain that needs to be
14     # validated, including any alternative names you may have listed.
15     #
16     # Parameters:
17     # - DOMAIN
18     #   The domain name (CN or subject alternative name) being
19     #   validated.
20     # - TOKEN_FILENAME
21     #   The name of the file containing the token to be served for HTTP
22     #   validation. Should be served by your web server as
23     #   /.well-known/acme-challenge/${TOKEN_FILENAME}.
24     # - TOKEN_VALUE
25     #   The token value that needs to be served for validation. For DNS
26     #   validation, this is what you want to put in the _acme-challenge
27     #   TXT record. For HTTP validation it is the value that is expected
28     #   be found in the $TOKEN_FILENAME file.
29
30     # Simple example: Use nsupdate with local named
31     # 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
32
33     _nsupdate add "$DOMAIN" "$TOKEN_FILENAME" "$TOKEN_VALUE"
34 }
35
36 clean_challenge() {
37     local DOMAIN="${1}" TOKEN_FILENAME="${2}" TOKEN_VALUE="${3}"
38
39     # This hook is called after attempting to validate each domain,
40     # whether or not validation was successful. Here you can delete
41     # files or DNS records that are no longer needed.
42     #
43     # The parameters are the same as for deploy_challenge.
44
45     # Simple example: Use nsupdate with local named
46     # 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
47
48     _nsupdate delete "$DOMAIN" "$TOKEN_FILENAME" "$TOKEN_VALUE"
49 }
50
51 sync_cert() {
52     local KEYFILE="${1}" CERTFILE="${2}" FULLCHAINFILE="${3}" CHAINFILE="${4}" REQUESTFILE="${5}"
53
54     # This hook is called after the certificates have been created but before
55     # they are symlinked. This allows you to sync the files to disk to prevent
56     # creating a symlink to empty files on unexpected system crashes.
57     #
58     # This hook is not intended to be used for further processing of certificate
59     # files, see deploy_cert for that.
60     #
61     # Parameters:
62     # - KEYFILE
63     #   The path of the file containing the private key.
64     # - CERTFILE
65     #   The path of the file containing the signed certificate.
66     # - FULLCHAINFILE
67     #   The path of the file containing the full certificate chain.
68     # - CHAINFILE
69     #   The path of the file containing the intermediate certificate(s).
70     # - REQUESTFILE
71     #   The path of the file containing the certificate signing request.
72
73     # Simple example: sync the files before symlinking them
74     # sync "${KEYFILE}" "${CERTFILE} "${FULLCHAINFILE}" "${CHAINFILE}" "${REQUESTFILE}"
75 }
76
77 deploy_cert() {
78     local DOMAIN="${1}" KEYFILE="${2}" CERTFILE="${3}" FULLCHAINFILE="${4}" CHAINFILE="${5}" TIMESTAMP="${6}"
79
80     # This hook is called once for each certificate that has been
81     # produced. Here you might, for instance, copy your new certificates
82     # to service-specific locations and reload the service.
83     #
84     # Parameters:
85     # - DOMAIN
86     #   The primary domain name, i.e. the certificate common
87     #   name (CN).
88     # - KEYFILE
89     #   The path of the file containing the private key.
90     # - CERTFILE
91     #   The path of the file containing the signed certificate.
92     # - FULLCHAINFILE
93     #   The path of the file containing the full certificate chain.
94     # - CHAINFILE
95     #   The path of the file containing the intermediate certificate(s).
96     # - TIMESTAMP
97     #   Timestamp when the specified certificate was created.
98
99     # Simple example: Copy file to nginx config
100     # cp "${KEYFILE}" "${FULLCHAINFILE}" /etc/nginx/ssl/; chown -R nginx: /etc/nginx/ssl
101     # systemctl reload nginx
102     cp --dereference --preserve --update --target-directory "$DEPLOYDIR" \
103       "$KEYFILE" "$CERTFILE" "$FULLCHAINFILE" "$CHAINFILE"
104 }
105
106 deploy_ocsp() {
107     local DOMAIN="${1}" OCSPFILE="${2}" TIMESTAMP="${3}"
108
109     # This hook is called once for each updated ocsp stapling file that has
110     # been produced. Here you might, for instance, copy your new ocsp stapling
111     # files to service-specific locations and reload the service.
112     #
113     # Parameters:
114     # - DOMAIN
115     #   The primary domain name, i.e. the certificate common
116     #   name (CN).
117     # - OCSPFILE
118     #   The path of the ocsp stapling file
119     # - TIMESTAMP
120     #   Timestamp when the specified ocsp stapling file was created.
121
122     # Simple example: Copy file to nginx config
123     # cp "${OCSPFILE}" /etc/nginx/ssl/; chown -R nginx: /etc/nginx/ssl
124     # systemctl reload nginx
125 }
126
127
128 unchanged_cert() {
129     local DOMAIN="${1}" KEYFILE="${2}" CERTFILE="${3}" FULLCHAINFILE="${4}" CHAINFILE="${5}"
130
131     # This hook is called once for each certificate that is still
132     # valid and therefore wasn't reissued.
133     #
134     # Parameters:
135     # - DOMAIN
136     #   The primary domain name, i.e. the certificate common
137     #   name (CN).
138     # - KEYFILE
139     #   The path of the file containing the private key.
140     # - CERTFILE
141     #   The path of the file containing the signed certificate.
142     # - FULLCHAINFILE
143     #   The path of the file containing the full certificate chain.
144     # - CHAINFILE
145     #   The path of the file containing the intermediate certificate(s).
146 }
147
148 invalid_challenge() {
149     local DOMAIN="${1}" RESPONSE="${2}"
150
151     # This hook is called if the challenge response has failed, so domain
152     # owners can be aware and act accordingly.
153     #
154     # Parameters:
155     # - DOMAIN
156     #   The primary domain name, i.e. the certificate common
157     #   name (CN).
158     # - RESPONSE
159     #   The response that the verification server returned
160
161     # Simple example: Send mail to root
162     # printf "Subject: Validation of ${DOMAIN} failed!\n\nOh noez!" | sendmail root
163 }
164
165 request_failure() {
166     local STATUSCODE="${1}" REASON="${2}" REQTYPE="${3}" HEADERS="${4}"
167
168     # This hook is called when an HTTP request fails (e.g., when the ACME
169     # server is busy, returns an error, etc). It will be called upon any
170     # response code that does not start with '2'. Useful to alert admins
171     # about problems with requests.
172     #
173     # Parameters:
174     # - STATUSCODE
175     #   The HTML status code that originated the error.
176     # - REASON
177     #   The specified reason for the error.
178     # - REQTYPE
179     #   The kind of request that was made (GET, POST...)
180     # - HEADERS
181     #   HTTP headers returned by the CA
182
183     # Simple example: Send mail to root
184     # printf "Subject: HTTP request failed failed!\n\nA http request failed with status ${STATUSCODE}!" | sendmail root
185 }
186
187 generate_csr() {
188     local DOMAIN="${1}" CERTDIR="${2}" ALTNAMES="${3}"
189
190     # This hook is called before any certificate signing operation takes place.
191     # It can be used to generate or fetch a certificate signing request with external
192     # tools.
193     # The output should be just the cerificate signing request formatted as PEM.
194     #
195     # Parameters:
196     # - DOMAIN
197     #   The primary domain as specified in domains.txt. This does not need to
198     #   match with the domains in the CSR, it's basically just the directory name.
199     # - CERTDIR
200     #   Certificate output directory for this particular certificate. Can be used
201     #   for storing additional files.
202     # - ALTNAMES
203     #   All domain names for the current certificate as specified in domains.txt.
204     #   Again, this doesn't need to match with the CSR, it's just there for convenience.
205
206     # Simple example: Look for pre-generated CSRs
207     # if [ -e "${CERTDIR}/pre-generated.csr" ]; then
208     #   cat "${CERTDIR}/pre-generated.csr"
209     # fi
210 }
211
212 startup_hook() {
213   # This hook is called before the cron command to do some initial tasks
214   # (e.g. starting a webserver).
215
216   :
217 }
218
219 exit_hook() {
220   local ERROR="${1:-}"
221
222   # This hook is called at the end of the cron command and can be used to
223   # do some final (cleanup or other) tasks.
224   #
225   # Parameters:
226   # - ERROR
227   #   Contains error message if dehydrated exits with error
228 }
229
230 _make_nsupdate_script() {
231   local op; op="$1"; shift
232   echo "server $SERVER"
233   echo "zone $ZONE"
234
235   local rrname txt
236   while [ -n "${1:-}" ]; do
237     if [ $# -lt 3 ]; then
238       echo >&2 "Expecting batches of 3 arguments, got $# in the last: $@"
239       return 1
240     fi
241     rrname="$1"
242     # $2 is ignored for dns-01
243     txt="$3"
244
245     echo "update $op ${rrname}.$ZONE ${TTL} IN TXT \"${txt}\""
246     shift 3 2>/dev/null || break
247   done
248   echo send
249 }
250
251 _nsupdate() {
252   local script
253   script="$(_make_nsupdate_script "$@")" || return 1
254   echo "$script" | $NSUPDATE
255 }
256
257 HANDLER="$1"; shift
258 if [[ "${HANDLER}" =~ ^(deploy_challenge|clean_challenge|sync_cert|deploy_cert|deploy_ocsp|unchanged_cert|invalid_challenge|request_failure|generate_csr|startup_hook|exit_hook)$ ]]; then
259   "$HANDLER" "$@"
260 fi