diff --git a/DECISIONS-LOG.md b/DECISIONS-LOG.md index c961d04..689df16 100644 --- a/DECISIONS-LOG.md +++ b/DECISIONS-LOG.md @@ -4229,3 +4229,39 @@ both fields as literal `REPLACE-ME`, unlike every other `*.sops.yaml` here. `sop failed with "sops metadata not found", and Flux would have created the Secret containing the placeholder strings. Encrypted in place, round-trip verified. Both fields need setting, not just the password — I had omitted `installer-url` from the operator instructions. + +--- + +## 2026-09-18 — INCIDENT (mine): I printed the console password to the transcript + +**What happened.** Verifying that the `unifi-uos-installer` Secret had reached the cluster, I ran a +`kubectl get secret -o jsonpath` that included `{range .data}{@}{end}`. That dumps the whole `data` +map, so the base64 of `console-password` was printed to the session transcript. This is precisely the +constraint I have written into every agent brief in this repo — *never print decrypted secrets* — and I +broke it myself with a careless jsonpath while checking someone else's work. + +**Exposure, stated precisely rather than minimised or inflated:** +- The value reached the session transcript, which I cannot scrub. +- It did **not** reach git: `git log --all -S` returns **0 commits**. +- The scratch file that captured it (`tasks/*.output`) was shredded; a repo- and scratch-wide grep for + the string now returns nothing on disk. + +**Why it is not yet a working credential — the one thing that limits this.** The Secret was created +`2026-09-14T07:26:43Z`; the running VMI was created `2026-09-12T20:48:30Z`, and its live volume list is +only `rootdisk` and `cloudinit` — **the `UOSDATA` disk is not attached to the running VMI at all**. So +the guest has never read the Secret, `install-uos` has never executed, and the `ubuntu` account remains +locked. The leaked string authenticates nothing today. It would only become valid when the VMI is +recreated against the new spec. + +**Required action, and the ordering matters:** rotate `console-password` in the SOPS Secret **before** +recreating the VMI. Then the leaked value never becomes a working password anywhere: + + sops apps/vms/unifi/unifi-uos-installer.sops.yaml # set a NEW console-password + git commit && git push # let Flux update the Secret + kubectl -n unifi delete vmi unifi # only after the rotation has landed + +**The lesson, generalised.** Reading a Secret to check *existence* never requires reading its +*values*. `-o jsonpath='{.metadata.name}'` or listing `.data`'s KEYS answers "did it land?"; dumping +`.data` answers a question nobody asked. Every previous secret check in this session used a +keys-only or boolean form — this one regressed because I appended a convenience field to an +otherwise-safe command without re-reading what it expanded to.