]>
Commit | Line | Data |
---|---|---|
f845b371 | 1 | #!/usr/bin/env sh |
2 | ||
6567bb4c | 3 | # Script for acme.sh to deploy certificates to haproxy |
4 | # | |
5 | # The following variables can be exported: | |
6 | # | |
7 | # export DEPLOY_HAPROXY_PEM="" | |
8 | # | |
9 | # REQUIRED: Defines location of PEM file for HAProxy | |
10 | # | |
11 | # export DEPLOY_HAPROXY_RELOAD="systemctl reload haproxy" | |
12 | # | |
13 | # OPTIONAL: Reload command used post deploy | |
14 | # | |
15 | # export DEPLOY_HAPROXY_ISSUER="no" | |
16 | # | |
17 | # OPTIONAL: Places CA file as "${DEPLOY_HAPROXY_PEM}.issuer" | |
18 | # Note: Required for OCSP stapling to work | |
19 | # | |
20 | # export DEPLOY_HAPROXY_BUNDLE="no" | |
21 | # | |
22 | # OPTIONAL: Deploy this certificate as part of a multi-cert bundle | |
23 | # This adds a suffix to the certificate based on the certificate type | |
24 | # eg RSA certificates will have .rsa as a suffix to the file name | |
25 | # HAProxy will load all certificates and provide one or the other | |
26 | # depending on client capabilities | |
27 | # Note: This functionality requires HAProxy was compiled against | |
28 | # a version of OpenSSL that supports this. | |
29 | # | |
f845b371 | 30 | |
31 | ######## Public functions ##################### | |
32 | ||
33 | #domain keyfile certfile cafile fullchain | |
34 | haproxy_deploy() { | |
35 | _cdomain="$1" | |
36 | _ckey="$2" | |
37 | _ccert="$3" | |
38 | _cca="$4" | |
39 | _cfullchain="$5" | |
40 | ||
6567bb4c | 41 | # Some defaults |
42 | DEPLOY_HAPROXY_BUNDLE_DEFAULT="no" | |
43 | DEPLOY_HAPROXY_ISSUER_DEFAULT="no" | |
44 | DEPLOY_HAPROXY_RELOAD_DEFAULT="systemctl reload haproxy" | |
45 | ||
46 | if [ -f "${DOMAIN_CONF}" ]; then | |
47 | # shellcheck disable=SC1090 | |
48 | . "${DOMAIN_CONF}" | |
49 | fi | |
50 | ||
51 | _debug _cdomain "${_cdomain}" | |
52 | _debug _ckey "${_ckey}" | |
53 | _debug _ccert "${_ccert}" | |
54 | _debug _cca "${_cca}" | |
55 | _debug _cfullchain "${_cfullchain}" | |
56 | ||
57 | # CERT is required | |
58 | if [ -z "${DEPLOY_HAPROXY_PEM}" ]; then | |
59 | if [ -z "${Le_Deploy_haproxy_pem}" ]; then | |
60 | _err "{DEPLOY_HAPROXY_PEM} not defined." | |
61 | return 1 | |
62 | fi | |
63 | else | |
c47e67e5 | 64 | Le_Deploy_haproxy_pem="${DEPLOY_HAPROXY_PEM}" |
65 | _savedomainconf Le_Deploy_haproxy_pem "${Le_Deploy_haproxy_pem}" | |
6567bb4c | 66 | fi |
67 | ||
68 | # BUNDLE is optional. If not provided then assume "${DEPLOY_HAPROXY_BUNDLE_DEFAULT}" | |
69 | if [ -n "${DEPLOY_HAPROXY_BUNDLE}" ]; then | |
70 | Le_Deploy_haproxy_bundle="${DEPLOY_HAPROXY_BUNDLE}" | |
71 | _savedomainconf Le_Deploy_haproxy_bundle "${Le_Deploy_haproxy_bundle}" | |
72 | elif [ -z "${Le_Deploy_haproxy_bundle}" ]; then | |
73 | Le_Deploy_haproxy_bundle="${DEPLOY_HAPROXY_BUNDLE_DEFAULT}" | |
74 | fi | |
75 | ||
76 | # ISSUER is optional. If not provided then assume "${DEPLOY_HAPROXY_ISSUER_DEFAULT}" | |
77 | if [ -n "${DEPLOY_HAPROXY_ISSUER}" ]; then | |
78 | Le_Deploy_haproxy_issuer="${DEPLOY_HAPROXY_ISSUER}" | |
79 | _savedomainconf Le_Deploy_haproxy_issuer "${Le_Deploy_haproxy_issuer}" | |
80 | elif [ -z "${Le_Deploy_haproxy_issuer}" ]; then | |
81 | Le_Deploy_haproxy_issuer="${DEPLOY_HAPROXY_ISSUER_DEFAULT}" | |
82 | fi | |
83 | ||
84 | # RELOAD is optional. If not provided then assume "${DEPLOY_HAPROXY_RELOAD_DEFAULT}" | |
85 | if [ -n "${DEPLOY_HAPROXY_RELOAD}" ]; then | |
86 | Le_Deploy_haproxy_reload="${DEPLOY_HAPROXY_RELOAD}" | |
87 | _savedomainconf Le_Deploy_haproxy_reload "${Le_Deploy_haproxy_reload}" | |
88 | elif [ -z "${Le_Deploy_haproxy_reload}" ]; then | |
89 | Le_Deploy_haproxy_reload="${DEPLOY_HAPROXY_RELOAD_DEFAULT}" | |
90 | fi | |
91 | ||
92 | # Set the suffix depending if we are creating a bundle or not | |
93 | if [ "${Le_Deploy_haproxy_bundle}" = "yes" ]; then | |
94 | _info "Bundle creation requested" | |
95 | # Initialise $Le_KeyLength if its not already set | |
96 | if [ -z "${Le_KeyLength}" ]; then | |
97 | Le_KeyLength="" | |
98 | fi | |
99 | if _isEccKey "${Le_KeyLength}"; then | |
100 | _info "ECC key type so set suffix to .ecc" | |
101 | _suffix=".ecc" | |
102 | else | |
103 | _info "RSA key type so set suffix to .rsa" | |
104 | _suffix=".rsa" | |
105 | fi | |
e9e99954 | 106 | else |
6567bb4c | 107 | _suffix="" |
108 | fi | |
109 | ||
110 | # Set variables for later | |
111 | _pem="${Le_Deploy_haproxy_pem}${_suffix}" | |
112 | _issuer="${_pem}.issuer" | |
113 | _ocsp="${_pem}.ocsp" | |
114 | _reload="${Le_Deploy_haproxy_reload}" | |
115 | ||
116 | _info "Deploying PEM file" | |
117 | # Create a temporary PEM file | |
118 | _temppem="$(_mktemp)" | |
119 | _debug _temppem "${_temppem}" | |
707e0539 | 120 | cat "${_ckey}" "${_ccert}" "${_cca}" >"${_temppem}" |
6567bb4c | 121 | _ret="$?" |
122 | ||
123 | # Check that we could create the temporary file | |
124 | if [ "${_ret}" != "0" ]; then | |
125 | _err "Error code ${_ret} returned during PEM file creation" | |
126 | [ -f "${_temppem}" ] && rm -f "${_temppem}" | |
127 | return ${_ret} | |
128 | fi | |
129 | ||
130 | # Move PEM file into place | |
131 | _info "Moving new certificate into place" | |
132 | _debug _pem "${_pem}" | |
707e0539 | 133 | cat "${_temppem}" >"${_pem}" |
6567bb4c | 134 | _ret=$? |
135 | ||
136 | # Clean up temp file | |
137 | [ -f "${_temppem}" ] && rm -f "${_temppem}" | |
138 | ||
139 | # Deal with any failure of moving PEM file into place | |
140 | if [ "${_ret}" != "0" ]; then | |
141 | _err "Error code ${_ret} returned while moving new certificate into place" | |
142 | return ${_ret} | |
143 | fi | |
144 | ||
145 | # Update .issuer file if requested | |
146 | if [ "${Le_Deploy_haproxy_issuer}" = "yes" ]; then | |
147 | _info "Updating .issuer file" | |
148 | _debug _issuer "${_issuer}" | |
707e0539 | 149 | cat "${_cca}" >"${_issuer}" |
6567bb4c | 150 | _ret="$?" |
151 | ||
152 | if [ "${_ret}" != "0" ]; then | |
153 | _err "Error code ${_ret} returned while copying issuer/CA certificate into place" | |
154 | return ${_ret} | |
155 | fi | |
156 | else | |
157 | [ -f "${_issuer}" ] _err "Issuer file update not requested but .issuer file exists" | |
158 | fi | |
159 | ||
160 | # Update .ocsp file if certificate was requested with --ocsp/--ocsp-must-staple option | |
161 | if [ -z "${Le_OCSP_Staple}" ]; then | |
162 | Le_OCSP_Staple="0" | |
163 | fi | |
164 | if [ "${Le_OCSP_Staple}" = "1" ]; then | |
165 | _info "Updating OCSP stapling info" | |
166 | _debug _ocsp "${_ocsp}" | |
167 | _info "Extracting OCSP URL" | |
168 | _ocsp_url=$(openssl x509 -noout -ocsp_uri -in "${_pem}") | |
169 | _debug _ocsp_url "${_ocsp_url}" | |
170 | ||
171 | # Only process OCSP if URL was present | |
172 | if [ "${_ocsp_url}" != "" ]; then | |
173 | # Extract the hostname from the OCSP URL | |
174 | _info "Extracting OCSP URL" | |
175 | _ocsp_host=$(echo "${_ocsp_url}" | cut -d/ -f3) | |
176 | _debug _ocsp_host "${_ocsp_host}" | |
177 | ||
178 | # Only process the certificate if we have a .issuer file | |
179 | if [ -r "${_issuer}" ]; then | |
180 | # Check if issuer cert is also a root CA cert | |
181 | _subjectdn=$(openssl x509 -in "${_issuer}" -subject -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10) | |
182 | _debug _subjectdn "${_subjectdn}" | |
183 | _issuerdn=$(openssl x509 -in "${_issuer}" -issuer -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10) | |
184 | _debug _issuerdn "${_issuerdn}" | |
185 | _info "Requesting OCSP response" | |
186 | # Request the OCSP response from the issuer and store it | |
187 | if [ "${_subjectdn}" = "${_issuerdn}" ]; then | |
188 | # If the issuer is a CA cert then our command line has "-CAfile" added | |
189 | openssl ocsp \ | |
707e0539 | 190 | -issuer "${_issuer}" \ |
191 | -cert "${_pem}" \ | |
192 | -url "${_ocsp_url}" \ | |
193 | -header Host "${_ocsp_host}" \ | |
194 | -respout "${_ocsp}" \ | |
195 | -verify_other "${_issuer}" \ | |
196 | -no_nonce \ | |
197 | -CAfile "${_issuer}" | |
6567bb4c | 198 | _ret=$? |
199 | else | |
200 | # Issuer is not a root CA so no "-CAfile" option | |
201 | openssl ocsp \ | |
707e0539 | 202 | -issuer "${_issuer}" \ |
203 | -cert "${_pem}" \ | |
204 | -url "${_ocsp_url}" \ | |
205 | -header Host "${_ocsp_host}" \ | |
206 | -respout "${_ocsp}" \ | |
207 | -verify_other "${_issuer}" \ | |
208 | -no_nonce | |
6567bb4c | 209 | _ret=$? |
210 | fi | |
211 | else | |
212 | # Non fatal: No issuer file was present so no OCSP stapling file created | |
213 | _err "OCSP stapling in use but no .issuer file was present" | |
214 | fi | |
215 | else | |
216 | # Non fatal: No OCSP url was found int the certificate | |
217 | _err "OCSP update requested but no OCSP URL was found in certificate" | |
218 | fi | |
219 | ||
220 | # Check return code of openssl command | |
221 | if [ "${_ret}" != "0" ]; then | |
707e0539 | 222 | _err "Updating OCSP stapling failed with return code ${_ret}" |
223 | return ${_ret} | |
6567bb4c | 224 | fi |
225 | else | |
226 | # An OCSP file was already present but certificate did not have OCSP extension | |
227 | if [ -f "${_ocsp}" ]; then | |
228 | _err "OCSP was not requested but .ocsp file exists." | |
229 | # Should remove the file at this step, although HAProxy just ignores it in this case | |
230 | # rm -f "${_ocsp}" || _err "Problem removing stale .ocsp file" | |
707e0539 | 231 | fi |
6567bb4c | 232 | fi |
233 | ||
234 | # Reload HAProxy | |
235 | _debug _reload "${_reload}" | |
236 | eval "${_reload}" | |
237 | _ret=$? | |
238 | if [ "${_ret}" != "0" ]; then | |
239 | _info "Reload successful" | |
e9e99954 | 240 | else |
6567bb4c | 241 | _err "Error code ${_ret} during reload" |
242 | return ${_ret} | |
e9e99954 | 243 | fi |
f845b371 | 244 | |
6567bb4c | 245 | return 0 |
f845b371 | 246 | } |