1 Commits

Author SHA1 Message Date
Lukas Schauer
911a822c0c added option to pass environment variables over sudo 2024-08-04 12:07:34 +02:00
5 changed files with 42 additions and 137 deletions

View File

@@ -1,17 +1,9 @@
# Change Log # Change Log
This file contains a log of major changes in dehydrated This file contains a log of major changes in dehydrated
## [0.7.2] - 2025-05-18 ## [x.x.x] - xxxx-xx-xx
## Added ## Added
- Implemented support for certificate profile selection - New config variable `DEHYDRATED_SUDO_ENV` to allow passing environment variables over sudo calls
- Added a configuration parameter to allow for timeouts during order processing (`ORDER_TIMEOUT`, defaults to 0 = no timeout)
- Allowed for automatic deletion of old files (`AUTO_CLEANUP_DELETE`, disabled by default)
## Changed
- Renew certificates with 32 days remaining (instead of 30) to avoid issues with monthly cronjobs (`RENEW_DAYS=32`)
## Fixed
- Changed behaviour of `openssl req` stdin handling to fix compatibility with OpenSSL version 3.2+
## [0.7.1] - 2022-10-31 ## [0.7.1] - 2022-10-31
## Changed ## Changed

View File

@@ -85,8 +85,6 @@ Parameters:
--alpn alpn-certs/directory Output alpn verification certificates into the specified directory --alpn alpn-certs/directory Output alpn verification certificates into the specified directory
--challenge (-t) http-01|dns-01|tls-alpn-01 Which challenge should be used? Currently http-01, dns-01, and tls-alpn-01 are supported --challenge (-t) http-01|dns-01|tls-alpn-01 Which challenge should be used? Currently http-01, dns-01, and tls-alpn-01 are supported
--algo (-a) rsa|prime256v1|secp384r1 Which public key algorithm should be used? Supported: rsa, prime256v1 and secp384r1 --algo (-a) rsa|prime256v1|secp384r1 Which public key algorithm should be used? Supported: rsa, prime256v1 and secp384r1
--acme-profile profile_name Use specified ACME profile
--order-timeout seconds Amount of seconds to wait for processing of order until erroring out
``` ```
## Chat ## Chat

View File

