Files
ops-warden/wiki/WorkloadSecurityPosture.md

7.5 KiB
Raw Blame History

Workload Security Posture — NetKingdom standard (draft)

Status: ops-warden-authored draft, WARDEN-WP-0015 T1. Pending promotion to canon along two homes (see Canon layering). Until landed, this file is the authoritative working draft; the canon copies supersede it once merged.

ops-warden's role: author + conformance. ops-warden does not enforce this standard at runtime (flex-auth) and does not hold the secrets (OpenBao). It authors the ops-security slice and ships conformance checks + dev-tier doubles.

NetKingdom IT-security posture is defined along two orthogonal axes. A workload's right to receive a secret depends on both, unified by a secret-flow lattice.


Axis A — Environment posture (how the secret store is secured)

The lifecycle tier of the secret store backing a workload. Contracts are identical at every tier (so automation and the warden access proxy run unchanged); only the backend's security posture changes.

R1 — Contract parity, posture divergence. Identical interface at every tier; only posture changes. This is why dev-tier contract doubles ("fake bao") work. R2 — Promote topology, regenerate material. Secret values are never promoted up the ladder; only structure (paths, policy shape, names). Values are generated fresh per tier. Test conveniences (reuse, single-unseal) stay quarantined in test. R3 — Dev touches no real data, ever. An insecure personal mock store in dev is sanctioned iff dev uses only synthetic data. Absolute invariant. R4 — Phase-changes are ceremonies, not copies. test → prod is a gated checklist (regenerate secrets, switch unseal model, enable break-glass, human sign-off), referencing the existing net-kingdom security-bootstrap-* and unseal-custody docs — not duplicating them.

dev test prod
backend mock / contract double OpenBao -dev (single-unseal) OpenBao sealed (Shamir 3-of-5)
real values forbidden (synthetic) generated, reuse allowed generated fresh, reuse forbidden
unseal n/a single key / auto 3-of-5 + break-glass
real user/business data never never allowed
audit optional on full, tamper-evident

Axis B — Workload maturity (how trusted a workload is)

Production is a posture, not a maturity. A workload can run in prod posture yet be low maturity (alpha with friendly customers). Maturity gates which secrets and data classes a prod workload may touch. Levels are a total order M0 < M1 < M2 < M3.

Level Phase Max DataClassification it may handle Promotion gate (into this level)
M0 Experimental / PoC synthetic only — (entry level)
M1 Alpha / early-access low-criticality, loss-acceptable; no confidential/restricted friendly-customer scope agreed, basic SLO, data-handling note
M2 Beta / GA up to confidential; SLOs; audited security review, SLO history, on-call, incident runbooks
M3 Critical / regulated restricted; break-glass; compliance pen-test, 3-of-5 custody, human-in-loop ops, compliance audit

DataClassification (confidential, restricted, …) is reused from the info-tech-canon Data Model — not redefined here. Promotion gates reuse the info-tech-canon DevSecOps Model's quality/policy gates and DeploymentVerification (SLOs / smoke / canary / operator confirmation), applied to maturity advancement.


The combined rule — secret-flow lattice

A secret carries a required_maturity (and implicitly the required_maturity of its DataClassification). Delivery is no-write-down:

deliver(secret → workload) is permitted only if
    workload.env_posture == prod                                 # Axis A
AND workload.maturity     >= secret.required_maturity             # Axis B
AND workload.maturity     >= required_maturity(dataclass(secret)) # data class floor

"Critical-infrastructure secrets must not be transferred to workloads below maturity M" is exactly the second clause. The lattice is checkable by ops-warden (conformance) and enforceable at runtime by flex-auth. Access semantics (who, on behalf of whom) remain governed by the CARING Access Governance Standard.

Worked example: an NPM_AUTH_TOKEN used only by a build pipeline → required_maturity: M1, dataclass internal. A production database password for regulated user data → required_maturity: M3, dataclass restricted; it may be delivered only to a prod-posture, M3 workload.


Using this to refine blockers

When a workstream says "blocked on security", classify it before escalating. The classification decides whether the blocker is real, belongs to an owning subsystem, or can be removed by a dev/test double.

Question Result
Is the work dev or test posture only? Use synthetic contract doubles or generated test values. Do not wait on real production secrets.
Is the work prod posture with real values? Require owner custody (usually OpenBao), flex-auth policy where applicable, and non-secret evidence only.
Is workload maturity below the secret's required_maturity or data-class floor? This is a real IT-security blocker until the workload advances, the secret is reclassified, or the design avoids the secret.
Does a route exist and the lane is exec_capable? warden access --fetch/--exec may remove operator copy/paste as a blocker by proxying the owner's tool as the caller.
Is unseal, break-glass, or issuer custody unresolved? Keep it as an operator ceremony/design blocker; do not paper it over with agent-visible values.

The evidence to record is route id, owner, env posture, workload maturity, required_maturity, policy decision id, OpenBao path/version, populated-key count, smoke id, or token accessor. Never record the secret value.

This is the practical bridge from WARDEN-WP-0014 (warden access) to WP-0015: access assist can remove manual secret handling friction, while posture/maturity decides whether the secret may flow at all.


Canon layering (where each part lands)

Part Canonical home ops-warden role
Generic WorkloadMaturityLevel concept + the secret-flow lattice info-tech-canon (DevSecOps / Landscape; reuses Data Model DataClassification, Security Model criticality) Contribute; do not fork
NetKingdom M0M3 security requirements + env-posture ceremonies net-kingdom canon (beside openbao-unseal-custody-models.md, responsibility-map.md) Author the ops-security slice
Machine-readable descriptors + conformance checker + dev doubles ops-warden (registry/policy/, scripts/) Own (WP-0015 T2T4)
Runtime enforcement of the lattice flex-auth Route; do not enforce here

Boundaries preserved

  • OpenBao holds secret values. ops-warden never custodies them.
  • flex-auth decides allow/deny (incl. enforcing this lattice at runtime).
  • CARING / Access Control governs access semantics and delegation.
  • key-cape establishes identity. ops-warden authors the standard and checks conformance — it does not become a broker, PDP, or IdP (responsibility-map).

See also

  • wiki/OperatorAccessAssist.md — the posture-aware warden access fetch surface
  • net-kingdom/docs/openbao-unseal-custody-models.md, responsibility-map.md, platform-root-custody.md, security-bootstrap-*
  • info-tech-canon: Security Model, DevSecOps Model, Data Model, CARING Access Governance
  • workplans/WARDEN-WP-0015-secret-lifecycle-tiering.md