diff --git a/docs/method/verification.md b/docs/method/verification.md new file mode 100644 index 0000000..67d5ce1 --- /dev/null +++ b/docs/method/verification.md @@ -0,0 +1,84 @@ +--- +id: RISK-METHOD-VERIFICATION +type: method +title: "What this register may verify for itself, and what it must take from owners" +status: adopted +owner: risk-nexus +adopted: "2026-08-20" +workplan: RISK-WP-0004-T05 +review_interval: 180d +--- + +# Verification + +`RISK-WP-0004-T05` asked what this repo can legitimately establish itself, +because two gradings were resting on file comparison. The answer was found by +trying, on 2026-08-20, rather than by reasoning about it. + +## The rule + +**A register may look. It may not touch, and it may not conclude on a system's +behalf.** + +Verification here means: running a read-only command a reporter has already +named, or that answers a question the register itself wrote down as open, and +recording exactly what came back. + +Permitted: + +- read-only reads of live state (`kubectl get`, `bao policy read`, an HTTP + probe of a documented endpoint); +- comparing what is deployed against what a repo said is deployed; +- recording the discrepancy and routing it as a **question**. + +Not permitted: + +- any write, apply, patch, restart or rotation — including one that would + obviously improve things; +- concluding what a defect means for a system this repo does not own. The + system stays authoritative about itself (`INTENT.md`); +- verifying instead of asking. The owner is asked first; verification settles + what an owner cannot see or has invited someone to check. + +`rapp-postgres` declined to check the NetworkPolicy on `flex-auth`'s behalf, +saying that would be reporting on a system they do not own. That was right +**for a reporter**. This register is the downstream party whose grade depended +on the answer, and `flex-auth` explicitly named the command and asked for +someone with credentials to run it. Those two positions are compatible. + +## What this host can actually reach — established 2026-08-20 + +| Target | Result | Consequence | +| --- | --- | --- | +| Kubernetes (`railiance01`) | **reads work** — `kubectl get ns`, `get networkpolicy -o json` | Live cluster state is verifiable by this register | +| OpenBao (`bao.coulomb.social`) | **403 permission denied** on `token lookup` and `policy read` | Policy claims are not verifiable here; `RISK-F-0009` rests on file comparison | + +The asymmetry is worth stating plainly: **the register can check what the +cluster admits, and cannot check what the secret store permits.** Every grade +touching an OpenBao policy is therefore a grade on a document, and says so. + +That is not a gap to close by acquiring credentials. A risk register holding +production secret-store access has traded a verification problem for a much +worse one. If OpenBao claims need verifying, the right answer is for the owner +to run the read and report it, which is what `ops-warden` did — the obstacle +there was an expired token, not the arrangement. + +## Recording a verification + +One file per verification in `docs/verifications/`, `RISK-V-NNNN`, stating the +command, the raw result, what it confirms, what it contradicts, and what it +does not establish. It names the findings it bears on, and those findings link +back. + +A verification is evidence, not a ruling. It can move a grade; it does not +close a finding on its own, and it never speaks for the owning repo. + +## Verification and the cadence ladder + +A verification that contradicts something is a check that is **not clean**: the +affected findings reset to `instant`. A verification that confirms what was +already recorded is clean, and may be exactly the evidence a rung is built on. + +The first one (`RISK-V-0001`) did both — it confirmed the ingress claim +`RISK-F-0001` was graded on, contradicted the egress claim in the same message, +and surfaced a third policy nobody had mentioned that bears on `RISK-F-0002`. diff --git a/docs/verifications/2026-08-20-flex-auth-networkpolicy.md b/docs/verifications/2026-08-20-flex-auth-networkpolicy.md new file mode 100644 index 0000000..0d9d3d2 --- /dev/null +++ b/docs/verifications/2026-08-20-flex-auth-networkpolicy.md @@ -0,0 +1,100 @@ +--- +id: RISK-V-0001 +type: verification +title: "flex-auth NetworkPolicy, verified against the live cluster" +date: "2026-08-20" +verified_by: risk-nexus +method: "read-only kubectl against railiance01" +findings: [RISK-F-0001, RISK-F-0002] +result: "ingress claim confirmed; egress claim contradicted; one policy not previously reported" +--- + +# RISK-V-0001 — the NetworkPolicy, actually looked at + +`RISK-F-0001` was graded twice on a fact nobody had checked. `flex-auth` said +so honestly — "I can tell you what is specified, not what is admitted" — and +named the command that would settle it. This register ran that command. + +``` +kubectl -n flex-auth get networkpolicy -o json +``` + +## What is confirmed + +**The ingress claim is exactly right**, and now rests on the live cluster +rather than a manifest: + +| Policy | Ingress from | Port | +| --- | --- | --- | +| `flex-auth-user-engine` | `namespaceSelector: user-engine` **and** `podSelector: user-engine` | 8080/TCP | +| `flex-auth-tenant-engine` | `namespaceSelector: tenant-engine` **and** `podSelector: tenant-engine` | 8080/TCP | + +Created 2026-08-09 and 2026-08-08 respectively — eleven days old, predating the +caller-authentication work, as `flex-auth` said. The reachable set during the +`A0` period was one workload per Deployment, not the cluster. + +`RISK-F-0001`'s `L2` grade is therefore **verified**, not inferred. That is the +first grade in this register standing on evidence this repo gathered itself. + +## What is contradicted + +`flex-auth` stated `egress: []` — "empty, i.e. none at all". **Live, all three +policies permit egress to any destination on TCP 443 and 6443**, with no `to` +selector. + +```json +"egress": [{"ports": [{"port": 443, "protocol": "TCP"}, + {"port": 6443, "protocol": "TCP"}]}] +``` + +6443 is the Kubernetes API server, which ADR-0004's TokenReview needs, so its +presence is unsurprising. 443 to anywhere is a different statement from "none +at all". + +This does **not** change `RISK-F-0001`'s grade — the finding is about who can +reach the decision surface, and ingress is what governs that. It does change +the evidence base, and it matters because the same sentence has been repeated +into two records. + +Routed to `flex-auth` as a question rather than a correction: does the +committed manifest say `egress: []`, in which case the deployed policy differs +from the file, or did the message misdescribe the manifest? Only they can say +which, and the two answers mean very different things. + +## What was not previously reported + +A **third** policy exists: `flex-auth-ops-warden`, created 2026-08-19T12:47Z — +the same day `flex-auth` reported the fix. + +``` +podSelector: app.kubernetes.io/name=flex-auth-ops-warden +policyTypes: [Ingress, Egress] +ingress: (no rules) +egress: 443, 6443 +``` + +`policyTypes` includes `Ingress` with no ingress rules, which in Kubernetes +means **deny all ingress**. On its face, nothing can reach that pin. + +**This bears directly on `RISK-F-0002`.** The remaining question there is +whether enabling `policy.enabled` breaks signing on availability grounds now +that the attestation hazard has lifted. If the flex-auth pin that `ops-warden` +is meant to call admits no ingress, then enabling a `fail_closed` gate against +it would fail closed — every `warden sign` would stop. + +The register is **not** concluding that. A policy may be mid-rollout, the pin +may not be the one `ops-warden` targets, and a second policy elsewhere may +admit the traffic. What the register is doing is putting the observation in +front of both owners before either of them flips a switch, which is precisely +what `RISK-F-0002` exists to prevent happening blind. + +## Limits of this verification + +- Read-only, and a point-in-time snapshot of 2026-08-20. +- It confirms what the API server admits **as specified**. Whether the CNI + enforces NetworkPolicy at all is a cluster property this check does not + establish, and `flex-auth` was right to flag it. +- OpenBao could not be checked: `bao token lookup` and + `bao policy read agent-high-risk-boundary` both return **403 permission + denied** from this host, the same wall `ops-warden` hit. `RISK-F-0009` + therefore still rests on file comparison. diff --git a/workplans/RISK-WP-0004-run-the-register.md b/workplans/RISK-WP-0004-run-the-register.md index 698aa30..e1c6361 100644 --- a/workplans/RISK-WP-0004-run-the-register.md +++ b/workplans/RISK-WP-0004-run-the-register.md @@ -4,7 +4,7 @@ type: workplan title: "Run the register: make the cadence actually happen, and close the gaps the first week found" domain: infotech repo: risk-nexus -status: proposed +status: active owner: the-custodian topic_slug: risk-nexus created: "2026-08-20"