veilor-os/docs/research/2026-05-05-agent-wave/04-hardening-tier-2.md
veilor-org 49a2e2557e docs: 9-agent research wave findings — v0.5.32 blocker map
Logs the full output of the 9-agent deep-dive run on 2026-05-05 to
docs/research/2026-05-05-agent-wave/. Pulls every actionable finding
into one indexed location so v0.5.32 planning has a paper trail.

Files:
  docs/research/2026-05-05-agent-wave/README.md             — index
  docs/research/2026-05-05-agent-wave/01-...real-hardware.md — Plymouth + LUKS edge cases
  docs/research/2026-05-05-agent-wave/02-...firstboot-ux.md  — SDDM + first-boot UX
  docs/research/2026-05-05-agent-wave/03-...spike-plan.md    — bootc-image-builder 1-week spike
  docs/research/2026-05-05-agent-wave/04-...tier-2.md         — AppArmor + nftables + audit + homed
  docs/research/2026-05-05-agent-wave/05-...launch.md         — threat model + v0.7 launch checklist
  docs/research/2026-05-05-agent-wave/06-...log-capture.md    — virtio-9p host-share for anaconda logs
  docs/research/2026-05-05-agent-wave/07-...skel-branding.md  — /etc/skel gap audit
  docs/research/2026-05-05-agent-wave/08-...ci-hardening.md   — SHA-pin actions + SBOM + SLSA L3
  docs/research/2026-05-05-agent-wave/09-...failure-modes.md  — real-hardware pessimistic audit

Plus the prior linter-applied:
  docs/ROADMAP.md      — Lessons learned section, v0.5.32 active block,
                          v0.6 promotion of veilor-postinstall + veilor-doctor,
                          v0.7 bootc spike scheduled
  docs/THREAT-MODEL.md  — drafted by Agent 5; in/out scope, comparison
                          matrix, v0.7 launch checklist

Top blockers identified for v0.5.32 (cross-cited in README):
  1. Suspend/resume wifi death (kernel.modules_disabled=1)
  2. veilor-firstboot.service WantedBy=graphical.target
  3. kernel-upgrade grub drift
  4. USBGuard hash-rules problem (already learned on onyx)
  5. firewalld blocks tailscale0
  6. /etc/skel/ empty
  7. virtio-9p log capture replaces broken virtio-serial path

