diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index 2c6e54f..6b88533 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -977,10 +977,27 @@ umask CAUSE was out of ruled scope, so a future apply may rewrite 0664 -- P5 will catch it. The key reaching state files in plaintext at all remains DOCFIX-175, rotation owed under SEC-018/-019. - **STILL OUTSTANDING (not done, not silently dropped):** ruling 1's TIER 2 `Pn` (tier 1 - is wired -- RESOLVED, see the tier-2 gate block below) - (VALIDITY); `--render`'s source-field derivation; and the `cardinality` field remains - largely inert with a one-token S5 bypass (`per-DC` -> `singleton`). + **STILL OUTSTANDING (not done, not silently dropped):** ruling 1's TIER 2 remote `Pn` + (tier 1 + tier-2-local ARE wired -- see the tier-2 gate block below); `--render`'s + source-field derivation and the manifest flip to generated output; and the `cardinality` + field remains largely inert with a one-token S5 bypass (`per-DC` -> `singleton`). + (A dangling fragment here, left by an earlier edit in this same session, was repaired at + session close -- noted rather than silently fixed, since CURRENT-STATE is the status + authority and its defects are worth seeing.) + **QUEUED FINDINGS CAPTURED 2026-07-26 at session close: + `docs/audit/queued-findings-20260726.txt`** -- an end-of-session sweep for content that + existed ONLY in the session transcript. Part A: the three secrets-storage items NOT + already repo-carried (Tang/Clevis as the no-HSM unseal mechanism; **MAAS 3.7's Vault + integration MEASURED `status: disabled`**, with the MAAS/Vault circular dependency that + must be designed around before enabling it on bare metal; a Vault SSH CA to retire the + static keypairs) plus sequencing advice -- framed so a future session does not re-propose + what D-068's analysis and D-137 item 2(a) ALREADY carry. Part B: ten committee findings + ACKNOWLEDGED but deliberately NOT acted on, the most consequential being that `mint-ref` + line pins rot SILENTLY (S4 checks existence and EOF, never content, so every pin becomes + wrong-but-passing when the runbooks are rewritten for Roosevelt) and that ruling-5 + REMEDIATION and ruling-5 EVASION are indistinguishable to S6. Part C: items deferred by + ruling, recorded so they are not later mistaken for oversights. NONE of it is ruled or + built; `cardinality` (B6) needs an operator ruling. ## 9. Additional defect found while authoring (FIXED in sweep Batch 0.3, 2026-07-19 -- wrap-aware exclusion, GA-F15; history below) diff --git a/docs/audit/queued-findings-20260726.txt b/docs/audit/queued-findings-20260726.txt new file mode 100644 index 0000000..71fedad --- /dev/null +++ b/docs/audit/queued-findings-20260726.txt @@ -0,0 +1,147 @@ +# Queued findings + unlogged advice -- end-of-session sweep, 2026-07-26 +# +# WHY THIS FILE EXISTS. The 2026-07-26 session ran long and produced two classes of +# content that lived only in the session transcript: committee findings that were +# ACKNOWLEDGED but deliberately NOT acted on, and a secrets-storage recommendation given +# verbally on request. A transcript is not a repo surface. This is the durable copy. +# +# NOTHING HERE IS RULED OR BUILT. These are logged findings and unruled advice (hard rule +# 1: findings are logged, never executed mid-step). Status lives in CURRENT-STATE only. + +================================================================================ +PART A -- ADVICE GIVEN VERBALLY THAT IS **NOT** ALREADY REPO-CARRIED +================================================================================ + +IMPORTANT FRAMING, checked before writing this: MOST of the secrets-storage +recommendation given in session was ALREADY in the repo and is NOT new. + - OpenBao / BUSL relicensing / the fork question .... docs/D-068-vault-1.8-vs-1.16-analysis.md + - Vault auto-unseal, root-Vault topology ............ same file + D-069 discussion + - `scripts/creds-mint.sh` (atomic mint->store->register, with modes, refusal-to-overwrite, + and a creds-audit gate) ........................... docs/design-decisions.md D-137, item 2(a) +A future session should read those FIRST and treat the items below as the delta, not as a +new proposal. Re-proposing what is already ruled is this project's measured failure mode. + +--- A1. Tang / Clevis (NBDE) as the no-HSM unseal mechanism [NOT in repo: 0 hits] +No HSM or KMS is available (operator-confirmed 2026-07-26), which removes the standard +Vault auto-unseal path. Network-bound disk encryption (Tang servers + Clevis binding) is +the usual on-prem substitute: unseal material is recoverable ONLY while the host can reach +N Tang servers on the management network, so a disk that leaves the datacenter is inert. +It maps onto the existing per-DC isolation posture (SEC-012/-016 per-DC power keys) and +costs no hardware. Suggested shape: DC Vaults transit-unseal from an Office1 unsealer; the +unsealer's own material Tang-bound (plus TPM measurement if Roosevelt hardware has TPM 2.0 +-- UNKNOWN, and it decides Tang-alone vs Tang+TPM); Shamir shares exist only as physical +break-glass, split across sites, never on a jumphost. + +--- A2. MAAS 3.7 Vault integration is AVAILABLE AND DISABLED [MEASURED 2026-07-26] + ssh voffice1 'sudo maas config-vault status' -> status: disabled + unconfigured_regions: [voffice1] +MAAS 3.3+ can store its secrets in Vault instead of its database -- including power +credentials, the category behind SEC-012, SEC-016 and SEC-021. This is a native, supported, +in-stack capability that is simply switched off. + ** CIRCULAR DEPENDENCY, design around it before enabling at Roosevelt: MAAS provisions + the metal, Vault runs on that metal, and MAAS-with-Vault will not start without Vault. + On bare metal that is a bootstrap-ordering problem, not a config step. The usual answer + is a management-site Vault that is NOT MAAS-provisioned. Enabling it in VR1 FIRST -- where + the substrate is virtual and recoverable -- is what a rehearsal is for. + +--- A3. Vault SSH secrets engine (SSH CA) [NOT in repo: 0 hits] +Six of the twelve no-mint credentials in the research capture are ed25519 keypairs, and +every per-DC power key, edge key and service key is a static file that lives forever. An +SSH CA issuing short-lived certificates collapses that entire category: no file to +consolidate, no key to rotate, no matrix row that can go stale. Highest structural leverage +of anything discussed, and it depends on the fork decision (A-framing) landing first. + +--- A4. Sequencing advice, and one recommendation to NOT do something +Recommended order: (1) resolve the Vault-vs-OpenBao fork question; (2) build the D-137 +`creds-mint.sh` already specified in item 2(a) -- BEFORE Stage 5, because Stage 5 is the +largest credential-minting event in the project (per-DC MAAS keys, the Juju cloud +credential, bootstrap controller/CA/agent secrets, and behind them Vault init material, +the 8 Octavia PKI artifacts and admin-openrc); (3) MAAS->Vault rehearsed in VR1; (4) SSH CA; +(5) Juju + Barbican secret backends. +RECOMMENDED AGAINST: a sops/age encryption-at-rest stopgap. It was raised and then withdrawn +in the same session -- if the Vault path is real it is throwaway work, and tooling churn +that presents as progress is this project's own recorded failure mode (GA-F06). + +================================================================================ +PART B -- COMMITTEE FINDINGS ACKNOWLEDGED BUT **NOT** ACTED ON +================================================================================ +From the six-lens audit, 2026-07-26. Each was reproduced or reasoned by its lens and left +deliberately. Ranked by consequence. + +--- B1. `mint-ref` line pins rot SILENTLY [lens 6] +`s4_mint_ref` checks only that the target file exists and that the line number is <= EOF. +There is NO content assertion. Edit anything above a cited line and the mint-ref now points +at unrelated code while S4 still reports `[ok] every script:/runbook: reference resolves`. +30+ rows carry line pins into actively-edited runbooks and scripts. AT ROOSEVELT the +runbooks are rewritten for bare metal, so every line-pinned mint-ref becomes +wrong-but-passing simultaneously. Suggested fix: store an anchor token (step id, function +name, short literal) alongside or instead of the line, and assert it appears at/near the +cited line. + +--- B2. Ruling-5 remediation and ruling-5 EVASION are indistinguishable to the checker [lens 4] +S6 groups by `id`. The sanctioned fix for the `maas-region-admin` conflation (migrate the 19 +`maas admin` call sites to a service identity) and the evasion (rename one row's id to +`maas-region-admin-svc`) BOTH turn the check green. The notes warn humans not to do the +latter; nothing mechanical distinguishes them. + +--- B3. No non-emptiness check in tier 2 [lens 2] +`creds-audit.sh:59` asserts `[ -s "$path" ]`; the matrix checker has no equivalent. A +zero-byte credential file reads as PRESENT and correctly-moded. + +--- B4. `sec-ref` is never validated [lens 2] +Contrast S4 (mint-ref) and S7 (notes-ref), both of which resolve their references. A wrong +SEC pointer is exactly the class caught by hand FOUR times this session (SEC-015 once, +then both `juju-maas-user` rows, plus the tfstate row). A validator must parse the ledger's +TABLE form (`| SEC-006 |`), not `## SEC-` headings. + +--- B5. No "source-of-record implies a consolidated copy" invariant [lens 2] +`netbox-secret-key` and `netbox-admin` are VM-resident with NO consolidated copy at all -- +the exact founding SEC-009 shape ("a VM-minted secret has no forcing function to reach the +folder") -- and nothing flags it. + +--- B6. `cardinality` is largely inert, with a one-token bypass [lenses 2 + 6] +Of 81 rows the field affects only S1's enum validation and S5's `per-DC` filter; +`singleton`, `per-site`, `per-node` and `per-tenant` have no semantic effect, and `per-node` +is used by no row. Relabelling a row `per-DC` -> `singleton` removes it from S5 entirely -- +the cheapest way to silence the standing SEC-021 asymmetry findings, and nothing guards it. +The plan claims cardinality is "REQUIRED for Roosevelt transfer -- without it the matrix +cannot express '9 nodes'"; as built it expresses no such thing. Either make it load-bearing +(an `instances` field, or template expansion generating the per-DC/per-node/per-tenant row +set) or demote the claim. THIS IS A DESIGN QUESTION AND NEEDS AN OPERATOR RULING. + +--- B7. S5 is structurally BINARY [lens 6] +`dcs = ["vr1-dc0", "vr1-dc1"]`, `DC_TOKEN_RE = dc[01]`, `SITE_KEY_RE` an enum of `vr1-*` +literals, and a pairwise set-difference. A third DC needs four source edits and S5 does not +generalise to N sites. Suggested fix: derive the site set from the matrix, validate +region-qualification by SHAPE not enum, and restructure S5 to group-by-normalised-shape +across N sites. + +--- B8. T22's metadata-only guard is narrower than it reads [lens 1] +The wordlist omits `open()` -- the checker's actual read mechanism -- and `dd`, `sed`, `awk`, +`base64`. It also greps comments and docstrings, so prose alone can false-RED it (measured +twice this session: the word "more" tripped it). T51 partially covers the transfer half. + +--- B9. `--dc` narrows only S5 [lens 1] +Its help text says it narrows the per-DC checks; in fact S1-S4, S6, S7 and tier 2 still +process all rows, so the flag WEAKENS a run rather than scoping it. Either make it narrow +the run or remove it. + +--- B10. Low severity, recorded for completeness [lens 1] +Dead code at the `observed`-membership guard (unreachable since `observed` is pre-populated); +`s3_render_drift`'s unused `notes` parameter; `os.path.join(repo, path)` returns an absolute +mint-ref path unchanged, escaping the repo bound; S7's orphan scan only considers keys +prefixed `n-`. + +================================================================================ +PART C -- ALSO DEFERRED BY RULING (recorded so they are not mistaken for oversights) +================================================================================ +- SEC-024 RETENTION: whether the two `terraform.tfstate.pre-*` state-surgery snapshots + should exist at all. Operator-deferred to stage close 2026-07-26. Both gates (G6, G16) + are CLOSED and the outer plan has converged to zero diff repeatedly since, but deletion + is irreversible with no other copy of that state. +- SEC-024 umask CAUSE: not investigated (outside the ruled scope). A future `tofu apply` + may write 0664 again; the P5 gate will catch it. +- `--render` source-field derivation from `vm-secret-locations`: not wired; two fields are + explicitly skipped as PENDING rather than silently matched. +- Manifests are not yet REPLACED by rendered output. Ruling 2 makes them generated; doing + the flip changes what `creds-audit` demands at three sites, so it stays operator-gated.