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:
+107
-27
@@ -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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user