mirror of
https://github.com/dehydrated-io/dehydrated.git
synced 2026-04-27 10:47:03 +02:00
Make certificate output location configurable (#210)
This commit is contained in:
committed by
Lukas Schauer
parent
d5b285868e
commit
785ffa5539
@@ -46,6 +46,7 @@ Parameters:
|
|||||||
--privkey (-p) path/to/key.pem Use specified private key instead of account key (useful for revocation)
|
--privkey (-p) path/to/key.pem Use specified private key instead of account key (useful for revocation)
|
||||||
--config (-f) path/to/config Use specified config file
|
--config (-f) path/to/config Use specified config file
|
||||||
--hook (-k) path/to/hook.sh Use specified script for hooks
|
--hook (-k) path/to/hook.sh Use specified script for hooks
|
||||||
|
--out (-o) certs/directory Output certificates into the specified directory
|
||||||
--challenge (-t) http-01|dns-01 Which challenge should be used? Currently http-01 and dns-01 are supported
|
--challenge (-t) http-01|dns-01 Which challenge should be used? Currently http-01 and dns-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
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -31,6 +31,9 @@
|
|||||||
# File containing the list of domains to request certificates for (default: $BASEDIR/domains.txt)
|
# File containing the list of domains to request certificates for (default: $BASEDIR/domains.txt)
|
||||||
#DOMAINS_TXT="${BASEDIR}/domains.txt"
|
#DOMAINS_TXT="${BASEDIR}/domains.txt"
|
||||||
|
|
||||||
|
# Output directory for generated certificates
|
||||||
|
#CERTDIR="${BASEDIR}/certs"
|
||||||
|
|
||||||
# Output directory for challenge-tokens to be served by webserver or deployed in HOOK (default: $BASEDIR/.acme-challenges)
|
# Output directory for challenge-tokens to be served by webserver or deployed in HOOK (default: $BASEDIR/.acme-challenges)
|
||||||
#WELLKNOWN="${BASEDIR}/.acme-challenges"
|
#WELLKNOWN="${BASEDIR}/.acme-challenges"
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ load_config() {
|
|||||||
# Default values
|
# Default values
|
||||||
CA="https://acme-v01.api.letsencrypt.org/directory"
|
CA="https://acme-v01.api.letsencrypt.org/directory"
|
||||||
LICENSE="https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf"
|
LICENSE="https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf"
|
||||||
|
CERTDIR=
|
||||||
CHALLENGETYPE="http-01"
|
CHALLENGETYPE="http-01"
|
||||||
CONFIG_D=
|
CONFIG_D=
|
||||||
DOMAINS_TXT=
|
DOMAINS_TXT=
|
||||||
@@ -118,11 +119,13 @@ load_config() {
|
|||||||
|
|
||||||
[[ -z "${ACCOUNT_KEY}" ]] && ACCOUNT_KEY="${BASEDIR}/private_key.pem"
|
[[ -z "${ACCOUNT_KEY}" ]] && ACCOUNT_KEY="${BASEDIR}/private_key.pem"
|
||||||
[[ -z "${ACCOUNT_KEY_JSON}" ]] && ACCOUNT_KEY_JSON="${BASEDIR}/private_key.json"
|
[[ -z "${ACCOUNT_KEY_JSON}" ]] && ACCOUNT_KEY_JSON="${BASEDIR}/private_key.json"
|
||||||
|
[[ -z "${CERTDIR}" ]] && CERTDIR="${BASEDIR}/certs"
|
||||||
[[ -z "${DOMAINS_TXT}" ]] && DOMAINS_TXT="${BASEDIR}/domains.txt"
|
[[ -z "${DOMAINS_TXT}" ]] && DOMAINS_TXT="${BASEDIR}/domains.txt"
|
||||||
[[ -z "${WELLKNOWN}" ]] && WELLKNOWN="${BASEDIR}/.acme-challenges"
|
[[ -z "${WELLKNOWN}" ]] && WELLKNOWN="${BASEDIR}/.acme-challenges"
|
||||||
[[ -z "${LOCKFILE}" ]] && LOCKFILE="${BASEDIR}/lock"
|
[[ -z "${LOCKFILE}" ]] && LOCKFILE="${BASEDIR}/lock"
|
||||||
|
|
||||||
[[ -n "${PARAM_HOOK:-}" ]] && HOOK="${PARAM_HOOK}"
|
[[ -n "${PARAM_HOOK:-}" ]] && HOOK="${PARAM_HOOK}"
|
||||||
|
[[ -n "${PARAM_CERTDIR:-}" ]] && CERTDIR="${PARAM_CERTDIR}"
|
||||||
[[ -n "${PARAM_CHALLENGETYPE:-}" ]] && CHALLENGETYPE="${PARAM_CHALLENGETYPE}"
|
[[ -n "${PARAM_CHALLENGETYPE:-}" ]] && CHALLENGETYPE="${PARAM_CHALLENGETYPE}"
|
||||||
[[ -n "${PARAM_KEY_ALGO:-}" ]] && KEY_ALGO="${PARAM_KEY_ALGO}"
|
[[ -n "${PARAM_KEY_ALGO:-}" ]] && KEY_ALGO="${PARAM_KEY_ALGO}"
|
||||||
|
|
||||||
@@ -154,7 +157,7 @@ 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."
|
||||||
|
|
||||||
# Export some environment variables to be used in hook script
|
# Export some environment variables to be used in hook script
|
||||||
export WELLKNOWN BASEDIR CONFIG
|
export WELLKNOWN BASEDIR CERTDIR CONFIG
|
||||||
|
|
||||||
# Checking for private key ...
|
# Checking for private key ...
|
||||||
register_new_key="no"
|
register_new_key="no"
|
||||||
@@ -505,19 +508,19 @@ sign_domain() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# If there is no existing certificate directory => make it
|
# If there is no existing certificate directory => make it
|
||||||
if [[ ! -e "${BASEDIR}/certs/${domain}" ]]; then
|
if [[ ! -e "${CERTDIR}/${domain}" ]]; then
|
||||||
echo " + Creating new directory ${BASEDIR}/certs/${domain} ..."
|
echo " + Creating new directory ${CERTDIR}/${domain} ..."
|
||||||
mkdir -p "${BASEDIR}/certs/${domain}"
|
mkdir -p "${CERTDIR}/${domain}" || _exiterr "Unable to create directory ${CERTDIR}/${domain}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
privkey="privkey.pem"
|
privkey="privkey.pem"
|
||||||
# generate a new private key if we need or want one
|
# generate a new private key if we need or want one
|
||||||
if [[ ! -r "${BASEDIR}/certs/${domain}/privkey.pem" ]] || [[ "${PRIVATE_KEY_RENEW}" = "yes" ]]; then
|
if [[ ! -r "${CERTDIR}/${domain}/privkey.pem" ]] || [[ "${PRIVATE_KEY_RENEW}" = "yes" ]]; then
|
||||||
echo " + Generating private key..."
|
echo " + Generating private key..."
|
||||||
privkey="privkey-${timestamp}.pem"
|
privkey="privkey-${timestamp}.pem"
|
||||||
case "${KEY_ALGO}" in
|
case "${KEY_ALGO}" in
|
||||||
rsa) _openssl genrsa -out "${BASEDIR}/certs/${domain}/privkey-${timestamp}.pem" "${KEYSIZE}";;
|
rsa) _openssl genrsa -out "${CERTDIR}/${domain}/privkey-${timestamp}.pem" "${KEYSIZE}";;
|
||||||
prime256v1|secp384r1) _openssl ecparam -genkey -name "${KEY_ALGO}" -out "${BASEDIR}/certs/${domain}/privkey-${timestamp}.pem";;
|
prime256v1|secp384r1) _openssl ecparam -genkey -name "${KEY_ALGO}" -out "${CERTDIR}/${domain}/privkey-${timestamp}.pem";;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -532,33 +535,33 @@ sign_domain() {
|
|||||||
tmp_openssl_cnf="$(_mktemp)"
|
tmp_openssl_cnf="$(_mktemp)"
|
||||||
cat "${OPENSSL_CNF}" > "${tmp_openssl_cnf}"
|
cat "${OPENSSL_CNF}" > "${tmp_openssl_cnf}"
|
||||||
printf "[SAN]\nsubjectAltName=%s" "${SAN}" >> "${tmp_openssl_cnf}"
|
printf "[SAN]\nsubjectAltName=%s" "${SAN}" >> "${tmp_openssl_cnf}"
|
||||||
openssl req -new -sha256 -key "${BASEDIR}/certs/${domain}/${privkey}" -out "${BASEDIR}/certs/${domain}/cert-${timestamp}.csr" -subj "/CN=${domain}/" -reqexts SAN -config "${tmp_openssl_cnf}"
|
openssl req -new -sha256 -key "${CERTDIR}/${domain}/${privkey}" -out "${CERTDIR}/${domain}/cert-${timestamp}.csr" -subj "/CN=${domain}/" -reqexts SAN -config "${tmp_openssl_cnf}"
|
||||||
rm -f "${tmp_openssl_cnf}"
|
rm -f "${tmp_openssl_cnf}"
|
||||||
|
|
||||||
crt_path="${BASEDIR}/certs/${domain}/cert-${timestamp}.pem"
|
crt_path="${CERTDIR}/${domain}/cert-${timestamp}.pem"
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
sign_csr "$(< "${BASEDIR}/certs/${domain}/cert-${timestamp}.csr" )" ${altnames} 3>"${crt_path}"
|
sign_csr "$(< "${CERTDIR}/${domain}/cert-${timestamp}.csr" )" ${altnames} 3>"${crt_path}"
|
||||||
|
|
||||||
# Create fullchain.pem
|
# Create fullchain.pem
|
||||||
echo " + Creating fullchain.pem..."
|
echo " + Creating fullchain.pem..."
|
||||||
cat "${crt_path}" > "${BASEDIR}/certs/${domain}/fullchain-${timestamp}.pem"
|
cat "${crt_path}" > "${CERTDIR}/${domain}/fullchain-${timestamp}.pem"
|
||||||
http_request get "$(openssl x509 -in "${BASEDIR}/certs/${domain}/cert-${timestamp}.pem" -noout -text | grep 'CA Issuers - URI:' | cut -d':' -f2-)" > "${BASEDIR}/certs/${domain}/chain-${timestamp}.pem"
|
http_request get "$(openssl x509 -in "${CERTDIR}/${domain}/cert-${timestamp}.pem" -noout -text | grep 'CA Issuers - URI:' | cut -d':' -f2-)" > "${CERTDIR}/${domain}/chain-${timestamp}.pem"
|
||||||
if ! grep -q "BEGIN CERTIFICATE" "${BASEDIR}/certs/${domain}/chain-${timestamp}.pem"; then
|
if ! grep -q "BEGIN CERTIFICATE" "${CERTDIR}/${domain}/chain-${timestamp}.pem"; then
|
||||||
openssl x509 -in "${BASEDIR}/certs/${domain}/chain-${timestamp}.pem" -inform DER -out "${BASEDIR}/certs/${domain}/chain-${timestamp}.pem" -outform PEM
|
openssl x509 -in "${CERTDIR}/${domain}/chain-${timestamp}.pem" -inform DER -out "${CERTDIR}/${domain}/chain-${timestamp}.pem" -outform PEM
|
||||||
fi
|
fi
|
||||||
cat "${BASEDIR}/certs/${domain}/chain-${timestamp}.pem" >> "${BASEDIR}/certs/${domain}/fullchain-${timestamp}.pem"
|
cat "${CERTDIR}/${domain}/chain-${timestamp}.pem" >> "${CERTDIR}/${domain}/fullchain-${timestamp}.pem"
|
||||||
|
|
||||||
# Update symlinks
|
# Update symlinks
|
||||||
[[ "${privkey}" = "privkey.pem" ]] || ln -sf "privkey-${timestamp}.pem" "${BASEDIR}/certs/${domain}/privkey.pem"
|
[[ "${privkey}" = "privkey.pem" ]] || ln -sf "privkey-${timestamp}.pem" "${CERTDIR}/${domain}/privkey.pem"
|
||||||
|
|
||||||
ln -sf "chain-${timestamp}.pem" "${BASEDIR}/certs/${domain}/chain.pem"
|
ln -sf "chain-${timestamp}.pem" "${CERTDIR}/${domain}/chain.pem"
|
||||||
ln -sf "fullchain-${timestamp}.pem" "${BASEDIR}/certs/${domain}/fullchain.pem"
|
ln -sf "fullchain-${timestamp}.pem" "${CERTDIR}/${domain}/fullchain.pem"
|
||||||
ln -sf "cert-${timestamp}.csr" "${BASEDIR}/certs/${domain}/cert.csr"
|
ln -sf "cert-${timestamp}.csr" "${CERTDIR}/${domain}/cert.csr"
|
||||||
ln -sf "cert-${timestamp}.pem" "${BASEDIR}/certs/${domain}/cert.pem"
|
ln -sf "cert-${timestamp}.pem" "${CERTDIR}/${domain}/cert.pem"
|
||||||
|
|
||||||
# Wait for hook script to clean the challenge and to deploy cert if used
|
# Wait for hook script to clean the challenge and to deploy cert if used
|
||||||
export KEY_ALGO
|
export KEY_ALGO
|
||||||
[[ -n "${HOOK}" ]] && "${HOOK}" "deploy_cert" "${domain}" "${BASEDIR}/certs/${domain}/privkey.pem" "${BASEDIR}/certs/${domain}/cert.pem" "${BASEDIR}/certs/${domain}/fullchain.pem" "${BASEDIR}/certs/${domain}/chain.pem" "${timestamp}"
|
[[ -n "${HOOK}" ]] && "${HOOK}" "deploy_cert" "${domain}" "${CERTDIR}/${domain}/privkey.pem" "${CERTDIR}/${domain}/cert.pem" "${CERTDIR}/${domain}/fullchain.pem" "${CERTDIR}/${domain}/chain.pem" "${timestamp}"
|
||||||
|
|
||||||
unset challenge_token
|
unset challenge_token
|
||||||
echo " + Done!"
|
echo " + Done!"
|
||||||
@@ -587,7 +590,7 @@ command_sign_domains() {
|
|||||||
IFS="${ORIGIFS}"
|
IFS="${ORIGIFS}"
|
||||||
domain="$(printf '%s\n' "${line}" | cut -d' ' -f1)"
|
domain="$(printf '%s\n' "${line}" | cut -d' ' -f1)"
|
||||||
morenames="$(printf '%s\n' "${line}" | cut -s -d' ' -f2-)"
|
morenames="$(printf '%s\n' "${line}" | cut -s -d' ' -f2-)"
|
||||||
cert="${BASEDIR}/certs/${domain}/cert.pem"
|
cert="${CERTDIR}/${domain}/cert.pem"
|
||||||
|
|
||||||
force_renew="${PARAM_FORCE:-no}"
|
force_renew="${PARAM_FORCE:-no}"
|
||||||
|
|
||||||
@@ -627,7 +630,7 @@ command_sign_domains() {
|
|||||||
else
|
else
|
||||||
# Certificate-Names unchanged and cert is still valid
|
# Certificate-Names unchanged and cert is still valid
|
||||||
echo "Skipping renew!"
|
echo "Skipping renew!"
|
||||||
[[ -n "${HOOK}" ]] && "${HOOK}" "unchanged_cert" "${domain}" "${BASEDIR}/certs/${domain}/privkey.pem" "${BASEDIR}/certs/${domain}/cert.pem" "${BASEDIR}/certs/${domain}/fullchain.pem" "${BASEDIR}/certs/${domain}/chain.pem"
|
[[ -n "${HOOK}" ]] && "${HOOK}" "unchanged_cert" "${domain}" "${CERTDIR}/${domain}/privkey.pem" "${CERTDIR}/${domain}/cert.pem" "${CERTDIR}/${domain}/fullchain.pem" "${CERTDIR}/${domain}/chain.pem"
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
@@ -706,7 +709,7 @@ command_cleanup() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Loop over all certificate directories
|
# Loop over all certificate directories
|
||||||
for certdir in "${BASEDIR}/certs/"*; do
|
for certdir in "${CERTDIR}/"*; do
|
||||||
# Skip if entry is not a folder
|
# Skip if entry is not a folder
|
||||||
[[ -d "${certdir}" ]] || continue
|
[[ -d "${certdir}" ]] || continue
|
||||||
|
|
||||||
@@ -775,7 +778,7 @@ command_help() {
|
|||||||
command_env() {
|
command_env() {
|
||||||
echo "# letsencrypt.sh configuration"
|
echo "# letsencrypt.sh configuration"
|
||||||
load_config
|
load_config
|
||||||
typeset -p CA LICENSE CHALLENGETYPE DOMAINS_TXT HOOK HOOK_CHAIN RENEW_DAYS ACCOUNT_KEY ACCOUNT_KEY_JSON KEYSIZE WELLKNOWN PRIVATE_KEY_RENEW OPENSSL_CNF CONTACT_EMAIL LOCKFILE
|
typeset -p CA LICENSE CERTDIR CHALLENGETYPE DOMAINS_TXT HOOK HOOK_CHAIN RENEW_DAYS ACCOUNT_KEY ACCOUNT_KEY_JSON KEYSIZE WELLKNOWN PRIVATE_KEY_RENEW OPENSSL_CNF CONTACT_EMAIL LOCKFILE
|
||||||
}
|
}
|
||||||
|
|
||||||
# Main method (parses script arguments and calls command_* methods)
|
# Main method (parses script arguments and calls command_* methods)
|
||||||
@@ -875,6 +878,14 @@ main() {
|
|||||||
PARAM_HOOK="${1}"
|
PARAM_HOOK="${1}"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
# PARAM_Usage: --out (-o) certs/directory
|
||||||
|
# PARAM_Description: Output certificates into the specified directory
|
||||||
|
--out|-o)
|
||||||
|
shift 1
|
||||||
|
check_parameters "${1:-}"
|
||||||
|
PARAM_CERTDIR="${1}"
|
||||||
|
;;
|
||||||
|
|
||||||
# PARAM_Usage: --challenge (-t) http-01|dns-01
|
# PARAM_Usage: --challenge (-t) http-01|dns-01
|
||||||
# PARAM_Description: Which challenge should be used? Currently http-01 and dns-01 are supported
|
# PARAM_Description: Which challenge should be used? Currently http-01 and dns-01 are supported
|
||||||
--challenge|-t)
|
--challenge|-t)
|
||||||
|
|||||||
Reference in New Issue
Block a user