Build chain and fullchain using local root CA and ACME intermediates

This commit is contained in:
2026-03-29 11:17:30 +02:00
parent fc9e5dfd67
commit 85959c25f7
+135 -80
View File
@@ -62,9 +62,9 @@
# Outputs text to stdout. # Outputs text to stdout.
_usage() { _usage() {
_log "Enter the function '_usage()'..." 1 _log "Enter the function '_usage()'..." 1
# command help: # command help:
# init-pki # init-pki
# update [ cmd-opts ] # update [ cmd-opts ]
# gen-req <filename_base> [ cmd-opts ] # gen-req <filename_base> [ cmd-opts ]
@@ -225,17 +225,17 @@ notice() {
# SDuesterhaupt: 2025-09-14 - Create a secure temporary file/directory # SDuesterhaupt: 2025-09-14 - Create a secure temporary file/directory
# #
# Wrapper for mktemp to create temporary files or directories in the session temp directory. # Wrapper for mktemp to create temporary files or directories in the session temp directory.
# Ensures that DYNTLS_TEMP_DIR_session is initialized and usable. # Ensures that DYNTLS_LE_TMP_DIR_session is initialized and usable.
# #
# No parameters. # No parameters.
# Outputs path of created temporary file/directory to stdout. # Outputs path of created temporary file/directory to stdout.
# Returns 0 on success or 1 on failure. # Returns 0 on success or 1 on failure.
dyntls_mktemp() { dyntls_mktemp() {
[ -n "$DYNTLS_TEMP_DIR_session" ] || _die "DYNTLS_TEMP_DIR_session not initialized!" 1 [ -n "$DYNTLS_LE_TMP_DIR_session" ] || _die "DYNTLS_LE_TMP_DIR_session not initialized!" 5
[ -d "$DYNTLS_TEMP_DIR_session" ] || mkdir -p "$DYNTLS_TEMP_DIR_session" \ [ -d "$DYNTLS_LE_TMP_DIR_session" ] || mkdir -p "$DYNTLS_LE_TMP_DIR_session" \
|| _die "Could not create temporary directory '$DYNTLS_TEMP_DIR_session'" 1 || _die "Could not create temporary directory '$DYNTLS_LE_TMP_DIR_session'" 5
template="$DYNTLS_TEMP_DIR_session/tmp.XXXXXX" template="$DYNTLS_LE_TMP_DIR_session/tmp.XXXXXX"
tempfile=$(mktemp "$template") || return 1 tempfile=$(mktemp "$template") || return 1
# Workaround für win32 mktemp # Workaround für win32 mktemp
@@ -257,7 +257,7 @@ dyntls_mktemp() {
# No parameters or output. # No parameters or output.
cleanup() { cleanup() {
# Entferne temporäres Sitzungsverzeichnis falls vorhanden # Entferne temporäres Sitzungsverzeichnis falls vorhanden
[ -n "$DYNTLS_TEMP_DIR_session" ] && rm -rf "$DYNTLS_TEMP_DIR_session" [ -n "$DYNTLS_LE_TMP_DIR_session" ] && rm -rf "$DYNTLS_LE_TMP_DIR_session"
# Terminal-Zustand wiederherstellen # Terminal-Zustand wiederherstellen
(stty echo 2>/dev/null) || { (set -o echo 2>/dev/null) && set -o echo; } (stty echo 2>/dev/null) || { (set -o echo 2>/dev/null) && set -o echo; }
@@ -278,12 +278,12 @@ cleanup() {
_vars_source_check() { _vars_source_check() {
_log "Enter the function '_vars_source_check()'..." 1 _log "Enter the function '_vars_source_check()'..." 1
[ -n "$DYNTLS_PKI" ] || _die "DYNTLS_PKI env-var undefined" 1 [ -n "$DYNTLS_PKI" ] || _die "DYNTLS_PKI env-var undefined" 5
[ -n "$DYNTLS_PKI_HTTP_DIR" ] || _die "DYNTLS_PKI_HTTP_DIR env-var undefined" 1 [ -n "$DYNTLS_PKI_HTTP_DIR" ] || _die "DYNTLS_PKI_HTTP_DIR env-var undefined" 5
[ -n "$DYNTLS_PKI_HTTP_CERT_DIR" ] || _die "DYNTLS_PKI_HTTP_CERT_DIR env-var undefined" 1 [ -n "$DYNTLS_PKI_HTTP_CERT_DIR" ] || _die "DYNTLS_PKI_HTTP_CERT_DIR env-var undefined" 5
[ -n "$DYNTLS_PKI_HTTP_KEY_DIR" ] || _die "DYNTLS_PKI_HTTP_KEY_DIR env-var undefined" 1 [ -n "$DYNTLS_PKI_HTTP_KEY_DIR" ] || _die "DYNTLS_PKI_HTTP_KEY_DIR env-var undefined" 5
[ -n "$DYNTLS_HTTPD_DEFAULT_DIR" ] || _die "DYNTLS_HTTPD_DEFAULT_DIR env-var undefined" 1 [ -n "$DYNTLS_HTTPD_DEFAULT_DIR" ] || _die "DYNTLS_HTTPD_DEFAULT_DIR env-var undefined" 5
[ -n "$DYNTLS_ENCRYPT_TOKEN_DIR" ] || _die "DYNTLS_ENCRYPT_TOKEN_DIR env-var undefined" 1 [ -n "$DYNTLS_ENCRYPT_TOKEN_DIR" ] || _die "DYNTLS_ENCRYPT_TOKEN_DIR env-var undefined" 5
_log "Leave the function '_vars_source_check()'..." 1 _log "Leave the function '_vars_source_check()'..." 1
@@ -305,13 +305,16 @@ _verify_pki_init() {
_vars_source_check _vars_source_check
[ -d "$DYNTLS_PKI" ] || _die "DYNTLS_PKI does not exist. $help_note" 1 [ -d "$DYNTLS_PKI" ] || _die "DYNTLS_PKI does not exist. $help_note" 5
[ -d "$DYNTLS_PKI_HTTP_DIR" ] || _die "DYNTLS_PKI_HTTP_DIR missing. $help_note" 1 [ -d "$DYNTLS_PKI_HTTP_DIR" ] || _die "DYNTLS_PKI_HTTP_DIR missing. $help_note" 5
[ -d "$DYNTLS_PKI_HTTP_CERT_DIR" ] || _die "DYNTLS_PKI_HTTP_CERT_DIR missing. $help_note" 1 [ -d "$DYNTLS_PKI_HTTP_CERT_DIR" ] || _die "DYNTLS_PKI_HTTP_CERT_DIR missing. $help_note" 5
[ -d "$DYNTLS_PKI_HTTP_KEY_DIR" ] || _die "DYNTLS_PKI_HTTP_KEY_DIR missing. $help_note" 1 [ -d "$DYNTLS_PKI_HTTP_KEY_DIR" ] || _die "DYNTLS_PKI_HTTP_KEY_DIR missing. $help_note" 5
[ -d "$DYNTLS_HTTPD_DEFAULT_DIR" ] || _die "DYNTLS_HTTPD_DEFAULT_DIR missing. $help_note" 1 [ -d "$DYNTLS_HTTPD_DEFAULT_DIR" ] || _die "DYNTLS_HTTPD_DEFAULT_DIR missing. $help_note" 5
[ -d "$DYNTLS_ENCRYPT_TOKEN_DIR" ] || _die "DYNTLS_ENCRYPT_TOKEN_DIR missing. $help_note" 1 [ -d "$DYNTLS_ENCRYPT_TOKEN_DIR" ] || _die "DYNTLS_ENCRYPT_TOKEN_DIR missing. $help_note" 5
[ -f "$DYNTLS_PKI_SERVER_BASEKEY" ] || _die "DYNTLS_PKI_SERVER_BASEKEY missing. $help_note" 1 [ -f "$DYNTLS_PKI_SERVER_BASEKEY" ] || _die "DYNTLS_PKI_SERVER_BASEKEY missing. $help_note" 5
[ -f "$DYNTLS_LE_CERT_DIR/$DYNTLS_LE_ROOT_CERT_FILE" ] \
|| _die "Root CA missing: $DYNTLS_LE_CERT_DIR/$DYNTLS_LE_ROOT_CERT_FILE. $help_note" 5
_log "Leave the function '_verify_pki_init()'..." 1 _log "Leave the function '_verify_pki_init()'..." 1
@@ -331,23 +334,42 @@ _init_pki() {
_log "Enter the function '_init_pki()'..." 1 _log "Enter the function '_init_pki()'..." 1
[ -d "$DYNTLS_PKI_HTTP_CERT_DIR" ] || mkdir -p "$DYNTLS_PKI_HTTP_CERT_DIR" \ [ -d "$DYNTLS_PKI_HTTP_CERT_DIR" ] || mkdir -p "$DYNTLS_PKI_HTTP_CERT_DIR" \
|| _die "Failed to create $DYNTLS_PKI_HTTP_CERT_DIR" 1 || _die "Failed to create $DYNTLS_PKI_HTTP_CERT_DIR" 5
[ -d "$DYNTLS_PKI_HTTP_KEY_DIR" ] || mkdir -p "$DYNTLS_PKI_HTTP_KEY_DIR" \ [ -d "$DYNTLS_PKI_HTTP_KEY_DIR" ] || mkdir -p "$DYNTLS_PKI_HTTP_KEY_DIR" \
|| _die "Failed to create $DYNTLS_PKI_HTTP_KEY_DIR" 1 || _die "Failed to create $DYNTLS_PKI_HTTP_KEY_DIR" 5
if [ ! -f "$DYNTLS_PKI_SERVER_BASEKEY" ] && [ "$DYNTLS_PKI_KEY_LNS" -ne 0 ]; then if [ ! -f "$DYNTLS_PKI_SERVER_BASEKEY" ] && [ "$DYNTLS_PKI_KEY_LNS" -ne 0 ]; then
_log "Create base server key, length $DYNTLS_PKI_KEY_SIZE bit" 1 _log "Create base server key, length $DYNTLS_PKI_KEY_SIZE bit" 1
#MyLEError=$(eval "$DYNTLS_OPENSSL genrsa -out $DYNTLS_PKI_SERVER_BASEKEY $DYNTLS_PKI_KEY_SIZE 2>&1") #MyLEError=$(eval "$DYNTLS_OPENSSL genrsa -out $DYNTLS_PKI_SERVER_BASEKEY $DYNTLS_PKI_KEY_SIZE 2>&1")
"$DYNTLS_OPENSSL" genrsa -out "$DYNTLS_PKI_SERVER_BASEKEY" "$DYNTLS_PKI_KEY_SIZE" 2>/dev/null \ "$DYNTLS_OPENSSL" genrsa -out "$DYNTLS_PKI_SERVER_BASEKEY" "$DYNTLS_PKI_KEY_SIZE" 2>/dev/null \
|| _die "Failed to generate base server key" 1 || _die "Failed to generate base server key" 5
fi fi
# Adjust the permission(s)
find "$DYNTLS_HTTPD_DEFAULT_DIR" -type d -exec chown "$DYNTLS_HTTPD_DEFAULT_OWNER" {} \; -exec chmod 755 {} \; find "$DYNTLS_HTTPD_DEFAULT_DIR" -type d -exec chown "$DYNTLS_HTTPD_DEFAULT_OWNER" {} \; -exec chmod 755 {} \;
find "$DYNTLS_PKI_HTTP_CERT_DIR" -type f -exec chmod 644 {} \; find "$DYNTLS_PKI_HTTP_CERT_DIR" -type f -exec chmod 644 {} \;
find "$DYNTLS_PKI_HTTP_KEY_DIR" -type f -exec chmod 440 {} \; find "$DYNTLS_PKI_HTTP_KEY_DIR" -type f -exec chmod 440 {} \;
[ -d "$DYNTLS_ENCRYPT_TOKEN_DIR" ] || mkdir -p "$DYNTLS_ENCRYPT_TOKEN_DIR" \ [ -d "$DYNTLS_ENCRYPT_TOKEN_DIR" ] || mkdir -p "$DYNTLS_ENCRYPT_TOKEN_DIR" \
|| _die "Failed to create $DYNTLS_ENCRYPT_TOKEN_DIR" 1 || _die "Failed to create $DYNTLS_ENCRYPT_TOKEN_DIR" 5
# Download Root Certificate(s)
[ -d "$DYNTLS_LE_CERT_DIR" ] || mkdir -p "$DYNTLS_LE_CERT_DIR" \
|| _die "Failed to create certs directory '$DYNTLS_LE_CERT_DIR'" 5
# Adjust the permission(s)
chmod 750 "$DYNTLS_LE_CERT_DIR"
if command -v wget >/dev/null 2>&1; then
_log "Download LE root from $DYNTLS_LE_ROOT_CERT_URL into $DYNTLS_LE_CERT_DIR" 1
if wget -q "$DYNTLS_LE_ROOT_CERT_URL" -O "$DYNTLS_LE_CERT_DIR/$DYNTLS_LE_ROOT_CERT_FILE"; then
chmod 400 "$DYNTLS_LE_CERT_DIR/$DYNTLS_LE_ROOT_CERT_FILE"
else
_die "Failed to download LE root cert" 5
fi
else
_die "wget not available" 5
fi
notice "init-pki complete; you may now create a certificate. notice "init-pki complete; you may now create a certificate.
Your PKI dirs are: $DYNTLS_PKI_HTTP_CERT_DIR, $DYNTLS_PKI_HTTP_KEY_DIR, $DYNTLS_ENCRYPT_TOKEN_DIR" Your PKI dirs are: $DYNTLS_PKI_HTTP_CERT_DIR, $DYNTLS_PKI_HTTP_KEY_DIR, $DYNTLS_ENCRYPT_TOKEN_DIR"
@@ -371,7 +393,7 @@ _init_log() {
if mkdir -p "$DYNTLS_LOG_DIR" 2>/dev/null; then if mkdir -p "$DYNTLS_LOG_DIR" 2>/dev/null; then
printf "Log directory '%s' created.\n" "$DYNTLS_LOG_DIR" printf "Log directory '%s' created.\n" "$DYNTLS_LOG_DIR"
else else
_die "Could not create log directory '$DYNTLS_LOG_DIR'" 1 _die "Could not create log directory '$DYNTLS_LOG_DIR'" 5
fi fi
fi fi
@@ -403,12 +425,15 @@ _vars_setup() {
. "$vars" . "$vars"
notice "Note: using dynTLS configuration from: $vars" notice "Note: using dynTLS configuration from: $vars"
fi fi
# Set defaults, preferring existing env-vars if present # Set defaults, preferring existing env-vars if present
set_var DYNTLS "$prog_dir" set_var DYNTLS "$prog_dir"
set_var DYNTLS_LE_CERT_DIR "$DYNTLS/certs"
set_var DYNTLS_LE_TMP_DIR "$DYNTLS/tmp"
set_var DYNTLS_LE_PROGRAM "letsencrypt_master.sh" set_var DYNTLS_LE_PROGRAM "letsencrypt_master.sh"
set_var DYNTLS_LE_ROOT_CERT_URL "https://letsencrypt.org/certs/isrgrootx1.pem"
set_var DYNTLS_LE_ROOT_CERT_FILE "isrgrootx1.pem"
set_var DYNTLS_OPENSSL openssl set_var DYNTLS_OPENSSL openssl
set_var DYNTLS_TMP "$DYNTLS/tmp"
#set_var DYNTLS_DN cn_only #set_var DYNTLS_DN cn_only
#set_var DYNTLS_REQ_COUNTRY "US" #set_var DYNTLS_REQ_COUNTRY "US"
#set_var DYNTLS_REQ_PROVINCE "California" #set_var DYNTLS_REQ_PROVINCE "California"
@@ -426,22 +451,23 @@ _vars_setup() {
set_var DYNTLS_PKI_HTTP_CERT_BACKUP_DIR "$DYNTLS_PKI_HTTP_CERT_DIR/backup" set_var DYNTLS_PKI_HTTP_CERT_BACKUP_DIR "$DYNTLS_PKI_HTTP_CERT_DIR/backup"
set_var DYNTLS_PKI_HTTP_KEY_DIR "$DYNTLS_PKI_HTTP_DIR/private" set_var DYNTLS_PKI_HTTP_KEY_DIR "$DYNTLS_PKI_HTTP_DIR/private"
set_var DYNTLS_PKI_CERT_SUFFIX "cert.pem" set_var DYNTLS_PKI_CERT_SUFFIX "cert.pem"
set_var DYNTLS_PKI_TMP_CHAIN_SUFFIX "cert.pem_chain"
set_var DYNTLS_PKI_CHAIN_SUFFIX "chain.pem"
set_var DYNTLS_PKI_FULLCHAIN_SUFFIX "fullchain.pem" set_var DYNTLS_PKI_FULLCHAIN_SUFFIX "fullchain.pem"
set_var DYNTLS_PKI_KEY_SUFFIX "key.pem" set_var DYNTLS_PKI_KEY_SUFFIX "key.pem"
set_var DYNTLS_PKI_LECA_CHAIN_FILE "LE_CA.chain.pem" #set_var DYNTLS_PKI_LECA_CHAIN_FILE "LE_CA.chain.pem"
set_var DYNTLS_PKI_LECA_CHAIN "$DYNTLS_PKI_HTTP_CERT_DIR/$DYNTLS_PKI_LECA_CHAIN_FILE" #set_var DYNTLS_PKI_LECA_CHAIN "$DYNTLS_PKI_HTTP_CERT_DIR/$DYNTLS_PKI_LECA_CHAIN_FILE"
set_var DYNTLS_PKI_LECA_R12_CHAIN_FILE "LE_CA-R12.chain.pem" #set_var DYNTLS_PKI_LECA_R12_CHAIN_FILE "LE_CA-R12.chain.pem"
set_var DYNTLS_PKI_LECA_R12_CHAIN "$DYNTLS_PKI_HTTP_CERT_DIR/$DYNTLS_PKI_LECA_R12_CHAIN_FILE" #set_var DYNTLS_PKI_LECA_R12_CHAIN "$DYNTLS_PKI_HTTP_CERT_DIR/$DYNTLS_PKI_LECA_R12_CHAIN_FILE"
set_var DYNTLS_PKI_LECA_R13_CHAIN_FILE "LE_CA-R13.chain.pem" #set_var DYNTLS_PKI_LECA_R13_CHAIN_FILE "LE_CA-R13.chain.pem"
set_var DYNTLS_PKI_LECA_R13_CHAIN "$DYNTLS_PKI_HTTP_CERT_DIR/$DYNTLS_PKI_LECA_R13_CHAIN_FILE" #set_var DYNTLS_PKI_LECA_R13_CHAIN "$DYNTLS_PKI_HTTP_CERT_DIR/$DYNTLS_PKI_LECA_R13_CHAIN_FILE"
set_var DYNTLS_PKI_CERT_EXPIRE 30 # Let's Encrypt default: 30 days set_var DYNTLS_PKI_CERT_EXPIRE 30 # Let's Encrypt default: 30 days
set_var DYNTLS_PKI_KEY_FORCE_RENEW 0 set_var DYNTLS_PKI_KEY_FORCE_RENEW 0
set_var DYNTLS_TEMP_DIR "$DYNTLS_TMP"
set_var DYNTLS_BACKUP_EXPIRATION 0 set_var DYNTLS_BACKUP_EXPIRATION 0
set_var DYNTLS_LOG_DIR "/var/log/dyntls" set_var DYNTLS_LOG_DIR "/var/log/dyntls"
set_var DYNTLS_LOG_FILE "$DYNTLS_LOG_DIR/dyntls.log" set_var DYNTLS_LOG_FILE "$DYNTLS_LOG_DIR/dyntls.log"
set_var DYNTLS_LOG_LEVEL "3" set_var DYNTLS_LOG_LEVEL 3
set_var DYNTLS_ENCRYPT_ACCOUNTKEY "$DYNTLS/private/letsencrypt_account.key" set_var DYNTLS_ENCRYPT_ACCOUNTKEY "$DYNTLS/private/letsencrypt_account.key"
set_var DYNTLS_PKI_SERVER_BASEKEY_FILE "base.$DYNTLS_PKI_KEY_SUFFIX" set_var DYNTLS_PKI_SERVER_BASEKEY_FILE "base.$DYNTLS_PKI_KEY_SUFFIX"
@@ -454,29 +480,29 @@ _vars_setup() {
set_var DYNTLS_DNS_TSIG "tsig.key" set_var DYNTLS_DNS_TSIG "tsig.key"
set_var DYNTLS_DNS_ZONE "" set_var DYNTLS_DNS_ZONE ""
set_var DYNTLS_HTTPD_DEFAULT_OWNER "apache." set_var DYNTLS_HTTPD_DEFAULT_OWNER "apache:apache"
set_var DYNTLS_RELOAD_WEBSERVER "false" set_var DYNTLS_RELOAD_WEBSERVER "false"
set_var DYNTLS_SEND_MAIL "false" set_var DYNTLS_SEND_MAIL "false"
set_list DYNTLS_DOMAIN_LIST "example365.tld:sub1.example365.tld:sub2.example365.tld" "1" set_list DYNTLS_DOMAIN_LIST "example365.tld:sub1.example365.tld:sub2.example365.tld" 1
set_list DYNTLS_DOMAINSERVICE_LIST "mail02.example365.tld:postfix:root.root:444:postfix:1:restart:Postfix" "1" set_list DYNTLS_DOMAINSERVICE_LIST "mail02.example365.tld:postfix:root.root:444:postfix:1:restart:Postfix" 1
set_var DYNTLS_PRODUCTIVE 0 set_var DYNTLS_PRODUCTIVE 0
set_list DYNTLS_CMD_PRE_LIST "" set_list DYNTLS_CMD_PRE_LIST ""
set_list DYNTLS_CMD_POST_LIST "" set_list DYNTLS_CMD_POST_LIST ""
# Assign value to $DYNTLS_TEMP_DIR_session and work around Windows mktemp bug when parent dir is missing # Assign value to $DYNTLS_LE_TMP_DIR_session and work around Windows mktemp bug when parent dir is missing
if [ -z "$DYNTLS_TEMP_DIR_session" ]; then if [ -z "$DYNTLS_LE_TMP_DIR_session" ]; then
if [ -d "$DYNTLS_TEMP_DIR" ]; then if [ -d "$DYNTLS_LE_TMP_DIR" ]; then
DYNTLS_TEMP_DIR_session="$(mktemp -du "$DYNTLS_TEMP_DIR/dyn-tls-$$.XXXXXX")" DYNTLS_LE_TMP_DIR_session="$(mktemp -du "$DYNTLS_LE_TMP_DIR/dyn-tls-$$.XXXXXX")"
else else
# If the directory does not exist then we have not run init-pki # If the directory does not exist then we have not run init-pki
mkdir -p "$DYNTLS_TEMP_DIR" || _die "Cannot create $DYNTLS_TEMP_DIR (permission?)" "1" mkdir -p "$DYNTLS_LE_TMP_DIR" || _die "Cannot create $DYNTLS_LE_TMP_DIR (permission?)" 5
DYNTLS_TEMP_DIR_session="$(mktemp -du "$DYNTLS_TEMP_DIR/dyn-tls-$$.XXXXXX")" DYNTLS_LE_TMP_DIR_session="$(mktemp -du "$DYNTLS_LE_TMP_DIR/dyn-tls-$$.XXXXXX")"
rm -rf "$DYNTLS_TEMP_DIR" rm -rf "$DYNTLS_LE_TMP_DIR"
fi fi
fi fi
@@ -653,7 +679,7 @@ _Hostname()
case "$MyDomainPart" in case "$MyDomainPart" in
tld) tld)
# Top Level Domain: # Top Level Domain:
# Must be alphabetic only, length 25 # Must be alphabetic only, length 2-5
if printf '%s\n' "$DYNTLS_MEMBER_HOSTNAME" | grep -Eq '^[A-Za-z]{2,5}$'; then if printf '%s\n' "$DYNTLS_MEMBER_HOSTNAME" | grep -Eq '^[A-Za-z]{2,5}$'; then
_log "Expression '$DYNTLS_MEMBER_HOSTNAME' is a valid TLD." 1 _log "Expression '$DYNTLS_MEMBER_HOSTNAME' is a valid TLD." 1
MyReturnFlag=0 MyReturnFlag=0
@@ -707,7 +733,7 @@ _Hostname()
fi fi
;; ;;
*) *)
_die "Invalid action '$MyDomainPart' in function _Hostname()." 1 _die "Invalid action '$MyDomainPart' in function _Hostname()." 5
;; ;;
esac esac
;; ;;
@@ -727,12 +753,12 @@ _Hostname()
printf '%s\n' "$MySubdomain" printf '%s\n' "$MySubdomain"
;; ;;
*) *)
_die "Invalid action '$MyDomainPart' in function _Hostname()." 1 _die "Invalid action '$MyDomainPart' in function _Hostname()." 5
;; ;;
esac esac
;; ;;
*) *)
_die "Invalid method '$MyMethod' in function _Hostname()." 1 _die "Invalid method '$MyMethod' in function _Hostname()." 5
;; ;;
esac esac
@@ -867,10 +893,15 @@ _ProvideCertDomainService() {
# Copy issued certificates into service PKI area # Copy issued certificates into service PKI area
_log "Copy the domain certificate, LE_CA chain and full chain from $DYNTLS_PKI_HTTP_CERT_DIR to the PKI service dir '$EffectivePkiDir/certs/'..." 1 _log "Copy the domain certificate, LE_CA chain and full chain from $DYNTLS_PKI_HTTP_CERT_DIR to the PKI service dir '$EffectivePkiDir/certs/'..." 1
#cp "$DYNTLS_DOMAIN_TARGET_CERT" \
# "$DYNTLS_PKI_LECA_CHAIN" \
# "$DYNTLS_PKI_LECA_R12_CHAIN" \
# "$DYNTLS_PKI_LECA_R13_CHAIN" \
# "$DYNTLS_PKI_HTTP_CERT_DIR/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_FULLCHAIN_SUFFIX" \
# "$EffectivePkiDir/certs/"
cp "$DYNTLS_DOMAIN_TARGET_CERT" \ cp "$DYNTLS_DOMAIN_TARGET_CERT" \
"$DYNTLS_PKI_LECA_CHAIN" \ "$DYNTLS_PKI_HTTP_CERT_DIR/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_CHAIN_SUFFIX" \
"$DYNTLS_PKI_LECA_R12_CHAIN" \
"$DYNTLS_PKI_LECA_R13_CHAIN" \
"$DYNTLS_PKI_HTTP_CERT_DIR/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_FULLCHAIN_SUFFIX" \ "$DYNTLS_PKI_HTTP_CERT_DIR/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_FULLCHAIN_SUFFIX" \
"$EffectivePkiDir/certs/" "$EffectivePkiDir/certs/"
@@ -952,8 +983,8 @@ _create_cert() {
######################################## ########################################
# 1. Temporary output for the new cert # 1. Temporary output for the new cert
######################################## ########################################
mkdir -p "$DYNTLS_TMP" mkdir -p "$DYNTLS_LE_TMP_DIR"
out_file_tmp="$DYNTLS_TMP/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_CERT_SUFFIX" out_file_tmp="$DYNTLS_LE_TMP_DIR/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_CERT_SUFFIX"
_log "Temporary certificate file: $out_file_tmp" 1 _log "Temporary certificate file: $out_file_tmp" 1
######################################## ########################################
@@ -1028,7 +1059,7 @@ _create_cert() {
elif [ -f "$out_file_tmp" ]; then elif [ -f "$out_file_tmp" ]; then
_log "Temporary certificate file exists, starting validation." 1 _log "Temporary certificate file exists, starting validation." 1
if openssl x509 -checkend $(($DYNTLS_PKI_CERT_EXPIRE*86400)) -noout -in "$out_file_tmp"; then if openssl x509 -checkend $(($DYNTLS_PKI_CERT_EXPIRE*86400)) -noout -in "$out_file_tmp"; then
_log "The verification of the new certificate was successful. The certificate seems to be valid and it is moved to its destination folder." "2" _log "The verification of the new certificate was successful. The certificate seems to be valid and it is moved to its destination folder." 2
_log "New certificate meets minimum validity window (${DYNTLS_PKI_CERT_EXPIRE} days)." 1 _log "New certificate meets minimum validity window (${DYNTLS_PKI_CERT_EXPIRE} days)." 1
if [ "$DYNTLS_PRODUCTIVE" -eq 1 ]; then if [ "$DYNTLS_PRODUCTIVE" -eq 1 ]; then
# Backup old cert # Backup old cert
@@ -1036,7 +1067,7 @@ _create_cert() {
_log "Using backup directory: $BackupDir" 1 _log "Using backup directory: $BackupDir" 1
mkdir -p "$BackupDir" && chmod 750 "$BackupDir" && chown root:root "$BackupDir" mkdir -p "$BackupDir" && chmod 750 "$BackupDir" && chown root:root "$BackupDir"
[ -f "$DYNTLS_DOMAIN_TARGET_CERT" ] && { [ -f "$DYNTLS_DOMAIN_TARGET_CERT" ] && {
_log "Backup the expired certificate '$DYNTLS_DOMAIN_TARGET_CERT' to '$BackupDir/'." "2" _log "Backup the expired certificate '$DYNTLS_DOMAIN_TARGET_CERT' to '$BackupDir/'." 2
cp "$DYNTLS_DOMAIN_TARGET_CERT" "$BackupDir/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_CERT_SUFFIX-$(date +%y%m%d)" cp "$DYNTLS_DOMAIN_TARGET_CERT" "$BackupDir/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_CERT_SUFFIX-$(date +%y%m%d)"
} }
@@ -1062,19 +1093,42 @@ _create_cert() {
_log "Moving issued certificate to target: $DYNTLS_DOMAIN_TARGET_CERT" 2 _log "Moving issued certificate to target: $DYNTLS_DOMAIN_TARGET_CERT" 2
mv "$out_file_tmp" "$DYNTLS_DOMAIN_TARGET_CERT" mv "$out_file_tmp" "$DYNTLS_DOMAIN_TARGET_CERT"
# Create fullchain file choosing correct chain (R12 vs R13) # Remove temporary file(s)
issuer_CN=$(openssl x509 -noout -issuer -in "$DYNTLS_DOMAIN_TARGET_CERT" | sed -n 's/^issuer=.*CN=//p') _log "Removing ACME chain file: $DYNTLS_LE_TMP_DIR/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_TMP_CHAIN_SUFFIX" 1
_log "Detected issuer CN for chain selection: $issuer_CN" 1 rm -f "$DYNTLS_LE_TMP_DIR/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_TMP_CHAIN_SUFFIX"
chainFile="$DYNTLS_PKI_LECA_R13_CHAIN"
[ "$issuer_CN" = "R12" ] && chainFile="$DYNTLS_PKI_LECA_R12_CHAIN" # Create fullchain file choosing correct chain (R12 vs R13)
_log "Using chain file: $chainFile" 1 #issuer_CN=$(openssl x509 -noout -issuer -in "$DYNTLS_DOMAIN_TARGET_CERT" | sed -n 's/^issuer=.*CN=//p')
#_log "Detected issuer CN for chain selection: $issuer_CN" 1
#chainFile="$DYNTLS_PKI_LECA_R13_CHAIN"
#[ "$issuer_CN" = "R12" ] && chainFile="$DYNTLS_PKI_LECA_R12_CHAIN"
#_log "Using chain file: $chainFile" 1
#fullchain_path="$DYNTLS_PKI_HTTP_CERT_DIR/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_FULLCHAIN_SUFFIX"
#_log "Creating fullchain file: $fullchain_path" 1
#cat "$DYNTLS_DOMAIN_TARGET_CERT" "$chainFile" > "$fullchain_path"
#chmod 640 "$DYNTLS_PKI_HTTP_CERT_DIR"/*.pem*
# Build CA chain: root + intermediates
tmp_chain="$DYNTLS_LE_TMP_DIR/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_TMP_CHAIN_SUFFIX"
root_cert="$DYNTLS_LE_CERT_DIR/$DYNTLS_LE_ROOT_CERT_FILE"
[ -f "$tmp_chain" ] || _die "Missing intermediate chain: $tmp_chain" 5
chain_path="$DYNTLS_PKI_HTTP_CERT_DIR/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_CHAIN_SUFFIX"
_log "Creating CA chain file: $chain_path" 1
cat "$tmp_chain" "$root_cert" > "$chain_path"
# Build fullchain: CA chain + leaf cert
fullchain_path="$DYNTLS_PKI_HTTP_CERT_DIR/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_FULLCHAIN_SUFFIX" fullchain_path="$DYNTLS_PKI_HTTP_CERT_DIR/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_FULLCHAIN_SUFFIX"
_log "Creating fullchain file: $fullchain_path" 1 _log "Creating fullchain file: $fullchain_path" 1
cat "$DYNTLS_DOMAIN_TARGET_CERT" "$chainFile" > "$fullchain_path" cat "$DYNTLS_DOMAIN_TARGET_CERT" "$chain_path" > "$fullchain_path"
chmod 640 "$DYNTLS_PKI_HTTP_CERT_DIR"/*.pem*
# Now copy or link the server key AFTER cert is issued # Adjust the permission(s)
chmod 640 "$chain_path" "$fullchain_path"
#chmod 640 "$DYNTLS_PKI_HTTP_CERT_DIR"/*.pem*
# Copy or link the server key AFTER cert is issued
KeyFile="$DYNTLS_PKI_HTTP_KEY_DIR/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_KEY_SUFFIX" KeyFile="$DYNTLS_PKI_HTTP_KEY_DIR/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_KEY_SUFFIX"
_log "Planned server key path: $KeyFile" 1 _log "Planned server key path: $KeyFile" 1
@@ -1094,13 +1148,14 @@ _create_cert() {
else else
_log "Staging mode: certificate issued but not installed." 2 _log "Staging mode: certificate issued but not installed." 2
rm -f "$out_file_tmp" rm -f "$out_file_tmp"
rm -f "$DYNTLS_TMP/$DYNTLS_MEMBER_HOSTNAME.cert.pem_chain" rm -f "$DYNTLS_LE_TMP_DIR/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_TMP_CHAIN_SUFFIX"
export DYNTLS_RELOAD_WEBSERVER="false" export DYNTLS_RELOAD_WEBSERVER="false"
fi fi
else else
_log "Issued certificate does not satisfy validity window; removing temporary file(s)." 4 _log "Issued certificate does not satisfy validity window; removing temporary file(s)." 4
rm -f "$out_file_tmp" rm -f "$out_file_tmp"
rm -f "$DYNTLS_TMP/$DYNTLS_MEMBER_HOSTNAME.cert.pem_chain" rm -f "$DYNTLS_LE_TMP_DIR/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_TMP_CHAIN_SUFFIX"
fi fi
fi fi
@@ -1419,7 +1474,7 @@ while :; do
export DYNTLS_PKI_CERT_EXPIRE="$2" export DYNTLS_PKI_CERT_EXPIRE="$2"
shift 2 shift 2
else else
_die "Missing value for --days" 1 _die "Missing value for --days" 5
fi fi
fi fi
;; ;;
@@ -1433,7 +1488,7 @@ while :; do
export DYNTLS_DOMAINS="$2" export DYNTLS_DOMAINS="$2"
shift 2 shift 2
else else
_die "Missing value for --hostnames/-H" 1 _die "Missing value for --hostnames/-H" 5
fi fi
fi fi
# Normalize domain string # Normalize domain string
@@ -1451,7 +1506,7 @@ while :; do
export DYNTLS_BIND_ZONE_KEY="$2" export DYNTLS_BIND_ZONE_KEY="$2"
shift 2 shift 2
else else
_die "Missing value for --key/-K" 1 _die "Missing value for --key/-K" 5
fi fi
fi fi
;; ;;
@@ -1484,7 +1539,7 @@ while :; do
export DYNTLS_DNS_SERVER="$2" export DYNTLS_DNS_SERVER="$2"
shift 2 shift 2
else else
_die "Missing value for --DNS/-D" 1 _die "Missing value for --DNS/-D" 5
fi fi
fi fi
;; ;;
@@ -1498,7 +1553,7 @@ while :; do
export DYNTLS_DNS_TSIG="$2" export DYNTLS_DNS_TSIG="$2"
shift 2 shift 2
else else
_die "Missing value for --tsig/-T" 1 _die "Missing value for --tsig/-T" 5
fi fi
fi fi
;; ;;
@@ -1512,7 +1567,7 @@ while :; do
export DYNTLS_VARS_FILE="$2" export DYNTLS_VARS_FILE="$2"
shift 2 shift 2
else else
_die "Missing value for --vars" 1 _die "Missing value for --vars" 5
fi fi
fi fi
;; ;;
@@ -1555,26 +1610,26 @@ _validate_command_params() {
add-cert) add-cert)
# Requires --hostnames / DYNTLS_DOMAINS to be set (one or more domains/SAN) # Requires --hostnames / DYNTLS_DOMAINS to be set (one or more domains/SAN)
if [ -z "$DYNTLS_DOMAINS" ]; then if [ -z "$DYNTLS_DOMAINS" ]; then
_die "'--hostnames' (DYNTLS_DOMAINS) option is required for add-cert command." 1 _die "'--hostnames' (DYNTLS_DOMAINS) option is required for add-cert command." 5
fi fi
;; ;;
check-cert) check-cert)
# Requires --hostnames / DYNTLS_DOMAINS (domain to check) # Requires --hostnames / DYNTLS_DOMAINS (domain to check)
if [ -z "$DYNTLS_DOMAINS" ]; then if [ -z "$DYNTLS_DOMAINS" ]; then
_die "'--hostnames' (DYNTLS_DOMAINS) option is required for check-cert command." 1 _die "'--hostnames' (DYNTLS_DOMAINS) option is required for check-cert command." 5
fi fi
;; ;;
remove-cert) remove-cert)
# Requires --hostnames / DYNTLS_DOMAINS (domain to remove) # Requires --hostnames / DYNTLS_DOMAINS (domain to remove)
if [ -z "$DYNTLS_DOMAINS" ]; then if [ -z "$DYNTLS_DOMAINS" ]; then
_die "'--hostnames' (DYNTLS_DOMAINS) option is required for remove-cert command." 1 _die "'--hostnames' (DYNTLS_DOMAINS) option is required for remove-cert command." 5
fi fi
;; ;;
update-cert) update-cert)
# No mandatory CLI options, but could add checks if your workflow requires them. # No mandatory CLI options, but could add checks if your workflow requires them.
# Example: Validate DYNTLS_DOMAIN_LIST is set: # Example: Validate DYNTLS_DOMAIN_LIST is set:
# if [ -z "$DYNTLS_DOMAIN_LIST" ]; then # if [ -z "$DYNTLS_DOMAIN_LIST" ]; then
# _die "'DYNTLS_DOMAIN_LIST' is required for update-cert command." 1 # _die "'DYNTLS_DOMAIN_LIST' is required for update-cert command." 5
# fi # fi
;; ;;
init-pki) init-pki)
@@ -1624,7 +1679,7 @@ case "$cmd" in
exit 0 exit 0
;; ;;
*) *)
_die "Unknown command '$cmd'. Run without commands for usage help." "1" _die "Unknown command '$cmd'. Run without commands for usage help." 5
;; ;;
esac esac