]>
Commit | Line | Data |
---|---|---|
f354e6de MW |
1 | #!/usr/bin/env sh |
2 | ||
3 | # Script for acme.sh to deploy certificates to lighttpd | |
4 | # | |
5 | # The following variables can be exported: | |
6 | # | |
7 | # export DEPLOY_LIGHTTPD_PEM_NAME="${domain}.pem" | |
8 | # | |
9 | # Defines the name of the PEM file. | |
10 | # Defaults to "<domain>.pem" | |
11 | # | |
12 | # export DEPLOY_LIGHTTPD_PEM_PATH="/etc/lighttpd" | |
13 | # | |
14 | # Defines location of PEM file for Lighttpd. | |
15 | # Defaults to /etc/lighttpd | |
16 | # | |
17 | # export DEPLOY_LIGHTTPD_RELOAD="systemctl reload lighttpd" | |
18 | # | |
19 | # OPTIONAL: Reload command used post deploy | |
20 | # This defaults to be a no-op (ie "true"). | |
21 | # It is strongly recommended to set this something that makes sense | |
22 | # for your distro. | |
23 | # | |
24 | # export DEPLOY_LIGHTTPD_ISSUER="yes" | |
25 | # | |
26 | # OPTIONAL: Places CA file as "${DEPLOY_LIGHTTPD_PEM}.issuer" | |
27 | # Note: Required for OCSP stapling to work | |
28 | # | |
29 | # export DEPLOY_LIGHTTPD_BUNDLE="no" | |
30 | # | |
31 | # OPTIONAL: Deploy this certificate as part of a multi-cert bundle | |
32 | # This adds a suffix to the certificate based on the certificate type | |
33 | # eg RSA certificates will have .rsa as a suffix to the file name | |
34 | # Lighttpd will load all certificates and provide one or the other | |
35 | # depending on client capabilities | |
36 | # Note: This functionality requires Lighttpd was compiled against | |
37 | # a version of OpenSSL that supports this. | |
38 | # | |
39 | ||
40 | ######## Public functions ##################### | |
41 | ||
42 | #domain keyfile certfile cafile fullchain | |
43 | lighttpd_deploy() { | |
44 | _cdomain="$1" | |
45 | _ckey="$2" | |
46 | _ccert="$3" | |
47 | _cca="$4" | |
48 | _cfullchain="$5" | |
49 | ||
50 | # Some defaults | |
51 | DEPLOY_LIGHTTPD_PEM_PATH_DEFAULT="/etc/lighttpd" | |
52 | DEPLOY_LIGHTTPD_PEM_NAME_DEFAULT="${_cdomain}.pem" | |
53 | DEPLOY_LIGHTTPD_BUNDLE_DEFAULT="no" | |
54 | DEPLOY_LIGHTTPD_ISSUER_DEFAULT="yes" | |
55 | DEPLOY_LIGHTTPD_RELOAD_DEFAULT="true" | |
56 | ||
f354e6de MW |
57 | _debug _cdomain "${_cdomain}" |
58 | _debug _ckey "${_ckey}" | |
59 | _debug _ccert "${_ccert}" | |
60 | _debug _cca "${_cca}" | |
61 | _debug _cfullchain "${_cfullchain}" | |
62 | ||
63 | # PEM_PATH is optional. If not provided then assume "${DEPLOY_LIGHTTPD_PEM_PATH_DEFAULT}" | |
c43c711f GS |
64 | _getdeployconf DEPLOY_LIGHTTPD_PEM_PATH |
65 | _debug2 DEPLOY_LIGHTTPD_PEM_PATH "${DEPLOY_LIGHTTPD_PEM_PATH}" | |
f354e6de MW |
66 | if [ -n "${DEPLOY_LIGHTTPD_PEM_PATH}" ]; then |
67 | Le_Deploy_lighttpd_pem_path="${DEPLOY_LIGHTTPD_PEM_PATH}" | |
68 | _savedomainconf Le_Deploy_lighttpd_pem_path "${Le_Deploy_lighttpd_pem_path}" | |
69 | elif [ -z "${Le_Deploy_lighttpd_pem_path}" ]; then | |
70 | Le_Deploy_lighttpd_pem_path="${DEPLOY_LIGHTTPD_PEM_PATH_DEFAULT}" | |
71 | fi | |
72 | ||
73 | # Ensure PEM_PATH exists | |
74 | if [ -d "${Le_Deploy_lighttpd_pem_path}" ]; then | |
75 | _debug "PEM_PATH ${Le_Deploy_lighttpd_pem_path} exists" | |
76 | else | |
77 | _err "PEM_PATH ${Le_Deploy_lighttpd_pem_path} does not exist" | |
78 | return 1 | |
79 | fi | |
80 | ||
81 | # PEM_NAME is optional. If not provided then assume "${DEPLOY_LIGHTTPD_PEM_NAME_DEFAULT}" | |
c43c711f GS |
82 | _getdeployconf DEPLOY_LIGHTTPD_PEM_NAME |
83 | _debug2 DEPLOY_LIGHTTPD_PEM_NAME "${DEPLOY_LIGHTTPD_PEM_NAME}" | |
f354e6de MW |
84 | if [ -n "${DEPLOY_LIGHTTPD_PEM_NAME}" ]; then |
85 | Le_Deploy_lighttpd_pem_name="${DEPLOY_LIGHTTPD_PEM_NAME}" | |
86 | _savedomainconf Le_Deploy_lighttpd_pem_name "${Le_Deploy_lighttpd_pem_name}" | |
87 | elif [ -z "${Le_Deploy_lighttpd_pem_name}" ]; then | |
88 | Le_Deploy_lighttpd_pem_name="${DEPLOY_LIGHTTPD_PEM_NAME_DEFAULT}" | |
89 | fi | |
90 | ||
91 | # BUNDLE is optional. If not provided then assume "${DEPLOY_LIGHTTPD_BUNDLE_DEFAULT}" | |
c43c711f GS |
92 | _getdeployconf DEPLOY_LIGHTTPD_BUNDLE |
93 | _debug2 DEPLOY_LIGHTTPD_BUNDLE "${DEPLOY_LIGHTTPD_BUNDLE}" | |
f354e6de MW |
94 | if [ -n "${DEPLOY_LIGHTTPD_BUNDLE}" ]; then |
95 | Le_Deploy_lighttpd_bundle="${DEPLOY_LIGHTTPD_BUNDLE}" | |
96 | _savedomainconf Le_Deploy_lighttpd_bundle "${Le_Deploy_lighttpd_bundle}" | |
97 | elif [ -z "${Le_Deploy_lighttpd_bundle}" ]; then | |
98 | Le_Deploy_lighttpd_bundle="${DEPLOY_LIGHTTPD_BUNDLE_DEFAULT}" | |
99 | fi | |
100 | ||
101 | # ISSUER is optional. If not provided then assume "${DEPLOY_LIGHTTPD_ISSUER_DEFAULT}" | |
c43c711f GS |
102 | _getdeployconf DEPLOY_LIGHTTPD_ISSUER |
103 | _debug2 DEPLOY_LIGHTTPD_ISSUER "${DEPLOY_LIGHTTPD_ISSUER}" | |
f354e6de MW |
104 | if [ -n "${DEPLOY_LIGHTTPD_ISSUER}" ]; then |
105 | Le_Deploy_lighttpd_issuer="${DEPLOY_LIGHTTPD_ISSUER}" | |
106 | _savedomainconf Le_Deploy_lighttpd_issuer "${Le_Deploy_lighttpd_issuer}" | |
107 | elif [ -z "${Le_Deploy_lighttpd_issuer}" ]; then | |
108 | Le_Deploy_lighttpd_issuer="${DEPLOY_LIGHTTPD_ISSUER_DEFAULT}" | |
109 | fi | |
110 | ||
111 | # RELOAD is optional. If not provided then assume "${DEPLOY_LIGHTTPD_RELOAD_DEFAULT}" | |
c43c711f GS |
112 | _getdeployconf DEPLOY_LIGHTTPD_RELOAD |
113 | _debug2 DEPLOY_LIGHTTPD_RELOAD "${DEPLOY_LIGHTTPD_RELOAD}" | |
f354e6de MW |
114 | if [ -n "${DEPLOY_LIGHTTPD_RELOAD}" ]; then |
115 | Le_Deploy_lighttpd_reload="${DEPLOY_LIGHTTPD_RELOAD}" | |
116 | _savedomainconf Le_Deploy_lighttpd_reload "${Le_Deploy_lighttpd_reload}" | |
117 | elif [ -z "${Le_Deploy_lighttpd_reload}" ]; then | |
118 | Le_Deploy_lighttpd_reload="${DEPLOY_LIGHTTPD_RELOAD_DEFAULT}" | |
119 | fi | |
120 | ||
121 | # Set the suffix depending if we are creating a bundle or not | |
122 | if [ "${Le_Deploy_lighttpd_bundle}" = "yes" ]; then | |
123 | _info "Bundle creation requested" | |
124 | # Initialise $Le_Keylength if its not already set | |
125 | if [ -z "${Le_Keylength}" ]; then | |
126 | Le_Keylength="" | |
127 | fi | |
128 | if _isEccKey "${Le_Keylength}"; then | |
129 | _info "ECC key type detected" | |
130 | _suffix=".ecdsa" | |
131 | else | |
132 | _info "RSA key type detected" | |
133 | _suffix=".rsa" | |
134 | fi | |
135 | else | |
136 | _suffix="" | |
137 | fi | |
138 | _debug _suffix "${_suffix}" | |
139 | ||
140 | # Set variables for later | |
141 | _pem="${Le_Deploy_lighttpd_pem_path}/${Le_Deploy_lighttpd_pem_name}${_suffix}" | |
142 | _issuer="${_pem}.issuer" | |
143 | _ocsp="${_pem}.ocsp" | |
144 | _reload="${Le_Deploy_lighttpd_reload}" | |
145 | ||
146 | _info "Deploying PEM file" | |
147 | # Create a temporary PEM file | |
148 | _temppem="$(_mktemp)" | |
149 | _debug _temppem "${_temppem}" | |
150 | cat "${_ckey}" "${_ccert}" "${_cca}" >"${_temppem}" | |
151 | _ret="$?" | |
152 | ||
153 | # Check that we could create the temporary file | |
154 | if [ "${_ret}" != "0" ]; then | |
155 | _err "Error code ${_ret} returned during PEM file creation" | |
156 | [ -f "${_temppem}" ] && rm -f "${_temppem}" | |
157 | return ${_ret} | |
158 | fi | |
159 | ||
160 | # Move PEM file into place | |
161 | _info "Moving new certificate into place" | |
162 | _debug _pem "${_pem}" | |
163 | cat "${_temppem}" >"${_pem}" | |
164 | _ret=$? | |
165 | ||
166 | # Clean up temp file | |
167 | [ -f "${_temppem}" ] && rm -f "${_temppem}" | |
168 | ||
169 | # Deal with any failure of moving PEM file into place | |
170 | if [ "${_ret}" != "0" ]; then | |
171 | _err "Error code ${_ret} returned while moving new certificate into place" | |
172 | return ${_ret} | |
173 | fi | |
174 | ||
175 | # Update .issuer file if requested | |
176 | if [ "${Le_Deploy_lighttpd_issuer}" = "yes" ]; then | |
177 | _info "Updating .issuer file" | |
178 | _debug _issuer "${_issuer}" | |
179 | cat "${_cca}" >"${_issuer}" | |
180 | _ret="$?" | |
181 | ||
182 | if [ "${_ret}" != "0" ]; then | |
183 | _err "Error code ${_ret} returned while copying issuer/CA certificate into place" | |
184 | return ${_ret} | |
185 | fi | |
186 | else | |
187 | [ -f "${_issuer}" ] && _err "Issuer file update not requested but .issuer file exists" | |
188 | fi | |
189 | ||
190 | # Update .ocsp file if certificate was requested with --ocsp/--ocsp-must-staple option | |
191 | if [ -z "${Le_OCSP_Staple}" ]; then | |
192 | Le_OCSP_Staple="0" | |
193 | fi | |
194 | if [ "${Le_OCSP_Staple}" = "1" ]; then | |
195 | _info "Updating OCSP stapling info" | |
196 | _debug _ocsp "${_ocsp}" | |
197 | _info "Extracting OCSP URL" | |
8419b42e | 198 | _ocsp_url=$(${ACME_OPENSSL_BIN:-openssl} x509 -noout -ocsp_uri -in "${_pem}") |
f354e6de MW |
199 | _debug _ocsp_url "${_ocsp_url}" |
200 | ||
201 | # Only process OCSP if URL was present | |
202 | if [ "${_ocsp_url}" != "" ]; then | |
203 | # Extract the hostname from the OCSP URL | |
204 | _info "Extracting OCSP URL" | |
205 | _ocsp_host=$(echo "${_ocsp_url}" | cut -d/ -f3) | |
206 | _debug _ocsp_host "${_ocsp_host}" | |
207 | ||
208 | # Only process the certificate if we have a .issuer file | |
209 | if [ -r "${_issuer}" ]; then | |
210 | # Check if issuer cert is also a root CA cert | |
8419b42e | 211 | _subjectdn=$(${ACME_OPENSSL_BIN:-openssl} x509 -in "${_issuer}" -subject -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10) |
f354e6de | 212 | _debug _subjectdn "${_subjectdn}" |
8419b42e | 213 | _issuerdn=$(${ACME_OPENSSL_BIN:-openssl} x509 -in "${_issuer}" -issuer -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10) |
f354e6de MW |
214 | _debug _issuerdn "${_issuerdn}" |
215 | _info "Requesting OCSP response" | |
216 | # If the issuer is a CA cert then our command line has "-CAfile" added | |
217 | if [ "${_subjectdn}" = "${_issuerdn}" ]; then | |
218 | _cafile_argument="-CAfile \"${_issuer}\"" | |
219 | else | |
220 | _cafile_argument="" | |
221 | fi | |
222 | _debug _cafile_argument "${_cafile_argument}" | |
223 | # if OpenSSL/LibreSSL is v1.1 or above, the format for the -header option has changed | |
8419b42e | 224 | _openssl_version=$(${ACME_OPENSSL_BIN:-openssl} version | cut -d' ' -f2) |
f354e6de MW |
225 | _debug _openssl_version "${_openssl_version}" |
226 | _openssl_major=$(echo "${_openssl_version}" | cut -d '.' -f1) | |
227 | _openssl_minor=$(echo "${_openssl_version}" | cut -d '.' -f2) | |
228 | if [ "${_openssl_major}" -eq "1" ] && [ "${_openssl_minor}" -ge "1" ] || [ "${_openssl_major}" -ge "2" ]; then | |
229 | _header_sep="=" | |
230 | else | |
231 | _header_sep=" " | |
232 | fi | |
233 | # Request the OCSP response from the issuer and store it | |
8419b42e | 234 | _openssl_ocsp_cmd="${ACME_OPENSSL_BIN:-openssl} ocsp \ |
f354e6de MW |
235 | -issuer \"${_issuer}\" \ |
236 | -cert \"${_pem}\" \ | |
237 | -url \"${_ocsp_url}\" \ | |
238 | -header Host${_header_sep}\"${_ocsp_host}\" \ | |
239 | -respout \"${_ocsp}\" \ | |
240 | -verify_other \"${_issuer}\" \ | |
241 | ${_cafile_argument} \ | |
242 | | grep -q \"${_pem}: good\"" | |
243 | _debug _openssl_ocsp_cmd "${_openssl_ocsp_cmd}" | |
244 | eval "${_openssl_ocsp_cmd}" | |
245 | _ret=$? | |
246 | else | |
247 | # Non fatal: No issuer file was present so no OCSP stapling file created | |
248 | _err "OCSP stapling in use but no .issuer file was present" | |
249 | fi | |
250 | else | |
251 | # Non fatal: No OCSP url was found int the certificate | |
252 | _err "OCSP update requested but no OCSP URL was found in certificate" | |
253 | fi | |
254 | ||
255 | # Non fatal: Check return code of openssl command | |
256 | if [ "${_ret}" != "0" ]; then | |
257 | _err "Updating OCSP stapling failed with return code ${_ret}" | |
258 | fi | |
259 | else | |
260 | # An OCSP file was already present but certificate did not have OCSP extension | |
261 | if [ -f "${_ocsp}" ]; then | |
262 | _err "OCSP was not requested but .ocsp file exists." | |
263 | # Could remove the file at this step, although Lighttpd just ignores it in this case | |
264 | # rm -f "${_ocsp}" || _err "Problem removing stale .ocsp file" | |
265 | fi | |
266 | fi | |
267 | ||
268 | # Reload Lighttpd | |
269 | _debug _reload "${_reload}" | |
270 | eval "${_reload}" | |
271 | _ret=$? | |
272 | if [ "${_ret}" != "0" ]; then | |
273 | _err "Error code ${_ret} during reload" | |
274 | return ${_ret} | |
275 | else | |
276 | _info "Reload successful" | |
277 | fi | |
278 | ||
279 | return 0 | |
280 | } |