@@ -291,8 +291,6 @@ store_configvars() {
__OPENSSL_CNF="${OPENSSL_CNF}" __OPENSSL_CNF="${OPENSSL_CNF}"
__RENEW_DAYS="${RENEW_DAYS}" __RENEW_DAYS="${RENEW_DAYS}"
__IP_VERSION="${IP_VERSION}" __IP_VERSION="${IP_VERSION}"
__ACME_PROFILE="${ACME_PROFILE}"
__ORDER_TIMEOUT=${ORDER_TIMEOUT}
} }
reset_configvars() { reset_configvars() {
@@ -311,8 +309,6 @@ reset_configvars() {
OPENSSL_CNF="${__OPENSSL_CNF}" OPENSSL_CNF="${__OPENSSL_CNF}"
RENEW_DAYS="${__RENEW_DAYS}" RENEW_DAYS="${__RENEW_DAYS}"
IP_VERSION="${__IP_VERSION}" IP_VERSION="${__IP_VERSION}"
ACME_PROFILE="${__ACME_PROFILE}"
ORDER_TIMEOUT=${__ORDER_TIMEOUT}
} }
hookscript_bricker_hook() { hookscript_bricker_hook() {
@@ -338,7 +334,6 @@ verify_config() {
fi fi
[[ "${API}" == "auto" || "${API}" == "1" || "${API}" == "2" ]] || _exiterr "Unsupported API version defined in config: ${API}" [[ "${API}" == "auto" || "${API}" == "1" || "${API}" == "2" ]] || _exiterr "Unsupported API version defined in config: ${API}"
[[ "${OCSP_DAYS}" =~ ^[0-9]+$ ]] || _exiterr "OCSP_DAYS must be a number" [[ "${OCSP_DAYS}" =~ ^[0-9]+$ ]] || _exiterr "OCSP_DAYS must be a number"
[[ "${ORDER_TIMEOUT}" =~ ^[0-9]+$ ]] || _exiterr "ORDER_TIMEOUT must be a number"
} }
# Setup default config values, search for and load configuration files # Setup default config values, search for and load configuration files
@@ -360,8 +355,6 @@ load_config() {
CA_LETSENCRYPT_TEST="https://acme-staging-v02.api.letsencrypt.org/directory" CA_LETSENCRYPT_TEST="https://acme-staging-v02.api.letsencrypt.org/directory"
CA_BUYPASS="https://api.buypass.com/acme/directory" CA_BUYPASS="https://api.buypass.com/acme/directory"
CA_BUYPASS_TEST="https://api.test4.buypass.no/acme/directory" CA_BUYPASS_TEST="https://api.test4.buypass.no/acme/directory"
CA_GOOGLE="https://dv.acme-v02.api.pki.goog/directory"
CA_GOOGLE_TEST="https://dv.acme-v02.test-api.pki.goog/directory"
# Default values # Default values
CA="letsencrypt" CA="letsencrypt"
@@ -379,7 +372,7 @@ load_config() {
HOOK= HOOK=
PREFERRED_CHAIN= PREFERRED_CHAIN=
HOOK_CHAIN="no" HOOK_CHAIN="no"
RENEW_DAYS="32" RENEW_DAYS="30"
KEYSIZE="4096" KEYSIZE="4096"
WELLKNOWN= WELLKNOWN=
PRIVATE_KEY_RENEW="yes" PRIVATE_KEY_RENEW="yes"
@@ -395,12 +388,10 @@ load_config() {
IP_VERSION= IP_VERSION=
CHAINCACHE= CHAINCACHE=
AUTO_CLEANUP="no" AUTO_CLEANUP="no"
AUTO_CLEANUP_DELETE="no"
DEHYDRATED_USER= DEHYDRATED_USER=
DEHYDRATED_GROUP= DEHYDRATED_GROUP=
DEHYDRATED_SUDO_ENV="no"
API="auto" API="auto"
ACME_PROFILE=""
ORDER_TIMEOUT=0
if [[ -z "${CONFIG:-}" ]]; then if [[ -z "${CONFIG:-}" ]]; then
echo "#" >&2 echo "#" >&2
@@ -452,7 +443,11 @@ load_config() {
if [[ -z "${DEHYDRATED_GROUP}" ]]; then if [[ -z "${DEHYDRATED_GROUP}" ]]; then
if [[ "${EUID}" != "${TARGET_UID}" ]]; then if [[ "${EUID}" != "${TARGET_UID}" ]]; then
echo "# INFO: Running $0 as ${DEHYDRATED_USER}" echo "# INFO: Running $0 as ${DEHYDRATED_USER}"
has_sudo && exec sudo -u "${DEHYDRATED_USER}" "${0}" "${ORIGARGS[@]}" if [ "${DEHYDRATED_SUDO_ENV}" = "yes" ]; then
has_sudo && exec sudo -E -H -u "${DEHYDRATED_USER}" "${0}" "${ORIGARGS[@]}"
else
has_sudo && exec sudo -u "${DEHYDRATED_USER}" "${0}" "${ORIGARGS[@]}"
fi
fi fi
else else
TARGET_GID="$(getent group "${DEHYDRATED_GROUP}" | cut -d':' -f3)" || _exiterr "DEHYDRATED_GROUP ${DEHYDRATED_GROUP} is invalid" TARGET_GID="$(getent group "${DEHYDRATED_GROUP}" | cut -d':' -f3)" || _exiterr "DEHYDRATED_GROUP ${DEHYDRATED_GROUP} is invalid"
@@ -462,7 +457,11 @@ load_config() {
fi fi
if [[ "${EUID}" != "${TARGET_UID}" ]] || [[ "${EGID}" != "${TARGET_GID}" ]]; then if [[ "${EUID}" != "${TARGET_UID}" ]] || [[ "${EGID}" != "${TARGET_GID}" ]]; then
echo "# INFO: Running $0 as ${DEHYDRATED_USER}/${DEHYDRATED_GROUP}" echo "# INFO: Running $0 as ${DEHYDRATED_USER}/${DEHYDRATED_GROUP}"
has_sudo && exec sudo -u "${DEHYDRATED_USER}" -g "${DEHYDRATED_GROUP}" "${0}" "${ORIGARGS[@]}" if [ "${DEHYDRATED_SUDO_ENV}" = "yes" ]; then
has_sudo && exec sudo -E -H -u "${DEHYDRATED_USER}" -g "${DEHYDRATED_GROUP}" "${0}" "${ORIGARGS[@]}"
else
has_sudo && exec sudo -u "${DEHYDRATED_USER}" -g "${DEHYDRATED_GROUP}" "${0}" "${ORIGARGS[@]}"
fi
fi fi
fi fi
elif [[ -n "${DEHYDRATED_GROUP}" ]]; then elif [[ -n "${DEHYDRATED_GROUP}" ]]; then
@@ -491,10 +490,6 @@ load_config() {
CA="${CA_BUYPASS}" CA="${CA_BUYPASS}"
elif [ "${CA}" = "buypass-test" ]; then elif [ "${CA}" = "buypass-test" ]; then
CA="${CA_BUYPASS_TEST}" CA="${CA_BUYPASS_TEST}"
elif [ "${CA}" = "google" ]; then
CA="${CA_GOOGLE}"
elif [ "${CA}" = "google-test" ]; then
CA="${CA_GOOGLE_TEST}"
fi fi
if [[ -z "${OLDCA}" ]] && [[ "${CA}" = "https://acme-v02.api.letsencrypt.org/directory" ]]; then if [[ -z "${OLDCA}" ]] && [[ "${CA}" = "https://acme-v02.api.letsencrypt.org/directory" ]]; then
@@ -558,8 +553,6 @@ load_config() {
[[ -n "${PARAM_KEY_ALGO:-}" ]] && KEY_ALGO="${PARAM_KEY_ALGO}" [[ -n "${PARAM_KEY_ALGO:-}" ]] && KEY_ALGO="${PARAM_KEY_ALGO}"
[[ -n "${PARAM_OCSP_MUST_STAPLE:-}" ]] && OCSP_MUST_STAPLE="${PARAM_OCSP_MUST_STAPLE}" [[ -n "${PARAM_OCSP_MUST_STAPLE:-}" ]] && OCSP_MUST_STAPLE="${PARAM_OCSP_MUST_STAPLE}"
[[ -n "${PARAM_IP_VERSION:-}" ]] && IP_VERSION="${PARAM_IP_VERSION}" [[ -n "${PARAM_IP_VERSION:-}" ]] && IP_VERSION="${PARAM_IP_VERSION}"
[[ -n "${PARAM_ACME_PROFILE:-}" ]] && ACME_PROFILE="${PARAM_ACME_PROFILE}"
[[ -n "${PARAM_ORDER_TIMEOUT:-}" ]] && ORDER_TIMEOUT="${PARAM_ORDER_TIMEOUT}"
if [ "${PARAM_FORCE_VALIDATION:-no}" = "yes" ] && [ "${PARAM_FORCE:-no}" = "no" ]; then if [ "${PARAM_FORCE_VALIDATION:-no}" = "yes" ] && [ "${PARAM_FORCE:-no}" = "no" ]; then
_exiterr "Argument --force-validation can only be used in combination with --force (-x)" _exiterr "Argument --force-validation can only be used in combination with --force (-x)"
@@ -603,10 +596,6 @@ init_system() {
_exiterr "Problem retrieving ACME/CA-URLs, check if your configured CA points to the directory entrypoint." _exiterr "Problem retrieving ACME/CA-URLs, check if your configured CA points to the directory entrypoint."
# Since reg URI is missing from directory we will assume it is the same as CA_NEW_REG without the new part # Since reg URI is missing from directory we will assume it is the same as CA_NEW_REG without the new part
CA_REG=${CA_NEW_REG/new-reg/reg} CA_REG=${CA_NEW_REG/new-reg/reg}
if [[ -n "${ACME_PROFILE}" ]]; then
_exiterr "ACME profiles are not supported in ACME v1."
fi
else else
CA_NEW_ORDER="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value newOrder)" && CA_NEW_ORDER="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value newOrder)" &&
CA_NEW_NONCE="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value newNonce)" && CA_NEW_NONCE="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value newNonce)" &&
@@ -615,35 +604,6 @@ init_system() {
CA_REQUIRES_EAB="$(printf "%s" "${CA_DIRECTORY}" | get_json_bool_value -p '"meta","externalAccountRequired"' || echo false)" && CA_REQUIRES_EAB="$(printf "%s" "${CA_DIRECTORY}" | get_json_bool_value -p '"meta","externalAccountRequired"' || echo false)" &&
CA_REVOKE_CERT="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value revokeCert)" || CA_REVOKE_CERT="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value revokeCert)" ||
_exiterr "Problem retrieving ACME/CA-URLs, check if your configured CA points to the directory entrypoint." _exiterr "Problem retrieving ACME/CA-URLs, check if your configured CA points to the directory entrypoint."
# Checking ACME profile
if [[ -n "${ACME_PROFILE}" ]]; then
# Extract available profiles from CA directory
declare -A available_profiles=()
while IFS=$'\t' read -r path value; do
if [[ "${value}" =~ ^\"([^\"]+)\"$ ]]; then
value=${BASH_REMATCH[1]}
fi
if [[ "${path}" =~ ^\[\"([^\"]+)\"\]$ ]]; then
available_profiles[${BASH_REMATCH[1]}]=$value
fi
done <<< "$(printf "%s" "${CA_DIRECTORY}" | get_json_dict_value -p '"meta","profiles"' 2>/dev/null)"
if [[ ${#available_profiles[@]} -eq 0 ]]; then
_exiterr "ACME profile not supported by this CA"
fi
# Check if the requested profile is available
found_profile="no"
for profile in "${!available_profiles[@]}"; do
if [[ "${profile}" == "${ACME_PROFILE}" ]]; then
found_profile="yes"
break
fi
done
if [[ "${found_profile}" == "no" ]]; then
_exiterr "ACME profile '${ACME_PROFILE}' not found, available profiles:$(for key in "${!available_profiles[@]}"; do printf "\n %s: %s" "${key}" "${available_profiles[$key]}"; done)"
fi
fi
fi fi
# Export some environment variables to be used in hook script # Export some environment variables to be used in hook script
@@ -752,14 +712,6 @@ init_system() {
fi fi
fi fi
# Google special sauce
if [[ "${CA}" = "${CA_GOOGLE}" ]]; then
if [[ -z "${CONTACT_EMAIL}" ]] || [[ -z "${EAB_KID:-}" ]] || [[ -z "${EAB_HMAC_KEY:-}" ]]; then
echo "Google requires contact email, EAB_KID and EAB_HMAC_KEY to be manually configured (see https://cloud.google.com/certificate-manager/docs/public-ca-tutorial)"
FAILED=true
fi
fi
# Check if external account is required # Check if external account is required
if [[ "${FAILED}" = "false" ]]; then if [[ "${FAILED}" = "false" ]]; then
if [[ "${CA_REQUIRES_EAB}" = "true" ]]; then if [[ "${CA_REQUIRES_EAB}" = "true" ]]; then
@@ -1066,13 +1018,13 @@ signed_request() {
# Extracts all subject names from a CSR # Extracts all subject names from a CSR
# Outputs either the CN, or the SANs, one per line # Outputs either the CN, or the SANs, one per line
extract_altnames() { extract_altnames() {
csrfile="${1}" # path to CSR file csr="${1}" # the CSR itself (not a file)
if ! "${OPENSSL}" req -in "${csrfile}" -verify -noout >/dev/null; then if ! <<<"${csr}" "${OPENSSL}" req -verify -noout >/dev/null 2>&1; then
_exiterr "Certificate signing request isn't valid" _exiterr "Certificate signing request isn't valid"
fi fi
reqtext="$("${OPENSSL}" req -in "${csrfile}" -noout -text)" reqtext="$( <<<"${csr}" "${OPENSSL}" req -noout -text )"
if <<<"${reqtext}" grep -q '^[[:space:]]*X509v3 Subject Alternative Name:[[:space:]]*$'; then if <<<"${reqtext}" grep -q '^[[:space:]]*X509v3 Subject Alternative Name:[[:space:]]*$'; then
# SANs used, extract these # SANs used, extract these
altnames="$( <<<"${reqtext}" awk '/X509v3 Subject Alternative Name:/{print;getline;print;}' | tail -n1 )" altnames="$( <<<"${reqtext}" awk '/X509v3 Subject Alternative Name:/{print;getline;print;}' | tail -n1 )"
@@ -1100,7 +1052,7 @@ get_last_cn() {
# Create certificate for domain(s) and outputs it FD 3 # Create certificate for domain(s) and outputs it FD 3
sign_csr() { sign_csr() {
csrfile="${1}" # path to CSR file csr="${1}" # the CSR itself (not a file)
if { true >&3; } 2>/dev/null; then if { true >&3; } 2>/dev/null; then
: # fd 3 looks OK : # fd 3 looks OK
@@ -1139,12 +1091,7 @@ sign_csr() {
challenge_identifiers="[${challenge_identifiers%, }]" challenge_identifiers="[${challenge_identifiers%, }]"
echo " + Requesting new certificate order from CA..." echo " + Requesting new certificate order from CA..."
local order_payload='{"identifiers": '"${challenge_identifiers}" order_location="$(signed_request "${CA_NEW_ORDER}" '{"identifiers": '"${challenge_identifiers}"'}' 4>&1 | grep -i ^Location: | cut -d':' -f2- | tr -d ' \t\r\n')"
if [[ -n "${ACME_PROFILE}" ]]; then
order_payload="${order_payload}"',"profile":"'"${ACME_PROFILE}"'"'
fi
order_payload="${order_payload}"'}'
order_location="$(signed_request "${CA_NEW_ORDER}" "${order_payload}" 4>&1 | grep -i ^Location: | cut -d':' -f2- | tr -d ' \t\r\n')"
result="$(signed_request "${order_location}" "" | jsonsh)" result="$(signed_request "${order_location}" "" | jsonsh)"
order_authorizations="$(echo "${result}" | get_json_array_values authorizations)" order_authorizations="$(echo "${result}" | get_json_array_values authorizations)"
@@ -1330,30 +1277,25 @@ sign_csr() {
# Finally request certificate from the acme-server and store it in cert-${timestamp}.pem and link from cert.pem # Finally request certificate from the acme-server and store it in cert-${timestamp}.pem and link from cert.pem
echo " + Requesting certificate..." echo " + Requesting certificate..."
csr64="$("${OPENSSL}" req -in "${csrfile}" -config "${OPENSSL_CNF}" -outform DER | urlbase64)" csr64="$( <<<"${csr}" "${OPENSSL}" req -config "${OPENSSL_CNF}" -outform DER | urlbase64)"
if [[ ${API} -eq 1 ]]; then if [[ ${API} -eq 1 ]]; then
crt64="$(signed_request "${CA_NEW_CERT}" '{"resource": "new-cert", "csr": "'"${csr64}"'"}' | "${OPENSSL}" base64 -e)" crt64="$(signed_request "${CA_NEW_CERT}" '{"resource": "new-cert", "csr": "'"${csr64}"'"}' | "${OPENSSL}" base64 -e)"
crt="$( printf -- '-----BEGIN CERTIFICATE-----\n%s\n-----END CERTIFICATE-----\n' "${crt64}" )" crt="$( printf -- '-----BEGIN CERTIFICATE-----\n%s\n-----END CERTIFICATE-----\n' "${crt64}" )"
else else
result="$(signed_request "${finalize}" '{"csr": "'"${csr64}"'"}' | jsonsh)" result="$(signed_request "${finalize}" '{"csr": "'"${csr64}"'"}' | jsonsh)"
waited=0
while :; do while :; do
orderstatus="$(echo "${result}" | get_json_string_value status)" orderstatus="$(echo "${result}" | get_json_string_value status)"
case "${orderstatus}" case "${orderstatus}"
in in
"processing" | "pending") "processing" | "pending")
if [ ${ORDER_TIMEOUT} -gt 0 ] && [ ${waited} -gt ${ORDER_TIMEOUT} ]; then
_exiterr "Timed out waiting for processing of order (still ${orderstatus})"
fi
echo " + Order is ${orderstatus}..." echo " + Order is ${orderstatus}..."
sleep 2; sleep 2;
waited=$((waited+2))
;; ;;
"valid") "valid")
break; break;
;; ;;
*) *)
_exiterr "Order has invalid/unknown status: ${orderstatus}" _exiterr "Order in status ${orderstatus}"
;; ;;
esac esac
result="$(signed_request "${order_location}" "" | jsonsh)" result="$(signed_request "${order_location}" "" | jsonsh)"
@@ -1577,7 +1519,7 @@ sign_domain() {
crt_path="${certdir}/cert-${timestamp}.pem" crt_path="${certdir}/cert-${timestamp}.pem"
# shellcheck disable=SC2086 # shellcheck disable=SC2086
sign_csr "${certdir}/cert-${timestamp}.csr" ${altnames} 3>"${crt_path}" sign_csr "$(< "${certdir}/cert-${timestamp}.csr")" ${altnames} 3>"${crt_path}"
# Create fullchain.pem # Create fullchain.pem
echo " + Creating fullchain.pem..." echo " + Creating fullchain.pem..."
@@ -1842,7 +1784,7 @@ command_sign_domains() {
# All settings that are allowed here should also be stored and # All settings that are allowed here should also be stored and
# restored in store_configvars() and reset_configvars() # restored in store_configvars() and reset_configvars()
case "${config_var}" in case "${config_var}" in
KEY_ALGO|OCSP_MUST_STAPLE|OCSP_FETCH|OCSP_DAYS|PRIVATE_KEY_RENEW|PRIVATE_KEY_ROLLOVER|KEYSIZE|CHALLENGETYPE|HOOK|PREFERRED_CHAIN|WELLKNOWN|HOOK_CHAIN|OPENSSL_CNF|RENEW_DAYS|ACME_PROFILE|ORDER_TIMEOUT) KEY_ALGO|OCSP_MUST_STAPLE|OCSP_FETCH|OCSP_DAYS|PRIVATE_KEY_RENEW|PRIVATE_KEY_ROLLOVER|KEYSIZE|CHALLENGETYPE|HOOK|PREFERRED_CHAIN|WELLKNOWN|HOOK_CHAIN|OPENSSL_CNF|RENEW_DAYS)
echo " + ${config_var} = ${config_value}" echo " + ${config_var} = ${config_value}"
declare -- "${config_var}=${config_value}" declare -- "${config_var}=${config_value}"
;; ;;
@@ -1859,18 +1801,16 @@ command_sign_domains() {
skip="no" skip="no"
# Allow for external CSR generation # Allow for external CSR generation
local csrfile="" local csr=""
if [[ -n "${HOOK}" ]]; then if [[ -n "${HOOK}" ]]; then
csr="$("${HOOK}" "generate_csr" "${domain}" "${certdir}" "${domain} ${morenames}")" || _exiterr 'generate_csr hook returned with non-zero exit code' csr="$("${HOOK}" "generate_csr" "${domain}" "${certdir}" "${domain} ${morenames}")" || _exiterr 'generate_csr hook returned with non-zero exit code'
if grep -qE "\-----BEGIN (NEW )?CERTIFICATE REQUEST-----" <<< "${csr}"; then if grep -qE "\-----BEGIN (NEW )?CERTIFICATE REQUEST-----" <<< "${csr}"; then
csrfile="$(_mktemp)" altnames="$(extract_altnames "${csr}")"
cat > "${csrfile}" <<< "${csr}"
altnames="$(extract_altnames "${csrfile}")"
domain="$(cut -d' ' -f1 <<< "${altnames}")" domain="$(cut -d' ' -f1 <<< "${altnames}")"
morenames="$(cut -s -d' ' -f2- <<< "${altnames}")" morenames="$(cut -s -d' ' -f2- <<< "${altnames}")"
echo " + Using CSR from hook script (real names: ${altnames})" echo " + Using CSR from hook script (real names: ${altnames})"
else else
csrfile="" csr=""
fi fi
fi fi
@@ -1920,10 +1860,7 @@ command_sign_domains() {
# Sign certificate for this domain # Sign certificate for this domain
if [[ ! "${skip}" = "yes" ]]; then if [[ ! "${skip}" = "yes" ]]; then
update_ocsp="yes" update_ocsp="yes"
if [[ -n "${csrfile}" ]]; then [[ -z "${csr}" ]] || printf "%s" "${csr}" > "${certdir}/cert-${timestamp}.csr"
cat "${csrfile}" > "${certdir}/cert-${timestamp}.csr"
rm "${csrfile}"
fi
# shellcheck disable=SC2086 # shellcheck disable=SC2086
if [[ "${PARAM_KEEP_GOING:-}" = "yes" ]]; then if [[ "${PARAM_KEEP_GOING:-}" = "yes" ]]; then
skip_exit_hook=yes skip_exit_hook=yes
@@ -1967,8 +1904,8 @@ command_sign_domains() {
[[ -n "${HOOK}" ]] && ("${HOOK}" "exit_hook" || echo 'exit_hook returned with non-zero exit code!' >&2) [[ -n "${HOOK}" ]] && ("${HOOK}" "exit_hook" || echo 'exit_hook returned with non-zero exit code!' >&2)
if [[ "${AUTO_CLEANUP}" == "yes" ]]; then if [[ "${AUTO_CLEANUP}" == "yes" ]]; then
echo " + Running automatic cleanup" echo "+ Running automatic cleanup"
PARAM_CLEANUPDELETE="${AUTO_CLEANUP_DELETE:-no}" command_cleanup noinit | _sed 's/^/ + /g' command_cleanup noinit
fi fi
exit "${exit_with_errorcode}" exit "${exit_with_errorcode}"
@@ -1984,18 +1921,19 @@ command_sign_csr() {
exec 3>&1 1>&2 exec 3>&1 1>&2
# load csr # load csr
local csrfile="${1}" csrfile="${1}"
if [ ! -r "${csrfile}" ]; then if [ ! -r "${csrfile}" ]; then
_exiterr "Could not read certificate signing request ${csrfile}" _exiterr "Could not read certificate signing request ${csrfile}"
fi fi
csr="$(cat "${csrfile}")"
# extract names # extract names
altnames="$(extract_altnames "${csrfile}")" altnames="$(extract_altnames "${csr}")"
# gen cert # gen cert
certfile="$(_mktemp)" certfile="$(_mktemp)"
# shellcheck disable=SC2086 # shellcheck disable=SC2086
sign_csr "${csrfile}" ${altnames} 3> "${certfile}" sign_csr "${csr}" ${altnames} 3> "${certfile}"
# print cert # print cert
echo "# CERT #" >&3 echo "# CERT #" >&3
@@ -2435,23 +2373,6 @@ main() {
check_parameters "${1:-}" check_parameters "${1:-}"
PARAM_KEY_ALGO="${1}" PARAM_KEY_ALGO="${1}"
;; ;;
# PARAM_Usage: --acme-profile profile_name
# PARAM_Description: Use specified ACME profile
--acme-profile)
shift 1
check_parameters "${1:-}"
PARAM_ACME_PROFILE="${1}"
;;
# PARAM_Usage: --order-timeout seconds
# PARAM_Description: Amount of seconds to wait for processing of order until erroring out
--order-timeout)
shift 1
check_parameters "${1:-}"
PARAM_ORDER_TIMEOUT=${1}
;;
*) *)
echo "Unknown parameter detected: ${1}" >&2 echo "Unknown parameter detected: ${1}" >&2
echo >&2 echo >&2

View File

@@ -16,13 +16,16 @@
# Which group should dehydrated run as? This will be implicitly enforced when running as root # Which group should dehydrated run as? This will be implicitly enforced when running as root
#DEHYDRATED_GROUP= #DEHYDRATED_GROUP=
# Should dehydrated pass environment variables over sudo?
#DEHYDRATED_SUDO_ENV="no"
# Resolve names to addresses of IP version only. (curl) # Resolve names to addresses of IP version only. (curl)
# supported values: 4, 6 # supported values: 4, 6
# default: <unset> # default: <unset>
#IP_VERSION= #IP_VERSION=
# URL to certificate authority or internal preset # URL to certificate authority or internal preset
# Presets: letsencrypt, letsencrypt-test, zerossl, buypass, buypass-test, google, google-test # Presets: letsencrypt, letsencrypt-test, zerossl, buypass, buypass-test
# default: letsencrypt # default: letsencrypt
#CA="letsencrypt" #CA="letsencrypt"
@@ -92,8 +95,8 @@
# Chain clean_challenge|deploy_challenge arguments together into one hook call per certificate (default: no) # Chain clean_challenge|deploy_challenge arguments together into one hook call per certificate (default: no)
#HOOK_CHAIN="no" #HOOK_CHAIN="no"
# Minimum days before expiration to automatically renew certificate (default: 32) # Minimum days before expiration to automatically renew certificate (default: 30)
#RENEW_DAYS="32" #RENEW_DAYS="30"
# Regenerate private keys instead of just signing new certificates on renewal (default: yes) # Regenerate private keys instead of just signing new certificates on renewal (default: yes)
#PRIVATE_KEY_RENEW="yes" #PRIVATE_KEY_RENEW="yes"
@@ -125,17 +128,8 @@
# Automatic cleanup (default: no) # Automatic cleanup (default: no)
#AUTO_CLEANUP="no" #AUTO_CLEANUP="no"
# Delete files during automatic cleanup instead of moving to archive (default: no)
#AUTO_CLEANUP_DELETE="no"
# ACME API version (default: auto) # ACME API version (default: auto)
#API=auto #API=auto
# Preferred issuer chain (default: <unset> -> uses default chain) # Preferred issuer chain (default: <unset> -> uses default chain)
#PREFERRED_CHAIN= #PREFERRED_CHAIN=
# Request certificate with specific profile (default: <unset>)
#ACME_PROFILE=
# Amount of seconds to wait for processing of order until erroring out (default: 0 => no timeout)
#ORDER_TIMEOUT=0

View File

@@ -139,7 +139,7 @@ secp384r1
The program exits 0 if everything was fine, 1 if an error occurred. The program exits 0 if everything was fine, 1 if an error occurred.
.SH BUGS .SH BUGS
Please report any bugs that you may encounter at the project web site Please report any bugs that you may encounter at the project web site
.UR https://github.com/dehydrated-io/dehydrated/issues .UR https://github.com/lukas2511/dehydrated/issues
.UE . .UE .
.SH AUTHOR .SH AUTHOR
Dehydrated was written by Lukas Schauer. This man page was contributed by Dehydrated was written by Lukas Schauer. This man page was contributed by
@@ -151,5 +151,5 @@ distribution for licensing information.
.SH SEE ALSO .SH SEE ALSO
Full documentation along with configuration examples are provided in the \fIdocs\fR Full documentation along with configuration examples are provided in the \fIdocs\fR
directory of the distribution, or at directory of the distribution, or at
.UR https://github.com/dehydrated-io/dehydrated/tree/master/docs .UR https://github.com/lukas2511/dehydrated/tree/master/docs
.UE . .UE .