diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index ad59fa5..a31aae4 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -2196,6 +2196,46 @@ instruction, the skill's tailnet citation, this label), and two of the three surfaced only because something adjacent was being fixed -- nothing here gates prose, so no check could have caught any of them. +- **PER-DC OCTAVIA PKI GENERATED 2026-07-29 (operator-executed on voffice1). STRUCTURALLY + COMPLETE; IDENTITY VERIFICATION STILL OWED.** The mint itself was run by the operator, because + the PreToolUse guard hard-blocks it for the session and that block was NOT worked around. + **PER-DC INDEPENDENCE IS PROVEN BY MEASUREMENT, which is the whole point of F1:** both DCs + hold 12 files across 3 dirs, and sha256 DIFFERS between DCs for the issuing-CA key + (`b49dcf02` vs `ad62b3fd`), the controller-CA key (`c8397205` vs `2f1a419c`), the controller + cert (`c7bbef14` vs `00e0a55b`) and the overlay (`2654cf6c` 4682 B vs `0aae59ac` 4690 B). + Before F1 these columns would have been IDENTICAL -- the second generation would have + overwritten the first. Both overlays are mode 600, carry exactly 5 `lb-mgmt-*` keys, are ASCII + clean, and are GITIGNORED (the F4 gate held). Every private key is 600; both passphrases are + the required 44 bytes. + **NOT YET CONFIRMED, and deliberately not claimed:** the four CA subjects, the controller + certs' SAN sets, and the chain verifications are UNREAD -- the guard blocks the session from + running `openssl` against those paths, so this is recorded as structurally complete with + identity unverified rather than as done. A cert can be well-formed and name the wrong DC. + **P5 ON VOFFICE1 WENT 6 -> 18 FINDINGS, ALL 12 NEW ONES GENUINE, AND THE REGISTER CAUGHT A + DEFECT THE SESSION HAD EXPLICITLY WAVED THROUGH.** E2 x4: the CA certs are mode **664**. This + document's own earlier reading of that was WRONG -- it was called harmless "for public certs", + reasoning only about confidentiality. The real exposure is INTEGRITY: 664 is group-WRITABLE, + so a group member can replace a trust anchor. E3 x8: `controller.cert.pem`, + `controller-ca.cert.srl`, `controller.cnf` and `controller.csr` exist per DC with NO matrix + row -- the 18-row set landed earlier this session was INCOMPLETE, an instance of + "enumerate what EXISTS, not only what is declared" applied to this session's own work. + **WORTH RECORDING AS VALIDATION: all 12 would have been INVISIBLE before today's F2 and F6 + fixes** -- the rows were `singleton` and the locations resolved on the jumphost, so a vcloud + run reported NOT PROBED. The register found real defects in precisely the mint it was repaired + to observe. + REMEDIATION, LOGGED NOT EXECUTED: `chmod 600` the six certs (closes E2); and for E3, either + declare all four artifacts per DC or have the generator delete the two build intermediates + (`controller.cnf`, `controller.csr`) and declare the two that must persist + (`controller-ca.cert.srl` for future issuance, `controller.cert.pem`) -- a runbook change, so + put to the operator rather than picked. + **TWO NEW FINDINGS FROM THE EXECUTION ITSELF: F8** the `1.0-GEN.c` heredoc is a live paste + hazard (the operator hit it and had to correct the block; an indented `CNF` terminator can + yield a cnf with no `[alt_names]` and therefore a cert with NO SANs, while every step still + reports OK -- nothing asserts the SAN set); **F9** the controller cert's DNS SANs are coupled + to D-106 and nothing recorded it -- they are inert only because `os-public-hostname` is set + NOWHERE (B5 IP-ONLY; R5 refused setting it at Stage 5 as a D-019 repeat), so when Stage 7 + turns FQDN endpoints on, both DCs' certs carrying `dc0.vr0` becomes wrong exactly when it + starts mattering, and the likely disposition is REISSUE inside D-106's own FQDN-SAN step. **F3 -- both `~/octavia-pki/` and `overlays/octavia-pki.yaml` are ABSENT here** (existence checked, no contents read). So this is generation FROM SCRATCH for both DCs: there is nothing to reuse, which retires the reuse-vs-regenerate choice diff --git a/docs/audit/stage5-findings-20260729-successor.md b/docs/audit/stage5-findings-20260729-successor.md index 94900df..2da170a 100644 --- a/docs/audit/stage5-findings-20260729-successor.md +++ b/docs/audit/stage5-findings-20260729-successor.md @@ -249,3 +249,60 @@ because something adjacent was being fixed. Nothing in this repo gates prose, so none of them could have been caught by a check. +--- + +## F8 -- Step 1.0-GEN.c's heredoc is a PASTE HAZARD, hit live during execution + +**Class: authoring defect in an execution surface.** Found by the operator while generating, +2026-07-29 -- they had to correct the block before it would run, and recorded the reason as +"CNF heredoc must start at column 1". + +`1.0-GEN.c` opens `cat > controller.cnf <<'CNF'` from inside an INDENTED `( { ... } )` +subshell. The heredoc body and its `CNF` terminator sit at column 1 in the file, which is +correct -- but the surrounding block is indented, so anyone who copies the step and pastes it +with the indentation preserved gets a terminator that no longer matches. The heredoc then +never closes and the rest of the block is swallowed as config text. + +**Why it matters more than a formatting nit:** the failure is not clean. Depending on where the +paste breaks, `controller.cnf` can end up holding shell code, or the block can run with a cnf +that lacks `[alt_names]` -- which would produce a controller cert with NO SANs at all while +every other step still reports OK. Nothing downstream asserts the SAN set. + +FIX OPTIONS (not executed -- the operator was mid-execution and hard rule 1 forbids editing the +step under them): use `<<-'CNF'` with tab-indented body, or de-indent the heredoc explicitly +with a comment saying why, or generate the cnf with `printf` lines instead of a heredoc. The +third is the most paste-proof. + +QUEUED ALSO: a post-generation assertion that the controller cert actually carries the expected +SAN set, since an empty `[alt_names]` currently passes every existing check. + +--- + +## F9 -- the Octavia controller cert's DNS SANs are COUPLED to D-106, and nothing records it + +**Class: unrecorded cross-stage coupling.** Raised by an operator question during generation: +"Why isn't `os-public-hostname` set before this process?" + +The answer is that it is deliberately set NOWHERE (measured: no option key in `bundle.yaml` or +any overlay -- every hit is prose). `bundle.yaml:11` posture B5 is IP-ONLY, "the dual VIPs ARE +the catalog endpoints ... No control-plane DNS dependency", and R5 explicitly REFUSED option +(c), setting it at Stage 5, because that recreates the D-019 root cause -- metal-only charms +pulling a public FQDN endpoint they cannot resolve before FQDN-SAN certs exist. D-106's order +also puts it structurally later: designate DEPLOYS at Stage 5 but is CONFIGURED at Stage 7, so +at PKI-generation time no zone exists and no FQDN resolves. + +**So today the controller cert's two DNS SANs are inert strings** -- amphorae reach the +controller on `o-hm0`'s charm-generated ULA by ADDRESS, and the controller verifies amphorae by +UUID. That is why the known `dc0.vr0` residue is harmless right now. + +**THE COUPLING NOBODY HAS WRITTEN DOWN:** when D-106 lands at Stage 7 and `os-public-hostname` +is set, those DNS SANs STOP being cosmetic -- and **both DCs' controller certs carry +`octavia-controller.omega.dc0.vr0...`**, so dc1's would be wrong at exactly the moment it starts +mattering. D-106's own sequence includes "Vault issues FQDN-SAN certs", so the likely correct +disposition is that the amphora controller cert is REISSUED as part of that step rather than +patched now (it is a 2-year cert, and the amphora PKI is a separate trust domain from the +Vault-issued API TLS). + +Recorded because otherwise Stage 7 arrives and nothing connects "issue FQDN-SAN certs" to "the +Octavia amphora control-plane cert also needs redoing, per DC". NOT a Stage-5 blocker. +