3 # Script for acme.sh to deploy certificates to haproxy
5 # The following variables can be exported:
7 # export DEPLOY_HAPROXY_PEM_NAME="${domain}.pem"
9 # Defines the name of the PEM file.
10 # Defaults to "<domain>.pem"
12 # export DEPLOY_HAPROXY_PEM_PATH="/etc/haproxy"
14 # Defines location of PEM file for HAProxy.
15 # Defaults to /etc/haproxy
17 # export DEPLOY_HAPROXY_RELOAD="systemctl reload haproxy"
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
24 # export DEPLOY_HAPROXY_ISSUER="no"
26 # OPTIONAL: Places CA file as "${DEPLOY_HAPROXY_PEM}.issuer"
27 # Note: Required for OCSP stapling to work
29 # export DEPLOY_HAPROXY_BUNDLE="no"
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 # HAProxy will load all certificates and provide one or the other
35 # depending on client capabilities
36 # Note: This functionality requires HAProxy was compiled against
37 # a version of OpenSSL that supports this.
40 ######## Public functions #####################
42 #domain keyfile certfile cafile fullchain
51 DEPLOY_HAPROXY_PEM_PATH_DEFAULT
="/etc/haproxy"
52 DEPLOY_HAPROXY_PEM_NAME_DEFAULT
="${_cdomain}.pem"
53 DEPLOY_HAPROXY_BUNDLE_DEFAULT
="no"
54 DEPLOY_HAPROXY_ISSUER_DEFAULT
="no"
55 DEPLOY_HAPROXY_RELOAD_DEFAULT
="true"
57 _debug _cdomain
"${_cdomain}"
58 _debug _ckey
"${_ckey}"
59 _debug _ccert
"${_ccert}"
61 _debug _cfullchain
"${_cfullchain}"
63 # PEM_PATH is optional. If not provided then assume "${DEPLOY_HAPROXY_PEM_PATH_DEFAULT}"
64 _getdeployconf DEPLOY_HAPROXY_PEM_PATH
65 _debug2 DEPLOY_HAPROXY_PEM_PATH
"${DEPLOY_HAPROXY_PEM_PATH}"
66 if [ -n "${DEPLOY_HAPROXY_PEM_PATH}" ]; then
67 Le_Deploy_haproxy_pem_path
="${DEPLOY_HAPROXY_PEM_PATH}"
68 _savedomainconf Le_Deploy_haproxy_pem_path
"${Le_Deploy_haproxy_pem_path}"
69 elif [ -z "${Le_Deploy_haproxy_pem_path}" ]; then
70 Le_Deploy_haproxy_pem_path
="${DEPLOY_HAPROXY_PEM_PATH_DEFAULT}"
73 # Ensure PEM_PATH exists
74 if [ -d "${Le_Deploy_haproxy_pem_path}" ]; then
75 _debug
"PEM_PATH ${Le_Deploy_haproxy_pem_path} exists"
77 _err
"PEM_PATH ${Le_Deploy_haproxy_pem_path} does not exist"
81 # PEM_NAME is optional. If not provided then assume "${DEPLOY_HAPROXY_PEM_NAME_DEFAULT}"
82 _getdeployconf DEPLOY_HAPROXY_PEM_NAME
83 _debug2 DEPLOY_HAPROXY_PEM_NAME
"${DEPLOY_HAPROXY_PEM_NAME}"
84 if [ -n "${DEPLOY_HAPROXY_PEM_NAME}" ]; then
85 Le_Deploy_haproxy_pem_name
="${DEPLOY_HAPROXY_PEM_NAME}"
86 _savedomainconf Le_Deploy_haproxy_pem_name
"${Le_Deploy_haproxy_pem_name}"
87 elif [ -z "${Le_Deploy_haproxy_pem_name}" ]; then
88 Le_Deploy_haproxy_pem_name
="${DEPLOY_HAPROXY_PEM_NAME_DEFAULT}"
91 # BUNDLE is optional. If not provided then assume "${DEPLOY_HAPROXY_BUNDLE_DEFAULT}"
92 _getdeployconf DEPLOY_HAPROXY_BUNDLE
93 _debug2 DEPLOY_HAPROXY_BUNDLE
"${DEPLOY_HAPROXY_BUNDLE}"
94 if [ -n "${DEPLOY_HAPROXY_BUNDLE}" ]; then
95 Le_Deploy_haproxy_bundle
="${DEPLOY_HAPROXY_BUNDLE}"
96 _savedomainconf Le_Deploy_haproxy_bundle
"${Le_Deploy_haproxy_bundle}"
97 elif [ -z "${Le_Deploy_haproxy_bundle}" ]; then
98 Le_Deploy_haproxy_bundle
="${DEPLOY_HAPROXY_BUNDLE_DEFAULT}"
101 # ISSUER is optional. If not provided then assume "${DEPLOY_HAPROXY_ISSUER_DEFAULT}"
102 _getdeployconf DEPLOY_HAPROXY_ISSUER
103 _debug2 DEPLOY_HAPROXY_ISSUER
"${DEPLOY_HAPROXY_ISSUER}"
104 if [ -n "${DEPLOY_HAPROXY_ISSUER}" ]; then
105 Le_Deploy_haproxy_issuer
="${DEPLOY_HAPROXY_ISSUER}"
106 _savedomainconf Le_Deploy_haproxy_issuer
"${Le_Deploy_haproxy_issuer}"
107 elif [ -z "${Le_Deploy_haproxy_issuer}" ]; then
108 Le_Deploy_haproxy_issuer
="${DEPLOY_HAPROXY_ISSUER_DEFAULT}"
111 # RELOAD is optional. If not provided then assume "${DEPLOY_HAPROXY_RELOAD_DEFAULT}"
112 _getdeployconf DEPLOY_HAPROXY_RELOAD
113 _debug2 DEPLOY_HAPROXY_RELOAD
"${DEPLOY_HAPROXY_RELOAD}"
114 if [ -n "${DEPLOY_HAPROXY_RELOAD}" ]; then
115 Le_Deploy_haproxy_reload
="${DEPLOY_HAPROXY_RELOAD}"
116 _savedomainconf Le_Deploy_haproxy_reload
"${Le_Deploy_haproxy_reload}"
117 elif [ -z "${Le_Deploy_haproxy_reload}" ]; then
118 Le_Deploy_haproxy_reload
="${DEPLOY_HAPROXY_RELOAD_DEFAULT}"
121 # Set the suffix depending if we are creating a bundle or not
122 if [ "${Le_Deploy_haproxy_bundle}" = "yes" ]; then
123 _info
"Bundle creation requested"
124 # Initialise $Le_Keylength if its not already set
125 if [ -z "${Le_Keylength}" ]; then
128 if _isEccKey
"${Le_Keylength}"; then
129 _info
"ECC key type detected"
132 _info
"RSA key type detected"
138 _debug _suffix
"${_suffix}"
140 # Set variables for later
141 _pem
="${Le_Deploy_haproxy_pem_path}/${Le_Deploy_haproxy_pem_name}${_suffix}"
142 _issuer
="${_pem}.issuer"
144 _reload
="${Le_Deploy_haproxy_reload}"
146 _info
"Deploying PEM file"
147 # Create a temporary PEM file
148 _temppem
="$(_mktemp)"
149 _debug _temppem
"${_temppem}"
150 cat "${_ckey}" "${_ccert}" "${_cca}" >"${_temppem}"
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}"
160 # Move PEM file into place
161 _info
"Moving new certificate into place"
162 _debug _pem
"${_pem}"
163 cat "${_temppem}" >"${_pem}"
167 [ -f "${_temppem}" ] && rm -f "${_temppem}"
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"
175 # Update .issuer file if requested
176 if [ "${Le_Deploy_haproxy_issuer}" = "yes" ]; then
177 _info
"Updating .issuer file"
178 _debug _issuer
"${_issuer}"
179 cat "${_cca}" >"${_issuer}"
182 if [ "${_ret}" != "0" ]; then
183 _err
"Error code ${_ret} returned while copying issuer/CA certificate into place"
187 [ -f "${_issuer}" ] && _err
"Issuer file update not requested but .issuer file exists"
190 # Update .ocsp file if certificate was requested with --ocsp/--ocsp-must-staple option
191 if [ -z "${Le_OCSP_Staple}" ]; then
194 if [ "${Le_OCSP_Staple}" = "1" ]; then
195 _info
"Updating OCSP stapling info"
196 _debug _ocsp
"${_ocsp}"
197 _info
"Extracting OCSP URL"
198 _ocsp_url
=$
(${ACME_OPENSSL_BIN:-openssl} x509
-noout -ocsp_uri -in "${_pem}")
199 _debug _ocsp_url
"${_ocsp_url}"
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}"
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
211 _subjectdn
=$
(${ACME_OPENSSL_BIN:-openssl} x509
-in "${_issuer}" -subject -noout | cut
-d'/' -f2,3,4,5,6,7,8,9,10)
212 _debug _subjectdn
"${_subjectdn}"
213 _issuerdn
=$
(${ACME_OPENSSL_BIN:-openssl} x509
-in "${_issuer}" -issuer -noout | cut
-d'/' -f2,3,4,5,6,7,8,9,10)
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}\""
222 _debug _cafile_argument
"${_cafile_argument}"
223 # if OpenSSL/LibreSSL is v1.1 or above, the format for the -header option has changed
224 _openssl_version
=$
(${ACME_OPENSSL_BIN:-openssl} version | cut
-d' ' -f2)
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
233 # Request the OCSP response from the issuer and store it
234 _openssl_ocsp_cmd
="${ACME_OPENSSL_BIN:-openssl} ocsp \
235 -issuer \"${_issuer}\" \
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}"
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"
251 # Non fatal: No OCSP url was found int the certificate
252 _err
"OCSP update requested but no OCSP URL was found in certificate"
255 # Non fatal: Check return code of openssl command
256 if [ "${_ret}" != "0" ]; then
257 _err
"Updating OCSP stapling failed with return code ${_ret}"
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 HAProxy just ignores it in this case
264 # rm -f "${_ocsp}" || _err "Problem removing stale .ocsp file"
269 _debug _reload
"${_reload}"
272 if [ "${_ret}" != "0" ]; then
273 _err
"Error code ${_ret} during reload"
276 _info
"Reload successful"