Fix domain-service mapping parsing and validation

This commit is contained in:
2026-04-25 10:16:04 +02:00
parent 563cfa9006
commit 79ea4d50af
+131 -38
View File
@@ -843,14 +843,23 @@ _ProvideCertDomainService() {
MyIsError=0 MyIsError=0
# Split list by '&' into individual domain-service mappings # Normalize DYNTLS_DOMAINSERVICE_LIST: '&' separated -> one mapping per line
IFS=$'\n' DomainServiceAry=$(echo "$DYNTLS_DOMAINSERVICE_LIST" | sed 's/&/\n/g') DomainServiceRaw=$(printf '%s\n' "$DYNTLS_DOMAINSERVICE_LIST" | tr '&' '\n')
for ServiceEntry in $DomainServiceAry; do
# Split one mapping into fields # Nothing to do if no mappings are configured
IFS=":" set -- $ServiceEntry if [ -z "$DomainServiceRaw" ]; then
Domain="$1"; PkiDir="$2"; UserGroup="$3"; FilePerm="$4" _log "No domain-service mappings configured." 1
Service="$5"; ServiceOwner="$6"; RestartFlag="$7"; RestartMode="$8"; DisplayName="$9" _log "Leave the function '_ProvideCertDomainService()'..." 1
return 0
fi
# Process each mapping line-by-line, split into colon-separated fields
while IFS=':' read -r \
Domain PkiDir UserGroup FilePerm Service ServiceOwner RestartFlag RestartMode DisplayName || \
[ -n "$Domain" ]
do
# Skip empty lines
[ -z "$Domain" ] && continue
# Decide whether PkiDir is relative (default) or absolute (contains '/') # Decide whether PkiDir is relative (default) or absolute (contains '/')
case "$PkiDir" in case "$PkiDir" in
@@ -858,84 +867,167 @@ _ProvideCertDomainService() {
# Absolute path (or in general a path containing '/') # Absolute path (or in general a path containing '/')
EffectivePkiDir="$PkiDir" EffectivePkiDir="$PkiDir"
;; ;;
"")
_log "Skipping mapping with empty pkiDir for domain=$Domain" 2
MyIsError=1
continue
;;
*) *)
# Relative service name > located below DYNTLS_PKI # Relative service name > located below DYNTLS_PKI
EffectivePkiDir="$DYNTLS_PKI/$PkiDir" EffectivePkiDir="$DYNTLS_PKI/$PkiDir"
;; ;;
esac esac
# Convert legacy user.group notation to user:group for chown to avoid deprecation warnings # Convert legacy user.group notation to user:group
case "$UserGroup" in
*.*)
UG_USER=${UserGroup%%.*} UG_USER=${UserGroup%%.*}
UG_GROUP=${UserGroup#*.} UG_GROUP=${UserGroup#*.}
UserGroup=$UG_USER:$UG_GROUP
# Legacy special case: "user." -> "user:user"
[ -n "$UG_GROUP" ] || UG_GROUP=$UG_USER
UserGroup="$UG_USER:$UG_GROUP"
;;
esac
# Validate required ownership field
case "$UserGroup" in
*:*)
;;
"")
_log "Skipping mapping with empty userGroup for domain=$Domain" 4
MyIsError=1
continue
;;
*)
_log "Skipping mapping with invalid userGroup '$UserGroup' for domain=$Domain" 4
MyIsError=1
continue
;;
esac
# Validate file permission field
case "$FilePerm" in
[0-7][0-7][0-7]|[0-7][0-7][0-7][0-7])
;;
*)
_log "Skipping mapping with invalid file permission '$FilePerm' for domain=$Domain" 4
MyIsError=1
continue
;;
esac
# Normalize restart flag
case "$RestartFlag" in
1)
;;
""|0)
RestartFlag=0
;;
*)
_log "Invalid restart flag '$RestartFlag' for domain=$Domain, forcing 0" 3
RestartFlag=0
;;
esac
# Fallback display name for logs if missing
[ -n "$DisplayName" ] || DisplayName=$Service
_log "Processing mapping: domain=$Domain, pkiDir=$PkiDir, userGroup=$UserGroup, perm=$FilePerm, service=$Service, owner=$ServiceOwner, restart=$RestartFlag, mode=$RestartMode, name=$DisplayName" 1 _log "Processing mapping: domain=$Domain, pkiDir=$PkiDir, userGroup=$UserGroup, perm=$FilePerm, service=$Service, owner=$ServiceOwner, restart=$RestartFlag, mode=$RestartMode, name=$DisplayName" 1
# Match against current hostname # Match against current hostname
if [ "$Domain" = "$DYNTLS_MEMBER_HOSTNAME" ]; then [ "$Domain" = "$DYNTLS_MEMBER_HOSTNAME" ] || continue
_log "$DisplayName-Domain recognized! Try to provide the certificate to $DisplayName..." 2 _log "$DisplayName-Domain recognized! Try to provide the certificate to $DisplayName..." 2
_log "Domain '$Domain' matches CN. Preparing service directory '$EffectivePkiDir'..." 1
# Ensure required directories exist # Ensure required directories exist
_log "Domain '$Domain' matches CN. Preparing service directory '$EffectivePkiDir'..." 1 mkdir -p "$EffectivePkiDir/certs" "$EffectivePkiDir/private" || {
mkdir -p "$EffectivePkiDir/certs" "$EffectivePkiDir/private" _log "Failed to create service PKI directories under '$EffectivePkiDir'." 4
MyIsError=1
continue
}
# Set ownership/permissions on directories # Set ownership/permissions on directories
_log "Adjust the owner of '$EffectivePkiDir/'..." 1 _log "Adjust the owner of '$EffectivePkiDir/'..." 1
find "$EffectivePkiDir" -type d | xargs -r chown "$UserGroup" find "$EffectivePkiDir" -type d -exec chown "$UserGroup" {} \; || {
find "$EffectivePkiDir" -type d | xargs -r chmod 750 _log "Failed to adjust directory ownership under '$EffectivePkiDir'." 4
MyIsError=1
}
find "$EffectivePkiDir" -type d -exec chmod 750 {} \; || {
_log "Failed to adjust directory permissions under '$EffectivePkiDir'." 4
MyIsError=1
}
# Provide base server key if missing # Provide base server key if missing
_log "Check whether the server base key '$EffectivePkiDir/private/$DYNTLS_PKI_SERVER_BASEKEY_FILE' exists..." 1 _log "Check whether the server base key '$EffectivePkiDir/private/$DYNTLS_PKI_SERVER_BASEKEY_FILE' exists..." 1
if [ ! -f "$EffectivePkiDir/private/$DYNTLS_PKI_SERVER_BASEKEY_FILE" ]; then if [ ! -f "$EffectivePkiDir/private/$DYNTLS_PKI_SERVER_BASEKEY_FILE" ]; then
_log "$DYNTLS_PKI_SERVER_BASEKEY doesn't exist. Copy it..." 1 _log "$DYNTLS_PKI_SERVER_BASEKEY doesn't exist. Copy it..." 1
cp "$DYNTLS_PKI_SERVER_BASEKEY" "$EffectivePkiDir/private/" cp "$DYNTLS_PKI_SERVER_BASEKEY" "$EffectivePkiDir/private/" || {
_log "Failed to copy base server key to '$EffectivePkiDir/private/'." 4
MyIsError=1
continue
}
fi fi
# 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, 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_HTTP_CERT_DIR/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_CHAIN_SUFFIX" \ "$DYNTLS_PKI_HTTP_CERT_DIR/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_CHAIN_SUFFIX" \
"$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/" || {
_log "Failed to copy certificate files to '$EffectivePkiDir/certs/'." 4
MyIsError=1
continue
}
# Provide server key: either symlink to base or copy unique key # Provide server key: either symlink to base or copy unique key
KeyPath="$EffectivePkiDir/private/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_KEY_SUFFIX" KeyPath="$EffectivePkiDir/private/$DYNTLS_MEMBER_HOSTNAME.$DYNTLS_PKI_KEY_SUFFIX"
if [ "$DYNTLS_PKI_KEY_LNS" -eq 1 ]; then if [ "$DYNTLS_PKI_KEY_LNS" -eq 1 ]; then
_log "Using relative symlink for service key: $KeyPath -> $DYNTLS_PKI_SERVER_BASEKEY_FILE" 1 _log "Using relative symlink for service key: $KeyPath -> $DYNTLS_PKI_SERVER_BASEKEY_FILE" 1
ln -sf "$DYNTLS_PKI_SERVER_BASEKEY_FILE" "$KeyPath" ln -sf "$DYNTLS_PKI_SERVER_BASEKEY_FILE" "$KeyPath" || {
_log "Failed to create service key symlink '$KeyPath'." 4
MyIsError=1
continue
}
else else
_log "Using dedicated service key copy at: $KeyPath (source: $EffectivePkiDir/private/$DYNTLS_PKI_SERVER_BASEKEY_FILE)" 1 _log "Using dedicated service key copy at: $KeyPath (source: $EffectivePkiDir/private/$DYNTLS_PKI_SERVER_BASEKEY_FILE)" 1
cp "$EffectivePkiDir/private/$DYNTLS_PKI_SERVER_BASEKEY_FILE" "$KeyPath" cp "$EffectivePkiDir/private/$DYNTLS_PKI_SERVER_BASEKEY_FILE" "$KeyPath" || {
_log "Failed to copy service key to '$KeyPath'." 4
MyIsError=1
continue
}
fi fi
# Adjust ownership and permissions on .pem files # Adjust ownership and permissions on .pem files
_log "Adjust the ownership of '$EffectivePkiDir/certs/*.pem'..." 1 find "$EffectivePkiDir/certs" -type f -name '*.pem' -exec chown "$UserGroup" {} \; || {
find "$EffectivePkiDir/certs" -type f -name '*.pem' | xargs -r chown "$UserGroup" _log "Failed to adjust certificate ownership under '$EffectivePkiDir/certs/'." 4
_log "Adjust the ownership of '$EffectivePkiDir/private/*.pem'..." 1 MyIsError=1
find "$EffectivePkiDir/private" -type f -name '*.pem' | xargs -r chown "$UserGroup" }
_log "Adjust the permissions of '$EffectivePkiDir/certs/*.pem'..." 1 find "$EffectivePkiDir/private" -type f -name '*.pem' -exec chown "$UserGroup" {} \; || {
find "$EffectivePkiDir/certs" -type f -name '*.pem' | xargs -r chmod "$FilePerm" _log "Failed to adjust key ownership under '$EffectivePkiDir/private/'." 4
_log "Adjust the permissions of '$EffectivePkiDir/private/*.pem'..." 1 MyIsError=1
find "$EffectivePkiDir/private" -type f -name '*.pem' | xargs -r chmod 440 }
find "$EffectivePkiDir/certs" -type f -name '*.pem' -exec chmod "$FilePerm" {} \; || {
_log "Failed to adjust certificate permissions under '$EffectivePkiDir/certs/'." 4
MyIsError=1
}
find "$EffectivePkiDir/private" -type f -name '*.pem' -exec chmod 440 {} \; || {
_log "Failed to adjust key permissions under '$EffectivePkiDir/private/'." 4
MyIsError=1
}
_log "Certificates and keys provided for service '$DisplayName'." 2 _log "Certificates and keys provided for service '$DisplayName'." 2
# Restart or reload the service if configured # Restart or reload the service if configured
if [ "$RestartFlag" -eq 1 ] && [ -n "$Service" ]; then if [ "$RestartFlag" -eq 1 ] && [ -n "$Service" ]; then
# fallback to restart if mode is missing or invalid
[ "$RestartMode" = "restart" ] || [ "$RestartMode" = "reload" ] || RestartMode="restart" [ "$RestartMode" = "restart" ] || [ "$RestartMode" = "reload" ] || RestartMode="restart"
if [ -n "$ServiceOwner" ] && [ "$ServiceOwner" != "root" ]; then if [ -n "$ServiceOwner" ] && [ "$ServiceOwner" != "root" ]; then
_log "Reloading service '$Service' as non-root user '$ServiceOwner'..." 1 _log "Reloading service '$Service' as non-root user '$ServiceOwner'..." 1
if sudo -u "$ServiceOwner" XDG_RUNTIME_DIR="/run/user/$(id -u $ServiceOwner)" \ if sudo -u "$ServiceOwner" XDG_RUNTIME_DIR="/run/user/$(id -u "$ServiceOwner")" \
systemctl --user "$RestartMode" "$Service.service"; then systemctl --user "$RestartMode" "$Service.service"; then
_log "Service '$DisplayName' successfully $RestartMode-ed as '$ServiceOwner'." 2 _log "Service '$DisplayName' successfully $RestartMode-ed as '$ServiceOwner'." 2
else else
@@ -954,8 +1046,9 @@ _ProvideCertDomainService() {
else else
_log "No restart required for service '$DisplayName'." 2 _log "No restart required for service '$DisplayName'." 2
fi fi
fi done <<EOF
done $DomainServiceRaw
EOF
_log "Leave the function '_ProvideCertDomainService()'..." 1 _log "Leave the function '_ProvideCertDomainService()'..." 1