You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

246 lines
7.8 KiB

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