Fix stig over hardening of kiosk account

This commit is contained in:
Audiobuzz
2026-06-18 13:28:01 +00:00
parent 215b0eb10c
commit 6608818902
5 changed files with 118 additions and 8 deletions
+40
View File
@@ -91,6 +91,21 @@ evaluates 0 rules; (c) `stig-deviations.sh` flags an **INVALID SCAN** and exits
non-zero on 0-evaluated. **Re-run the hardened build** and confirm pass/fail
counts are non-zero before trusting any deviations report.
**FINDING 2026-06-18 (FIXED) — hardening locked the fleet out.** The first
genuinely-evaluated hardened image (app `215b0eb`) broke **both** login paths:
the Chromium kiosk dropped to a getty login prompt, and admin SSH was rejected
with `Permission denied (publickey)`. Root cause: STIG enables `pam_faillock`
(account phase) + password aging/inactivity, and the **kiosk + fleetadmin
accounts are passwordless / key-only**, so the hardened PAM *account* phase
treats them as expired/lockable (sshd key auth succeeds, then `pam_acct_mgmt`
fails). Fix (provisioner `2c-STIG-postfix`, runs after remediation): exempt the
two appliance accounts — `chage -M -1 -m 0 -I -1 -E -1` + `faillock --reset`;
kiosk uses a dedicated `/etc/pam.d/kiosk` (`PAMName=kiosk`, permissive account /
full session for seat); sshd gets an `account sufficient pam_succeed_if.so user
= fleetadmin` first-rule bypass. Scoped to those two accounts; everyone else
keeps full STIG. Justified as register deviation #10. **Bench-verify on rebuild:
kiosk renders + admin SSH works with hardening on.**
Remaining (future hardening, currently waived — see the register): FIPS,
firewall, per-host/rotatable admin access. **Remote audit offload — receiver
DONE** (`serving/audit-collector/`, rsyslog over TCP/514, per-source-host files;
@@ -517,3 +532,28 @@ smoke test.
secure `nvme connect` as the test path has.
- **Future hardening waived for now** (from the STIG register): FIPS, firewall,
remote audit offload, per-host/rotatable admin (SSH CA / config-agent).
## [ ] 9. (OPTIONAL / nice-to-have) Convert provisioning to Ansible where it pays off
Low priority — only the *config-management* half of the build is a candidate, and
the ROI is modest because the build VM is single-shot (idempotency buys little)
and reproducibility/auditability favour minimal shell. **Not** a wholesale
rewrite: the load-bearing logic (dracut module hook ordering, `extract-artifacts.sh`,
`build-oci.sh`) is initramfs-runtime / host-side build tooling, not provisioning,
and stays shell.
The high-ROI, low-risk slice if/when we pick this up:
- **STIG via the SSG Ansible playbook** (`ssg-rl9-playbook-stig.yml`, shipped
with scap-security-guide) instead of `oscap --remediate` — the upstream path
and far more *reviewable* (you can diff exactly what each rule changes). Keep
`oscap eval` (no remediate) for the report + the 0-eval guard (item #2).
- Restyle the brittle imperative bits as declarative tasks: chrony.conf edit
(`lineinfile`/`blockinfile` vs `sed`), sshd drop-in / NM dispatcher / kiosk
file installs (`template`/`copy`), datastream-by-`os-release` as `assert`.
Bonus: sidesteps the `%{...}`→`%%{` HCL-escaping footgun.
Tips the balance toward "do it" only if: we start managing the **serving hosts**
(dnsmasq/nginx/SPDK/chrony/audit-collector) with config-management too (shared
roles to amortise — currently they're docker-compose), provisioning grows much
more branchy, or we want molecule-tested hardening roles validated without a
full ~17-min Packer build.