CR: P16g AppArmor Deployment — Implementation
Implementation Plan
Phase 1: Install & Enable (Day 1)
1a. Install AppArmor userspace
sudo pacman -S apparmor
| Package | Purpose |
|---|---|
|
Meta-package: parser, utilities, profiles, systemd service |
1b. Enable AppArmor in boot parameters
AppArmor is compiled into the Arch kernel but must be activated via kernel command line.
# BEFORE — check current boot parameters
cat /proc/cmdline
# Find the loader entry
ls /boot/loader/entries/
# Read current entry
cat /boot/loader/entries/arch.conf
Three boot entries exist: arch.conf, arch-fallback.conf, arch-lts.conf. All three must be updated.
|
Lesson learned during execution: The Also fixed: |
# BEFORE — verify all three entries
grep '^options' /boot/loader/entries/arch.conf
grep '^options' /boot/loader/entries/arch-fallback.conf
grep '^options' /boot/loader/entries/arch-lts.conf
# APPLY — full-line replacement (one line each, no wrapping)
# arch.conf
sudo sed -i 's|^options.*|options cryptdevice=UUID=a33cc5e6-0e54-4aa4-bc26-d08a212aa32a:cryptroot root=/dev/mapper/cryptroot rootflags=subvol=@ rw nvidia_drm.modeset=1 mem_sleep_default=s2idle acpi_mask_gpe=0x6E lsm=landlock,lockdown,yama,integrity,apparmor,bpf apparmor=1 security=apparmor|' /boot/loader/entries/arch.conf
# arch-fallback.conf
sudo sed -i 's|^options.*|options cryptdevice=UUID=a33cc5e6-0e54-4aa4-bc26-d08a212aa32a:cryptroot root=/dev/mapper/cryptroot rootflags=subvol=@ rw nvidia_drm.modeset=1 mem_sleep_default=s2idle acpi_mask_gpe=0x6E lsm=landlock,lockdown,yama,integrity,apparmor,bpf apparmor=1 security=apparmor|' /boot/loader/entries/arch-fallback.conf
# arch-lts.conf
sudo sed -i 's|^options.*|options cryptdevice=UUID=a33cc5e6-0e54-4aa4-bc26-d08a212aa32a:cryptroot root=/dev/mapper/cryptroot rootflags=subvol=@ rw nvidia_drm.modeset=1 mem_sleep_default=s2idle acpi_mask_gpe=0x6E lsm=landlock,lockdown,yama,integrity,apparmor,bpf apparmor=1 security=apparmor|' /boot/loader/entries/arch-lts.conf
# VERIFY — all three entries, full file review
cat /boot/loader/entries/arch.conf
cat /boot/loader/entries/arch-fallback.conf
cat /boot/loader/entries/arch-lts.conf
options cryptdevice=UUID=a33cc5e6-0e54-4aa4-bc26-d08a212aa32a:cryptroot root=/dev/mapper/cryptroot rootflags=subvol=@ rw nvidia_drm.modeset=1 mem_sleep_default=s2idle acpi_mask_gpe=0x6E lsm=landlock,lockdown,yama,integrity,apparmor,bpf apparmor=1 security=apparmor
1c. Enable AppArmor service
sudo systemctl enable apparmor.service
1d. Reboot and verify
sudo reboot
After reboot:
# Verify LSM stack
cat /sys/kernel/security/lsm
# Verify AppArmor is active
aa-enabled
# Check loaded profiles
sudo aa-status
Phase 2: Complain-Mode Baseline (Day 1-3)
2a. Load default profiles in complain mode
# Set all profiles to complain mode (logs violations but doesn't block)
sudo aa-complain /etc/apparmor.d/*
# Verify profile count
sudo aa-status | head -10
2b. Use the system normally for 2-3 days
Normal usage generates audit logs showing what each application accesses. This data informs custom profiles.
# Monitor AppArmor audit events
sudo journalctl -k | grep -i apparmor | tail -20
# Generate profile suggestions from logs
sudo aa-logprof
Phase 3: Enforce High-Risk Profiles (Day 3-7)
3a. Identify high-risk applications
| Application | Risk | Priority |
|---|---|---|
Firefox / Chromium |
Browser exploits → credential exfiltration |
High |
node / npm |
Supply chain attacks via npm packages |
High |
Docker daemon |
Container escape → host filesystem |
High |
python / pip |
Malicious packages |
Medium |
Claude Code (node-based) |
Broad filesystem access by design |
Medium — profile carefully |
3b. Create custom deny rules for credential stores
The critical protection: deny high-risk apps access to sensitive directories.
# Example: deny Firefox access to credential stores
# /etc/apparmor.d/local/usr.bin.firefox
deny owner @{HOME}/.secrets/ rw,
deny owner @{HOME}/.secrets/** rw,
deny owner @{HOME}/.gnupg/ rw,
deny owner @{HOME}/.gnupg/** rw,
deny owner @{HOME}/.age/ rw,
deny owner @{HOME}/.age/** rw,
deny owner @{HOME}/.local/share/gopass/ rw,
deny owner @{HOME}/.local/share/gopass/** rw,
deny owner @{HOME}/.ssh/id_* rw,
3c. Enforce profiles for verified applications
# Switch from complain to enforce (one at a time, test each)
sudo aa-enforce /etc/apparmor.d/usr.bin.firefox
# Verify enforcement
sudo aa-status | grep -A2 enforce
Phase 4: Docker Confinement (Day 7+)
# Verify Docker uses AppArmor by default
docker info | grep -i apparmor
# Run a test container and verify AppArmor profile is applied
docker run --rm alpine cat /proc/self/attr/current