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.
+4 -2
View File
@@ -30,6 +30,7 @@ Posture decisions (2026-06-18, lab phase):
| 7 | **Smart card login** (`require_smart_card_login`, `sssd_enable_smartcard`, `install_smartcard_packages`) | Diskless hosts have no smartcard reader; admin access is SSH key-based. Enforcing smartcard login would lock the host out. | Admin auth is an SSH **key-only** account; root is locked; password auth disabled. |
| 8 | **NOPASSWD sudo** (`sudo_remove_nopasswd`) | The baked admin is a **passwordless, key-only** account, so `sudo` cannot prompt for a password — NOPASSWD is required for it to function at all. | Single fleet-generic admin, key-only, `wheel`; no interactive password exists to protect. Tracked for the eventual per-host/rotatable access model (SSH CA / config-agent). |
| 9 | **GUI / autologin / GDM** (gnome screensaver, GDM banner, automatic-login rules) | No GNOME/GDM is installed; the kiosk is an **intentional** autologin single-app (weston + Chromium) session on kiosk builds. | Kiosk user is unprivileged and passwordless; the session runs a single locked-down browser (no shell, no nav). Applies to kiosk builds only; non-kiosk builds don't install the GUI stack. |
| 10 | **Password aging / faillock on the key-only APPLIANCE ACCOUNTS** (`accounts_*_age_*`, `account_disable_post_pw_expiration`, `pam_faillock` account phase) — applied to the *system* but **exempted for the `fleetadmin` and `kiosk` users** | These two accounts are **passwordless / key-only**. The hardened PAM *account* phase (faillock + password aging/inactivity) treats a passwordless account as expired/lockable, which **locked the fleet out**: the kiosk autologin session never opened (getty kept tty1) and sshd denied the valid key with `Permission denied (publickey)` (pubkey auth succeeds, then `pam_acct_mgmt` fails). Fixed 2026-06-18. | The exemption is **scoped to these two appliance accounts only** (post-STIG `chage -M -1 -m 0 -I -1 -E -1` + `faillock --reset`; kiosk uses a dedicated `/etc/pam.d/kiosk`; sshd gets an `account sufficient pam_succeed_if.so user = fleetadmin` bypass as its first account rule). Every other account keeps the full STIG password policy + faillock. These accounts have **no password to age** and (key-only, `PasswordAuthentication no`) **no password-auth path for faillock to protect**. Folds into the per-host/rotatable access model (SSH CA / config-agent). |
## Things that are NOT deviations (kept / enforced)
@@ -39,8 +40,9 @@ Posture decisions (2026-06-18, lab phase):
key-only (drop-in `50-fleet-hardening.conf`); STIG ciphers/MACs/KEX applied.
- **No per-host state**: SSH host keys stripped at build, regenerated at first
boot into the overlay; `machine-id` empty.
- Password-policy / faillock rules remain selected — harmless (no interactive
passwords) and keep the report honest.
- Password-policy / faillock rules remain **selected and applied system-wide**
(kept honest in the report); they are exempted only for the two key-only
appliance accounts — see deviation #10.
## How to read the generated report