Newer
Older
openstack-caracal-dc-dc / docs / security-ledger.md

Security exposure / obligation ledger (DOCFIX-078)

Commercial posture: every credential exposure, rotation obligation, and security TODO gets a ROW here with an owner and status -- never only a comment in a script header (where the libvirt item below lived for a week). Review this ledger at every phase-00 (teardown) and before any handoff. Locations of key material are deliberately NOT recorded here -- custody detail lives off-repo per D-069.

id date item source / evidence owner status
SEC-001 2026-06-26 libvirt SSH credential printed in plaintext by maas machine power-parameters during reenroll work scripts/reenroll-hosts.sh header note operator OPEN -- rotate at v1 close (operator ruling 2026-07-06; was "after rebuild")
SEC-002 2026-06-17 juju action params persist in the operation log -- charm authorization must use short-lived child tokens DOCFIX-011 operator STANDING RULE (verify each vault authorize)
SEC-003 2026-07-03 Vault unseal-key custody is single-operator (bus factor) D-069 operator OPEN -- assign custodians + rehearse second-person unseal (DEFERRED 2026-07-06 by operator; note: keeps d011-06 MANUAL, gates D-011 full close)
SEC-004 2026-05-27 repo temporarily PUBLIC for v1 web_fetch workflow project completion list operator OPEN -- flip to private at v1 close (deferral reaffirmed 2026-07-06)
SEC-005 2026-07-13 long-lived GitBucket PAT stored in PLAINTEXT on the jumphost (credential.helper store, mode 600) so the agent can push unattended; GitBucket PATs are account-wide -- no per-repo scoping exists docs/changelog-20260713-git-credential-store.md operator OPEN -- dedicated token (not a reused personal one); revoke + rotate at v1 close, or immediately if the jumphost is shared/rebuilt. Revoke: GitBucket -> Account Settings -> Applications
SEC-006 2026-07-12 NetBox API token PASTED INTO AGENT CHAT CONTEXT during D-111 IPv6 reconciliation -- the token is BURNED (it exists in a transcript that is not under our control) and must be revoked + reissued, not merely rotated on schedule docs/changelog-20260712-office1-opnsense-edge-build.md; flagged again at 2026-07-12 session close operator OPEN -- DEFERRED by operator ruling 2026-07-13: revoke at completion of this deployment. Until then the token is live and exposed. Revoke: NetBox -> Admin -> API Tokens
SEC-007 2026-07-12 ~/vr1-office1-creds/ on the jumphost holds the Office1 edge root password + its bcrypt hash + the office1_svc SSH PRIVATE key + (added 2026-07-13) the OPNsense API key/secret (opnsense-api.txt, 0600), all in plaintext (dir 0700, files 0600) 2026-07-12 edge build; custody detail deliberately not recorded here per D-069 operator OPEN -- required for edge management (D-112(c) makes SSH the only management path), so this is a ROTATION obligation, not a delete-me. Rotate at v1 close / if the jumphost is rebuilt or shared
SEC-008 2026-07-13 ~/vr1-office1-creds/tailscale-authkey.txt (vcloud, 0600) -- the operator's 48-char Tailscale auth key for the SELF-HOSTED control plane tailscale.baldurkeep.com. Used to enrol office1-tailscale. Consumed BY PATH and never printed into a session; the copy shipped to the node was SHREDDED after tailscale up (tailscaled holds its own node key now). 2026-07-13 Office1 Tailscale enrolment; docs/vr1-office1-as-built.md operator OPEN -- ROTATION obligation, not a delete-me: the key is still on vcloud for re-enrolment. Revoke/reissue on the control server at v1 close, or immediately if vcloud is rebuilt or shared.
SEC-009 2026-07-15 Credential/env SPRAWL + world-readable exposure on vcloud: three env files sat loose in ~ outside the consolidated ~/vr1-office1-creds/ -- .vr1-netbox.env (upstream NetBox token), vr1-office1.env (edge root-password hash + SSH key path), and vr1-stage1.env which held TF_VAR_maas_api_key (a MAAS API secret) at mode 0664 (group/world-readable); tailscale-authkey.txt in the creds dir was also 0664. docs/changelog-20260715-creds-consolidation.md operator REMEDIATED 2026-07-15 -- all three moved into ~/vr1-office1-creds/, every sensitive file chmod 600. STANDING CONVENTION established (below). Note: this is a CLOSED in-house test; the rotation obligations of SEC-005/006/007 still apply at v1 close, this row only closes the SPRAWL + PERMS exposure.

STANDING CONVENTION (SEC-009, 2026-07-15): per-site credential/env consolidation. ALL sensitive files AND environment/config files for a site live in a single ~/<site>-creds/ folder on vcloud, mode 0700, files 0600 (public keys 0644). No loose env files in ~. Sites: ~/vr1-office1-creds/ (exists); when DC deployment starts, ~/vr1-dc0-creds/ and ~/vr1-dc1-creds/ follow the SAME pattern from day one -- do not accumulate loose vr1-dc0*.env in ~ and consolidate later. This is a DATA-LOSS / continuity control as much as a security one: scattered creds get lost between sessions and after compaction. Rationale is looser-security-but-strict-hygiene: this is a closed in-house test, so real credential hardening (rotation, revocation, non-shared tokens) is deferred to post-teardown redeploy cycles (test2/3/4+), but consolidation happens NOW so nothing is lost.

ADDENDUM (2026-07-15): the sandbox NetBox token was MISSED by the original consolidation. It lived only at /root/netbox-secrets/api.token on office1-netbox, never in ~/vr1-office1-creds/ -- the prior consolidation moved the three loose ~ env files but did not pull this VM-resident secret into the folder, contrary to the standing convention ("ALL sensitive files for a site live in ~/<site>-creds/"). Found while starting C2 sub-task (i) (the fidelity re-check needed it). Now consolidated to ~/vr1-office1-creds/vr1-netbox-sandbox.env (mode 0600; NETBOX_URL=http://10.10.1.10:8000

  • the assembled nbt_<key>.<plaintext> token), copied off the VM without being printed into the session. The /root/netbox-secrets/ copy remains the source-of-record on the VM; this is a working copy on the jumphost, mirroring how vr1-netbox.env holds the upstream token. See docs/changelog-20260715-fidelity-check-scope-correctness.md.

ENFORCEMENT (2026-07-15) -- so the miss cannot recur, esp. for DC0/DC1. The convention was never ENFORCED; a VM-minted secret had no forcing function to get consolidated and no check to catch a miss. Now built (docs/changelog-20260715-creds-audit.md):

  • creds-manifests/<site>.manifest -- declares EXACTLY the secrets a site must hold, each with its mode and PROVENANCE (local, or <vm>:<path> for VM-minted secrets -- the class that was missed). creds-manifests/vr1-office1.manifest seeded (11 entries) and the live folder audits CLEAN.
  • scripts/creds-audit.sh <site> -- verifies the live ~/<site>-creds/ against the manifest (presence, 0700 folder / declared file modes, non-empty), flags UNDECLARED files in the folder, and scans the home root for SPRAWL (loose *.env/*.token/*authkey* outside any *-creds/). Reads NO secret values -- metadata only. Harness tests/creds-audit/ (7/7).
  • Standing rule: run bash scripts/creds-audit.sh vr1-dcN at the CLOSE of each DC standup, and consolidate+manifest every secret AT MINT TIME (not "later" -- later is when it is lost). Wired into the dc-dc-phase3 runbook.