#!/usr/bin/env sh
-VER=2.8.1
+VER=2.8.2
PROJECT_NAME="acme.sh"
_SCRIPT_="$0"
-_SUB_FOLDERS="dnsapi deploy"
+_SUB_FOLDER_NOTIFY="notify"
+_SUB_FOLDER_DNSAPI="dnsapi"
+_SUB_FOLDER_DEPLOY="deploy"
+
+_SUB_FOLDERS="$_SUB_FOLDER_DNSAPI $_SUB_FOLDER_DEPLOY $_SUB_FOLDER_NOTIFY"
LETSENCRYPT_CA_V1="https://acme-v01.api.letsencrypt.org/directory"
LETSENCRYPT_STAGING_CA_V1="https://acme-staging.api.letsencrypt.org/directory"
#none
SYSLOG_LEVEL_NONE=0
+NOTIFY_LEVEL_DISABLE=0
+NOTIFY_LEVEL_ERROR=1
+NOTIFY_LEVEL_RENEW=2
+NOTIFY_LEVEL_SKIP=3
+
+NOTIFY_LEVEL_DEFAULT=$NOTIFY_LEVEL_RENEW
+
+NOTIFY_MODE_BULK=0
+NOTIFY_MODE_CERT=1
+
+NOTIFY_MODE_DEFAULT=$NOTIFY_MODE_BULK
+
_DEBUG_WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh"
_PREPARE_LINK="https://github.com/Neilpang/acme.sh/wiki/Install-preparations"
_DNS_MANUAL_WIKI="https://github.com/Neilpang/acme.sh/wiki/dns-manual-mode"
+_NOTIFY_WIKI="https://github.com/Neilpang/acme.sh/wiki/notify"
+
_DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead."
_DNS_MANUAL_WARN="It seems that you are using dns manual mode. please take care: $_DNS_MANUAL_ERR"
done
}
+_json_encode() {
+ _j_str="$(sed 's/"/\\"/g' | sed "s/\r/\\r/g")"
+ _debug3 "_json_encode"
+ _debug3 "_j_str" "$_j_str"
+ echo "$_j_str" | _hex_dump | _lower_case | sed 's/0a/5c 6e/g' | tr -d ' ' | _h2b | tr -d "\r\n"
+}
+
#options file
_sed_i() {
options="$1"
_err "See: $_DEBUG_WIKI"
fi
+ if [ "$IN_CRON" ]; then
+ if [ "$NOTIFY_LEVEL" ] && [ $NOTIFY_LEVEL -ge $NOTIFY_LEVEL_ERROR ]; then
+ if [ "$NOTIFY_MODE" = "$NOTIFY_MODE_CERT" ]; then
+ _send_notify "Renew $_main_domain error" "There is an error." "$NOTIFY_HOOK" 1
+ fi
+ fi
+ fi
+
#run the post hook
if [ "$_chk_post_hook" ]; then
_info "Run post hook:'$_chk_post_hook'"
_chk_post_hook="$1"
_chk_renew_hook="$2"
_debug _on_issue_success
+ if [ "$IN_CRON" ]; then
+ if [ "$NOTIFY_LEVEL" ] && [ $NOTIFY_LEVEL -ge $NOTIFY_LEVEL_RENEW ]; then
+ if [ "$NOTIFY_MODE" = "$NOTIFY_MODE_CERT" ]; then
+ _send_notify "Renew $_main_domain success" "Good, the cert is renewed." "$NOTIFY_HOOK" 0
+ fi
+ fi
+ fi
#run the post hook
if [ "$_chk_post_hook" ]; then
_info "Run post hook:'$_chk_post_hook'"
d_api="$_SCRIPT_HOME/$_hookcat/$_hookname"
elif [ -f "$_SCRIPT_HOME/$_hookcat/$_hookname.sh" ]; then
d_api="$_SCRIPT_HOME/$_hookcat/$_hookname.sh"
- elif [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname" ]; then
+ elif [ "$_hookdomain" ] && [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname" ]; then
d_api="$LE_WORKING_DIR/$_hookdomain/$_hookname"
- elif [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname.sh" ]; then
+ elif [ "$_hookdomain" ] && [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname.sh" ]; then
d_api="$LE_WORKING_DIR/$_hookdomain/$_hookname.sh"
elif [ -f "$LE_WORKING_DIR/$_hookname" ]; then
d_api="$LE_WORKING_DIR/$_hookname"
txt="$(printf "%s" "$keyauthorization" | _digest "sha256" | _url_replace)"
_debug txt "$txt"
- d_api="$(_findHook "$_dns_root_d" dnsapi "$_currentRoot")"
+ d_api="$(_findHook "$_dns_root_d" $_SUB_FOLDER_DNSAPI "$_currentRoot")"
_debug d_api "$d_api"
dns_entry="$dns_entry$dvsep$txt${dvsep}$d_api"
if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then
_info "Skip, Next renewal time is: $(__green "$Le_NextRenewTimeStr")"
_info "Add '$(__red '--force')' to force to renew."
+
+ if [ "$IN_CRON" = "1" ]; then
+ if [ "$NOTIFY_LEVEL" ] && [ $NOTIFY_LEVEL -ge $NOTIFY_LEVEL_SKIP ]; then
+ if [ "$NOTIFY_MODE" = "$NOTIFY_MODE_CERT" ]; then
+ _send_notify "Renew $Le_Domain skipped" "Good, the cert next renewal time is $Le_NextRenewTimeStr." "$NOTIFY_HOOK" "$RENEW_SKIP"
+ fi
+ fi
+ fi
+
return "$RENEW_SKIP"
fi
_stopRenewOnError="$1"
_debug "_stopRenewOnError" "$_stopRenewOnError"
_ret="0"
-
+ _success_msg=""
+ _error_msg=""
+ _skipped_msg=""
for di in "${CERT_HOME}"/*.*/; do
_debug di "$di"
if ! [ -d "$di" ]; then
if [ "$rc" != "0" ]; then
if [ "$rc" = "$RENEW_SKIP" ]; then
_info "Skipped $d"
- elif [ "$_stopRenewOnError" ]; then
- _err "Error renew $d, stop now."
- return "$rc"
+ _skipped_msg="${_skipped_msg} $d
+"
else
- _ret="$rc"
- _err "Error renew $d."
+ _error_msg="${_error_msg} $d
+"
+ if [ "$_stopRenewOnError" ]; then
+ _err "Error renew $d, stop now."
+ _ret="$rc"
+ break
+ else
+ _ret="$rc"
+ _err "Error renew $d."
+ fi
fi
+ else
+ _success_msg="${_success_msg} $d
+"
fi
done
+
+ if [ "$IN_CRON" = "1" ]; then
+ if [ -z "$NOTIFY_MODE" ] || [ "$NOTIFY_MODE" = "$NOTIFY_MODE_BULK" ]; then
+ _msg_subject="Renew"
+ if [ "$_error_msg" ]; then
+ _msg_subject="${_msg_subject} Error"
+ fi
+ if [ "$_success_msg" ]; then
+ _msg_subject="${_msg_subject} Success"
+ fi
+ if [ "$_skipped_msg" ]; then
+ _msg_subject="${_msg_subject} Skipped"
+ fi
+ _msg_data="Error certs:
+${_error_msg}
+Success certs:
+${_success_msg}
+Skipped certs:
+$_skipped_msg
+"
+ _send_notify "$_msg_subject" "$_msg_data" "$NOTIFY_HOOK" 0
+ fi
+ fi
+
return "$_ret"
}
_hooks="$2"
for _d_api in $(echo "$_hooks" | tr ',' " "); do
- _deployApi="$(_findHook "$_d" deploy "$_d_api")"
+ _deployApi="$(_findHook "$_d" $_SUB_FOLDER_DEPLOY "$_d_api")"
if [ -z "$_deployApi" ]; then
_err "The deploy hook $_d_api is not found."
return 1
echo "v$VER"
}
+# subject content hooks code
+_send_notify() {
+ _nsubject="$1"
+ _ncontent="$2"
+ _nhooks="$3"
+ _nerror="$4"
+
+ if [ "$NOTIFY_LEVEL" = "$NOTIFY_LEVEL_DISABLE" ]; then
+ _debug "The NOTIFY_LEVEL is $NOTIFY_LEVEL, disabled, just return."
+ return 0
+ fi
+
+ if [ -z "$_nhooks" ]; then
+ _debug "The NOTIFY_HOOK is empty, just return."
+ return 0
+ fi
+
+ _send_err=0
+ for _n_hook in $(echo "$_nhooks" | tr ',' " "); do
+ _n_hook_file="$(_findHook "" $_SUB_FOLDER_NOTIFY "$_n_hook")"
+ _info "Found $_n_hook_file"
+
+ if ! (
+ if ! . "$_n_hook_file"; then
+ _err "Load file $_n_hook_file error. Please check your api file and try again."
+ return 1
+ fi
+
+ d_command="${_n_hook}_send"
+ if ! _exists "$d_command"; then
+ _err "It seems that your api file is not correct, it must have a function named: $d_command"
+ return 1
+ fi
+
+ if ! $d_command "$_nsubject" "$_ncontent" "$_nerror"; then
+ _err "Error send message by $d_command"
+ return 1
+ fi
+
+ return 0
+ ); then
+ _err "Set $_n_hook_file error."
+ _send_err=1
+ else
+ _info "$_n_hook $(__green Success)"
+ fi
+ done
+ return $_send_err
+
+}
+
+# hook
+_set_notify_hook() {
+ _nhooks="$1"
+
+ _test_subject="Hello, this is notification from $PROJECT_NAME"
+ _test_content="If you receive this email, your notification works."
+
+ _send_notify "$_test_subject" "$_test_content" "$_nhooks" 0
+
+}
+
+#[hook] [level] [mode]
+setnotify() {
+ _nhook="$1"
+ _nlevel="$2"
+ _nmode="$3"
+
+ _initpath
+
+ if [ -z "$_nhook$_nlevel$_nmode" ]; then
+ _usage "Usage: $PROJECT_ENTRY --set-notify [--notify-hook mailgun] [--notify-level $NOTIFY_LEVEL_DEFAULT] [--notify-mode $NOTIFY_MODE_DEFAULT]"
+ _usage "$_NOTIFY_WIKI"
+ return 1
+ fi
+
+ if [ "$_nlevel" ]; then
+ _info "Set notify level to: $_nlevel"
+ export "NOTIFY_LEVEL=$_nlevel"
+ _saveaccountconf "NOTIFY_LEVEL" "$NOTIFY_LEVEL"
+ fi
+
+ if [ "$_nmode" ]; then
+ _info "Set notify mode to: $_nmode"
+ export "NOTIFY_MODE=$_nmode"
+ _saveaccountconf "NOTIFY_MODE" "$NOTIFY_MODE"
+ fi
+
+ if [ "$_nhook" ]; then
+ _info "Set notify hook to: $_nhook"
+ if [ "$_nhook" = "$NO_VALUE" ]; then
+ _info "Clear notify hook"
+ _clearaccountconf "NOTIFY_HOOK"
+ else
+ if _set_notify_hook "$_nhook"; then
+ export NOTIFY_HOOK="$_nhook"
+ _saveaccountconf "NOTIFY_HOOK" "$NOTIFY_HOOK"
+ return 0
+ else
+ _err "Can not set notify hook to: $_nhook"
+ return 1
+ fi
+ fi
+ fi
+
+}
+
showhelp() {
_initpath
version
--create-domain-key Create an domain private key, professional use.
--createCSR, -ccsr Create CSR , professional use.
--deactivate Deactivate the domain authz, professional use.
+ --set-notify Set the cron notification hook, level or mode.
+
Parameters:
--domain, -d domain.tld Specifies a domain, used to issue, renew or revoke etc.
--use-wget Force to use wget, if you have both curl and wget installed.
--yes-I-know-dns-manual-mode-enough-go-ahead-please Force to use dns manual mode: $_DNS_MANUAL_WIKI
--branch, -b Only valid for '--upgrade' command, specifies the branch name to upgrade to.
- "
+
+ --notify-level 0|1|2|3 Set the notification level: Default value is $NOTIFY_LEVEL_DEFAULT.
+ 0: disabled, no notification will be sent.
+ 1: send notification only when there is an error. No news is good news.
+ 2: send notification when a cert is successfully renewed, or there is an error
+ 3: send notification when a cert is skipped, renewdd, or error
+ --notify-mode 0|1 Set notification mode. Default value is $NOTIFY_MODE_DEFAULT.
+ 0: Bulk mode. Send all the domain's notifications in one message(mail)
+ 1: Cert mode. Send a message for every single cert.
+ --notify-hook [hookname] Set the notify hook
+
+"
}
# nocron noprofile
_syslog=""
_use_wget=""
_server=""
+ _notify_hook=""
+ _notify_level=""
+ _notify_mode=""
while [ ${#} -gt 0 ]; do
case "${1}" in
--deactivate-account)
_CMD="deactivateaccount"
;;
+ --set-notify)
+ _CMD="setnotify"
+ ;;
--domain | -d)
_dvalue="$2"
export BRANCH="$2"
shift
;;
+ --notify-hook)
+ _nhook="$2"
+ if _startswith "$_nhook" "-"; then
+ _err "'$_nhook' is not a hook name for '$1'"
+ return 1
+ fi
+ if [ "$_notify_hook" ]; then
+ _notify_hook="$_notify_hook,$_nhook"
+ else
+ _notify_hook="$_nhook"
+ fi
+ shift
+ ;;
+ --notify-level)
+ _nlevel="$2"
+ if _startswith "$_nlevel" "-"; then
+ _err "'$_nlevel' is not a integer for '$1'"
+ return 1
+ fi
+ _notify_level="$_nlevel"
+ shift
+ ;;
+ --notify-mode)
+ _nmode="$2"
+ if _startswith "$_nmode" "-"; then
+ _err "'$_nmode' is not a integer for '$1'"
+ return 1
+ fi
+ _notify_mode="$_nmode"
+ shift
+ ;;
*)
_err "Unknown parameter : $1"
return 1
createCSR)
createCSR "$_domain" "$_altdomains" "$_ecc"
;;
-
+ setnotify)
+ setnotify "$_notify_hook" "$_notify_level" "$_notify_mode"
+ ;;
*)
if [ "$_CMD" ]; then
_err "Invalid command: $_CMD"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
- _fullchain=$(tr '\n\r' '@#' <"$_cfullchain" | sed 's/@/\\n/g;s/#/\\r/g')
- _key=$(tr '\n\r' '@#' <"$_ckey" | sed 's/@/\\n/g;s/#/\\r/g')
+ _fullchain=$(tr '\r\n' '*#' <"$_cfullchain" | sed 's/*#/#/g;s/##/#/g;s/#/\\n/g')
+ _key=$(tr '\r\n' '*#' <"$_ckey" | sed 's/*#/#/g;s/#/\\n/g')
_debug _fullchain "$_fullchain"
_debug _key "$_key"
#!/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_NAME="${domain}.pem"
+#
+# 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"
+#
+# 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"
+#
+# 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 #####################
_cca="$4"
_cfullchain="$5"
- _debug _cdomain "$_cdomain"
- _debug _ckey "$_ckey"
- _debug _ccert "$_ccert"
- _debug _cca "$_cca"
- _debug _cfullchain "$_cfullchain"
-
- # 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
- else
- _reload="${DEPLOY_HAPROXY_RELOAD}"
- _savedomainconf DEPLOY_HAPROXY_RELOAD "$DEPLOY_HAPROXY_RELOAD"
+ # 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="true"
+
+ 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}"
+
+ # 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
- _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."
+ # Ensure PEM_PATH exists
+ if [ -d "${Le_Deploy_haproxy_pem_path}" ]; then
+ _debug "PEM_PATH ${Le_Deploy_haproxy_pem_path} exists"
+ else
+ _err "PEM_PATH ${Le_Deploy_haproxy_pem_path} does not exist"
return 1
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"
+ # 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}"
+ 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
- # restart HAProxy
- _info "Run reload: $_reload"
- if eval "$_reload"; then
- _info "Reload success!"
- return 0
+ # 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
+
+ # 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 detected"
+ _suffix=".ecdsa"
+ else
+ _info "RSA key type detected"
+ _suffix=".rsa"
+ fi
else
- _err "Reload error"
- return 1
+ _suffix=""
+ fi
+ _debug _suffix "${_suffix}"
+
+ # Set variables for later
+ _pem="${Le_Deploy_haproxy_pem_path}/${Le_Deploy_haproxy_pem_name}${_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}" \
+ | grep -q "${_pem}: good"
+ _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 \
+ | grep -q "${_pem}: good"
+ _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
+
+ # Non fatal: Check return code of openssl command
+ if [ "${_ret}" != "0" ]; then
+ _err "Updating OCSP stapling failed with return code ${_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."
+ # 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
+
+ # Reload HAProxy
+ _debug _reload "${_reload}"
+ eval "${_reload}"
+ _ret=$?
+ if [ "${_ret}" != "0" ]; then
+ _err "Error code ${_ret} during reload"
+ return ${_ret}
+ else
+ _info "Reload successful"
fi
+ return 0
}
# DDNSS uses GET to update domain info
if [ "$method" = "GET" ]; then
- response="$(_get "$url" | sed 's/<[^>]*>//g;/</N;//ba' | _tail_n 1)"
+ response="$(_get "$url" | sed 's/<[a-zA-Z\/][^>]*>//g' | _tail_n 1)"
else
_err "Unsupported method"
return 1
--- /dev/null
+#!/usr/bin/env sh
+
+# support local mail app
+
+mail_send() {
+ _subject="$1"
+ _content="$2"
+ _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
+ _debug "_subject" "$_subject"
+ _debug "_content" "$_content"
+ _debug "_statusCode" "$_statusCode"
+
+ _err "Not implemented yet."
+ return 1
+}
--- /dev/null
+#!/usr/bin/env sh
+
+#Support mailgun.com api
+
+#MAILGUN_API_KEY="xxxx"
+#MAILGUN_TO="yyyy@gmail.com"
+
+#MAILGUN_REGION="us|eu" #optional, use "us" as default
+#MAILGUN_API_DOMAIN="xxxxxx.com" #optional, use the default sandbox domain
+#MAILGUN_FROM="xxx@xxxxx.com" #optional, use the default sendbox account
+
+_MAILGUN_BASE="https://api.mailgun.net/v3"
+
+# subject content statusCode
+mailgun_send() {
+ _subject="$1"
+ _content="$2"
+ _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
+ _debug "_statusCode" "$_statusCode"
+
+ MAILGUN_API_KEY="${MAILGUN_API_KEY:-$(_readaccountconf_mutable MAILGUN_API_KEY)}"
+ if [ -z "$MAILGUN_API_KEY" ]; then
+ MAILGUN_API_KEY=""
+ _err "You didn't specify a mailgun api key MAILGUN_API_KEY yet ."
+ _err "You can get yours from here https://mailgun.com"
+ return 1
+ fi
+ _saveaccountconf_mutable MAILGUN_API_KEY "$MAILGUN_API_KEY"
+
+ MAILGUN_REGION="${MAILGUN_REGION:-$(_readaccountconf_mutable MAILGUN_REGION)}"
+ if [ -z "$MAILGUN_REGION" ]; then
+ MAILGUN_REGION=""
+ _info "The MAILGUN_REGION is not set, so use the default us region."
+ _MAILGUN_BASE="https://api.mailgun.net/v3"
+ else
+ _saveaccountconf_mutable MAILGUN_REGION "$MAILGUN_REGION"
+ _MAILGUN_BASE="https://api.eu.mailgun.net/v3"
+ fi
+
+ MAILGUN_TO="${MAILGUN_TO:-$(_readaccountconf_mutable MAILGUN_TO)}"
+ if [ -z "$MAILGUN_TO" ]; then
+ MAILGUN_TO=""
+ _err "You didn't specify an email to MAILGUN_TO receive messages."
+ return 1
+ fi
+ _saveaccountconf_mutable MAILGUN_TO "$MAILGUN_TO"
+
+ MAILGUN_API_DOMAIN="${MAILGUN_API_DOMAIN:-$(_readaccountconf_mutable MAILGUN_API_DOMAIN)}"
+ if [ -z "$MAILGUN_API_DOMAIN" ]; then
+ _info "The MAILGUN_API_DOMAIN is not set, try to get the default sending sandbox domain for you."
+ if ! _mailgun_rest GET "/domains"; then
+ _err "Can not get sandbox domain."
+ return 1
+ fi
+ _sendboxDomain="$(echo "$response" | _egrep_o '"name": *"sandbox.*.mailgun.org"' | cut -d : -f 2 | tr -d '" ')"
+ _debug _sendboxDomain "$_sendboxDomain"
+ MAILGUN_API_DOMAIN="$_sendboxDomain"
+ if [ -z "$MAILGUN_API_DOMAIN" ]; then
+ _err "Can not get sandbox domain for MAILGUN_API_DOMAIN"
+ return 1
+ fi
+
+ _info "$(__green "When using sandbox domain, you must verify your email first.")"
+ #todo: add recepient
+ fi
+ if [ -z "$MAILGUN_API_DOMAIN" ]; then
+ _err "Can not get MAILGUN_API_DOMAIN"
+ return 1
+ fi
+ _saveaccountconf_mutable MAILGUN_API_DOMAIN "$MAILGUN_API_DOMAIN"
+
+ MAILGUN_FROM="${MAILGUN_FROM:-$(_readaccountconf_mutable MAILGUN_FROM)}"
+ if [ -z "$MAILGUN_FROM" ]; then
+ MAILGUN_FROM="$PROJECT_NAME@$MAILGUN_API_DOMAIN"
+ _info "The MAILGUN_FROM is not set, so use the default value: $MAILGUN_FROM"
+ else
+ _debug MAILGUN_FROM "$MAILGUN_FROM"
+ _saveaccountconf_mutable MAILGUN_FROM "$MAILGUN_FROM"
+ fi
+
+ #send from url
+ _msg="/$MAILGUN_API_DOMAIN/messages?from=$(printf "%s" "$MAILGUN_FROM" | _url_encode)&to=$(printf "%s" "$MAILGUN_TO" | _url_encode)&subject=$(printf "%s" "$_subject" | _url_encode)&text=$(printf "%s" "$_content" | _url_encode)"
+ _debug "_msg" "$_msg"
+ _mailgun_rest POST "$_msg"
+ if _contains "$response" "Queued. Thank you."; then
+ _info "mailgun send success."
+ return 0
+ else
+ _err "mailgun send error"
+ _err "$response"
+ return 1
+ fi
+
+}
+
+# method uri data
+_mailgun_rest() {
+ _method="$1"
+ _mguri="$2"
+ _mgdata="$3"
+ _debug _mguri "$_mguri"
+ _mgurl="$_MAILGUN_BASE$_mguri"
+ _debug _mgurl "$_mgurl"
+
+ _auth="$(printf "%s" "api:$MAILGUN_API_KEY" | _base64)"
+ export _H1="Authorization: Basic $_auth"
+ export _H2="Content-Type: application/json"
+
+ if [ "$_method" = "GET" ]; then
+ response="$(_get "$_mgurl")"
+ else
+ _debug _mgdata "$_mgdata"
+ response="$(_post "$_mgdata" "$_mgurl" "" "$_method")"
+ fi
+ if [ "$?" != "0" ]; then
+ _err "Error: $_mguri"
+ _err "$response"
+ return 1
+ fi
+ _debug2 response "$response"
+ return 0
+
+}
--- /dev/null
+#!/usr/bin/env sh
+
+# support pop
+
+pop_send() {
+ _subject="$1"
+ _content="$2"
+ _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
+ _debug "_subject" "$_subject"
+ _debug "_content" "$_content"
+ _debug "_statusCode" "$_statusCode"
+
+ _err "Not implemented yet."
+ return 1
+}
--- /dev/null
+#!/usr/bin/env sh
+
+#Support SENDGRID.com api
+
+#SENDGRID_API_KEY=""
+#SENDGRID_TO="xxxx@xxx.com"
+#SENDGRID_FROM="xxxx@cccc.com"
+
+sendgrid_send() {
+ _subject="$1"
+ _content="$2"
+ _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
+ _debug "_statusCode" "$_statusCode"
+
+ SENDGRID_API_KEY="${SENDGRID_API_KEY:-$(_readaccountconf_mutable SENDGRID_API_KEY)}"
+ if [ -z "$SENDGRID_API_KEY" ]; then
+ SENDGRID_API_KEY=""
+ _err "You didn't specify a sendgrid api key SENDGRID_API_KEY yet ."
+ _err "You can get yours from here https://sendgrid.com"
+ return 1
+ fi
+ _saveaccountconf_mutable SENDGRID_API_KEY "$SENDGRID_API_KEY"
+
+ SENDGRID_TO="${SENDGRID_TO:-$(_readaccountconf_mutable SENDGRID_TO)}"
+ if [ -z "$SENDGRID_TO" ]; then
+ SENDGRID_TO=""
+ _err "You didn't specify an email to SENDGRID_TO receive messages."
+ return 1
+ fi
+ _saveaccountconf_mutable SENDGRID_TO "$SENDGRID_TO"
+
+ SENDGRID_FROM="${SENDGRID_FROM:-$(_readaccountconf_mutable SENDGRID_FROM)}"
+ if [ -z "$SENDGRID_FROM" ]; then
+ SENDGRID_FROM=""
+ _err "You didn't specify an email to SENDGRID_FROM receive messages."
+ return 1
+ fi
+ _saveaccountconf_mutable SENDGRID_FROM "$SENDGRID_FROM"
+
+ export _H1="Authorization: Bearer $SENDGRID_API_KEY"
+ export _H2="Content-Type: application/json"
+
+ _content="$(echo "$_content" | _json_encode)"
+ _data="{\"personalizations\": [{\"to\": [{\"email\": \"$SENDGRID_TO\"}]}],\"from\": {\"email\": \"$SENDGRID_FROM\"},\"subject\": \"$_subject\",\"content\": [{\"type\": \"text/plain\", \"value\": \"$_content\"}]}"
+ response="" #just make shellcheck happy
+ if _post "$_data" "https://api.sendgrid.com/v3/mail/send"; then
+ if [ -z "$response" ]; then
+ _info "sendgrid send sccess."
+ return 0
+ fi
+ fi
+ _err "sendgrid send error."
+ _err "$response"
+ return 1
+
+}
--- /dev/null
+#!/usr/bin/env sh
+
+# support smtp
+
+smtp_send() {
+ _subject="$1"
+ _content="$2"
+ _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
+ _debug "_subject" "$_subject"
+ _debug "_content" "$_content"
+ _debug "_statusCode" "$_statusCode"
+
+ _err "Not implemented yet."
+ return 1
+}