diff --git a/docs/TODO.md b/docs/TODO.md index 7a21b37..3ab4651 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -1401,3 +1401,38 @@ bench (`serving/dot1x-bench/`) + careful SELinux-label verification + a reconcil note in `design-v2-errata.md`. **Do AFTER TPM enrolment (#11) is bench-verified.** Tailoring edits: re-select the 6 `partition_for_*` (+dev_shm), delete/gut register entry #1, re-run `scripts/stig-deviations.sh` to confirm the new passes. + +## [ ] 16. Enable a locked-down host firewall (firewalld) — defense-in-depth + STIG passes + +**DECISION 2026-07-03: enable a *configured* firewalld.** Currently REMOVED + masked +(`diskless.pkr.hcl` 2d, commit 4346ce7) because an UNCONFIGURED weak-dep firewalld was +running and flooding the SIEM with `lib_t` `.pyc` AVCs. The design deferred the firewall +as "future hardening, currently waived" ([stig-deviations.md](stig-deviations.md) #4) — +NOT incompatible, just unverified during boot-chain bring-up. A diskless kiosk is an +ideal firewall candidate: near-zero legit inbound (admin SSH only; `fleet-hostapi` is +loopback), and the load-bearing paths are outbound (NVMe/TCP, DHCP) or L2 (EAPOL/MACsec). + +**Payoff:** defense-in-depth (limits a compromised same-segment peer) + converts **4 +STIG waivers → passes** (`service_firewalld_enabled`, `package_firewalld_installed`, +`set_firewalld_default_zone`, `configured_firewalld_default_deny` — re-select in the +tailoring; retires deviation-register #4). + +**Must do together:** +1. **Config:** default-DENY inbound zone; allow **SSH** (key-only admin) + + established/related; assign `macsec0` (secure) / `en*` (test) to it. hostapi + (:9099 loopback) + kiosk→hostapi PNA need no rule. +2. **Fix the `.pyc` AVC root cause (REQUIRED — an enabled firewalld re-hits it):** the + reproducible erofs `-T 0` zeroes mtimes, so Python thinks every site-package `.pyc` + is stale and rewrites it → `firewalld_t` (and ANY Python daemon, e.g. `tuned`) + write/unlink AVCs on `lib_t`. Fix once with `python3 -m compileall --invalidation-mode + unchecked-hash` over the Python trees BEFORE the erofs build → mtime-independent + `.pyc`, no rewrites, and MORE reproducible. (Worth doing regardless of firewalld — + it's the true root cause of the firewalld AVCs seen 2026-07-03.) +3. **Tailoring:** re-select the 4 firewalld rules. + +**THE load-bearing bench gate (why #4 deferred it):** the NVMe/TCP root is an OUTBOUND +connection to `:4420` established in the initramfs BEFORE firewalld starts. Verify it +**SURVIVES** firewalld start + `firewall-cmd --reload` (established/related allowed by +default → should, but UNVERIFIED); a reconnect within `ctrl_loss_tmo` re-establishes +*through* the firewall; DHCP renew + MKA keepalives unaffected; SSH in; no AVCs; verity +hash reproducible. If it drops the root, that is the fleet-wide outage risk — gate hard.