docs(ssp): v0.3 — add the fleet-management plane + July hardening changes

The SSP (v0.2, 2026-06-27) and annex predated the entire management/enrolment
plane and the July hardening work. Bring both to v0.3 (2026-07-10):

SSP:
- Scope/boundary: on-host fleet-agent now IN scope; server-side manager/broker/
  step-ca/InfluxDB named as connected systems; new host interface (g) = outbound
  mTLS to the management plane. Boot chain gains step 8 (post-switch-root agent).
- Data: management telemetry (operational metadata, mTLS-encrypted, no per-host
  secret); the agent stream is the one non-plaintext transit path.
- §5.2 Protect: agent reuses the TPM identity for mTLS; WebAuthn-passkey admin
  MFA (first human-admin MFA); 3 local SELinux modules; the 2026-07-04 fapolicyd
  overlay watch_fs fix (app-control was inactive on the root until then).
- §5.3 Detect: operational health telemetry signal (distinct from auditd/Wazuh).
- §6 Essential Eight: MFA + admin rows updated (passkeys now enforced on mgmt UI).
- §7: new R-14 (mgmt plane = connected system pending authorisation) + R-15
  (deferred agent actuators = future remote-mutation channel); R-05 MFA clause met.

Annex:
- §2.3 hardening: fapolicyd overlay-effectiveness fix + residual; 3 local SELinux
  allow modules on the MAC row.
- §2.4 auth: agent mTLS on the machine-auth row; MFA row now Implemented for the
  mgmt UI (passkeys), Partial for host SSH.
- §2.5 mgmt: new rows for TPM enrolment lifecycle (broker) and server-authoritative
  management plane. §2.6: operational health-monitoring row. §2.7: mgmt-plane
  segmentation (OPNsense L3, outbound-only). §2.9: agent mTLS, fleet CA (step-ca),
  cert-lifecycle auto-renewal.
- §3 register: R-14, R-15 added; R-05 updated; heatmap + note + 3 new assessor
  notes (scope the mgmt plane, witness fapolicyd deny, confirm actuators inert).
