diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index 923a236..5776758 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -196,8 +196,24 @@ management traffic only (MAAS/Juju/operator)" -- naming Juju -- and D-128 puts the Juju CLIENT on voffice1. So the question is WHICH RULED SURFACE GOVERNS, with the other amended; it is D-number material under the GA-R3 A1 test because it decides where the - Juju client lives at every future DC standup. **QUESTION IS OPEN AND BLOCKING; no - reachability change has been made.** + Juju client lives at every future DC standup. + **RULED 2026-07-30 -- D-138 ADOPTED (GA-R5). Operator answer, exact utterance: "Move the + cloud-facing client into the DC (Recommended)".** Tools that dial the CLOUD at L3 -- the + Juju client, and `phase-03`..`phase-06`'s `openstack` CLI work -- run from INSIDE the DC. + `voffice1` stays the Plane-2 host for everything application-proxied or `qemu+ssh`-mediated + (MAAS, NetBox, the inner tofu roots). **SEC-010, D-052 and D-125 are UNCHANGED and nothing + is punctured**; D-128's "Plane 2 runs on voffice1" is AMENDED to exclude cloud-facing tools. + Scope was set by ENUMERATION before the ruling: the gap was never bootstrap-only, because + keystone's VIP front-loads `10.12.4.50` on provider-public, so routing instead would have + meant opening TWO planes per DC across ports 22, 17070, 5000, 9292, 8774, 9696, 8776, 8778, + 9876, 9311, 9511 and 443. **CONSEQUENCE, now a standing DC-standup obligation:** the client + host needs its DC's MAAS credential locally, and that key is MAAS ADMIN-scoped over a + region SHARED by both DCs -- so each DC's client host receives ONLY its own credential + (never a copy of the whole client credential store, which would put dc1's credential on + dc0's rack and destroy SEC-018/-019 per-DC isolation), and the residency gets its own + security-ledger row (**SEC-026**, opened 2026-07-30). Gap register item 20's DC half CLOSES + on this ruling rather than on a tool, and `site-baseleg.sh`'s deferred DC rows stay + DEFERRED with their `# MEASURE first` note now ANSWERED: no host-side leg is wanted. **UNBLOCKED AND NOW BUILT, both DCs (the D-134 amendment stops being ruled-but-not-built):** operator ruled 2026-07-30, exact utterance **"Fix now: static .5 + v6, re-bootstrap (Recommended)"**. Question as presented: the controller had bootstrapped onto an AUTO, diff --git a/docs/changelog-20260730-stage5-open.md b/docs/changelog-20260730-stage5-open.md index 48fd1e8..343520b 100644 --- a/docs/changelog-20260730-stage5-open.md +++ b/docs/changelog-20260730-stage5-open.md @@ -176,3 +176,37 @@ the original single auto link. dc0 = `7n87bt` iface `419` subnet `6`; dc1 = `p8tdwg` iface `426` subnet `11`. Both machines are `Ready` and powered off, so this is safe at any time before they are allocated. + +### 6. D-138 ADOPTED + SEC-026 opened -- the cloud-facing client moves into the DC + +**What.** New `## D-138` in `docs/design-decisions.md` (ARCH); new `SEC-026` row in +`docs/security-ledger.md`; `docs/CURRENT-STATE.md` section 1 updated in the same commit +(GA-R1/C1). Counters after: **22 open SEC**, next-free **D 139** / DOCFIX 206 / +BUNDLEFIX 053, reconciled by `bash scripts/ledger-scan.sh`. + +**Why (evidence).** Operator ruling 2026-07-30, exact utterance **"Move the cloud-facing +client into the DC (Recommended)"**, taken on the Stage-5 bootstrap failure. Admitted as +a D-number under GA-R3's A1 test: it decides where the Juju client lives at every future +DC standup, and it AMENDS D-128. Full question, options and consequences are in the D-138 +entry. + +**The ruling costs nothing in security posture, which is why it is the smaller change.** +SEC-010, D-052's DC-local invariant and D-125's proven egress isolation are all untouched; +no rule was punctured and no plane was opened. The alternative would have opened two +planes per DC across a dozen ports and required D-125 to be re-tested. + +**SEC-026 is a consequence, not an afterthought.** D-138 puts a MAAS ADMIN-scoped key on a +DC-local host, and the MAAS region is shared across both DCs -- so that host has +region-wide MAAS admin including over the other DC's hardware. The row's load-bearing +control is isolation: each DC's client host gets ONLY its own credential. Copying +voffice1's whole `credentials.yaml` (which holds both `vr1-dc0-cred` and `vr1-dc1-cred`) +to a DC rack would, in one act, destroy the per-DC isolation SEC-018/-019 exist to create. + +**repo-lint L10 did its job.** The first attempt to land D-138 alone FAILED the pending +change-set check -- a Status-bearing surface changed without `CURRENT-STATE.md` in the +same commit. Recorded because it is a gate proving it can fail, on a real commit rather +than a fixture. + +**Revert.** `git revert ` removes D-138, SEC-026 and the CURRENT-STATE +paragraph together. Nothing was executed on the cloud under this ruling yet, so no live +state depends on it at the time of writing. diff --git a/docs/design-decisions.md b/docs/design-decisions.md index a115a4a..c03b2ce 100644 --- a/docs/design-decisions.md +++ b/docs/design-decisions.md @@ -6465,3 +6465,74 @@ entry carrying a revert. NOTE the T24 caveat carried from the 2026-07-27 close: the finding-class baseline covers TIER 1 ONLY, so a tier-2/3 regression introduced by these edits would not turn the gauntlet red on its own. + +--- + +## D-138: ADOPTED -- the cloud-facing client lives IN the DC; the Office1 transit stays management-terminating, not management-transiting [ARCH] + +**Status: RULED 2026-07-30** (operator, GA-R5). Raised by the FIRST live `juju bootstrap` +of Stage 5, which failed on this and could not have succeeded without it. + +**Question as presented.** Stage 5 could not proceed: `voffice1` -- the D-128 Plane-2 +execution host, and therefore the Juju client -- has NO L3 path to any DC node plane, and +two deliberate controls forbid creating one. This is a contradiction between surfaces that +are BOTH ruled: + +- **SEC-010 + D-052** make `metal-admin` DC-LOCAL. The SEC-010 row states it in writing -- + "Nothing routes across the fiber THROUGH vvr1-dc0; the rack proxies MAAS at the app layer + (originated/terminated, not forwarded)" and "Region route must target only the rack + transit /30, never 10.12.8.0/22". CLOSED 2026-07-20 on the operator's exact utterance + "Close SEC-010 (Recommended)", applied and verified both ends by a named gate (EXIT 0, + `docs/audit/stepB-check-20260720-final.txt`). +- **D-100** says the Office1<->DC fiber "carries management traffic only (MAAS/Juju/ + operator)" -- naming Juju explicitly. +- **D-128** puts the Plane-2 execution host, and so the Juju CLIENT, on `voffice1`. + +**Operator answer, exact utterance: "Move the cloud-facing client into the DC +(Recommended)".** + +**RULED (1) -- the client moves, the boundary does not.** Tools that dial the CLOUD at L3 +run from INSIDE the DC: the Juju client (bootstrap, and every agent connection) and the +`openstack` CLI work in `phase-03`..`phase-06`. `voffice1` remains the Plane-2 host for +everything that is application-proxied or `qemu+ssh`-mediated -- MAAS, NetBox, the inner +`tofu` roots. SEC-010, D-052's DC-local invariant, and D-125's proven egress isolation are +UNCHANGED; nothing is punctured. + +**RULED (2) -- why the contradiction was real and is now resolved.** SEC-010's cost was +priced with the sentence "a MAAS rack proxies at the application layer and needs no kernel +forwarding, so pinning is free." That is TRUE of every Plane-2 tool then in use and FALSE +of Juju, which dials the MACHINE at L3. **Juju was not in scope when the pin was priced.** +D-100's "carries Juju traffic" is preserved in the sense that matters: management traffic +crosses the fiber and TERMINATES on the rack; it does not TRANSIT the rack onto a node +plane. D-128's "Plane 2 runs on voffice1" is AMENDED to exclude cloud-facing tools. + +**Scope was established by ENUMERATION before ruling, not discovered afterwards.** The gap +is not bootstrap-only: `scripts/phase-03-admin-openrc.sh` builds +`OS_AUTH_URL=https://${KEYSTONE_VIP}:5000/v3`, and keystone's VIP front-loads `10.12.4.50` +on PROVIDER-PUBLIC -- a second plane `voffice1` also cannot reach. Routing instead would +have meant opening two planes per DC across ports 22, 17070, 5000, 9292, 8774, 9696, 8776, +8778, 9876, 9311, 9511, 443 and more. That breadth is what made the client-side answer the +smaller change. + +**CONSEQUENCE THAT MUST BE HANDLED AT EVERY DC STANDUP -- a per-DC cloud credential now +lands on a DC-local host.** The Juju client needs its DC's MAAS credential where it runs. +The `juju-vr1-dcN` API key is MAAS **admin-scoped** (SEC-018/-019: full machine/power/ +deploy) and the MAAS region is SHARED across both DCs, so a DC-local host holding it has +region-wide MAAS admin. Two standing requirements follow: (a) each DC's client host +receives ONLY THAT DC's credential -- never a copy of the whole client credential store, +which would put dc1's credential on dc0's rack and destroy the SEC-018/-019 per-DC +isolation; (b) the residency is a NEW exposure and gets its own security-ledger row at the +standup that creates it. Roosevelt analog: the per-DC management bastion holds only its own +DC's cloud credential. + +**Roosevelt analog.** Each DC has a management entry point inside it; the NOC reaches that +entry point, not every DC's admin plane directly. That is the more faithful model for bare +metal, where routing a headend onto every DC's admin network is exactly the flat-management +-plane design this project is rehearsing away from. + +**Cross-notes.** AMENDS D-128 (Plane-2 host scope). PRESERVES SEC-010, D-052, D-125. +Resolves the `scripts/site-baseleg.sh:42,47` deferral -- the DC rows stay DEFERRED and +their `# MEASURE first` note is now ANSWERED: the measurement was taken 2026-07-30 and the +answer is that no host-side leg is wanted. Workflow-doc gap register item 20's DC half +CLOSES on this ruling rather than on a tool. Failure capture: +`docs/audit/stage5-bootstrap-reachability-20260730.txt`. diff --git a/docs/security-ledger.md b/docs/security-ledger.md index 697592b..676ec2d 100644 --- a/docs/security-ledger.md +++ b/docs/security-ledger.md @@ -76,3 +76,4 @@ and enforcement is a blocking preflight gate rather than a run-it-and-remember habit. The current rule text is in D-137; this paragraph is kept as the record of what existed before it. +| SEC-026 | 2026-07-30 | **A MAAS admin-scoped API key becomes RESIDENT on a DC-local host, by D-138.** D-138 (RULED 2026-07-30) moves the cloud-facing client -- the Juju client, and `phase-03`..`phase-06`'s `openstack` CLI work -- INTO each DC, because `voffice1` has no L3 path to any DC node plane and SEC-010/D-052/D-125 deliberately forbid creating one. The client needs its DC's MAAS credential where it runs, so `juju-vr1-dc0`'s key (SEC-018) now lives on the dc0 client host, and `juju-vr1-dc1`'s (SEC-019) will on dc1's. **The exposure is wider than the DC it sits in: the key is MAAS ADMIN-scoped (full machine/power/deploy) and the MAAS region is SHARED by BOTH DCs**, so a host inside dc0 holding it has region-wide MAAS admin, including over dc1's hardware. This is a NEW residency, not a new key -- SEC-018/-019 already carry the keys' own rotation obligations. | 2026-07-30 Stage-5 bootstrap failure + D-138 ruling; capture `docs/audit/stage5-bootstrap-reachability-20260730.txt` | operator | **OPEN.** (1) **ISOLATION IS THE LOAD-BEARING CONTROL:** each DC's client host receives ONLY THAT DC's credential. Never copy the whole Juju client credential store (`~/.local/share/juju/credentials.yaml` on voffice1 holds BOTH `vr1-dc0-cred` and `vr1-dc1-cred`) to a DC host -- that single act would put dc1's credential on dc0's rack and destroy the per-DC isolation SEC-018/-019 exist to create. Verify after any client rebuild that `juju credentials --client` on a DC host lists exactly one. (2) ROTATE at v1 close, or immediately if the DC client host is rebuilt or shared. (3) SCOPE HARDENING CANDIDATE, Roosevelt-relevant: MAAS has no per-DC admin scope, so the blast radius is regional by construction; a narrower grant (or a per-DC MAAS region) is the fix and is deferred, not solved. (4) The residency must be re-asserted at every DC standup as part of D-138's definition-of-done. |