Harden quarantine provisioning; enforce strict permissions and update Ansible and docs
This commit is contained in:
104
scripts/provision_dirs.sh
Normal file
104
scripts/provision_dirs.sh
Normal file
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
# Provision quarantine and state directories for upload-logger
|
||||
# Usage: sudo ./provision_dirs.sh [--config path/to/upload-logger.json]
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
CFG="${1:-$ROOT_DIR/upload-logger.json}"
|
||||
|
||||
QUIET=0
|
||||
if [[ "${2:-}" == "--quiet" ]]; then QUIET=1; fi
|
||||
|
||||
info(){ if [[ $QUIET -ne 1 ]]; then echo "[INFO] $*"; fi }
|
||||
err(){ echo "[ERROR] $*" >&2; }
|
||||
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
err "This script must be run as root to set ownership and SELinux contexts."
|
||||
err "Rerun as: sudo $0"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Defaults
|
||||
QUARANTINE_DIR_DEFAULT="$ROOT_DIR/quarantine"
|
||||
STATE_DIR_DEFAULT="$ROOT_DIR/state"
|
||||
QUARANTINE_OWNER_DEFAULT="root"
|
||||
QUARANTINE_GROUP_DEFAULT="www-data"
|
||||
QUARANTINE_PERMS_DEFAULT="0700"
|
||||
STATE_PERMS_DEFAULT="0750"
|
||||
SELINUX_FCONTEXT_DEFAULT="httpd_sys_rw_content_t"
|
||||
|
||||
QUARANTINE_DIR="$QUARANTINE_DIR_DEFAULT"
|
||||
STATE_DIR="$STATE_DIR_DEFAULT"
|
||||
QUARANTINE_OWNER="$QUARANTINE_OWNER_DEFAULT"
|
||||
QUARANTINE_GROUP="$QUARANTINE_GROUP_DEFAULT"
|
||||
QUARANTINE_PERMS="$QUARANTINE_PERMS_DEFAULT"
|
||||
STATE_PERMS="$STATE_PERMS_DEFAULT"
|
||||
SELINUX_FCONTEXT="$SELINUX_FCONTEXT_DEFAULT"
|
||||
|
||||
if [[ -f "$CFG" ]]; then
|
||||
info "Loading config from $CFG"
|
||||
# Use jq-like parsing with grep/sed to avoid requiring jq on systems
|
||||
QUARANTINE_DIR=$(grep -oP '"quarantine_dir"\s*:\s*"\K[^"]+' "$CFG" || echo "$QUARANTINE_DIR")
|
||||
STATE_DIR=$(grep -oP '"state_dir"\s*:\s*"\K[^"]+' "$CFG" || echo "$STATE_DIR")
|
||||
QUARANTINE_PERMS=$(grep -oP '"quarantine_dir_perms"\s*:\s*"\K[^"]+' "$CFG" || echo "$QUARANTINE_PERMS")
|
||||
QUARANTINE_OWNER=$(grep -oP '"quarantine_owner"\s*:\s*"\K[^"]+' "$CFG" || echo "$QUARANTINE_OWNER")
|
||||
QUARANTINE_GROUP=$(grep -oP '"quarantine_group"\s*:\s*"\K[^"]+' "$CFG" || echo "$QUARANTINE_GROUP")
|
||||
fi
|
||||
|
||||
info "Ensuring directories exist"
|
||||
mkdir -p -- "$QUARANTINE_DIR"
|
||||
mkdir -p -- "$STATE_DIR"
|
||||
|
||||
info "Setting permissions and ownership"
|
||||
chmod ${QUARANTINE_PERMS} "$QUARANTINE_DIR" || true
|
||||
chown ${QUARANTINE_OWNER}:${QUARANTINE_GROUP} "$QUARANTINE_DIR" || true
|
||||
chmod ${STATE_PERMS} "$STATE_DIR" || true
|
||||
chown ${QUARANTINE_OWNER}:${QUARANTINE_GROUP} "$STATE_DIR" || true
|
||||
|
||||
# Ensure existing files in quarantine are not world-readable/executable.
|
||||
if [[ -d "$QUARANTINE_DIR" ]]; then
|
||||
info "Hardening existing files in $QUARANTINE_DIR"
|
||||
# Set files to 0600 and directories to 0700
|
||||
find "$QUARANTINE_DIR" -type d -print0 | xargs -0 -r chmod 0700 || true
|
||||
find "$QUARANTINE_DIR" -type f -print0 | xargs -0 -r chmod 0600 || true
|
||||
chown -R ${QUARANTINE_OWNER}:${QUARANTINE_GROUP} "$QUARANTINE_DIR" || true
|
||||
fi
|
||||
|
||||
info "Verifying permissions"
|
||||
ls -ld "$QUARANTINE_DIR" "$STATE_DIR"
|
||||
|
||||
# SELinux handling (best-effort)
|
||||
if command -v getenforce >/dev/null 2>&1 && [[ "$(getenforce)" != "Disabled" ]]; then
|
||||
info "SELinux enabled on system; attempting to configure file context"
|
||||
if command -v semanage >/dev/null 2>&1; then
|
||||
info "Registering fcontext for $QUARANTINE_DIR -> $SELINUX_FCONTEXT"
|
||||
semanage fcontext -a -t ${SELINUX_FCONTEXT} "${QUARANTINE_DIR}(/.*)?" || true
|
||||
info "Registering fcontext for $STATE_DIR -> ${SELINUX_FCONTEXT}"
|
||||
semanage fcontext -a -t ${SELINUX_FCONTEXT} "${STATE_DIR}(/.*)?" || true
|
||||
info "Applying contexts with restorecon"
|
||||
restorecon -Rv "$QUARANTINE_DIR" "$STATE_DIR" || true
|
||||
else
|
||||
info "semanage not available; skipping fcontext registration. Install policycoreutils-python-utils or provide manual guidance."
|
||||
fi
|
||||
else
|
||||
info "SELinux not enabled or getenforce unavailable; skipping SELinux steps"
|
||||
fi
|
||||
|
||||
# Optional tmpfiles.d entry to recreate directories at boot (idempotent)
|
||||
TMPFILE="/etc/tmpfiles.d/upload-logger.conf"
|
||||
if [[ -w /etc/tmpfiles.d || $QUIET -eq 1 ]]; then
|
||||
info "Writing tmpfiles.d entry to ${TMPFILE}"
|
||||
cat > "$TMPFILE" <<EOF
|
||||
d ${QUARANTINE_DIR} ${QUARANTINE_PERMS} ${QUARANTINE_OWNER} ${QUARANTINE_GROUP} -
|
||||
d ${STATE_DIR} ${STATE_PERMS} ${QUARANTINE_OWNER} ${QUARANTINE_GROUP} -
|
||||
EOF
|
||||
else
|
||||
info "Skipping tmpfiles.d entry (no permission to write /etc/tmpfiles.d)"
|
||||
fi
|
||||
|
||||
info "Provisioning complete. Ensure PHP-FPM worker user can write to the state directory if needed."
|
||||
echo
|
||||
info "Summary:"
|
||||
stat -c "%U:%G %a %n" "$QUARANTINE_DIR" "$STATE_DIR" || true
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user