This commit is contained in:
Audiobuzz
2026-07-10 22:56:34 +00:00
parent 3284a2713b
commit 57fb5c3a3e
2 changed files with 166 additions and 56 deletions
+107 -27
View File
@@ -15,11 +15,11 @@
|---|---|
| System name | Diskless Fleet Boot System ("the fleet") |
| Document type | System Security Plan (SSP) |
| Version | 0.2 (DRAFT — pre-assessment) |
| Date | 2026-06-27 |
| Version | 0.3 (DRAFT — pre-assessment) |
| Date | 2026-07-10 |
| Author / maintainer | System Owner (delegate) |
| 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) |
| 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. **v0.3 adds the fleet-management plane** (on-host `fleet-agent` telemetry over TPM-mTLS — bench-verified on hardware 2026-07-10; server-side manager with **WebAuthn-passkey** admin MFA + TPM enrolment broker) and July hardening changes (three local SELinux modules; fapolicyd overlay exec-guard fix). |
| 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); [Fleet-management design](fleet-management-design.md); [TPM enrolment design](tpm-enrolment-design.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
> annex are drafted against the ISM structure as understood to a January 2026
@@ -45,14 +45,20 @@ decision.
**In scope:** the boot chain (UEFI HTTP boot → signed UKI → dracut initramfs →
network authentication → encrypted root mount → verified read-only OS), the
runtime workstation OS image, the host's cryptographic identity (TPM), and the
hardening baseline applied to the image.
runtime workstation OS image, the host's cryptographic identity (TPM), the
hardening baseline applied to the image, and the **on-host `fleet-agent`** (the
in-image telemetry client that streams host health to the management plane over
TPM-mTLS — new in v0.3; `files/agent/`).
**Out of scope (separately authorised):** the lab serving stack (DHCP/HTTP/
NVMe-oF target, audit collector — `serving/`), the 802.1X authenticator/RADIUS
infrastructure, the certificate enrolment authority, the network fabric, and
physical security of the facility. These are dependencies referenced here but
carry their own security documentation and authorisation.
**Out of scope (separately authorised — connected systems):** the lab serving
stack (DHCP/HTTP/NVMe-oF target, audit collector — `serving/`); the **server-side
fleet-management plane** (`serving/fleet-manager/` — the control-plane hub, its
admin web UI, the InfluxDB metrics store, and the Traefik ingress); the **TPM
enrolment broker** (`serving/enrol-broker/`) and the **step-ca fleet certificate
authority** it signs against; the 802.1X authenticator/RADIUS infrastructure; the
network fabric; and physical security of the facility. These are dependencies the
host connects to and are described here where the host interacts with them, but
each carries its own security documentation and authorisation.
## 2. System description
@@ -104,18 +110,28 @@ manifest. One commit = one release = one digest = one manifest entry.
7. `switch-root` into the real system; NetworkManager renews the DHCP lease so
the network-mounted root stays alive; the host derives its NVMe `hostnqn` from
the TPM certificate serial and (kiosk builds) launches the locked-down kiosk.
8. **Post-boot management (v0.3):** the hardened **`fleet-agent`** service dials
the management plane and identifies with the **same TPM key/cert** used for
802.1X and the NVMe `hostnqn` ("one identity, three stages"), streaming host
health over mTLS. It is telemetry-only in v1 — it receives desired-state /
commands but **only logs** them (no host mutation). It is a
**post-switch-root** component only (not in the initramfs).
### 2.3 Authorisation boundary
The authorisation boundary is the **running workstation host**: the UKI, the
initramfs and its custom 802.1X/MACsec dracut module, the verified erofs root,
the tmpfs overlay, the TPM-backed identity, and the hardened OS configuration.
The boundary's external interfaces are: (a) the **access link** (802.1X-controlled
port, MACsec-encrypted); (b) the **NVMe/TCP** root storage session; (c)
**outbound audit log** forwarding; (d) the **kiosk application** endpoint the
browser renders; (e) the **boot transport** (UEFI HTTP boot, or PXE/TFTP→iPXE)
that delivers the UKI; and (f) **USB/peripheral** ports, now mediated by USBGuard
(§5.2). Each crossing is a control point addressed in Annex A.
the tmpfs overlay, the TPM-backed identity, the hardened OS configuration, and the
in-image **`fleet-agent`**. The boundary's external interfaces are: (a) the
**access link** (802.1X-controlled port, MACsec-encrypted); (b) the **NVMe/TCP**
root storage session; (c) **outbound audit log** forwarding; (d) the **kiosk
application** endpoint the browser renders; (e) the **boot transport** (UEFI HTTP
boot, or PXE/TFTP→iPXE) that delivers the UKI; (f) **USB/peripheral** ports, now
mediated by USBGuard (§5.2); and (g) the **management plane** — an *outbound-only*
mTLS gRPC session from `fleet-agent` to the fleet-manager (`manager.fleet.lab:9600`,
across the OPNsense L3 hop from the host VLAN to the management network; no inbound
host port), authenticated with the host's TPM identity cert. Each crossing is a
control point addressed in Annex A.
### 2.4 Data and classification
@@ -127,7 +143,16 @@ that delivers the UKI; and (f) **USB/peripheral** ports, now mediated by USBGuar
CI/HSM-held and **never enter the build VM or the repository**.
- **Data in transit:** access link protected by **MACsec**; NVMe/TCP root and
audit-log offload currently **plaintext on an isolated lab LAN** (see residual
risk R-04, R-07 in Annex A).
risk R-04, R-07 in Annex A). The **management-plane** telemetry stream is
**mTLS-encrypted** (fleet CA) end-to-end — unlike the NVMe/audit hops, it is not
plaintext.
- **Management telemetry (v0.3):** the agent sends host **health** (load/cpu/temp/
memory/tmpfs, uptime, NVMe-root state, 802.1X/MACsec + SELinux state, chrony
clock health, kiosk state) and **inventory facts** (image version, kernel,
cert-serial). This is **operational metadata, not user data**, and it carries **no
per-host secret** (identity is the reused TPM cert; the private key never leaves
the TPM). It is retained server-side (InfluxDB) — a **connected-system**
responsibility (see §1, R-14).
- **Data at rest in the overlay:** ephemeral, RAM-only, discarded at power-off.
The **system's data classification governs this SSP's marking and the required
@@ -164,8 +189,27 @@ This system follows the ISM A&A lifecycle:
Milestones (POA&M)** (this repo's [TODO.md](TODO.md) is the working POA&M
source).
**Current status:** Pre-assessment **DRAFT (v0.2, updated 2026-06-27)**. The system
is functional in a lab configuration. **Progress since v0.1 (2026-06-20):** DISA
**Current status:** Pre-assessment **DRAFT (v0.3, updated 2026-07-10)**. The system
is functional in a lab configuration.
**Progress since v0.2 (2026-07-10):** the **fleet-management plane** was built and,
on the host side, **bench-verified end-to-end on real hardware** (`comet-beacon-54`):
the in-image **`fleet-agent`** streams health to the server over **mTLS using the
reused TPM identity** (telemetry-only — desired-state/commands are received but only
logged, zero host mutation). The server-side manager adds a **WebAuthn-passkey**
(phishing-resistant, origin-bound) admin plane — the first **human-admin MFA** on the
management plane — and a **TPM enrolment broker** (unauthenticated pre-auth CSR → OOB
fingerprint → admin-mTLS approve → step-ca sign) that births the per-host inventory
record. Its server-side server cert now **auto-renews** from the co-located CA. Host
hardening also advanced: **three local SELinux policy modules** were added (all
documented deviations — [stig-deviations.md](stig-deviations.md) #14–16), and a
**material fapolicyd finding was fixed (2026-07-04)** — the app-allow-listing exec
guard was effectively *inactive on the overlay root* (`overlay` missing from
`watch_fs`) and is now enforcing across the whole root (see §5.2). The server-side
plane (manager/broker/InfluxDB/step-ca) is a **connected system** pending its own
authorisation (R-14).
**Progress since v0.1 (2026-06-20):** DISA
STIG hardening applied and **bench-verified** on a real build (kiosk, key-only SSH,
audit offload, DHCP-named host, NVMe/verity root all good with hardening on);
USBGuard device control enabled + verified; admin confined to `staff_u`; **UEFI
@@ -201,7 +245,18 @@ summarises the implementation posture.
### 5.2 Protect
- **Identity & authentication:** mutual **802.1X EAP-TLS** with a
**non-exportable TPM key**; network access controlled at the switch port.
**non-exportable TPM key**; network access controlled at the switch port. The
**management-plane agent reuses the same TPM identity** for mTLS to the
fleet-manager (one non-exportable key backs 802.1X, the NVMe `hostnqn`, and the
agent stream — "one identity, three stages"), and the server keys inventory off
the verified cert serial, so a host can only ever report as itself.
- **Management-plane admin MFA (v0.3):** the server-side admin web UI enforces
**WebAuthn passkeys** — phishing-resistant, origin-bound, hardware-backed
MFA — behind a Traefik ingress that terminates a Let's Encrypt cert (DNS-01).
This is the first human-admin MFA in the system (the manager/broker admin planes
are a **connected system**, but the control is noted here as it closes the
long-standing "no admin MFA" gap for management operations; host SSH admin
remains key-only — R-05).
- **Link protection:** **MACsec** on the access link.
- **Boot & OS integrity:** **Secure Boot** + **signed UKI** with an **immutable
cmdline**; **dm-verity** read-only root (continuous cryptographic integrity);
@@ -221,7 +276,21 @@ summarises the implementation posture.
SSH**, root login disabled, hardened ciphers/MACs/KEX (note: STIG crypto policy
drops ed25519 → admin key must be ECDSA/RSA); **kiosk lockdown** (single locked
browser, no shell/navigation); **postfix removed** (no local MTA — audit-failure
notification rides the remote offload, not email).
notification rides the remote offload, not email). Three **local SELinux policy
modules** are shipped for architecture-specific allows, each a documented
deviation ([stig-deviations.md](stig-deviations.md) #14–16): `chrony_dhcp_dispatcher`
(NM-dispatcher chrony reload), `fapolicyd_tmpfs` (statfs the overlay upper), and
`fleet_agent_chronylog` (agent reads chrony's tracking log). No blanket
permissive domains; SELinux stays enforcing.
- **Application-control effectiveness fix (2026-07-04):** a bench finding showed
fapolicyd's exec guard was **effectively inactive on the root** — the diskless
root is `overlayfs`, which was **absent from fapolicyd's `watch_fs`**, so
fapolicyd marked no mounts and intercepted no exec on `/`, `/usr` or `/tmp`.
Adding `overlay` to `watch_fs` turned app-allow-listing **on for the whole
overlay root for the first time** — verified: a novel non-RPM binary in `/tmp`
is now denied (`FAN_DENY`), nothing legitimate broke. (Residual: path-based trust
doesn't catch a *modified trusted path* via copy-up — tracked as TODO #15 /
the `integrity=sha256` option — noted in stig-deviations #15.)
- **Privileged access:** single **key-only `wheel` admin**, root locked. The admin
is now **confined to the `staff_u` SELinux user** with a sudoers role/type
transition (`sysadm_r`/`sysadm_t`) so privilege elevation re-labels the SELinux
@@ -252,7 +321,16 @@ summarises the implementation posture.
2026-06-27** (`wazuh-logtest` + a live `sudo` surfacing `USER_CMD`/`CRED_*` in
the dashboard). Config is declarative (`serving/siem/`, mounted via
`/wazuh-config-mount`).
- *Gaps:* both offload hops (host→collector, collector→Wazuh) currently
- **Fleet health telemetry (v0.3):** the `fleet-agent` streams host health
(resource pressure, NVMe-root/auth/SELinux/chrony/kiosk state, uptime) to the
manager over mTLS; the manager persists a time-series (InfluxDB) and flags
version-drift, SELinux-permissive, and reboot-pending in an admin dashboard. This
is an **operational-health** signal (complements the auditd/Wazuh **security-event**
path — different purpose, different data): e.g. a host reporting `SELinux:
permissive` or overlay RAM exhaustion is surfaced for the operator. The store and
dashboard are a **connected system** (server-side); the host-side contribution is
the read-only probe + mTLS stream.
- *Gaps:* both audit-offload hops (host→collector, collector→Wazuh) currently
**plaintext** (TLS planned, R-07); **log retention/archival** (ISM) not yet
configured; default Wazuh credentials to be rotated before production.
@@ -275,9 +353,9 @@ AO will expect a maturity view:
| Patch applications | **Process** | Patching = rebuild + re-sign + redeploy a new digest; cadence/SLA to be defined. |
| Configure MS Office macros | **N/A** | No office suite; kiosk is a locked browser. |
| User application hardening | **Strong (kiosk)** | Chromium locked down via enterprise policy; no plugins/shell/nav. |
| Restrict admin privileges | **Partial** | Single key-only `wheel` admin, root locked, now **SELinux-confined to `staff_u`** with a sudo role/type transition (NOPASSWD, see R-05); no per-host/rotatable model or admin-MFA yet. |
| Restrict admin privileges | **Partial** | Single key-only `wheel` admin, root locked, now **SELinux-confined to `staff_u`** with a sudo role/type transition (NOPASSWD, see R-05); **management-plane** admin actions now require a **WebAuthn passkey** (v0.3). Still no per-host/rotatable *host* access model. |
| Patch operating systems | **Process** | Same rebuild/redeploy model; immutable image means uniform, atomic OS updates. |
| Multi-factor authentication | **Strong (machine)** | Host auth is certificate + TPM-bound key (something-the-machine-has, non-exportable). Human admin MFA to be addressed for the management plane. |
| Multi-factor authentication | **Strong (machine) + admin passkey** | Host auth is certificate + TPM-bound key (something-the-machine-has, non-exportable). **Human admin MFA is now enforced on the management-plane UI via WebAuthn passkeys** (phishing-resistant, origin-bound) — v0.3. Host SSH admin remains key-only (no separate human MFA — R-05). |
| Regular backups | **N/A (by design)** | Diskless, stateless hosts hold nothing to back up; recoverability is re-provisioning from a pinned digest. Backup applies to serving-side state, out of scope here. |
## 7. Residual risk summary
@@ -292,12 +370,14 @@ production ATO:
| R-02 | `debug_shell=true` bakes a **passwordless root shell** on a tty. | **High** | Treat — must be removed before production (lab-only). |
| R-03 | STIG hardening **applied + bench-verified** (2026-06-20); residual is that CI ships **unsigned, Secure Boot OFF** and `enable_stig` must be confirmed on for production builds. | **Medium** | Treat — confirm `enable_stig=true` in CI + enforce signing/SB before assessment. |
| R-04 | NVMe/TCP root traffic **plaintext** on the lab LAN. | **Medium** | Accept (isolated LAN) / treat for production. |
| R-05 | NOPASSWD key-only admin (now `staff_u`-confined); no per-host/rotatable access model or admin-MFA. | **Medium** | Accept with compensating controls / roadmap. |
| R-05 | NOPASSWD key-only **host** admin (now `staff_u`-confined); no per-host/rotatable access model. (Management-plane admin MFA now enforced via WebAuthn passkeys — v0.3.) | **Medium** | Accept with compensating controls / roadmap. |
| R-06 | **FIPS off**; ASD-approved-cryptography conformance not yet asserted. | **Medium** | Treat — required for PROTECTED+; revisit with signing. |
| R-07 | Audit-log offload **plaintext** on both hops (host→collector, collector→Wazuh); **log retention not yet configured**. SIEM **analysis + alerting now in place** (Wazuh, decode+alert bench-verified 2026-06-27). | **Low–Medium** | Treat — TLS both hops + ISM retention/archival + rotate Wazuh creds 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-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). |
| R-14 | **Management/enrolment plane is a connected system, built but not yet separately authorised.** The host now trusts + streams to the fleet-manager and enrols via the broker/**step-ca fleet CA** (a new trust anchor + key material) whose one **unauthenticated pre-auth CSR endpoint** is a new server-side surface. Host-side exposure is limited (outbound-only mTLS, read-only telemetry, commands logged-not-applied in v1). | **Medium** | Treat — separate SSP/authorisation for the management plane (CA key protection, broker endpoint hardening, InfluxDB token/data, admin-plane exposure). |
| R-15 | **Deferred agent reconcile actuators.** v1 receives `DesiredState`/`Command` but only logs them; when actuation (apply kiosk_url / reboot / drain) is built, the agent becomes a **remote host-mutation channel** needing re-assessment. | **Low** (v1) | Treat at build time — assess the command/authZ path before enabling actuators. |
Each is detailed, ISM-cross-referenced, rated and assigned a treatment in Annex A.