78 lines
2.9 KiB
Bash
78 lines
2.9 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
# veilor-os — 40-apparmor: load veilor-shipped AppArmor profiles in
|
||
|
|
# COMPLAIN mode. v0.6 scope: "loaded, present, nothing breaks".
|
||
|
|
#
|
||
|
|
# Per docs/research/2026-05-05-agent-wave/04-hardening-tier-2.md, v0.6
|
||
|
|
# ships AppArmor stacked alongside SELinux, but every veilor-shipped
|
||
|
|
# profile stays in complain mode (logs only, no enforce). Real policy
|
||
|
|
# authoring is post-v0.6.
|
||
|
|
#
|
||
|
|
# Idempotent: profiles already in complain mode are skipped. Run as
|
||
|
|
# root during kickstart %post or post-install.
|
||
|
|
|
||
|
|
set -uo pipefail
|
||
|
|
|
||
|
|
GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; NC='\033[0m'
|
||
|
|
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
|
||
|
|
info() { echo -e "${YELLOW}[INFO]${NC} $*"; }
|
||
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||
|
|
err() { echo -e "${RED}[ERR]${NC} $*"; }
|
||
|
|
|
||
|
|
[[ $EUID -eq 0 ]] || { err "Must run as root"; exit 1; }
|
||
|
|
|
||
|
|
echo "════════════════════════════════════════════════════════"
|
||
|
|
echo " veilor-os :: 40-apparmor (complain mode only)"
|
||
|
|
echo "════════════════════════════════════════════════════════"
|
||
|
|
|
||
|
|
PROFILE_DIR=/etc/apparmor.d/veilor.d
|
||
|
|
|
||
|
|
# ── Sanity: tools present? ──
|
||
|
|
if ! command -v apparmor_parser >/dev/null 2>&1; then
|
||
|
|
warn "apparmor_parser not installed — skipping (package step missed?)"
|
||
|
|
exit 0
|
||
|
|
fi
|
||
|
|
if ! command -v aa-complain >/dev/null 2>&1; then
|
||
|
|
warn "aa-complain not installed (apparmor-utils missing) — skipping"
|
||
|
|
exit 0
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [[ ! -d $PROFILE_DIR ]]; then
|
||
|
|
info "$PROFILE_DIR not present — no veilor profiles to load"
|
||
|
|
exit 0
|
||
|
|
fi
|
||
|
|
|
||
|
|
# ── Walk every profile we ship and force complain mode ──
|
||
|
|
shopt -s nullglob
|
||
|
|
loaded=0
|
||
|
|
skipped=0
|
||
|
|
failed=0
|
||
|
|
|
||
|
|
for profile in "$PROFILE_DIR"/*; do
|
||
|
|
[[ -f $profile ]] || continue
|
||
|
|
name=$(basename "$profile")
|
||
|
|
|
||
|
|
# Already in complain mode? aa-status reports loaded profiles by
|
||
|
|
# internal profile name, not file path — best-effort match against
|
||
|
|
# the file basename to avoid re-parsing on repeat runs.
|
||
|
|
if command -v aa-status >/dev/null 2>&1 \
|
||
|
|
&& aa-status --complaining 2>/dev/null | grep -qE "(^|/)veilor-${name}([[:space:]]|$)"; then
|
||
|
|
info "$name already in complain mode — skipping"
|
||
|
|
skipped=$((skipped + 1))
|
||
|
|
continue
|
||
|
|
fi
|
||
|
|
|
||
|
|
info "loading $name (complain mode)"
|
||
|
|
if aa-complain "$profile" >/dev/null 2>&1; then
|
||
|
|
ok "$name → complain"
|
||
|
|
loaded=$((loaded + 1))
|
||
|
|
else
|
||
|
|
warn "$name failed to load (parser may reject stub on this kernel)"
|
||
|
|
failed=$((failed + 1))
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
|
||
|
|
echo "────────────────────────────────────────────────────────"
|
||
|
|
info "summary: loaded=$loaded skipped=$skipped failed=$failed"
|
||
|
|
ok "v0.6 AppArmor stub: complain-mode only — no enforcement, log-only"
|
||
|
|
exit 0
|