Fix domain-service mapping parsing and validation
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user