From 5e2bfef575d02def941b5785d5e7ae5fb246850e Mon Sep 17 00:00:00 2001 From: Audiobuzz Date: Fri, 19 Jun 2026 00:06:39 +0000 Subject: [PATCH] Add banner and debug shell --- diskless.pkr.hcl | 64 +++++++++++++++++++++++++++++++++++++++- docs/stig-deviations.md | 2 ++ files/banner/fleet-issue | 18 +++++++++++ 3 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 files/banner/fleet-issue diff --git a/diskless.pkr.hcl b/diskless.pkr.hcl index b283969..f7b1fec 100644 --- a/diskless.pkr.hcl +++ b/diskless.pkr.hcl @@ -136,6 +136,12 @@ variable "enable_stig" { default = true } +variable "debug_shell" { + type = bool + description = "DEBUG/LAB ONLY. true: enable systemd's debug-shell.service — a passwordless root /bin/sh on tty2 (Ctrl+Alt+F2) that bypasses login/PAM entirely. (Placed on tty2, with the login getty there masked, because constrained consoles often expose only tty1-6; tty1 stays the kiosk.) Use to get into a hardened image when login is broken (locked root + key-only accounts). This is a deliberate security hole; NEVER ship it. Default false." + default = true +} + variable "sb_key" { type = string description = "Secure Boot signing key (PEM) for the UKI. Empty = unsigned lab build. Production: CI/HSM-held; never enters the build VM." @@ -412,7 +418,10 @@ build { # the main config) overrides the ks's PermitRootLogin yes. Takes effect on # the next boot only (sshd isn't restarted), so the live build session is # unaffected. - "printf 'PermitRootLogin no\\nPasswordAuthentication no\\nKbdInteractiveAuthentication no\\n' > /etc/ssh/sshd_config.d/50-fleet-hardening.conf", + # Banner: show the fleet (starship) login notice pre-auth. The banner file + # itself is written by the '2e. Fleet login banner' step below (after STIG, + # so it overrides the DoD banner). Set here too so it works with enable_stig=false. + "printf 'PermitRootLogin no\\nPasswordAuthentication no\\nKbdInteractiveAuthentication no\\nBanner /etc/issue.net\\n' > /etc/ssh/sshd_config.d/50-fleet-hardening.conf", "chmod 0644 /etc/ssh/sshd_config.d/50-fleet-hardening.conf", "restorecon /etc/ssh/sshd_config.d/50-fleet-hardening.conf", # Guarantee sshd is enabled (it's our ONLY way in once root is locked and @@ -426,6 +435,35 @@ build { ] } + # --- 2c-debug. Break-glass root shell (DEBUG/LAB ONLY) ------------------- + # debug_shell=true enables systemd's debug-shell.service: a passwordless root + # /bin/sh on tty9 (Ctrl+Alt+F9) that does NOT go through login/PAM — so you can + # get into a hardened image even when root is locked, the accounts are key-only, + # and login/sshd are broken. This is a deliberate security hole for diagnosing + # boot/login regressions; never ship it. The symlink into sysinit.target.wants + # guarantees it starts early regardless of the unit's [Install] section. + provisioner "shell" { + environment_vars = ["DEBUG_SHELL=${var.debug_shell}"] + inline = [ + "set -e", + "if [ \"$DEBUG_SHELL\" != \"true\" ]; then echo 'debug_shell=false -> no debug shell baked.'; exit 0; fi", + "echo '############################################################'", + "echo '## WARNING: debug_shell=true — PASSWORDLESS ROOT on tty2. ##'", + "echo '## DEBUG/LAB IMAGE ONLY. Do NOT deploy to production. ##'", + "echo '############################################################'", + "systemctl enable debug-shell.service 2>/dev/null || true", + "mkdir -p /etc/systemd/system/sysinit.target.wants", + "ln -sf /usr/lib/systemd/system/debug-shell.service /etc/systemd/system/sysinit.target.wants/debug-shell.service", + # Default debug-shell is tty9 (outside the getty range) — but constrained + # consoles (noVNC/SPICE) often only expose tty1-6. Move it to tty2, which + # IS reachable, and mask the login getty there so they don't fight over the + # VT. Result: Ctrl+Alt+F2 = passwordless root shell. (tty1 stays the kiosk.) + "mkdir -p /etc/systemd/system/debug-shell.service.d", + "printf '[Service]\\nTTYPath=/dev/tty2\\n' > /etc/systemd/system/debug-shell.service.d/tty.conf", + "systemctl mask getty@tty2.service autovt@tty2.service 2>/dev/null || true", + ] + } + # --- 2c-STIG. DISA STIG hardening (OpenSCAP + SSG), diskless/UKI/kiosk tailored # Runs after admin (so it hardens the full system incl. the admin/sshd config) # and BEFORE hygiene 2d (so 2d can strip the scanner tooling + reports). The @@ -524,6 +562,30 @@ build { ] } + # --- 2e. Fleet login banner (starship-themed) ---------------------------- + # Replaces the DoD/USG warning banner STIG writes (banner_etc_issue*) with the + # fleet (ISV AURELIAN) notice. Runs AFTER the STIG step so it overrides what + # remediation wrote; the sshd 'Banner /etc/issue.net' directive is set in 2c. + # Keeps a (themed) monitored/authorized-only notice — that warning is the + # banner's actual security purpose; only the wording changes. This makes the + # STIG banner-content rules fail by design (documented: stig-deviations.md #11). + provisioner "file" { + source = "files/banner" + destination = "/tmp/" + } + provisioner "shell" { + inline = [ + "set -eux", + # /etc/issue = console getty (pre-login); issue.net = SSH pre-auth banner; + # motd = post-login. Same fleet notice in all three. + "install -D -m0644 /tmp/banner/fleet-issue /etc/issue", + "install -D -m0644 /tmp/banner/fleet-issue /etc/issue.net", + "install -D -m0644 /tmp/banner/fleet-issue /etc/motd", + "restorecon /etc/issue /etc/issue.net /etc/motd", + "rm -rf /tmp/banner", + ] + } + # --- 2d. Final image hygiene: strip caches/logs after the LAST dnf step -- # MUST be the last provisioner. The `dnf clean all` in step 2 runs BEFORE the # kiosk (2b) and admin (2c) provisioners, and 2b enables EPEL + installs diff --git a/docs/stig-deviations.md b/docs/stig-deviations.md index ab0b099..1073538 100644 --- a/docs/stig-deviations.md +++ b/docs/stig-deviations.md @@ -32,6 +32,8 @@ Posture decisions (2026-06-18, lab phase): | 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). | +| 11 | **Login banner content** (`banner_etc_issue`, `banner_etc_issue_net`, `banner_etc_motd`) | STIG requires the verbatim DoD/USG "you are accessing a U.S. Government Information System" text. This is a fictional starship fleet, not a USG system, so `/etc/issue{,.net}` + `/etc/motd` carry the fleet (ISV AURELIAN) notice instead (provisioner step 2e, `files/banner/fleet-issue`). The content rules therefore fail by design. | The banner **keeps its security function**: it still states authorized-crew-only, that the terminal is monitored/logged, and that unauthorized access is prohibited — only the wording is themed. `sshd_enable_warning_banner` (Banner is shown) still passes. | + ## Things that are NOT deviations (kept / enforced) - **SELinux enforcing** (`selinux --enforcing`; labels preserved into the erofs). diff --git a/files/banner/fleet-issue b/files/banner/fleet-issue new file mode 100644 index 0000000..acf509f --- /dev/null +++ b/files/banner/fleet-issue @@ -0,0 +1,18 @@ ++===================================================================+ +| | +| I S V A U R E L I A N | +| | +| Lancer-class Deep Survey Cruiser | +| Fleet Registry FN-774 | +| | ++===================================================================+ +| | +| AUTHORIZED CREW ONLY. This terminal is bonded to the ship's | +| core AI; every keystroke is logged to the bridge. Unauthorized | +| access is a breach of the Fleet Charter and will be met with | +| containment protocols. If you are not cleared for this vessel, | +| disconnect now and report to your duty station. | +| | +| Safe travels, and mind the airlocks. | +| | ++===================================================================+