diff --git a/diskless.pkr.hcl b/diskless.pkr.hcl index 4a69e5a..34b7d4e 100644 --- a/diskless.pkr.hcl +++ b/diskless.pkr.hcl @@ -531,14 +531,17 @@ build { destination = "${var.artifact_dir}/${var.image_version}/stig-arf.xml" } - # --- 2c-STIG-postfix. Keep the key-only APPLIANCE ACCOUNTS usable after STIG. - # STIG turns on pam_faillock (account phase) + password aging/inactivity - # (account_disable_post_pw_expiration, accounts_*_age_*). The kiosk autologin - # user and the fleet admin are PASSWORDLESS / key-only, so the hardened account - # phase rejects them: the kiosk PAM session never opens (getty keeps tty1), and - # sshd denies the otherwise-valid key as "Permission denied (publickey)" (key - # auth succeeds, then pam_acct_mgmt fails). Runs AFTER remediation so STIG can't - # re-break it. Justified in docs/stig-deviations.md (#10, appliance accounts). + # --- 2c-STIG-postfix. Undo the STIG settings that lock out this architecture. + # Runs AFTER remediation so STIG can't re-break it. Two fixes: + # (a) APPLIANCE ACCOUNTS: STIG enables pam_faillock (account phase) + password + # aging/inactivity. The kiosk + fleet-admin accounts are PASSWORDLESS / + # key-only, so the hardened account phase rejects them (kiosk session never + # opens; sshd account phase denies). Exempt just those two accounts. + # (b) fapolicyd: STIG's app-allowlisting blocks non-RPM executables, killing + # the kiosk (ExecStart=/usr/local/bin/kiosk-session). Keep fapolicyd (it's + # the exec-guard for the writable overlay that dm-verity can't cover) and + # trust the custom kiosk binary instead of disabling it. + # Both justified in docs/stig-deviations.md (#10). provisioner "shell" { environment_vars = [ "ENABLE_STIG=${var.enable_stig}", @@ -565,6 +568,17 @@ build { " restorecon /etc/pam.d/sshd", " echo \"==> /etc/pam.d/sshd: account-stack bypass ensured for $ADMIN_USER\"", "fi", + # fapolicyd (STIG app-allowlisting) blocks execution of any non-RPM file. + # The kiosk's ExecStart=/usr/local/bin/kiosk-session is exactly that, so + # fapolicyd kills the kiosk. KEEP fapolicyd (it's the real exec-guard for the + # writable RAM overlay, which dm-verity does NOT cover) and instead TRUST the + # custom kiosk files: add them to fapolicyd's trust DB and rebuild it. weston + # /chromium are RPM-installed so already trusted. (See docs/stig-deviations.md.) + "if command -v fapolicyd-cli >/dev/null 2>&1; then", + " for f in /usr/local/bin/kiosk-session; do { [ -f \"$f\" ] && fapolicyd-cli --file add \"$f\"; } || true; done", + " fapolicyd-cli --update 2>/dev/null || true", + " echo '==> fapolicyd: trusted custom kiosk binaries + rebuilt trust db'", + "fi", ] } diff --git a/docs/TODO.md b/docs/TODO.md index 358b30e..32b1cd6 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -106,6 +106,24 @@ full session for seat); sshd gets an `account sufficient pam_succeed_if.so user keeps full STIG. Justified as register deviation #10. **Bench-verify on rebuild: kiosk renders + admin SSH works with hardening on.** +**UPDATE 2026-06-19 — offline erofs inspection of the hardened image (mounted +`rootfs.erofs` read-only) pinned the real causes; the PAM-account theory above +was incomplete:** +- **Kiosk = fapolicyd (CONFIRMED).** fapolicyd is `enabled` and `kiosk-session` + was not in its trust → it blocks `/usr/local/bin/kiosk-session`. Fix: KEEP + fapolicyd (it's the exec-guard for the writable overlay dm-verity can't cover) + and add the kiosk binary to its trust DB at build (2c-STIG-postfix). Not waived. +- **SSH = NOT a STIG/PAM/SELinux issue.** `enforcing=0` didn't help; pam_namespace + is inert (empty namespace.conf); account bypass present; key file + perms + + sshd config all correct. Remaining cause: **baked key mismatch** — the + `SSH_AUTHORIZED_KEY` CI secret bakes `audiobuzz@s3` + (`SHA256:30p4vOQdWk0TdRQIR3VMo95yc6I7cRmCwIBRVjIHaV4`); if the client uses a + different private key → `Permission denied (publickey)`. AWAITING client + fingerprint / `ssh -vvv` to confirm; fix is the secret, not code. +- Side note: SMBIOS cmdline-extra injection works only after a Proxmox VM + **stop/start** (not `reset`); and the debug-shell-on-tty2 attempt did not come + up — diagnosis ended up done via offline erofs mount instead. + Remaining (future hardening, currently waived — see the register): FIPS, firewall, per-host/rotatable admin access. **Remote audit offload — WIRED both ends** (2026-06-19): receiver `serving/audit-collector/` (rsyslog TCP/514, diff --git a/docs/stig-deviations.md b/docs/stig-deviations.md index 1f3f5ec..c08443e 100644 --- a/docs/stig-deviations.md +++ b/docs/stig-deviations.md @@ -37,6 +37,12 @@ Posture decisions (2026-06-18, lab phase): ## Things that are NOT deviations (kept / enforced) - **SELinux enforcing** (`selinux --enforcing`; labels preserved into the erofs). +- **fapolicyd** kept **enabled** (NOT waived) — it's the real exec-allowlist guard + for the writable RAM overlay, which dm-verity does **not** cover. The only + adjustment: the one non-RPM executable, `/usr/local/bin/kiosk-session`, is added + to fapolicyd's trust DB at build (provisioner 2c-STIG-postfix) so the kiosk runs; + everything else stays RPM-trust-only. (fapolicyd blocking that binary was the + original kiosk-won't-start cause.) - **auditd** enabled; STIG audit rules applied; logs locally. - **sshd hardening**: root login off, password & keyboard-interactive auth off, key-only (drop-in `50-fleet-hardening.conf`); STIG ciphers/MACs/KEX applied.