Update SSP

This commit is contained in:
Audiobuzz
2026-06-25 23:46:42 +00:00
parent dea7ca451a
commit c3507cda6e
5 changed files with 232 additions and 40 deletions
+150 -9
View File
@@ -572,13 +572,67 @@ this item builds the rollout machinery around it.
stay served); security rollback via dbx-revoke / TPM monotonic counter stay served); security rollback via dbx-revoke / TPM monotonic counter
(design §6). (design §6).
- **Drain & retire** an old version only when SPDK/nvmet reports zero connected - **Drain & retire** an old version only when SPDK/nvmet reports zero connected
controllers on it. controllers on it. **Drain accuracy:** account for hosts powered off mid-rollout
— an assigned-but-offline host will reconnect to a version that may be gone, so
don't remove a version while any host that could return is still assigned to it.
- **Availability**: run NVMe/TCP target replicas behind distinct discovery - **Availability**: run NVMe/TCP target replicas behind distinct discovery
entries (design §7) — never serve the whole fleet from one unreplicated node, entries (design §7) — never serve the whole fleet from one unreplicated node,
especially mid-rollout (N versions + reboot bursts). especially mid-rollout (N versions + reboot bursts).
- Note: kiosk *content* changes are server-side (the website) and need no fleet - Note: kiosk *content* changes are server-side (the website) and need no fleet
update — only OS/UKI/rootfs changes require a reboot. update — only OS/UKI/rootfs changes require a reboot.
### SPDK restart / availability is the load-bearing constraint (analysis 2026-06-25)
SPDK sits in the **live data path of every running host's root fs**, so a process
restart isn't like restarting a stateless service — it tears down **every**
NVMe/TCP association at once (fleet-wide, NOT version-scoped). The rollout design
must be built around **never restarting the process that holds live connections.**
- **Core principle:** a host changes root version *only by rebooting* (no live
swap). So: **version transitions = reboots; SPDK changes = additive/online; the
process stays up.** Routine rollouts never restart SPDK.
- **Online add/remove via JSON-RPC, no restart.** `nvmf_tgt` is fully
runtime-configurable (`bdev_aio_create`, `nvmf_create_subsystem`,
`nvmf_subsystem_add_ns`, `..._add_listener`). Add vY's namespaces live (existing
vX connections untouched); remove vX live once drained. **Per-version subsystem
(distinct NQN)** matters here: adding vY as a *new subsystem* never disturbs the
subsystem vX hosts are attached to — adding a *namespace* to a shared subsystem
fires a namespace-change AER + rescan at running hosts. Per-version subsystem
also gives clean per-release drain + per-release hostNQN allow-listing.
- **What a connection loss does to a running host:** root is **read-only erofs +
tmpfs overlay**. tmpfs writes (RAM) + page-cached reads keep working; **cold
reads block**. The nvme-tcp host driver reconnects (`reconnect_delay`) until
`ctrl_loss_tmo`. **Fast SPDK restart** (same NQN/UUID/addr within the window) →
host **survives with a stall**; **long/changed/expired** → root I/O errors, host
needs a reboot ("keep alive timeout / no route to host"). Read-only +
content-addressed makes reconnect unusually clean (no write/reservation state).
- **Cheap host-side mitigation:** tune `ctrl_loss_tmo` (even `-1` = retry forever)
+ `reconnect_delay` at `nvme connect` time (dracut nvmf step). For a diskless box
"hang and recover" beats "die" — there's nothing better to fail to.
- **Structural answer — HA + NVMe-oF multipath (ANA):** run ≥2 targets serving
**byte-identical, same-UUID** namespaces; hosts multipath across them, so one
target can be restarted/upgraded while the other serves (no root loss). The
**read-only, content-addressed root makes replication trivially coherent** (no
write-coherence problem) — this architecture is ideally suited to it. Wrinkle:
the **immutable UKI cmdline** points at one discovery address, so multipath needs
discovery to return multiple paths (or a DNS name resolving to several targets).
- **Planned SPDK restarts only via drain/failover** (multipath fail-over, or a
maintenance window with generous `ctrl_loss_tmo` so hosts recover not die). There
is **no zero-impact single-node SPDK restart.**
- **Implementation gap (current lab):** SPDK runs as a container with
`spdk-setup.sh` as entrypoint + the artifact image mounted → effectively
**single-version, configured at container start**, so changing versions =
container restart = drop all connections. The work here is a **long-lived target
+ an RPC-driven control path** ("add release / remove release / drain status")
decoupled from container lifecycle, with per-version subsystems.
- **Capacity:** each concurrently-served version costs target memory/hugepages +
file-backed bdev overhead — plan for N live versions (current + previous +
canary) during long rollouts.
- **Attach gating + discovery:** with several subsystems advertised, the dracut
connect + per-subsystem hostNQN allow-list must ensure a vX host attaches **only**
vX's namespace (the by-UUID verity ref protects *what mounts*, but gate the
*attach* too); `rd.nvmf.discover` selection must be deterministic, not connect-all.
## [ ] 7. Harden / evaluate the NVMe-oF target (serving-node resilience) ## [ ] 7. Harden / evaluate the NVMe-oF target (serving-node resilience)
There is **no production-grade memory-safe NVMe-oF target** — the Rust NVMe work There is **no production-grade memory-safe NVMe-oF target** — the Rust NVMe work
@@ -607,7 +661,13 @@ export is read-only + single-namespace = inherently small attack surface.
- **Network-isolate :4420** so only the boot VLAN reaches the target (compose - **Network-isolate :4420** so only the boot VLAN reaches the target (compose
with 802.1X/MACsec segmentation in prod). with 802.1X/MACsec segmentation in prod).
- **Replicas** behind distinct discovery entries (availability is the real risk - **Replicas** behind distinct discovery entries (availability is the real risk
— it's the fleet's disk). Ties into #6 (rolling updates) availability. — it's the fleet's disk). The target is a **fleet-wide SPOF in every running
host's root data path**; a process restart drops *all* NVMe/TCP associations at
once. Structural fix = **HA + NVMe-oF multipath (ANA)** over byte-identical,
same-UUID, read-only namespaces (replication is coherent precisely because the
root is read-only + content-addressed); cheap mitigation = generous host
`ctrl_loss_tmo`/`reconnect_delay`. See the **"SPDK restart / availability"**
analysis under #6 (rolling updates) — same constraint, fuller treatment.
- Revisit a memory-safe target only if/when an off-the-shelf one matures - Revisit a memory-safe target only if/when an off-the-shelf one matures
(e.g. a future Rust-for-Linux `nvmet`). (e.g. a future Rust-for-Linux `nvmet`).
@@ -631,6 +691,13 @@ smoke test.
documented upgrade on the same CA. **BENCH-VERIFY** items flagged in the files: documented upgrade on the same CA. **BENCH-VERIFY** items flagged in the files:
hostapd MACsec build, openssl tpm2 provider vs pkcs11 key ref, EAP-TLS version. hostapd MACsec build, openssl tpm2 provider vs pkcs11 key ref, EAP-TLS version.
PKI product decision (greenfield): start step-ca; OpenBao/EJBCA/Dogtag later. PKI product decision (greenfield): start step-ca; OpenBao/EJBCA/Dogtag later.
- **First step (DONE 2026-06-22): `enrol/tpm-selftest.sh`** — non-destructive TPM
capability check (run on the booted open-port image, no `disable_dot1x` needed)
to de-risk the TPM half before the full path. Likely first finding: no openssl
TPM2 **provider** in the image (`tpm2-tss` ≠ the provider) — add `tpm2-openssl`.
- **Enrolment of the per-host identity** (key@`0x81010001` + cert@NV) is its own
design — see **#11** (TOFU + OOB fingerprint broker, pre-auth permit-set,
provisioning UKI). `tpm-provision.sh` is the manual bench stand-in for it.
- **NVMe discovery by DNS:** `nvmet_traddr=nvme.fleet.lab` (CI), resolved at boot - **NVMe discovery by DNS:** `nvmet_traddr=nvme.fleet.lab` (CI), resolved at boot
by the serving dnsmasq — drop the hardcoded `192.168.50.10`. by the serving dnsmasq — drop the hardcoded `192.168.50.10`.
- **Signing — SIGNED-UKI + SECURE-BOOT-ON PATH BENCH-VERIFIED on the Proxmox VM - **Signing — SIGNED-UKI + SECURE-BOOT-ON PATH BENCH-VERIFIED on the Proxmox VM
@@ -645,7 +712,9 @@ smoke test.
EFI attribute prefix in a bash variable (`ATTR=$'\x27\x00\x00\x00'`). Bash EFI attribute prefix in a bash variable (`ATTR=$'\x27\x00\x00\x00'`). Bash
strings can't hold NULs → only `0x27` survived → efivarfs read a corrupt strings can't hold NULs → only `0x27` survived → efivarfs read a corrupt
attribute u32 → every write failed with `EINVAL` ("dd: Invalid argument"). attribute u32 → every write failed with `EINVAL` ("dd: Invalid argument").
Now emitted directly with `printf` at write time. (Red herring on the way: Now emitted directly with `printf` at write time. **Baked fix VERIFIED on the
820 (2026-06-22): `sudo fleet-sb-enroll` enrolled db→KEK→PK cleanly, no inline
workaround.** (Red herring on the way:
Proxmox EFI disks default to `pre-enrolled-keys=1`, so `mokutil --db` shows Proxmox EFI disks default to `pre-enrolled-keys=1`, so `mokutil --db` shows
the MS cert even in Setup Mode — looked like a non-empty-db rejection but was the MS cert even in Setup Mode — looked like a non-empty-db rejection but was
the NUL bug all along; it failed identically on a clean `pre-enrolled-keys=0` the NUL bug all along; it failed identically on a clean `pre-enrolled-keys=0`
@@ -657,12 +726,15 @@ smoke test.
(`.gitea/workflows/dnsmasq-image.yaml`) — no longer built at deploy time, and (`.gitea/workflows/dnsmasq-image.yaml`) — no longer built at deploy time, and
carries no keys/binary. (Decision: separate `fleet-ipxe` image, not baked into carries no keys/binary. (Decision: separate `fleet-ipxe` image, not baked into
dnsmasq, so the daemon image stays key-agnostic across SB environments.) dnsmasq, so the daemon image stays key-agnostic across SB environments.)
- **820 / PXE signed chain — BENCH-VERIFIED 2026-06-22.** Real hardware (HP
EliteBook 820 G4), Secure Boot **enforcing** (`mokutil --sb-state` = enabled,
Setup Mode no, db/KEK/PK enrolled): firmware verifies the signed `snponly.efi`
(fleet-ipxe image) → signed UKI and boots. Confirms the whole `fleet-ipxe`
signing pipeline + the PXE→iPXE→UKI chain under SB on real silicon (the VM only
covered the HTTP path, which has no iPXE stage).
- **REMAINING for production:** (a) **secure path** — re-verify signed boot with - **REMAINING for production:** (a) **secure path** — re-verify signed boot with
`disable_dot1x=false` (802.1X/MACsec), not just the test path; (b) **820 / PXE `disable_dot1x=false` (802.1X/MACsec), not just the test path; (b) confirm
path** — BENCH-VERIFY the signed `fleet-ipxe` chain on the 820 (the VM's HTTP signing is reproducible (verity hash stable across two signed builds).
path has no iPXE stage, so the signed iPXE binary is still unverified on real
PXE hardware); (c) confirm signing is reproducible (verity hash stable across
two signed builds).
- **PXE-only iPXE fallback — BENCH-VERIFIED on the EliteBook 820 G4 (2026-06-20).** - **PXE-only iPXE fallback — BENCH-VERIFIED on the EliteBook 820 G4 (2026-06-20).**
Firmware without UEFI HTTP boot chainloads `serving/tftp/snponly.efi` → renders Firmware without UEFI HTTP boot chainloads `serving/tftp/snponly.efi` → renders
`autoexec.ipxe` (ifopen + DHCP-retry + `imgargs <real cmdline>`) → UKI over HTTP `autoexec.ipxe` (ifopen + DHCP-retry + `imgargs <real cmdline>`) → UKI over HTTP
@@ -757,7 +829,9 @@ full ~17-min Packer build.
Speed up bringing up new workstations: bake the **public** PK/KEK/db certs into an Speed up bringing up new workstations: bake the **public** PK/KEK/db certs into an
image, detect Secure Boot **Setup Mode** at boot, and auto-enroll them so a image, detect Secure Boot **Setup Mode** at boot, and auto-enroll them so a
fresh/reset box adopts the fleet trust root without a manual firmware-setup visit. fresh/reset box adopts the fleet trust root without a manual firmware-setup visit.
Pairs with #8 (signing) + [secure-boot-keys.md](secure-boot-keys.md). Pairs with #8 (signing) + [secure-boot-keys.md](secure-boot-keys.md). Shares the
provisioning-UKI + isolated-environment vehicle with **#11** (which enrols the
*network* identity); build them together.
**Tooling gap (found 2026-06-20): `efitools` is NOT packaged for EL9** — no **Tooling gap (found 2026-06-20): `efitools` is NOT packaged for EL9** — no
`efi-updatevar`/`efi-readvar`/`KeyTool`. Resolved for the OS-side path by writing `efi-updatevar`/`efi-readvar`/`KeyTool`. Resolved for the OS-side path by writing
@@ -817,3 +891,70 @@ enrolls.
reasonable for a controlled fleet; the highest-assurance path is attended/firmware reasonable for a controlled fleet; the highest-assurance path is attended/firmware
or manufacturer pre-provisioning. Default recommendation: **separate provisioning or manufacturer pre-provisioning. Default recommendation: **separate provisioning
UKI + isolated VLAN + read-back verify.** UKI + isolated VLAN + read-back verify.**
## [ ] 11. (DESIGN) TPM 802.1X identity enrolment (TOFU + OOB fingerprint)
How a host gets its **802.1X EAP-TLS client identity** the first time — the key at
TPM handle `0x81010001` + cert at NV `0x01800001` that invariant #1 says must come
from enrolment, never the image. Distinct from #10 (that enrols *Secure Boot*
PK/KEK/db); this enrols the *network identity*. They share the provisioning UKI +
isolated-environment vehicle. Pairs with #8 + the CA decision (start **step-ca**,
[serving/dot1x-bench/](../serving/dot1x-bench/); OpenBao/EJBCA/Dogtag later).
**Chosen pattern — trust-on-first-use with out-of-band fingerprint approval:**
on an empty TPM the host generates a key *in* the TPM, builds a CSR, submits it to
an enrolment **broker**, and shows a **fingerprint** on the Plymouth splash; an
admin visually cross-checks that fingerprint against the broker's pending-list and
approves; the broker has step-ca sign the CSR and returns the cert; the host writes
it to NV `0x01800001` and proceeds to authenticate. Sound, recognised pattern
(SSH/WireGuard/Signal-style OOB verification); good fit for invariant #1.
**Key design decisions (settled 2026-06-22):**
- **The pre-auth permit-set already exists — enrolment rides in it.** The firmware
can't do 802.1X, so the UKI fetch (DHCP/DNS/TFTP/HTTP to the serving host) is
**always pre-auth**; the secure model therefore *requires* a pre-auth permit-set
(low-impact 802.1X / pre-auth dACL / boot→secure dynamic VLAN; RADIUS returns the
secure VLAN on Access-Accept). The enrolment endpoint is just **another entry in
that set** — expose it as an `/enrol/` location on the **existing serving nginx**,
reverse-proxied to the broker. No new network mechanism.
- **The broker is the only new component.** step-ca signs but has no human-approval
queue: broker = `POST CSR + context → PENDING + fingerprint → admin approves →
step-ca signs → host polls → cert`. Exposed to *unauthenticated* devices by
design → harden: OOB-fingerprint gate (no auto-sign), rate-limit, time-boxed
pending, HTTPS (image trusts the serving CA), pre-auth permit scoped to only
these services + the serving host.
- **Trigger on EMPTY-NV only — split the three events:** empty NV → enrol (human);
valid key + expired/near-expiry cert → **renew** automatically (no human, it
already holds a trusted key); auth fails with a present cert → **alert + retry,
do NOT re-enrol** (auto-reenrol on failure would mask revocation and churn keys
on a transient RADIUS outage). Re-enrol after the first time = explicit admin
action (clear/flag the host).
- **Fingerprint: what it proves + entropy.** It proves "this CSR came from *this
physical device*" (approver reads the screen) — it does NOT prove TPM residency.
Pair it with **TPM attestation** (step-ca ACME `device-attest-01`, EK/AK) for the
residency proof: fingerprint = human authorises the device, attestation = the key
is really in a TPM (together → strong SSP R-01 story). Size for entropy — a short
hex fp is grindable; use a word-list/BIP39-style encoding (reads short, more
bits) + rate-limiting + a server nonce. Show device context (asset/port/location)
so the admin knows *what* they're approving.
- **Pre-auth traffic has no MACsec (plaintext at L2).** Fine for enrol (CSR/cert
are public; OOB fingerprint gives authenticity) — and it's exactly **why the UKI
must be Secure-Boot-signed** (#8): integrity of the boot comes from the signature,
not the network. Enrolment design + Secure Boot are two halves of the same
"pre-auth path is hostile" assumption.
- **Run it in a provisioning UKI/mode, not the production initramfs** — the boot
hook ordering is load-bearing (invariant #2); don't park it on a multi-minute
human-approval wait. Shares the #10 provisioning-UKI vehicle.
**Bench caveat:** `hostapd` wired is strictly port-based (no pre-auth per-flow
ACL) — before EAP success it passes nothing, so the bench can't reproduce
"boot + enrol pre-auth on the same port." Model the pre-auth state with a separate
provisioning bridge/VLAN on the rig; the in-place low-impact pre-auth permit is a
real-switch feature to validate on the 820's switch.
**First step DONE (2026-06-22):** `serving/dot1x-bench/enrol/tpm-selftest.sh` — a
non-destructive TPM capability check (device, key persist, NV roundtrip, openssl
TPM2 provider, CSR signed by the TPM key) to de-risk the TPM half before any of
this. Expected gap: the image installs `tpm2-tss` but no openssl TPM2 **provider**
(`tpm2-openssl`) — add it to the build once the self-test confirms.
+38 -1
View File
@@ -4,7 +4,7 @@ Records where the as-built implementation diverges from
`diskless-fleet-design-v2.pdf`. The PDF remains authoritative for the `diskless-fleet-design-v2.pdf`. The PDF remains authoritative for the
architecture; this note captures deltas discovered bringing the build up on architecture; this note captures deltas discovered bringing the build up on
**Rocky 9.8** until they are folded into a consolidated **v3**. Last updated **Rocky 9.8** until they are folded into a consolidated **v3**. Last updated
2026-06-15. 2026-06-22.
The architecture is unchanged: 802.1X EAP-TLS with a TPM-held key, MACsec on the The architecture is unchanged: 802.1X EAP-TLS with a TPM-held key, MACsec on the
access link, dm-verity-protected erofs root over NVMe/TCP, signed UKI, and the access link, dm-verity-protected erofs root over NVMe/TCP, signed UKI, and the
@@ -57,6 +57,43 @@ indices shift with the transient discovery controller.
[../serving/spdk-setup.sh](../serving/spdk-setup.sh) (2nd bdev/namespace), and [../serving/spdk-setup.sh](../serving/spdk-setup.sh) (2nd bdev/namespace), and
CLAUDE.md invariant #9. CLAUDE.md invariant #9.
## 1c. Design-level addition — pre-auth boot path & per-host identity enrolment
Two design points the PDF leaves implicit; both are load-bearing for the secure
model and are recorded here pending v3.
**The boot path is inherently pre-auth, so a pre-auth permit-set is mandatory.**
The firmware (UEFI HTTP boot / PXE→iPXE) fetches the UKI **before** any OS or
supplicant exists — there is no firmware 802.1X supplicant — so the UKI/initramfs
fetch always happens in the unauthenticated state. The secure model therefore
requires the authenticator to permit a *scoped* set of services pre-auth
(DHCP/DNS + TFTP + HTTP to the serving host) and only complete 802.1X once the
**OS** is running; RADIUS returns the secure VLAN on Access-Accept, after which
DHCP-for-the-running-system and the NVMe/TCP root ride **`macsec0`** (post-auth,
encrypted). Mechanism on a real switch: low-impact 802.1X / a pre-auth dACL /
boot→secure dynamic VLAN. Consequences:
- Pre-auth traffic has **no MACsec** (plaintext at L2). Integrity of the boot
therefore comes from **Secure Boot** (the signed UKI + signed `fleet-ipxe`), not
the network — this is *why* signing matters: the boot transport is untrusted.
- `hostapd` wired (the bench authenticator) is strictly port-based and can't model
a pre-auth per-flow permit — the in-place pre-auth ACL is a real-switch feature,
validated on the 820's switch, not the VM rig (see `serving/dot1x-bench/`).
**Per-host 802.1X identity is created by an enrolment flow, never baked in**
(invariant #1). Chosen pattern: **trust-on-first-use with out-of-band fingerprint
approval** — on an empty TPM the host generates a key *in* the TPM
(`0x81010001`), submits a CSR to an enrolment **broker** (reachable via the same
pre-auth permit-set, e.g. an `/enrol/` location on the serving nginx → broker →
step-ca signer), and shows a fingerprint on the Plymouth splash; an admin
cross-checks it and approves; the signed cert is written to NV `0x01800001` and
authentication proceeds. Enrol triggers on **empty-NV only** (expired cert →
automatic renew; auth-failure-with-cert → alert, not re-enrol). The fingerprint
authorises *which device*; **TPM attestation** (step-ca ACME `device-attest-01`)
proves *key residency* — use both for full assurance. Runs in a provisioning
UKI/mode, not the production initramfs. Full design + decisions: **TODO #11** (the
network-identity counterpart to **#10**, which enrols Secure Boot PK/KEK/db; both
share the provisioning-UKI vehicle).
## 2. Implementation notes (not architectural) ## 2. Implementation notes (not architectural)
These don't contradict the PDF (it doesn't specify them) but are worth recording. These don't contradict the PDF (it doesn't specify them) but are worth recording.
+8 -4
View File
@@ -154,10 +154,14 @@ Mode failure (that surfaces as EACCES / "Permission denied"). Diagnose top-down:
`pre-enrolled-keys=0` disk if the NUL bug is present. For a clean OVMF test bed: `pre-enrolled-keys=0` disk if the NUL bug is present. For a clean OVMF test bed:
`qm set <vmid> --efidisk0 <storage>:1,efitype=4m,pre-enrolled-keys=0`. `qm set <vmid> --efidisk0 <storage>:1,efitype=4m,pre-enrolled-keys=0`.
**Verified:** with the fix, a Proxmox VM enrols db→KEK→PK from the baked `.auth` **Verified end-to-end on real hardware (2026-06-22):** `fleet-sb-enroll` (the
files and boots the CI-signed UKI under **enforcing Secure Boot** over the HTTP baked, fixed script) enrols db→KEK→PK cleanly, and both boot transports verify
boot path (`mokutil --sb-state` = enabled). The PXE/iPXE front-end additionally under **enforcing Secure Boot** (`mokutil --sb-state` = enabled):
needs `snponly.efi` signed with `db` — see the iPXE section below. - **Proxmox VM — HTTP boot:** firmware → signed UKI (2026-06-20).
- **HP EliteBook 820 G4 — PXE boot:** firmware → signed `snponly.efi` (fleet-ipxe)
→ signed UKI (2026-06-22).
So the full signing pipeline (UKI + `fleet-ipxe`, both against the same enrolled
`db`) is proven on real silicon, not just in the VM.
## 4. Wire `db` into the build ## 4. Wire `db` into the build
+16 -10
View File
@@ -9,10 +9,12 @@
> **A&A framework:** ASD *Information Security Manual* (ISM) — engagement target > **A&A framework:** ASD *Information Security Manual* (ISM) — engagement target
> **May 2026 release**. > **May 2026 release**.
> >
> **Annex version:** 0.2 (2026-06-20). v0.2 reflects: STIG hardening applied + > **Annex version:** 0.2 (updated 2026-06-22). v0.2 reflects: STIG hardening
> bench-verified, USBGuard device control enabled, admin `staff_u` confinement, > applied + bench-verified, USBGuard device control enabled, admin `staff_u`
> audit offload verified, UKI signing wired (not yet enforced — new R-13), > confinement, audit offload verified, PXE/iPXE boot path added, and **UEFI Secure
> PXE/iPXE boot path added. > Boot signing verified enforcing on real hardware** (VM HTTP + 820 PXE) — R-13
> reduced from Medium to Low (residual is making signed + SB-on the standing
> default).
--- ---
@@ -150,7 +152,7 @@ ISM/PSPF style). Ratings are **pre-treatment** unless stated; the AO accepts the
| Topic | ISM (rep.) | Requirement intent | System implementation | Status | Residual | | Topic | ISM (rep.) | Requirement intent | System implementation | Status | Residual |
|---|---|---|---|---|---| |---|---|---|---|---|---|
| Media sanitisation / no data remanence | ISM-0347*, ISM-1218* | Prevent data remanence. | **Diskless** — no persistent local media; writable layer is **RAM tmpfs**, gone at power-off. | Implemented | — | | Media sanitisation / no data remanence | ISM-0347*, ISM-1218* | Prevent data remanence. | **Diskless** — no persistent local media; writable layer is **RAM tmpfs**, gone at power-off. | Implemented | — |
| Tamper-evidence / boot integrity | ISM-1542*, ISM-0312* | Detect firmware/boot tampering. | Design: **UEFI Secure Boot** + signed UKI (+ signed iPXE on the PXE path) + immutable signed cmdline + dm-verity; TPM measurements available. Signing **wired in CI** + key/enrolment procedure + baked `fleet-sb-enroll` helper, but **lab runs unsigned with SB OFF**. | Partial | **R-13** (signing not enforced), R-11 (no remote attestation) | | Tamper-evidence / boot integrity | ISM-1542*, ISM-0312* | Detect firmware/boot tampering. | Design: **UEFI Secure Boot** + signed UKI (+ signed iPXE on the PXE path) + immutable signed cmdline + dm-verity; TPM measurements available. **Verified enforcing on real hardware (2026-06-22):** CI-signed UKI under SB on a VM (HTTP) and signed iPXE→UKI under SB on an 820 (PXE), `db` enrolled via `fleet-sb-enroll`. Residual is making signed + SB-on the standing default for all builds/hosts. | Implemented (default-posture residual) | **R-13** (not yet default), R-11 (no remote attestation) |
| Device identification | ISM-1195* | Uniquely identify devices. | Identity derived from TPM cert (hostnqn from cert serial); no spoofable per-host config. | Implemented | — | | Device identification | ISM-1195* | Uniquely identify devices. | Identity derived from TPM cert (hostnqn from cert serial); no spoofable per-host config. | Implemented | — |
### 2.11 Guidelines for Procurement, Outsourcing & Evaluated Products ### 2.11 Guidelines for Procurement, Outsourcing & Evaluated Products
@@ -176,7 +178,7 @@ asked to accept. Treatments map to [docs/TODO.md](TODO.md) (working POA&M).
| **R-05** | **NOPASSWD key-only admin**; no per-host or rotatable access model; human admin MFA on the mgmt plane not enforced. | 2.4 (ISM-1507*/1173*) | Possible × Moderate → **Medium** | Single fleet-generic admin, key-only, root disabled, ECDSA/RSA key, **now SELinux-confined to `staff_u`** with sudo role/type elevation, fully audited; no interactive password to attack. | Per-host/rotatable access (SSH CA / config-agent) + admin MFA on the management plane. | **Low–Medium** | Platform team — *roadmap* | | **R-05** | **NOPASSWD key-only admin**; no per-host or rotatable access model; human admin MFA on the mgmt plane not enforced. | 2.4 (ISM-1507*/1173*) | Possible × Moderate → **Medium** | Single fleet-generic admin, key-only, root disabled, ECDSA/RSA key, **now SELinux-confined to `staff_u`** with sudo role/type elevation, fully audited; no interactive password to attack. | Per-host/rotatable access (SSH CA / config-agent) + admin MFA on the management plane. | **Low–Medium** | Platform team — *roadmap* |
| **R-06** | **FIPS off**; ISM **AACA/AACP conformance not formally asserted**; crypto-module evaluation status unconfirmed. | 2.9 (ISM-0471*/1139*/1277*) | Possible × Major → **Medium** | Modern STIG crypto policy; non-exportable TPM key; no deliberately weak algorithms. Acceptable at OFFICIAL; **mandatory to resolve for PROTECTED+.** | Assert AACA/AACP conformance; decide on FIPS module / evaluated crypto alongside Secure Boot signing. | **Low** (at appropriate classification) | Security + Platform — *before PROTECTED+* | | **R-06** | **FIPS off**; ISM **AACA/AACP conformance not formally asserted**; crypto-module evaluation status unconfirmed. | 2.9 (ISM-0471*/1139*/1277*) | Possible × Major → **Medium** | Modern STIG crypto policy; non-exportable TPM key; no deliberately weak algorithms. Acceptable at OFFICIAL; **mandatory to resolve for PROTECTED+.** | Assert AACA/AACP conformance; decide on FIPS module / evaluated crypto alongside Secure Boot signing. | **Low** (at appropriate classification) | Security + Platform — *before PROTECTED+* |
| **R-07** | Audit-log **offload plaintext**, **single-site**, **no SIEM alerting**; logs interceptable/repudiable and not actively reviewed. (Transport **bench-verified working** 2026-06-20.) | 2.6 (ISM-1432*/0109*/0859*) | Possible × Moderate → **Medium** | Isolated LAN; disk-assisted queue (no loss on collector blip); auditd local copy; per-source files; LinuxAudit captures USBGuard events. | rsyslog **TLS** (gtls/6514) + bundle CA in image (re-select the 3 waived `rsyslog_encrypt_offload_*` rules); define retention + integrity; forward to SIEM with alerting. | **Low** | Platform/SecOps — *production* | | **R-07** | Audit-log **offload plaintext**, **single-site**, **no SIEM alerting**; logs interceptable/repudiable and not actively reviewed. (Transport **bench-verified working** 2026-06-20.) | 2.6 (ISM-1432*/0109*/0859*) | Possible × Moderate → **Medium** | Isolated LAN; disk-assisted queue (no loss on collector blip); auditd local copy; per-source files; LinuxAudit captures USBGuard events. | rsyslog **TLS** (gtls/6514) + bundle CA in image (re-select the 3 waived `rsyslog_encrypt_offload_*` rules); define retention + integrity; forward to SIEM with alerting. | **Low** | Platform/SecOps — *production* |
| **R-13** | **Boot chain unsigned / Secure Boot OFF** in the lab — the UKI and (on the PXE path) iPXE are not signed and SB is not enforced, so a substituted boot artifact would not be rejected by firmware. | 2.10 (ISM-1542*/0312*) | Possible × Major → **Medium** | dm-verity still rejects a tampered *root*; isolated lab LAN; signing is **wired in CI** + key/enrolment procedure + baked `fleet-sb-enroll` ready; only the enforcement is pending. | Enrol fleet `db` (PK/KEK/db per [secure-boot-keys.md](secure-boot-keys.md)); set `SB_KEY`/`SB_CERT` CI secrets; `sbsign` the UKI **and** iPXE; enable Secure Boot on targets. | **Low** | Platform team — *before production* | | **R-13** | **Boot-chain signing not yet the standing default** — signing + Secure Boot enforcement are **verified end-to-end on real hardware** (VM HTTP UKI 2026-06-20; 820 PXE signed iPXE→UKI 2026-06-22, SB enforcing, `db` enrolled), but unsigned/SB-OFF lab builds remain possible (CI signs only when `SB_KEY`/`SB_CERT` are set) and not every host has `db` enrolled, so a substituted artifact could still boot on an un-enrolled/unsigned host. | 2.10 (ISM-1542*/0312*) | Unlikely × Major → **Low** | Capability **proven on hardware**; dm-verity rejects a tampered *root* regardless; isolated lab LAN. | Make signed + Secure-Boot-on the **default for all production builds/hosts**: keep `SB_KEY`/`SB_CERT` CI secrets set; enrol `db` fleet-wide; treat an unsigned build as lab-only. | **Low** | Platform team — *before production* |
| **R-08** | **Placeholder RADIUS CA** (`files/etc/dot1x/radius-ca.pem`) — real EAP-TLS trust anchor not provisioned; auth cannot succeed and trust is unestablished. | 2.4 (ISM-1546*) | Certain (lab) × Major → **Medium** | Documented as a placeholder; environment-specific provisioning is the intended path; no real CA committed. | Provision the environment's real RADIUS CA out-of-band (not committed unless classification permits). | **Low** | Environment owner — *before production* | | **R-08** | **Placeholder RADIUS CA** (`files/etc/dot1x/radius-ca.pem`) — real EAP-TLS trust anchor not provisioned; auth cannot succeed and trust is unestablished. | 2.4 (ISM-1546*) | Certain (lab) × Major → **Medium** | Documented as a placeholder; environment-specific provisioning is the intended path; no real CA committed. | Provision the environment's real RADIUS CA out-of-band (not committed unless classification permits). | **Low** | Environment owner — *before production* |
| **R-09** | **Host firewall disabled**; host exposes more network surface than necessary. | 2.7 (ISM-1416*) | Possible × Moderate → **Low–Medium** | Isolated LAN; minimal services; egress controlled at the network/serving layer; no kiosk inbound. | Re-enable firewalld with explicit allow rules (NVMe/TCP `:4420`, DHCP, log offload, SSH) once the secure path is verified. | **Low** | Platform/network — *after R-01* | | **R-09** | **Host firewall disabled**; host exposes more network surface than necessary. | 2.7 (ISM-1416*) | Possible × Moderate → **Low–Medium** | Isolated LAN; minimal services; egress controlled at the network/serving layer; no kiosk inbound. | Re-enable firewalld with explicit allow rules (NVMe/TCP `:4420`, DHCP, log offload, SSH) once the secure path is verified. | **Low** | Platform/network — *after R-01* |
| **R-10** | **Patch SLA undefined** — no documented cadence for rebuilding/redeploying against new CVEs. | 2.5 (ISM-1144*/1472*) | Likely × Moderate → **Medium** | Atomic rebuild/redeploy model makes patching fast & uniform; reproducible builds. | Define patch cadence & critical-CVE SLA; automate rebuild triggers. | **Low** | Platform team — *roadmap* | | **R-10** | **Patch SLA undefined** — no documented cadence for rebuilding/redeploying against new CVEs. | 2.5 (ISM-1144*/1472*) | Likely × Moderate → **Medium** | Atomic rebuild/redeploy model makes patching fast & uniform; reproducible builds. | Define patch cadence & critical-CVE SLA; automate rebuild triggers. | **Low** | Platform team — *roadmap* |
@@ -204,7 +206,9 @@ R-12 and R-13** (and confirming R-03's `enable_stig=true`) are **closed before
production**, and R-04/R-05/R-06/R-07/R-09/R-10/R-11 are either accepted with production**, and R-04/R-05/R-06/R-07/R-09/R-10/R-11 are either accepted with
compensating controls (isolated-LAN lab) or carried on the POA&M with target compensating controls (isolated-LAN lab) or carried on the POA&M with target
dates. Newly strengthened in v0.2: device control (USBGuard, now Implemented), dates. Newly strengthened in v0.2: device control (USBGuard, now Implemented),
admin SELinux confinement (R-05), and STIG applied+verified (R-03 reduced).* admin SELinux confinement (R-05), STIG applied+verified (R-03 reduced), and
**Secure Boot signing verified enforcing on real hardware (R-13 reduced
Medium→Low)**.*
--- ---
@@ -224,9 +228,11 @@ admin SELinux confinement (R-05), and STIG applied+verified (R-03 reduced).*
anything flagged **REVIEW** is an unjustified finding. anything flagged **REVIEW** is an unjustified finding.
6. **Confirm lab-only flags are off** in the assessed build: `debug_shell=false`, 6. **Confirm lab-only flags are off** in the assessed build: `debug_shell=false`,
`enable_stig=true`, `disable_dot1x=false`, real RADIUS CA in place. `enable_stig=true`, `disable_dot1x=false`, real RADIUS CA in place.
7. **Confirm boot-chain signing is enforced** (R-13): `db` enrolled, Secure Boot 7. **Confirm boot-chain signing is the default** (R-13): signing + Secure Boot
ON, UKI + iPXE signed (`sbverify`). The PXE/iPXE path's SB-OFF cmdline enforcement are **verified on hardware** (VM HTTP + 820 PXE, 2026-06-22) —
workaround should be a no-op once SB is on. confirm the *assessed* build is signed and the *assessed* hosts have `db`
enrolled with Secure Boot ON (`mokutil --sb-state`, `sbverify` UKI + iPXE). The
PXE/iPXE SB-OFF cmdline workaround is a no-op once SB is on.
8. **Witness device control** (USBGuard): a USB mass-storage device is blocked and 8. **Witness device control** (USBGuard): a USB mass-storage device is blocked and
logged, console HID still works. logged, console HID still works.
+20 -16
View File
@@ -16,9 +16,9 @@
| System name | Diskless Fleet Boot System ("the fleet") | | System name | Diskless Fleet Boot System ("the fleet") |
| Document type | System Security Plan (SSP) | | Document type | System Security Plan (SSP) |
| Version | 0.2 (DRAFT — pre-assessment) | | Version | 0.2 (DRAFT — pre-assessment) |
| Date | 2026-06-20 | | Date | 2026-06-22 |
| Author / maintainer | System Owner (delegate) | | Author / maintainer | System Owner (delegate) |
| Status | Lab / pre-production. STIG hardening applied + bench-verified (unsigned, Secure Boot OFF); secure path (802.1X/MACsec) not yet bench-verified. | | Status | Lab / pre-production. STIG hardening applied + bench-verified; **UEFI Secure Boot signing verified enforcing on real hardware** (VM HTTP + EliteBook 820 PXE); secure path (802.1X/MACsec) not yet bench-verified. |
| Companion documents | [Annex A — ISM control cross-reference & residual risk](ssp-annex-a-ism-residual-risk.md); [Architecture design v2](diskless-fleet-design-v2.pdf); [Design errata](design-v2-errata.md); [STIG deviation register](stig-deviations.md); [Backlog / POA&M source](TODO.md) | | Companion documents | [Annex A — ISM control cross-reference & residual risk](ssp-annex-a-ism-residual-risk.md); [Architecture design v2](diskless-fleet-design-v2.pdf); [Design errata](design-v2-errata.md); [STIG deviation register](stig-deviations.md); [Backlog / POA&M source](TODO.md) |
> **Currency caveat (read before relying on control numbers).** This SSP and its > **Currency caveat (read before relying on control numbers).** This SSP and its
@@ -164,19 +164,23 @@ This system follows the ISM A&A lifecycle:
Milestones (POA&M)** (this repo's [TODO.md](TODO.md) is the working POA&M Milestones (POA&M)** (this repo's [TODO.md](TODO.md) is the working POA&M
source). source).
**Current status:** Pre-assessment **DRAFT (v0.2)**. The system is functional in a **Current status:** Pre-assessment **DRAFT (v0.2, updated 2026-06-22)**. The system
lab configuration. **Progress since v0.1 (2026-06-20):** DISA STIG hardening is functional in a lab configuration. **Progress since v0.1 (2026-06-20):** DISA
applied and **bench-verified** on a real build (kiosk, key-only SSH, audit STIG hardening applied and **bench-verified** on a real build (kiosk, key-only SSH,
offload, DHCP-named host, NVMe/verity root all good with hardening on); USBGuard audit offload, DHCP-named host, NVMe/verity root all good with hardening on);
device control enabled + verified; admin confined to `staff_u`; UKI signing wired USBGuard device control enabled + verified; admin confined to `staff_u`; and —
in CI + Secure Boot key/enrolment procedure documented; both **HTTP-boot and newly — **UEFI Secure Boot signing verified enforcing end-to-end on real
PXE/iPXE** boot paths working (the latter verified on an EliteBook 820 G4). hardware**: the CI-signed UKI boots under Secure Boot on a VM (HTTP boot), and the
Several controls remain **partial or deferred**, tracked as residual risks with signed iPXE→UKI chain boots under Secure Boot on an EliteBook 820 G4 (PXE boot),
treatments (Annex A §3). The two largest gates on a production ATO: (a) the with `db`/`KEK`/`PK` enrolled via the baked `fleet-sb-enroll` helper. Several
secure path (**802.1X/MACsec**) is implemented but **not yet bench-verified** and controls remain **partial or deferred**, tracked as residual risks with treatments
is disabled in test builds (`disable_dot1x=true`, R-01); (b) the lab runs (Annex A §3). The largest remaining gates on a production ATO: (a) the secure path
**unsigned with Secure Boot OFF** (R-13) and with a lab-only **passwordless-root (**802.1X/MACsec**) is implemented but **not yet bench-verified** and is disabled
debug shell** that must be removed (R-02). in test builds (`disable_dot1x=true`, R-01); (b) a lab-only **passwordless-root
debug shell** must be removed (R-02). Boot-chain signing / Secure Boot — a major
v0.1 gate — is now **demonstrated on hardware**; the residual (R-13) is reduced to
making signed + Secure-Boot-on the **standing default** for every production
host/build.
## 5. Security control implementation — by ISM cyber security principle ## 5. Security control implementation — by ISM cyber security principle
@@ -281,7 +285,7 @@ production ATO:
| R-07 | Audit-log offload **plaintext** (bench-verified working), single-site, no SIEM alerting. | **Medium** | Treat — TLS offload + monitoring on roadmap. | | R-07 | Audit-log offload **plaintext** (bench-verified working), single-site, no SIEM alerting. | **Medium** | Treat — TLS offload + monitoring on roadmap. |
| R-08 | **Placeholder RADIUS CA** in the repo; real trust anchor not yet provisioned. | **Medium** | Treat — environment-specific, before production. | | R-08 | **Placeholder RADIUS CA** in the repo; real trust anchor not yet provisioned. | **Medium** | Treat — environment-specific, before production. |
| R-09 | Host **firewall disabled** (workstation). | **Low–Medium** | Accept (isolated LAN) / treat with explicit allow-rules. | | R-09 | Host **firewall disabled** (workstation). | **Low–Medium** | Accept (isolated LAN) / treat with explicit allow-rules. |
| R-13 | **Boot chain unsigned / Secure Boot OFF** in the lab (UKI + iPXE); CI signing wired but not enforced. | **Medium** | Treat — enrol `db`, enforce SB + sign UKI & iPXE before production. | | R-13 | **Boot-chain signing not yet the standing default.** Signing + Secure Boot enforcement **verified end-to-end on hardware** (VM HTTP UKI 2026-06-20; 820 PXE signed iPXE→UKI 2026-06-22), but unsigned/SB-OFF lab builds are still possible (CI signs only when `SB_KEY`/`SB_CERT` are set) and not all hosts have `db` enrolled. | **Low** | Treat — make signed + Secure-Boot-on the default for all production builds/hosts (set CI secrets; enrol `db` fleet-wide). |
Each is detailed, ISM-cross-referenced, rated and assigned a treatment in Annex A. Each is detailed, ISM-cross-referenced, rated and assigned a treatment in Annex A.