fix(rpm): preserve config on upgrade, set correct ownership/permissions
RPM packaging improvements: - Fix %config(noreplace) directive in spec file (logcorrelator.yml) - Fix post script: use correct path for .yml.example (/etc/logcorrelator/) - Set /var/run/logcorrelator ownership to logcorrelator:logcorrelator - Set correct permissions: /var/run (755), /var/log (750), /var/lib (750) - Add %config(noreplace) for logrotate.d/logcorrelator - Add comprehensive RPM test script (packaging/test/test-rpm.sh) Documentation updates: - Update architecture.yml with filesystem permissions section - Document socket ownership (logcorrelator:logcorrelator, 0666) - Document config file policy (%config(noreplace) behavior) - Add systemd hardening directives (NoNewPrivileges, ProtectSystem) - Update ClickHouse schema: mark non-implemented fields - Remove materialized view SQL (managed externally) - Add stdout sink module documentation Build pipeline: - Update Dockerfile.package with comments for config policy - Add /var/lib/logcorrelator directory creation - Document fpm %config(noreplace) limitations Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
@ -28,6 +28,12 @@ logcorrelator est un service système écrit en Go qui reçoit deux flux de logs
|
||||
via des sockets Unix, corrèle les événements HTTP applicatifs avec des événements
|
||||
réseau, et produit des logs corrélés en temps réel vers ClickHouse et/ou fichier local.
|
||||
|
||||
Notes de sécurité :
|
||||
- Le service s'exécute sous l'utilisateur logcorrelator (non-root)
|
||||
- Les sockets Unix sont créés avec des permissions 0666 (world read/write)
|
||||
- Les répertoires critiques sont protégés : /var/log (750), /var/lib (750), /etc (750)
|
||||
- /var/run/logcorrelator est en 755 pour permettre la création de sockets
|
||||
|
||||
%prep
|
||||
# No source extraction needed - binary is pre-built
|
||||
|
||||
@ -52,73 +58,25 @@ install -m 0644 %{_sourcedir}/logcorrelator.service %{buildroot}/etc/systemd/sys
|
||||
# Install logrotate config
|
||||
install -m 0644 %{_sourcedir}/logrotate %{buildroot}/etc/logrotate.d/logcorrelator
|
||||
|
||||
%post
|
||||
# Create logcorrelator user and group
|
||||
if ! getent group logcorrelator >/dev/null 2>&1; then
|
||||
groupadd --system logcorrelator
|
||||
fi
|
||||
|
||||
if ! getent passwd logcorrelator >/dev/null 2>&1; then
|
||||
useradd --system \
|
||||
--gid logcorrelator \
|
||||
--home-dir /var/lib/logcorrelator \
|
||||
--no-create-home \
|
||||
--shell /usr/sbin/nologin \
|
||||
logcorrelator
|
||||
fi
|
||||
|
||||
# Create directories
|
||||
mkdir -p /var/lib/logcorrelator
|
||||
mkdir -p /var/log/logcorrelator
|
||||
mkdir -p /var/run/logcorrelator
|
||||
|
||||
# Set ownership
|
||||
chown -R logcorrelator:logcorrelator /var/lib/logcorrelator
|
||||
chown -R logcorrelator:logcorrelator /var/log/logcorrelator
|
||||
chown -R logcorrelator:logcorrelator /var/run/logcorrelator
|
||||
chown -R logcorrelator:logcorrelator /etc/logcorrelator
|
||||
|
||||
# Set permissions
|
||||
chmod 750 /var/lib/logcorrelator
|
||||
chmod 750 /var/log/logcorrelator
|
||||
chmod 755 /var/run/logcorrelator
|
||||
chmod 750 /etc/logcorrelator
|
||||
|
||||
# Copy default config if not exists
|
||||
if [ ! -f /etc/logcorrelator/logcorrelator.yml ]; then
|
||||
cp /etc/logcorrelator/logcorrelator.yml.example /etc/logcorrelator/logcorrelator.yml
|
||||
chown logcorrelator:logcorrelator /etc/logcorrelator/logcorrelator.yml
|
||||
chmod 640 /etc/logcorrelator/logcorrelator.yml
|
||||
fi
|
||||
|
||||
# Reload systemd
|
||||
systemctl daemon-reload
|
||||
systemctl enable logcorrelator.service
|
||||
systemctl start logcorrelator.service
|
||||
# Note: %post, %preun, %postun scripts are provided externally via Dockerfile.package
|
||||
# They are injected during RPM build using fpm --after-install, --before-remove, --after-remove
|
||||
|
||||
%preun
|
||||
if [ $1 -eq 0 ]; then
|
||||
# Package removal, not upgrade
|
||||
systemctl stop logcorrelator.service
|
||||
systemctl disable logcorrelator.service
|
||||
fi
|
||||
# Placeholder: actual preun script is provided externally via Dockerfile.package
|
||||
# See packaging/rpm/preun for the actual script
|
||||
|
||||
%postun
|
||||
systemctl daemon-reload
|
||||
if [ $1 -ge 1 ]; then
|
||||
# Package upgrade, restart service
|
||||
systemctl try-restart logcorrelator.service
|
||||
fi
|
||||
# Placeholder: actual postun script is provided externally via Dockerfile.package
|
||||
# See packaging/rpm/postun for the actual script
|
||||
|
||||
%files
|
||||
/usr/bin/logcorrelator
|
||||
/etc/logcorrelator/logcorrelator.yml
|
||||
/etc/logcorrelator/logcorrelator.yml.example
|
||||
%config(noreplace) /etc/logcorrelator/logcorrelator.yml
|
||||
/etc/logcorrelator/logcorrelator.yml.example
|
||||
/var/log/logcorrelator
|
||||
/var/run/logcorrelator
|
||||
/etc/systemd/system/logcorrelator.service
|
||||
/etc/logrotate.d/logcorrelator
|
||||
%config(noreplace) /etc/logrotate.d/logcorrelator
|
||||
|
||||
%changelog
|
||||
* Tue Mar 03 2026 logcorrelator <dev@example.com> - 1.1.7-1
|
||||
|
||||
@ -1,6 +1,12 @@
|
||||
#!/bin/bash
|
||||
# post script for logcorrelator RPM package
|
||||
# post install script for logcorrelator RPM package
|
||||
# Compatible with CentOS 7, Rocky Linux 8, 9, 10
|
||||
#
|
||||
# Configuration file policy:
|
||||
# - logcorrelator.yml: %config(noreplace) - NEVER overwritten on upgrade
|
||||
# - logcorrelator.yml.example: ALWAYS updated with new configuration options
|
||||
# - On first install: logcorrelator.yml is created from logcorrelator.yml.example
|
||||
# - On upgrade: existing logcorrelator.yml is preserved
|
||||
|
||||
set -e
|
||||
|
||||
@ -24,19 +30,34 @@ mkdir -p /var/log/logcorrelator
|
||||
mkdir -p /var/run/logcorrelator
|
||||
|
||||
# Set ownership
|
||||
# /var/run/logcorrelator: must be owned by logcorrelator for socket creation
|
||||
# /var/log/logcorrelator: must be owned by logcorrelator for log file writing
|
||||
# /var/lib/logcorrelator: home directory for the service
|
||||
chown -R logcorrelator:logcorrelator /var/lib/logcorrelator
|
||||
chown -R logcorrelator:logcorrelator /var/log/logcorrelator
|
||||
chown -R logcorrelator:logcorrelator /var/run/logcorrelator
|
||||
chown -R logcorrelator:logcorrelator /etc/logcorrelator
|
||||
|
||||
# Set permissions
|
||||
# /var/run/logcorrelator: 755 to allow other users/apps to create sockets if needed
|
||||
# /var/log/logcorrelator: 750 to restrict log access
|
||||
# /var/lib/logcorrelator: 750 for service data
|
||||
# /etc/logcorrelator: 750 to restrict config access
|
||||
chmod 755 /var/run/logcorrelator
|
||||
chmod 750 /var/lib/logcorrelator
|
||||
chmod 750 /var/log/logcorrelator
|
||||
chmod 750 /etc/logcorrelator
|
||||
|
||||
# Copy default config if not exists
|
||||
# Copy default config example (always updated)
|
||||
# The main config file is preserved across upgrades via %config(noreplace)
|
||||
if [ -f /etc/logcorrelator/logcorrelator.yml.example ]; then
|
||||
chown logcorrelator:logcorrelator /etc/logcorrelator/logcorrelator.yml.example
|
||||
chmod 640 /etc/logcorrelator/logcorrelator.yml.example
|
||||
fi
|
||||
|
||||
# Create main config file only if it doesn't exist (first install)
|
||||
if [ ! -f /etc/logcorrelator/logcorrelator.yml ]; then
|
||||
cp /usr/share/logcorrelator/logcorrelator.yml.example /etc/logcorrelator/logcorrelator.yml
|
||||
cp /etc/logcorrelator/logcorrelator.yml.example /etc/logcorrelator/logcorrelator.yml
|
||||
chown logcorrelator:logcorrelator /etc/logcorrelator/logcorrelator.yml
|
||||
chmod 640 /etc/logcorrelator/logcorrelator.yml
|
||||
fi
|
||||
|
||||
258
packaging/test/test-rpm.sh
Executable file
258
packaging/test/test-rpm.sh
Executable file
@ -0,0 +1,258 @@
|
||||
#!/bin/bash
|
||||
# Test script for logcorrelator RPM package
|
||||
# Verifies installation, permissions, and service status
|
||||
#
|
||||
# Usage: ./packaging/test/test-rpm.sh [el8|el9|el10]
|
||||
#
|
||||
# This script tests the RPM package in a Docker container to ensure:
|
||||
# - Installation succeeds
|
||||
# - File permissions are correct
|
||||
# - Service starts properly
|
||||
# - Sockets are created with correct ownership
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
||||
RPM_DIR="${PROJECT_ROOT}/dist/rpm"
|
||||
|
||||
# Default to el8 if no argument provided
|
||||
DISTRO="${1:-el8}"
|
||||
|
||||
echo "========================================="
|
||||
echo "Testing logcorrelator RPM for ${DISTRO}"
|
||||
echo "========================================="
|
||||
|
||||
# Find the RPM file
|
||||
case "${DISTRO}" in
|
||||
el8|rocky8)
|
||||
RPM_PATH="${RPM_DIR}/el8"
|
||||
BASE_IMAGE="rockylinux:8"
|
||||
;;
|
||||
el9|rocky9)
|
||||
RPM_PATH="${RPM_DIR}/el9"
|
||||
BASE_IMAGE="rockylinux:9"
|
||||
;;
|
||||
el10|alma10)
|
||||
RPM_PATH="${RPM_DIR}/el10"
|
||||
BASE_IMAGE="almalinux:10"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown distribution: ${DISTRO}"
|
||||
echo "Valid options: el8, el9, el10"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Find the latest RPM file
|
||||
RPM_FILE=$(ls -t "${RPM_PATH}"/logcorrelator-*.rpm 2>/dev/null | head -n 1)
|
||||
|
||||
if [ -z "${RPM_FILE}" ]; then
|
||||
echo "ERROR: No RPM file found in ${RPM_PATH}"
|
||||
echo "Please run 'make package-rpm' first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Testing RPM: ${RPM_FILE}"
|
||||
echo "Base image: ${BASE_IMAGE}"
|
||||
echo ""
|
||||
|
||||
# Create test script
|
||||
TEST_SCRIPT=$(cat <<'EOF'
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "=== Installing logcorrelator RPM ==="
|
||||
rpm -ivh /tmp/logcorrelator.rpm
|
||||
|
||||
echo ""
|
||||
echo "=== Checking user and group ==="
|
||||
if ! getent group logcorrelator >/dev/null; then
|
||||
echo "FAIL: logcorrelator group not created"
|
||||
exit 1
|
||||
fi
|
||||
echo "OK: logcorrelator group exists"
|
||||
|
||||
if ! getent passwd logcorrelator >/dev/null; then
|
||||
echo "FAIL: logcorrelator user not created"
|
||||
exit 1
|
||||
fi
|
||||
echo "OK: logcorrelator user exists"
|
||||
|
||||
echo ""
|
||||
echo "=== Checking directory permissions ==="
|
||||
|
||||
# Check /var/run/logcorrelator
|
||||
DIR="/var/run/logcorrelator"
|
||||
if [ ! -d "$DIR" ]; then
|
||||
echo "FAIL: $DIR does not exist"
|
||||
exit 1
|
||||
fi
|
||||
OWNER=$(stat -c '%U:%G' "$DIR")
|
||||
PERMS=$(stat -c '%a' "$DIR")
|
||||
if [ "$OWNER" != "logcorrelator:logcorrelator" ]; then
|
||||
echo "FAIL: $DIR owner is $OWNER (expected logcorrelator:logcorrelator)"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$PERMS" != "755" ]; then
|
||||
echo "FAIL: $DIR permissions are $PERMS (expected 755)"
|
||||
exit 1
|
||||
fi
|
||||
echo "OK: $DIR - owner=$OWNER, permissions=$PERMS"
|
||||
|
||||
# Check /var/log/logcorrelator
|
||||
DIR="/var/log/logcorrelator"
|
||||
if [ ! -d "$DIR" ]; then
|
||||
echo "FAIL: $DIR does not exist"
|
||||
exit 1
|
||||
fi
|
||||
OWNER=$(stat -c '%U:%G' "$DIR")
|
||||
PERMS=$(stat -c '%a' "$DIR")
|
||||
if [ "$OWNER" != "logcorrelator:logcorrelator" ]; then
|
||||
echo "FAIL: $DIR owner is $OWNER (expected logcorrelator:logcorrelator)"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$PERMS" != "750" ]; then
|
||||
echo "FAIL: $DIR permissions are $PERMS (expected 750)"
|
||||
exit 1
|
||||
fi
|
||||
echo "OK: $DIR - owner=$OWNER, permissions=$PERMS"
|
||||
|
||||
# Check /var/lib/logcorrelator
|
||||
DIR="/var/lib/logcorrelator"
|
||||
if [ ! -d "$DIR" ]; then
|
||||
echo "FAIL: $DIR does not exist"
|
||||
exit 1
|
||||
fi
|
||||
OWNER=$(stat -c '%U:%G' "$DIR")
|
||||
PERMS=$(stat -c '%a' "$DIR")
|
||||
if [ "$OWNER" != "logcorrelator:logcorrelator" ]; then
|
||||
echo "FAIL: $DIR owner is $OWNER (expected logcorrelator:logcorrelator)"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$PERMS" != "750" ]; then
|
||||
echo "FAIL: $DIR permissions are $PERMS (expected 750)"
|
||||
exit 1
|
||||
fi
|
||||
echo "OK: $DIR - owner=$OWNER, permissions=$PERMS"
|
||||
|
||||
echo ""
|
||||
echo "=== Checking config files ==="
|
||||
|
||||
# Check config file exists and has correct permissions
|
||||
CONFIG="/etc/logcorrelator/logcorrelator.yml"
|
||||
if [ ! -f "$CONFIG" ]; then
|
||||
echo "FAIL: $CONFIG does not exist"
|
||||
exit 1
|
||||
fi
|
||||
OWNER=$(stat -c '%U:%G' "$CONFIG")
|
||||
PERMS=$(stat -c '%a' "$CONFIG")
|
||||
if [ "$OWNER" != "logcorrelator:logcorrelator" ]; then
|
||||
echo "FAIL: $CONFIG owner is $OWNER (expected logcorrelator:logcorrelator)"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$PERMS" != "640" ]; then
|
||||
echo "FAIL: $CONFIG permissions are $PERMS (expected 640)"
|
||||
exit 1
|
||||
fi
|
||||
echo "OK: $CONFIG - owner=$OWNER, permissions=$PERMS"
|
||||
|
||||
# Check example config file
|
||||
EXAMPLE_CONFIG="/etc/logcorrelator/logcorrelator.yml.example"
|
||||
if [ ! -f "$EXAMPLE_CONFIG" ]; then
|
||||
echo "FAIL: $EXAMPLE_CONFIG does not exist"
|
||||
exit 1
|
||||
fi
|
||||
OWNER=$(stat -c '%U:%G' "$EXAMPLE_CONFIG")
|
||||
PERMS=$(stat -c '%a' "$EXAMPLE_CONFIG")
|
||||
if [ "$OWNER" != "logcorrelator:logcorrelator" ]; then
|
||||
echo "FAIL: $EXAMPLE_CONFIG owner is $OWNER (expected logcorrelator:logcorrelator)"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$PERMS" != "640" ]; then
|
||||
echo "FAIL: $EXAMPLE_CONFIG permissions are $PERMS (expected 640)"
|
||||
exit 1
|
||||
fi
|
||||
echo "OK: $EXAMPLE_CONFIG - owner=$OWNER, permissions=$PERMS"
|
||||
|
||||
echo ""
|
||||
echo "=== Checking systemd service ==="
|
||||
if [ ! -f /etc/systemd/system/logcorrelator.service ]; then
|
||||
echo "FAIL: systemd service file not found"
|
||||
exit 1
|
||||
fi
|
||||
echo "OK: systemd service file exists"
|
||||
|
||||
echo ""
|
||||
echo "=== Checking logrotate config ==="
|
||||
if [ ! -f /etc/logrotate.d/logcorrelator ]; then
|
||||
echo "FAIL: logrotate config not found"
|
||||
exit 1
|
||||
fi
|
||||
echo "OK: logrotate config exists"
|
||||
|
||||
echo ""
|
||||
echo "=== Testing service start ==="
|
||||
# Try to start the service (may fail in container without full systemd)
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
systemctl daemon-reload || true
|
||||
if systemctl start logcorrelator.service 2>/dev/null; then
|
||||
echo "OK: service started successfully"
|
||||
|
||||
# Wait for sockets to be created
|
||||
sleep 2
|
||||
|
||||
echo ""
|
||||
echo "=== Checking sockets ==="
|
||||
HTTP_SOCKET="/var/run/logcorrelator/http.socket"
|
||||
NETWORK_SOCKET="/var/run/logcorrelator/network.socket"
|
||||
|
||||
if [ -S "$HTTP_SOCKET" ]; then
|
||||
OWNER=$(stat -c '%U:%G' "$HTTP_SOCKET")
|
||||
PERMS=$(stat -c '%a' "$HTTP_SOCKET")
|
||||
echo "OK: $HTTP_SOCKET exists - owner=$OWNER, permissions=$PERMS"
|
||||
if [ "$PERMS" != "666" ]; then
|
||||
echo "WARN: socket permissions are $PERMS (expected 666)"
|
||||
fi
|
||||
else
|
||||
echo "WARN: $HTTP_SOCKET not found (service may not have started)"
|
||||
fi
|
||||
|
||||
if [ -S "$NETWORK_SOCKET" ]; then
|
||||
OWNER=$(stat -c '%U:%G' "$NETWORK_SOCKET")
|
||||
PERMS=$(stat -c '%a' "$NETWORK_SOCKET")
|
||||
echo "OK: $NETWORK_SOCKET exists - owner=$OWNER, permissions=$PERMS"
|
||||
if [ "$PERMS" != "666" ]; then
|
||||
echo "WARN: socket permissions are $PERMS (expected 666)"
|
||||
fi
|
||||
else
|
||||
echo "WARN: $NETWORK_SOCKET not found (service may not have started)"
|
||||
fi
|
||||
|
||||
systemctl stop logcorrelator.service || true
|
||||
else
|
||||
echo "WARN: service failed to start (expected in minimal container)"
|
||||
fi
|
||||
else
|
||||
echo "WARN: systemctl not available (minimal container)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "========================================="
|
||||
echo "All tests passed!"
|
||||
echo "========================================="
|
||||
EOF
|
||||
)
|
||||
|
||||
# Run test in Docker container
|
||||
echo "Running tests in Docker container..."
|
||||
echo ""
|
||||
|
||||
docker run --rm \
|
||||
-v "${RPM_FILE}:/tmp/logcorrelator.rpm:ro" \
|
||||
-v "${TEST_SCRIPT}:/test.sh:ro" \
|
||||
"${BASE_IMAGE}" \
|
||||
bash /test.sh
|
||||
|
||||
echo ""
|
||||
echo "Test completed successfully for ${DISTRO}"
|
||||
Reference in New Issue
Block a user