From 6567bb4c12d684f5856a96115777770ae762ccf3 Mon Sep 17 00:00:00 2001 From: andrewheberle Date: Thu, 10 May 2018 11:51:59 +0800 Subject: [PATCH 01/14] Update haproxy deploy hook Add functionality to add OCSP stapling info (.ocsp file), issuer (.issuer file) and multi-cert bundles (suffix on pem file based on key type). This also corrects the order of key, certificate and intermediate in the PEM file, which although HAProxy does not seem to care, was incorrect in the prior version. --- deploy/haproxy.sh | 256 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 222 insertions(+), 34 deletions(-) diff --git a/deploy/haproxy.sh b/deploy/haproxy.sh index 5c1a40e2..02f6a069 100644 --- a/deploy/haproxy.sh +++ b/deploy/haproxy.sh @@ -1,8 +1,32 @@ #!/usr/bin/env sh -#Here is a script to deploy cert to haproxy server. - -#returns 0 means success, otherwise error. +# Script for acme.sh to deploy certificates to haproxy +# +# The following variables can be exported: +# +# export DEPLOY_HAPROXY_PEM="" +# +# REQUIRED: Defines location of PEM file for HAProxy +# +# export DEPLOY_HAPROXY_RELOAD="systemctl reload haproxy" +# +# OPTIONAL: Reload command used post deploy +# +# export DEPLOY_HAPROXY_ISSUER="no" +# +# OPTIONAL: Places CA file as "${DEPLOY_HAPROXY_PEM}.issuer" +# Note: Required for OCSP stapling to work +# +# export DEPLOY_HAPROXY_BUNDLE="no" +# +# OPTIONAL: Deploy this certificate as part of a multi-cert bundle +# This adds a suffix to the certificate based on the certificate type +# eg RSA certificates will have .rsa as a suffix to the file name +# HAProxy will load all certificates and provide one or the other +# depending on client capabilities +# Note: This functionality requires HAProxy was compiled against +# a version of OpenSSL that supports this. +# ######## Public functions ##################### @@ -14,45 +38,209 @@ haproxy_deploy() { _cca="$4" _cfullchain="$5" - _debug _cdomain "$_cdomain" - _debug _ckey "$_ckey" - _debug _ccert "$_ccert" - _debug _cca "$_cca" - _debug _cfullchain "$_cfullchain" + # Some defaults + DEPLOY_HAPROXY_BUNDLE_DEFAULT="no" + DEPLOY_HAPROXY_ISSUER_DEFAULT="no" + DEPLOY_HAPROXY_RELOAD_DEFAULT="systemctl reload haproxy" - # handle reload preference - DEFAULT_HAPROXY_RELOAD="/usr/sbin/service haproxy restart" - if [ -z "${DEPLOY_HAPROXY_RELOAD}" ]; then - _reload="${DEFAULT_HAPROXY_RELOAD}" - _cleardomainconf DEPLOY_HAPROXY_RELOAD + if [ -f "${DOMAIN_CONF}" ]; then + # shellcheck disable=SC1090 + . "${DOMAIN_CONF}" + fi + + _debug _cdomain "${_cdomain}" + _debug _ckey "${_ckey}" + _debug _ccert "${_ccert}" + _debug _cca "${_cca}" + _debug _cfullchain "${_cfullchain}" + + # CERT is required + if [ -z "${DEPLOY_HAPROXY_PEM}" ]; then + if [ -z "${Le_Deploy_haproxy_pem}" ]; then + _err "{DEPLOY_HAPROXY_PEM} not defined." + return 1 + fi else - _reload="${DEPLOY_HAPROXY_RELOAD}" - _savedomainconf DEPLOY_HAPROXY_RELOAD "$DEPLOY_HAPROXY_RELOAD" + Le_Deploy_haproxy_cert="${DEPLOY_HAPROXY_PEM}" + _savedomainconf Le_Deploy_haproxy_cert "${Le_Deploy_haproxy_pem}" fi - _savedomainconf DEPLOY_HAPROXY_PEM_PATH "$DEPLOY_HAPROXY_PEM_PATH" - # work out the path where the PEM file should go - _pem_path="${DEPLOY_HAPROXY_PEM_PATH}" - if [ -z "$_pem_path" ]; then - _err "Path to save PEM file not found. Please define DEPLOY_HAPROXY_PEM_PATH." - return 1 + # BUNDLE is optional. If not provided then assume "${DEPLOY_HAPROXY_BUNDLE_DEFAULT}" + if [ -n "${DEPLOY_HAPROXY_BUNDLE}" ]; then + Le_Deploy_haproxy_bundle="${DEPLOY_HAPROXY_BUNDLE}" + _savedomainconf Le_Deploy_haproxy_bundle "${Le_Deploy_haproxy_bundle}" + elif [ -z "${Le_Deploy_haproxy_bundle}" ]; then + Le_Deploy_haproxy_bundle="${DEPLOY_HAPROXY_BUNDLE_DEFAULT}" fi - _pem_full_path="$_pem_path/$_cdomain.pem" - _info "Full path to PEM $_pem_full_path" - # combine the key and fullchain into a single pem and install - cat "$_cfullchain" "$_ckey" >"$_pem_full_path" - chmod 600 "$_pem_full_path" - _info "Certificate successfully deployed" + # ISSUER is optional. If not provided then assume "${DEPLOY_HAPROXY_ISSUER_DEFAULT}" + if [ -n "${DEPLOY_HAPROXY_ISSUER}" ]; then + Le_Deploy_haproxy_issuer="${DEPLOY_HAPROXY_ISSUER}" + _savedomainconf Le_Deploy_haproxy_issuer "${Le_Deploy_haproxy_issuer}" + elif [ -z "${Le_Deploy_haproxy_issuer}" ]; then + Le_Deploy_haproxy_issuer="${DEPLOY_HAPROXY_ISSUER_DEFAULT}" + fi - # restart HAProxy - _info "Run reload: $_reload" - if eval "$_reload"; then - _info "Reload success!" - return 0 + # RELOAD is optional. If not provided then assume "${DEPLOY_HAPROXY_RELOAD_DEFAULT}" + if [ -n "${DEPLOY_HAPROXY_RELOAD}" ]; then + Le_Deploy_haproxy_reload="${DEPLOY_HAPROXY_RELOAD}" + _savedomainconf Le_Deploy_haproxy_reload "${Le_Deploy_haproxy_reload}" + elif [ -z "${Le_Deploy_haproxy_reload}" ]; then + Le_Deploy_haproxy_reload="${DEPLOY_HAPROXY_RELOAD_DEFAULT}" + fi + + # Set the suffix depending if we are creating a bundle or not + if [ "${Le_Deploy_haproxy_bundle}" = "yes" ]; then + _info "Bundle creation requested" + # Initialise $Le_KeyLength if its not already set + if [ -z "${Le_KeyLength}" ]; then + Le_KeyLength="" + fi + if _isEccKey "${Le_KeyLength}"; then + _info "ECC key type so set suffix to .ecc" + _suffix=".ecc" + else + _info "RSA key type so set suffix to .rsa" + _suffix=".rsa" + fi else - _err "Reload error" - return 1 + _suffix="" fi + # Set variables for later + _pem="${Le_Deploy_haproxy_pem}${_suffix}" + _issuer="${_pem}.issuer" + _ocsp="${_pem}.ocsp" + _reload="${Le_Deploy_haproxy_reload}" + + _info "Deploying PEM file" + # Create a temporary PEM file + _temppem="$(_mktemp)" + _debug _temppem "${_temppem}" + cat "${_ckey}" "${_ccert}" "${_cca}" > "${_temppem}" + _ret="$?" + + # Check that we could create the temporary file + if [ "${_ret}" != "0" ]; then + _err "Error code ${_ret} returned during PEM file creation" + [ -f "${_temppem}" ] && rm -f "${_temppem}" + return ${_ret} + fi + + # Move PEM file into place + _info "Moving new certificate into place" + _debug _pem "${_pem}" + cat "${_temppem}" > "${_pem}" + _ret=$? + + # Clean up temp file + [ -f "${_temppem}" ] && rm -f "${_temppem}" + + # Deal with any failure of moving PEM file into place + if [ "${_ret}" != "0" ]; then + _err "Error code ${_ret} returned while moving new certificate into place" + return ${_ret} + fi + + # Update .issuer file if requested + if [ "${Le_Deploy_haproxy_issuer}" = "yes" ]; then + _info "Updating .issuer file" + _debug _issuer "${_issuer}" + cat "${_cca}" > "${_issuer}" + _ret="$?" + + if [ "${_ret}" != "0" ]; then + _err "Error code ${_ret} returned while copying issuer/CA certificate into place" + return ${_ret} + fi + else + [ -f "${_issuer}" ] _err "Issuer file update not requested but .issuer file exists" + fi + + # Update .ocsp file if certificate was requested with --ocsp/--ocsp-must-staple option + if [ -z "${Le_OCSP_Staple}" ]; then + Le_OCSP_Staple="0" + fi + if [ "${Le_OCSP_Staple}" = "1" ]; then + _info "Updating OCSP stapling info" + _debug _ocsp "${_ocsp}" + _info "Extracting OCSP URL" + _ocsp_url=$(openssl x509 -noout -ocsp_uri -in "${_pem}") + _debug _ocsp_url "${_ocsp_url}" + + # Only process OCSP if URL was present + if [ "${_ocsp_url}" != "" ]; then + # Extract the hostname from the OCSP URL + _info "Extracting OCSP URL" + _ocsp_host=$(echo "${_ocsp_url}" | cut -d/ -f3) + _debug _ocsp_host "${_ocsp_host}" + + # Only process the certificate if we have a .issuer file + if [ -r "${_issuer}" ]; then + # Check if issuer cert is also a root CA cert + _subjectdn=$(openssl x509 -in "${_issuer}" -subject -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10) + _debug _subjectdn "${_subjectdn}" + _issuerdn=$(openssl x509 -in "${_issuer}" -issuer -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10) + _debug _issuerdn "${_issuerdn}" + _info "Requesting OCSP response" + # Request the OCSP response from the issuer and store it + if [ "${_subjectdn}" = "${_issuerdn}" ]; then + # If the issuer is a CA cert then our command line has "-CAfile" added + openssl ocsp \ + -issuer "${_issuer}" \ + -cert "${_pem}" \ + -url "${_ocsp_url}" \ + -header Host "${_ocsp_host}" \ + -respout "${_ocsp}" \ + -verify_other "${_issuer}" \ + -no_nonce \ + -CAfile "${_issuer}" + _ret=$? + else + # Issuer is not a root CA so no "-CAfile" option + openssl ocsp \ + -issuer "${_issuer}" \ + -cert "${_pem}" \ + -url "${_ocsp_url}" \ + -header Host "${_ocsp_host}" \ + -respout "${_ocsp}" \ + -verify_other "${_issuer}" \ + -no_nonce + _ret=$? + fi + else + # Non fatal: No issuer file was present so no OCSP stapling file created + _err "OCSP stapling in use but no .issuer file was present" + fi + else + # Non fatal: No OCSP url was found int the certificate + _err "OCSP update requested but no OCSP URL was found in certificate" + fi + + # Check return code of openssl command + if [ "${_ret}" != "0" ]; then + _err "Updating OCSP stapling failed with return code ${_ret}" + return ${_ret} + fi + else + # An OCSP file was already present but certificate did not have OCSP extension + if [ -f "${_ocsp}" ]; then + _err "OCSP was not requested but .ocsp file exists." + # Should remove the file at this step, although HAProxy just ignores it in this case + # rm -f "${_ocsp}" || _err "Problem removing stale .ocsp file" + fi + fi + + # Reload HAProxy + _debug _reload "${_reload}" + eval "${_reload}" + _ret=$? + if [ "${_ret}" != "0" ]; then + _info "Reload successful" + else + _err "Error code ${_ret} during reload" + return ${_ret} + fi + + return 0 } From 3a95bfb699b602a5ce544f375a2aba5b266a3d94 Mon Sep 17 00:00:00 2001 From: andrewheberle Date: Thu, 10 May 2018 12:02:58 +0800 Subject: [PATCH 02/14] Document updated haproxy deploy hook --- deploy/README.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/deploy/README.md b/deploy/README.md index 181989da..621e15fc 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -258,15 +258,27 @@ acme.sh --deploy -d ftp.example.com --deploy-hook strongswan ## 10. Deploy the cert to HAProxy -You must specify the path where you want the concatenated key and certificate chain written. +You must specify the file where you want the concatenated key and certificate chain written. ```sh -export DEPLOY_HAPROXY_PEM_PATH=/etc/haproxy +export DEPLOY_HAPROXY_PEM=/etc/haproxy/server.pem ``` You may optionally define the command to reload HAProxy. The value shown below will be used as the default if you don't set this environment variable. ```sh -export DEPLOY_HAPROXY_RELOAD="/usr/sbin/service haproxy restart" +export DEPLOY_HAPROXY_RELOAD="systemctl reload haproxy" +``` + +You may optionally specify that the issuer certificate is transferred to "${DEPLOY_HAPROXY_PEM}.issuer". This is a requirement to support OCSP stapling in HAProxy. The value shown below will be used as the default if you don't set this environment variable. + +```sh +export DEPLOY_HAPROXY_ISSUER="no" +``` + +You may optionally specify that you wish to support HAProxy's multi-cert bundle functionality. This allows serving of both RSA and ECC certificates on the same proxy. This adds a ".rsa" or ".ecc" suffix to the files generated (.pem, .ocsp and .issuer). The value shown below will be used as the default if you don't set this environment variable. + +```sh +export DEPLOY_HAPROXY_BUNDLE="no" ``` You can then deploy the certificate as follows From c47e67e52c95f18a0133413763287741c7d02865 Mon Sep 17 00:00:00 2001 From: andrewheberle Date: Thu, 10 May 2018 12:06:25 +0800 Subject: [PATCH 03/14] Fix variable name --- deploy/haproxy.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/haproxy.sh b/deploy/haproxy.sh index 02f6a069..06bd74ea 100644 --- a/deploy/haproxy.sh +++ b/deploy/haproxy.sh @@ -61,8 +61,8 @@ haproxy_deploy() { return 1 fi else - Le_Deploy_haproxy_cert="${DEPLOY_HAPROXY_PEM}" - _savedomainconf Le_Deploy_haproxy_cert "${Le_Deploy_haproxy_pem}" + Le_Deploy_haproxy_pem="${DEPLOY_HAPROXY_PEM}" + _savedomainconf Le_Deploy_haproxy_pem "${Le_Deploy_haproxy_pem}" fi # BUNDLE is optional. If not provided then assume "${DEPLOY_HAPROXY_BUNDLE_DEFAULT}" From 707e053949c839073c4b1f46db09a4ebb299aab5 Mon Sep 17 00:00:00 2001 From: andrewheberle Date: Thu, 10 May 2018 12:18:03 +0800 Subject: [PATCH 04/14] whitespace fixes --- deploy/haproxy.sh | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/deploy/haproxy.sh b/deploy/haproxy.sh index 06bd74ea..47a935bc 100644 --- a/deploy/haproxy.sh +++ b/deploy/haproxy.sh @@ -117,7 +117,7 @@ haproxy_deploy() { # Create a temporary PEM file _temppem="$(_mktemp)" _debug _temppem "${_temppem}" - cat "${_ckey}" "${_ccert}" "${_cca}" > "${_temppem}" + cat "${_ckey}" "${_ccert}" "${_cca}" >"${_temppem}" _ret="$?" # Check that we could create the temporary file @@ -130,7 +130,7 @@ haproxy_deploy() { # Move PEM file into place _info "Moving new certificate into place" _debug _pem "${_pem}" - cat "${_temppem}" > "${_pem}" + cat "${_temppem}" >"${_pem}" _ret=$? # Clean up temp file @@ -146,7 +146,7 @@ haproxy_deploy() { if [ "${Le_Deploy_haproxy_issuer}" = "yes" ]; then _info "Updating .issuer file" _debug _issuer "${_issuer}" - cat "${_cca}" > "${_issuer}" + cat "${_cca}" >"${_issuer}" _ret="$?" if [ "${_ret}" != "0" ]; then @@ -187,25 +187,25 @@ haproxy_deploy() { if [ "${_subjectdn}" = "${_issuerdn}" ]; then # If the issuer is a CA cert then our command line has "-CAfile" added openssl ocsp \ - -issuer "${_issuer}" \ - -cert "${_pem}" \ - -url "${_ocsp_url}" \ - -header Host "${_ocsp_host}" \ - -respout "${_ocsp}" \ - -verify_other "${_issuer}" \ - -no_nonce \ - -CAfile "${_issuer}" + -issuer "${_issuer}" \ + -cert "${_pem}" \ + -url "${_ocsp_url}" \ + -header Host "${_ocsp_host}" \ + -respout "${_ocsp}" \ + -verify_other "${_issuer}" \ + -no_nonce \ + -CAfile "${_issuer}" _ret=$? else # Issuer is not a root CA so no "-CAfile" option openssl ocsp \ - -issuer "${_issuer}" \ - -cert "${_pem}" \ - -url "${_ocsp_url}" \ - -header Host "${_ocsp_host}" \ - -respout "${_ocsp}" \ - -verify_other "${_issuer}" \ - -no_nonce + -issuer "${_issuer}" \ + -cert "${_pem}" \ + -url "${_ocsp_url}" \ + -header Host "${_ocsp_host}" \ + -respout "${_ocsp}" \ + -verify_other "${_issuer}" \ + -no_nonce _ret=$? fi else @@ -219,8 +219,8 @@ haproxy_deploy() { # Check return code of openssl command if [ "${_ret}" != "0" ]; then - _err "Updating OCSP stapling failed with return code ${_ret}" - return ${_ret} + _err "Updating OCSP stapling failed with return code ${_ret}" + return ${_ret} fi else # An OCSP file was already present but certificate did not have OCSP extension @@ -228,7 +228,7 @@ haproxy_deploy() { _err "OCSP was not requested but .ocsp file exists." # Should remove the file at this step, although HAProxy just ignores it in this case # rm -f "${_ocsp}" || _err "Problem removing stale .ocsp file" - fi + fi fi # Reload HAProxy From ba20af48d32720fa011be9b27c6b5597cb32ff54 Mon Sep 17 00:00:00 2001 From: andrewheberle Date: Thu, 10 May 2018 15:25:28 +0800 Subject: [PATCH 05/14] Support HAPROXY_DEPLOY_PEM_PATH Adds compatibility to original haproxy deploy hook while still allowing custom PEM file name (via HAPROXY_DEPLOY_PEM_NAME) --- deploy/haproxy.sh | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/deploy/haproxy.sh b/deploy/haproxy.sh index 47a935bc..cadc8a60 100644 --- a/deploy/haproxy.sh +++ b/deploy/haproxy.sh @@ -4,9 +4,15 @@ # # The following variables can be exported: # -# export DEPLOY_HAPROXY_PEM="" +# export DEPLOY_HAPROXY_PEM_NAME="${domain}.pem" # -# REQUIRED: Defines location of PEM file for HAProxy +# Defines the name of the PEM file. +# Defaults to "domain.pem" +# +# export DEPLOY_HAPROXY_PEM_PATH="/etc/haproxy" +# +# Defines location of PEM file for HAProxy. +# Defaults to /etc/haproxy # # export DEPLOY_HAPROXY_RELOAD="systemctl reload haproxy" # @@ -39,6 +45,8 @@ haproxy_deploy() { _cfullchain="$5" # Some defaults + DEPLOY_HAPROXY_PEM_PATH_DEFAULT="/etc/haproxy" + DEPLOY_HAPROXY_PEM_NAME_DEFAULT="${_cdomain}.pem" DEPLOY_HAPROXY_BUNDLE_DEFAULT="no" DEPLOY_HAPROXY_ISSUER_DEFAULT="no" DEPLOY_HAPROXY_RELOAD_DEFAULT="systemctl reload haproxy" @@ -54,15 +62,28 @@ haproxy_deploy() { _debug _cca "${_cca}" _debug _cfullchain "${_cfullchain}" - # CERT is required - if [ -z "${DEPLOY_HAPROXY_PEM}" ]; then - if [ -z "${Le_Deploy_haproxy_pem}" ]; then - _err "{DEPLOY_HAPROXY_PEM} not defined." - return 1 - fi + # PEM_PATH is optional. If not provided then assume "${DEPLOY_HAPROXY_PEM_PATH_DEFAULT}" + if [ -n "${DEPLOY_HAPROXY_PEM_PATH}" ]; then + Le_Deploy_haproxy_pem_path="${DEPLOY_HAPROXY_PEM_PATH}" + _savedomainconf Le_Deploy_haproxy_pem_path "${Le_Deploy_haproxy_pem_path}" + elif [ -z "${Le_Deploy_haproxy_pem_path}" ]; then + Le_Deploy_haproxy_pem_path="${DEPLOY_HAPROXY_PEM_PATH_DEFAULT}" + fi + + # Ensure PEM_PATH exists + if [ -d "${Le_Deploy_haproxy_pem_path}" ]; then + _debug "PEM_PATH ${Le_Deploy_haproxy_pem_path} exists" else - Le_Deploy_haproxy_pem="${DEPLOY_HAPROXY_PEM}" - _savedomainconf Le_Deploy_haproxy_pem "${Le_Deploy_haproxy_pem}" + _err "PEM_PATH ${Le_Deploy_haproxy_pem_path} does not exist" + return 1 + fi + + # PEM_NAME is optional. If not provided then assume "${DEPLOY_HAPROXY_PEM_NAME_DEFAULT}" + if [ -n "${DEPLOY_HAPROXY_PEM_NAME}" ]; then + Le_Deploy_haproxy_pem_name="${DEPLOY_HAPROXY_PEM_NAME}" + _savedomainconf Le_Deploy_haproxy_pem_name "${Le_Deploy_haproxy_pem_name}" + elif [ -z "${Le_Deploy_haproxy_pem_name}" ]; then + Le_Deploy_haproxy_pem_name="${DEPLOY_HAPROXY_PEM_NAME_DEFAULT}" fi # BUNDLE is optional. If not provided then assume "${DEPLOY_HAPROXY_BUNDLE_DEFAULT}" @@ -108,7 +129,7 @@ haproxy_deploy() { fi # Set variables for later - _pem="${Le_Deploy_haproxy_pem}${_suffix}" + _pem="${Le_Deploy_haproxy_pem_path}/${Le_Deploy_haproxy_pem_name}${_suffix}" _issuer="${_pem}.issuer" _ocsp="${_pem}.ocsp" _reload="${Le_Deploy_haproxy_reload}" From 675e2d25d6f7c75745d866c6b08f9414977134a4 Mon Sep 17 00:00:00 2001 From: andrewheberle Date: Thu, 10 May 2018 15:28:54 +0800 Subject: [PATCH 06/14] update for new haproxy deploy vars --- deploy/README.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/deploy/README.md b/deploy/README.md index 621e15fc..7b058c4d 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -258,9 +258,16 @@ acme.sh --deploy -d ftp.example.com --deploy-hook strongswan ## 10. Deploy the cert to HAProxy -You must specify the file where you want the concatenated key and certificate chain written. +You may specify the directory where you want the concatenated key and certificate chain written. The value shown below will be used as the default if you don't set this environment variable. + ```sh -export DEPLOY_HAPROXY_PEM=/etc/haproxy/server.pem +export DEPLOY_HAPROXY_PEM_PATH=/etc/haproxy +``` + +You may optionally specify the file name where you want the concatenated key and certificate chain written. The value shown below will be used as the default if you don't set this environment variable. + +```sh +export DEPLOY_HAPROXY_PEM_PATH=$domain ``` You may optionally define the command to reload HAProxy. The value shown below will be used as the default if you don't set this environment variable. From 08d29a8342309e4c4a7c9a63c88af9d2dea26735 Mon Sep 17 00:00:00 2001 From: andrewheberle Date: Mon, 14 May 2018 10:58:46 +0800 Subject: [PATCH 07/14] Fix return from reload --- deploy/haproxy.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/haproxy.sh b/deploy/haproxy.sh index cadc8a60..cf5dc329 100644 --- a/deploy/haproxy.sh +++ b/deploy/haproxy.sh @@ -257,10 +257,10 @@ haproxy_deploy() { eval "${_reload}" _ret=$? if [ "${_ret}" != "0" ]; then - _info "Reload successful" - else _err "Error code ${_ret} during reload" return ${_ret} + else + _info "Reload successful" fi return 0 From 733b4e0a342d2bb2096b9e88e8ca7b93ba2449d5 Mon Sep 17 00:00:00 2001 From: andrewheberle Date: Mon, 14 May 2018 11:26:03 +0800 Subject: [PATCH 08/14] Fix Le_Keylength case --- deploy/haproxy.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deploy/haproxy.sh b/deploy/haproxy.sh index cf5dc329..75e76ef0 100644 --- a/deploy/haproxy.sh +++ b/deploy/haproxy.sh @@ -113,11 +113,11 @@ haproxy_deploy() { # Set the suffix depending if we are creating a bundle or not if [ "${Le_Deploy_haproxy_bundle}" = "yes" ]; then _info "Bundle creation requested" - # Initialise $Le_KeyLength if its not already set - if [ -z "${Le_KeyLength}" ]; then - Le_KeyLength="" + # Initialise $Le_Keylength if its not already set + if [ -z "${Le_Keylength}" ]; then + Le_Keylength="" fi - if _isEccKey "${Le_KeyLength}"; then + if _isEccKey "${Le_Keylength}"; then _info "ECC key type so set suffix to .ecc" _suffix=".ecc" else From 7d19d784dfd34691cca574c26ef004e6df303e9a Mon Sep 17 00:00:00 2001 From: andrewheberle Date: Mon, 14 May 2018 13:16:56 +0800 Subject: [PATCH 09/14] Update cert suffix for bundles .ocsp generation --- deploy/haproxy.sh | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/deploy/haproxy.sh b/deploy/haproxy.sh index 75e76ef0..0f5874d6 100644 --- a/deploy/haproxy.sh +++ b/deploy/haproxy.sh @@ -118,15 +118,16 @@ haproxy_deploy() { Le_Keylength="" fi if _isEccKey "${Le_Keylength}"; then - _info "ECC key type so set suffix to .ecc" - _suffix=".ecc" + _info "ECC key type detected" + _suffix=".ecdsa" else - _info "RSA key type so set suffix to .rsa" + _info "RSA key type detected" _suffix=".rsa" fi else _suffix="" fi + _debug _suffix "${_suffix}" # Set variables for later _pem="${Le_Deploy_haproxy_pem_path}/${Le_Deploy_haproxy_pem_name}${_suffix}" @@ -215,7 +216,8 @@ haproxy_deploy() { -respout "${_ocsp}" \ -verify_other "${_issuer}" \ -no_nonce \ - -CAfile "${_issuer}" + -CAfile "${_issuer}" | \ + grep -q "${_pem}: good" _ret=$? else # Issuer is not a root CA so no "-CAfile" option @@ -226,7 +228,8 @@ haproxy_deploy() { -header Host "${_ocsp_host}" \ -respout "${_ocsp}" \ -verify_other "${_issuer}" \ - -no_nonce + -no_nonce | \ + grep -q "${_pem}: good" _ret=$? fi else @@ -238,10 +241,9 @@ haproxy_deploy() { _err "OCSP update requested but no OCSP URL was found in certificate" fi - # Check return code of openssl command + # Non fatal: Check return code of openssl command if [ "${_ret}" != "0" ]; then _err "Updating OCSP stapling failed with return code ${_ret}" - return ${_ret} fi else # An OCSP file was already present but certificate did not have OCSP extension From 8d348954a7f9af9418727159f5c4376133c06a60 Mon Sep 17 00:00:00 2001 From: andrewheberle Date: Mon, 14 May 2018 13:22:46 +0800 Subject: [PATCH 10/14] Whitepspace --- deploy/haproxy.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deploy/haproxy.sh b/deploy/haproxy.sh index 0f5874d6..f6e3716f 100644 --- a/deploy/haproxy.sh +++ b/deploy/haproxy.sh @@ -216,8 +216,8 @@ haproxy_deploy() { -respout "${_ocsp}" \ -verify_other "${_issuer}" \ -no_nonce \ - -CAfile "${_issuer}" | \ - grep -q "${_pem}: good" + -CAfile "${_issuer}" \ + | grep -q "${_pem}: good" _ret=$? else # Issuer is not a root CA so no "-CAfile" option @@ -228,8 +228,8 @@ haproxy_deploy() { -header Host "${_ocsp_host}" \ -respout "${_ocsp}" \ -verify_other "${_issuer}" \ - -no_nonce | \ - grep -q "${_pem}: good" + -no_nonce \ + | grep -q "${_pem}: good" _ret=$? fi else From 31d9ba7e02777cfd1492f2cfeea2db1bd78b9867 Mon Sep 17 00:00:00 2001 From: andrewheberle Date: Fri, 28 Sep 2018 08:45:18 +0800 Subject: [PATCH 11/14] Change default for reload --- deploy/haproxy.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/deploy/haproxy.sh b/deploy/haproxy.sh index f6e3716f..0318c23c 100644 --- a/deploy/haproxy.sh +++ b/deploy/haproxy.sh @@ -17,6 +17,9 @@ # export DEPLOY_HAPROXY_RELOAD="systemctl reload haproxy" # # OPTIONAL: Reload command used post deploy +# This defaults to be a no-op (ie "true"). +# It is strongly recommended to set this something that makes sense +# for your distro. # # export DEPLOY_HAPROXY_ISSUER="no" # @@ -249,7 +252,7 @@ haproxy_deploy() { # An OCSP file was already present but certificate did not have OCSP extension if [ -f "${_ocsp}" ]; then _err "OCSP was not requested but .ocsp file exists." - # Should remove the file at this step, although HAProxy just ignores it in this case + # Could remove the file at this step, although HAProxy just ignores it in this case # rm -f "${_ocsp}" || _err "Problem removing stale .ocsp file" fi fi From 0a4e61c1dd421f1e36eb9945891c1e1a0ac2d848 Mon Sep 17 00:00:00 2001 From: andrewheberle Date: Fri, 28 Sep 2018 08:46:39 +0800 Subject: [PATCH 12/14] Readme update --- deploy/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/README.md b/deploy/README.md index 7b058c4d..8cefeffa 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -267,13 +267,13 @@ export DEPLOY_HAPROXY_PEM_PATH=/etc/haproxy You may optionally specify the file name where you want the concatenated key and certificate chain written. The value shown below will be used as the default if you don't set this environment variable. ```sh -export DEPLOY_HAPROXY_PEM_PATH=$domain +export DEPLOY_HAPROXY_PEM_NAME=$domain ``` You may optionally define the command to reload HAProxy. The value shown below will be used as the default if you don't set this environment variable. ```sh -export DEPLOY_HAPROXY_RELOAD="systemctl reload haproxy" +export DEPLOY_HAPROXY_RELOAD="true" ``` You may optionally specify that the issuer certificate is transferred to "${DEPLOY_HAPROXY_PEM}.issuer". This is a requirement to support OCSP stapling in HAProxy. The value shown below will be used as the default if you don't set this environment variable. From 454c90820d56db2d62d0315d4232eefecbc2cc8a Mon Sep 17 00:00:00 2001 From: andrewheberle Date: Fri, 28 Sep 2018 08:57:13 +0800 Subject: [PATCH 13/14] Actually set reload default --- deploy/haproxy.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/haproxy.sh b/deploy/haproxy.sh index 0318c23c..2479aebd 100644 --- a/deploy/haproxy.sh +++ b/deploy/haproxy.sh @@ -7,7 +7,7 @@ # export DEPLOY_HAPROXY_PEM_NAME="${domain}.pem" # # Defines the name of the PEM file. -# Defaults to "domain.pem" +# Defaults to ".pem" # # export DEPLOY_HAPROXY_PEM_PATH="/etc/haproxy" # @@ -52,7 +52,7 @@ haproxy_deploy() { DEPLOY_HAPROXY_PEM_NAME_DEFAULT="${_cdomain}.pem" DEPLOY_HAPROXY_BUNDLE_DEFAULT="no" DEPLOY_HAPROXY_ISSUER_DEFAULT="no" - DEPLOY_HAPROXY_RELOAD_DEFAULT="systemctl reload haproxy" + DEPLOY_HAPROXY_RELOAD_DEFAULT="true" if [ -f "${DOMAIN_CONF}" ]; then # shellcheck disable=SC1090 From 37ef0a0cb62cc70c0b4ef6158d21946576e56fac Mon Sep 17 00:00:00 2001 From: andrewheberle Date: Tue, 30 Apr 2019 15:32:36 +0800 Subject: [PATCH 14/14] Fix README.md confict --- deploy/README.md | 294 +---------------------------------------------- 1 file changed, 2 insertions(+), 292 deletions(-) diff --git a/deploy/README.md b/deploy/README.md index 8cefeffa..fc633ad7 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -1,296 +1,6 @@ # Using deploy api -Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert). +deploy hook usage: -Here are the scripts to deploy the certs/key to the server/services. +https://github.com/Neilpang/acme.sh/wiki/deployhooks -## 1. Deploy the certs to your cpanel host - -If you want to deploy using cpanel UAPI see 7. - -(cpanel deploy hook is not finished yet, this is just an example.) - - - -Then you can deploy now: - -```sh -export DEPLOY_CPANEL_USER=myusername -export DEPLOY_CPANEL_PASSWORD=PASSWORD -acme.sh --deploy -d example.com --deploy-hook cpanel -``` - -## 2. Deploy ssl cert on kong proxy engine based on api - -Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert). -Currently supports Kong-v0.10.x. - -```sh -acme.sh --deploy -d ftp.example.com --deploy-hook kong -``` - -## 3. Deploy the cert to remote server through SSH access - -The ssh deploy plugin allows you to deploy certificates to a remote host -using SSH command to connect to the remote server. The ssh plugin is invoked -with the following command... - -```sh -acme.sh --deploy -d example.com --deploy-hook ssh -``` -Prior to running this for the first time you must tell the plugin where -and how to deploy the certificates. This is done by exporting the following -environment variables. This is not required for subsequent runs as the -values are stored by acme.sh in the domain configuration files. - -Required... -``` -export DEPLOY_SSH_USER=username -``` -Optional... -``` -export DEPLOY_SSH_CMD=custom ssh command -export DEPLOY_SSH_SERVER=url or ip address of remote host -export DEPLOY_SSH_KEYFILE=filename for private key -export DEPLOY_SSH_CERTFILE=filename for certificate file -export DEPLOY_SSH_CAFILE=filename for intermediate CA file -export DEPLOY_SSH_FULLCHAIN=filename for fullchain file -export DEPLOY_SSH_REMOTE_CMD=command to execute on remote host -export DEPLOY_SSH_BACKUP=yes or no -``` - -**DEPLOY_SSH_USER** -Username at the remote host that SSH will login with. Note that -SSH must be able to login to remote host without a password... SSH Keys -must have been exchanged with the remote host. Validate and test that you -can login to USER@URL from the host running acme.sh before using this script. - -The USER@URL at the remote server must also have has permissions to write to -the target location of the certificate files and to execute any commands -(e.g. to stop/start services). - -**DEPLOY_SSH_CMD** -You can customize the ssh command used to connect to the remote host. For example -if you need to connect to a specific port at the remote server you can set this -to, for example, "ssh -p 22" or to use `sshpass` to provide password inline -instead of exchanging ssh keys (this is not recommended, using keys is -more secure). - -**DEPLOY_SSH_SERVER** -URL or IP Address of the remote server. If not provided then the domain -name provided on the acme.sh --deploy command line is used. - -**DEPLOY_SSH_KEYFILE** -Target filename for the private key issued by LetsEncrypt. - -**DEPLOY_SSH_CERTFILE** -Target filename for the certificate issued by LetsEncrypt. -If this is the same as the previous filename (for keyfile) then it is -appended to the same file. - -**DEPLOY_SSH_CAFILE** -Target filename for the CA intermediate certificate issued by LetsEncrypt. -If this is the same as a previous filename (for keyfile or certfile) then -it is appended to the same file. - -**DEPLOY_SSH_FULLCHAIN** -Target filename for the fullchain certificate issued by LetsEncrypt. -If this is the same as a previous filename (for keyfile, certfile or -cafile) then it is appended to the same file. - -**DEPLOY_SSH_REMOTE_CMD** -Command to execute on the remote server after copying any certificates. This -could be any additional command required for example to stop and restart -the service. - -**DEPLOY_SSH_BACKUP** -Before writing a certificate file to the remote server the existing -certificate will be copied to a backup directory on the remote server. -These are placed in a hidden directory in the home directory of the SSH -user -```sh -~/.acme_ssh_deploy/[domain name]-backup-[timestamp] -``` -Any backups older than 180 days will be deleted when new certificates -are deployed. This defaults to "yes" set to "no" to disable backup. - -###Examples using SSH deploy -The following example illustrates deploying certificates to a QNAP NAS -(tested with QTS version 4.2.3) - -```sh -export DEPLOY_SSH_USER="admin" -export DEPLOY_SSH_KEYFILE="/etc/stunnel/stunnel.pem" -export DEPLOY_SSH_CERTFILE="/etc/stunnel/stunnel.pem" -export DEPLOY_SSH_CAFILE="/etc/stunnel/uca.pem" -export DEPLOY_SSH_REMOTE_CMD="/etc/init.d/stunnel.sh restart" - -acme.sh --deploy -d qnap.example.com --deploy-hook ssh -``` -Note how in this example both the private key and certificate point to -the same file. This will result in the certificate being appended -to the same file as the private key... a common requirement of several -services. - -The next example illustrates deploying certificates to a Unifi -Controller (tested with version 5.4.11). - -```sh -export DEPLOY_SSH_USER="root" -export DEPLOY_SSH_KEYFILE="/var/lib/unifi/unifi.example.com.key" -export DEPLOY_SSH_FULLCHAIN="/var/lib/unifi/unifi.example.com.cer" -export DEPLOY_SSH_REMOTE_CMD="openssl pkcs12 -export \ - -inkey /var/lib/unifi/unifi.example.com.key \ - -in /var/lib/unifi/unifi.example.com.cer \ - -out /var/lib/unifi/unifi.example.com.p12 \ - -name ubnt -password pass:temppass \ - && keytool -importkeystore -deststorepass aircontrolenterprise \ - -destkeypass aircontrolenterprise \ - -destkeystore /var/lib/unifi/keystore \ - -srckeystore /var/lib/unifi/unifi.example.com.p12 \ - -srcstoretype PKCS12 -srcstorepass temppass -alias ubnt -noprompt \ - && service unifi restart" - -acme.sh --deploy -d unifi.example.com --deploy-hook ssh -``` -In this example we execute several commands on the remote host -after the certificate files have been copied... to generate a pkcs12 file -compatible with Unifi, to import it into the Unifi keystore and then finally -to restart the service. - -Note also that once the certificate is imported -into the keystore the individual certificate files are no longer -required. We could if we desired delete those files immediately. If we -do that then we should disable backup at the remote host (as there are -no files to backup -- they were erased during deployment). For example... -```sh -export DEPLOY_SSH_BACKUP=no -# modify the end of the remote command... -&& rm /var/lib/unifi/unifi.example.com.key \ - /var/lib/unifi/unifi.example.com.cer \ - /var/lib/unifi/unifi.example.com.p12 \ -&& service unifi restart -``` - -## 4. Deploy the cert to local vsftpd server - -```sh -acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd -``` - -The default vsftpd conf file is `/etc/vsftpd.conf`, if your vsftpd conf is not in the default location, you can specify one: - -```sh -export DEPLOY_VSFTPD_CONF="/etc/vsftpd.conf" - -acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd -``` - -The default command to restart vsftpd server is `service vsftpd restart`, if it doesn't work, you can specify one: - -```sh -export DEPLOY_VSFTPD_RELOAD="/etc/init.d/vsftpd restart" - -acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd -``` - -## 5. Deploy the cert to local exim4 server - -```sh -acme.sh --deploy -d ftp.example.com --deploy-hook exim4 -``` - -The default exim4 conf file is `/etc/exim/exim.conf`, if your exim4 conf is not in the default location, you can specify one: - -```sh -export DEPLOY_EXIM4_CONF="/etc/exim4/exim4.conf.template" - -acme.sh --deploy -d ftp.example.com --deploy-hook exim4 -``` - -The default command to restart exim4 server is `service exim4 restart`, if it doesn't work, you can specify one: - -```sh -export DEPLOY_EXIM4_RELOAD="/etc/init.d/exim4 restart" - -acme.sh --deploy -d ftp.example.com --deploy-hook exim4 -``` - -## 6. Deploy the cert to OSX Keychain - -```sh -acme.sh --deploy -d ftp.example.com --deploy-hook keychain -``` - -## 7. Deploy to cpanel host using UAPI - -This hook is using UAPI and works in cPanel & WHM version 56 or newer. -``` -acme.sh --deploy -d example.com --deploy-hook cpanel_uapi -``` -DEPLOY_CPANEL_USER is required only if you run the script as root and it should contain cpanel username. -```sh -export DEPLOY_CPANEL_USER=username -acme.sh --deploy -d example.com --deploy-hook cpanel_uapi -``` -Please note, that the cpanel_uapi hook will deploy only the first domain when your certificate will automatically renew. Therefore you should issue a separate certificate for each domain. - -## 8. Deploy the cert to your FRITZ!Box router - -You must specify the credentials that have administrative privileges on the FRITZ!Box in order to deploy the certificate, plus the URL of your FRITZ!Box, through the following environment variables: -```sh -$ export DEPLOY_FRITZBOX_USERNAME=my_username -$ export DEPLOY_FRITZBOX_PASSWORD=the_password -$ export DEPLOY_FRITZBOX_URL=https://fritzbox.example.com -``` - -After the first deployment, these values will be stored in your $HOME/.acme.sh/account.conf. You may now deploy the certificate like this: - -```sh -acme.sh --deploy -d fritzbox.example.com --deploy-hook fritzbox -``` - -## 9. Deploy the cert to strongswan - -```sh -acme.sh --deploy -d ftp.example.com --deploy-hook strongswan -``` - -## 10. Deploy the cert to HAProxy - -You may specify the directory where you want the concatenated key and certificate chain written. The value shown below will be used as the default if you don't set this environment variable. - -```sh -export DEPLOY_HAPROXY_PEM_PATH=/etc/haproxy -``` - -You may optionally specify the file name where you want the concatenated key and certificate chain written. The value shown below will be used as the default if you don't set this environment variable. - -```sh -export DEPLOY_HAPROXY_PEM_NAME=$domain -``` - -You may optionally define the command to reload HAProxy. The value shown below will be used as the default if you don't set this environment variable. - -```sh -export DEPLOY_HAPROXY_RELOAD="true" -``` - -You may optionally specify that the issuer certificate is transferred to "${DEPLOY_HAPROXY_PEM}.issuer". This is a requirement to support OCSP stapling in HAProxy. The value shown below will be used as the default if you don't set this environment variable. - -```sh -export DEPLOY_HAPROXY_ISSUER="no" -``` - -You may optionally specify that you wish to support HAProxy's multi-cert bundle functionality. This allows serving of both RSA and ECC certificates on the same proxy. This adds a ".rsa" or ".ecc" suffix to the files generated (.pem, .ocsp and .issuer). The value shown below will be used as the default if you don't set this environment variable. - -```sh -export DEPLOY_HAPROXY_BUNDLE="no" -``` - -You can then deploy the certificate as follows -```sh -acme.sh --deploy -d haproxy.example.com --deploy-hook haproxy -``` - -The path for the PEM file will be stored with the domain configuration and will be available when renewing, so that deploy will happen automatically when renewed.