docs/TODO: add #16 — enable a locked-down firewalld (defense-in-depth + STIG passes)

Captures the decision to re-enable a CONFIGURED firewalld (currently removed),
the required .pyc/-T0 root-cause fix (compileall --unchecked-hash), the 4 STIG
waivers it converts, and the load-bearing NVMe/TCP-survives-firewalld bench gate.
This commit is contained in:
Audiobuzz
2026-07-03 01:31:03 +00:00
parent 4a8143d0bc
commit 33de300af8
+35
View File
@@ -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.