Wave + verifier pattern (per ROADMAP lessons learned #4) validated:
9 parallel agents on distinct topics produced converging blocker
list. The same pattern landed v0.5.31 four-bug fix from the prior
4-agent verification wave on v0.5.30 outcome.
2026-05-05 14:52:53 +01:00

125 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Hardening tier 2 — concrete plan
**Agent 4 of 9-agent wave, 2026-05-05.**
## Repo state already in tree
- `scripts/apparmor/` ships **3 profiles** (`thorium`, `veilor-power`,
`lm-studio`) — complain-mode, **not auto-loaded**. No browser/mail
/Element profile.
- `scripts/selinux/` ships custom `.te` modules — primary MAC.
- `overlay/etc/audit/plugins.d/veilor-remote.conf` +
`audisp-remote.conf.disabled` — **scaffold present, opt-in switch
missing**.
- `kickstart/veilor-os.ks` — single live-ks. Real LUKS install lives
in `overlay/usr/local/bin/veilor-installer` (generates ks at runtime).
- No nftables overlay. No homed scaffold. No `veilor-audit-shipping` CLI.
## Item-by-item plan
### 1. AppArmor stack with SELinux — M
Fedora 43 ships `apparmor-parser`/`libapparmor`. Kernel has both LSMs.
Stacking works since 5.1; SELinux stays primary, AppArmor confines
specific binaries by path. **No conflict** — they layer. Risk: AA
profiles based on Debian/Ubuntu paths fail on Fedora.
**Files:**
- `kickstart/veilor-os.ks` `%packages` add `apparmor-parser apparmor-utils apparmor-profiles`
- `overlay/etc/apparmor.d/veilor.d/` (new) — vendor profiles
`firefox`, `thunderbird`, `element-desktop`, `signal-desktop`
- `scripts/40-apparmor.sh` (new) — parses + sets all veilor profiles
to **complain** on first install (logs only, no break)
- `overlay/usr/local/bin/veilor-doctor` — adds AA status check
**Test:** `aa-status | grep complain` shows >=4 loaded; firefox writes
outside policy → audit.log denial.
### 2. systemd-homed opt-in — L
Default LUKS storage `homectl` drops key on suspend; resume needs PAM
unlock again — **breaks "lid open, keep working"**. Use
`--storage=fscrypt` on top of existing btrfs `/home` subvol —
suspend transparent, encrypts at rest with per-user key.
**Files:**
- `overlay/usr/local/bin/veilor-homed-enable` (new) — confirms warning,
runs `homectl create admin --storage=fscrypt --real-name="veilor admin"`
after migrating files
- `overlay/etc/pam.d/sddm` drop-in for `pam_systemd_home.so`
- doc in `docs/HARDENING.md`. **Not auto-run** — only via post-install.
### 3. nftables alongside firewalld — S
firewalld speaks nftables backend on F43 — they don't conflict;
firewalld owns `inet firewalld` table. veilor-os preset = separate
`inet veilor` table loaded by its own service.
**Files:**
- `overlay/etc/nftables/veilor.nft` (new) — table `inet veilor`:
ssh per-IP rate limit (5/min), ICMP rate limit, optional
`ip6 daddr ::/0 drop` toggled by sysctl-style `/etc/veilor/ipv6.disabled`,
anti-port-scan via `meter` set
- `overlay/etc/systemd/system/veilor-nftables.service` (new) —
`After=firewalld.service`
- `kickstart/veilor-os.ks` `%packages` add `nftables`, services-enabled
add `veilor-nftables`
**Test:** `nft list ruleset` shows both `firewalld` AND `veilor`;
`hping3 -S -p 22 --flood` from second VM gets rate-limited.
### 4. Audit log shipping — S
Plumbing **already in tree** (`audisp-remote.conf.disabled`,
`veilor-remote.conf` with `active=no`). What's missing: CLI to flip
the switch with cert pinning.
**Files:**
- `overlay/usr/local/bin/veilor-audit-shipping` (new)
- `enable HOST PORT FINGERPRINT` writes
`/etc/veilor/audit-pin.sha256`, copies `audisp-remote.conf.disabled`
`audisp-remote.conf` with substituted host/port, enables plugin
(`active=yes`), restarts auditd
- `disable` reverses
- audisp-remote speaks TLS directly; cert pinning via `verify_peer=yes`
+ `peer_cert_fingerprint`
- Use **self-signed pinned**, not LE — collectors are LAN/VPN
**Test:** stand up `rsyslog` listener on nullstone with self-signed
cert; run helper; trigger `sudo -i`; tail nullstone for AUTHPRIV
event; revoke cert → events stop with logged TLS error.
### 5. Installer kickstart split — needs re-scope, S
Roadmap item is **stale**. As of v0.5.30 we already do real LUKS+btrfs
in `veilor-installer` which generates ks at runtime. **Re-scope:**
extract that generated ks template into static
`kickstart/veilor-os-install.ks` (parameterised via `%include
/tmp/answers.ks`), so reviewable in repo and reusable headlessly.
**Files:**
- split `overlay/usr/local/bin/veilor-installer` heredoc into
`kickstart/veilor-os-install.ks`
- installer just writes answers + `cp` the ks
- CI lints both with `ksvalidator`
### 6. Audit baseline re-run — S
Mechanical: `cp security/audit-template.md
security/veilor-os-distro/2026-05-DD.md`, run on VM, target lower
findings count than v0.2's baseline.
## Order, dependencies, ship plan
Dependencies: (5) blocks (6) — audit a stable installer, not a
moving heredoc. Else parallel.
**Total effort:** 2S + 1S(rescope) + 1S + 1M + 1L ≈ **57 dev-days**.
- **v0.5.32 (small wins):** (4) audit shipping CLI + (3) nftables
preset. Both S, scaffold completion, pure overlay (no kickstart risk).
- **v0.5.33:** (5) ks split + (6) audit baseline re-run.
- **v0.6 (medium):** (1) AppArmor stack — package install + 4 profiles
+ doctor integration; complain-mode keeps blast radius zero.
- **v0.7 (big lift):** (2) systemd-homed — UX-disruptive, needs
migration helper + doc page + suspend/lock/swap testing.