diff --git a/docs/changelog-20260724-caveman-disable.md b/docs/changelog-20260724-caveman-disable.md index e261786..7d0264c 100644 --- a/docs/changelog-20260724-caveman-disable.md +++ b/docs/changelog-20260724-caveman-disable.md @@ -171,3 +171,21 @@ no persistent copy on the region; never printed (SEC-006); consumed by Juju via path/stdin, never argv. Each issued key = a per-DC SEC rotation row. - Revert: `git revert ` (removes Step 2.0). No live/cloud state touched. + +## Item 7 -- Per-DC MAAS service credentials created (SEC-018/-019) [CLOUD MUTATION, driven] + +- Executed phase-4 Step 2.0 for both DCs (operator: "You drive it"), logged + window `~/as-executed/2026-07-24-dc-maas-creds.log`. Passwordless sudo on + voffice1 confirmed; `maas createadmin --password` supported (read-only precheck). +- Created dedicated MAAS superusers **`juju-vr1-dc0`** and **`juju-vr1-dc1`** + (random passwords generated ON the region, UNSTORED -- Juju auths via the API + key), and staged each user's API key into the vcloud per-site folder: + `~/vr1-dc0-creds/maas-api-key.txt` and `~/vr1-dc1-creds/maas-api-key.txt` (0600). + Keys generated FROM the jumphost (no persistent region copy), verified by + FORMAT ONLY (both parts=3, 70 chars), never printed. Result fail=0. +- **SEC-018** (dc0 key) + **SEC-019** (dc1 key) opened -- per-DC rotation + obligations (open SEC 13 -> 15; reconciled at Stage 4 close per the G14 pattern). + as-executed index entry added (log itself stays uncommitted, secret-adjacent). +- Revert: on voffice1 `sudo maas apikey --username=juju-vr1-dc0 --delete=` + (+ dc1) and `sudo maas deleteuser juju-vr1-dc0` (+ dc1); `shred -u` the two + vcloud key files; `git revert ` for the SEC/index/changelog rows. diff --git a/docs/security-ledger.md b/docs/security-ledger.md index bdd9766..a322b46 100644 --- a/docs/security-ledger.md +++ b/docs/security-ledger.md @@ -29,6 +29,10 @@ | SEC-017 | 2026-07-24 | **Third-party Claude Code plugin `caveman@caveman` (JuliusBrussee/caveman) installed at USER scope on vcloud -- a standing per-session/per-prompt third-party code-execution surface on a credential-bearing jumphost.** SessionStart + UserPromptSubmit hooks run `node` on every session start and every prompt while `enabledPlugins` is true, INDEPENDENT of the `CAVEMAN_DEFAULT_MODE` guard (the env var gates terse-output ARMING, NOT hook EXECUTION). Inspected benign at SHA `0d95a81` by a 4-seat council audit + operator self-remeasure 2026-07-24: no network egress, no shell, one gated subprocess (`/caveman-stats` only), symlink-hardened flag I/O, zero PATH contribution/shadowing. This verdict is POINT-IN-TIME: `plugin.json` carries no `version` field (every git commit is a new "version"), the marketplace source tracks the default branch with no tag/SHA ref -> the code is NOT declaratively pinnable; third-party-marketplace auto-update is OFF by default (Claude Code 2.1.218) but flippable via the `/plugin` UI or managed settings. Baseline: git clone HEAD `0d95a81d35a9f2d123a5e9430d1cfc43d55f1bb0` (tree clean), executing cache copy == clone (only a `.in_use` runtime marker differs); 6 audited files' full sha256 recorded in the 2026-07-24 changelog. | docs/changelog-20260723-caveman-optin-guard.md (commit 338c919); docs/changelog-20260724-caveman-disable.md; this session's council audit | operator | **OPEN -- supply-chain re-verify obligation (NOT a credential rotation).** DISABLED on the live host 2026-07-24: `enabledPlugins."caveman@caveman"=false` at BOTH user (`~/.claude/settings.json`) and committed repo (`.claude/settings.json`, higher precedence) scope, `CAVEMAN_DEFAULT_MODE=off` retained -- this STOPS the per-turn hook execution from the next session start. Marketplace entry RETAINED so a deliberate re-enable for hardened-workflow deployment TESTING stays possible. STANDING DUTY: on ANY re-enable OR plugin update, RE-VERIFY the hooks against the baseline (confirm the clone is at `0d95a81`; re-hash + `diff` the cache copy vs the marketplace clone) BEFORE trusting -- the benign verdict does not survive a version bump. Keep-available-vs-uninstall decision DEFERRED (NOT yet ruled). Provenance for the disable: operator accepted the council-review recommendations this session (exact utterance: "I'll accept your recommendations"). Register note: OPS adoption, no D-number (GA-R3 -- no Roosevelt-delta; precedent D-129); this row is the durable home the ledger mandate requires ("row at discovery, never only a note"). Count note: this row takes open SEC rows 12 -> 13; CURRENT-STATE G14 reconciles the count at Stage 4 close per its existing deferral pattern. | +| SEC-018 | 2026-07-24 | **Dedicated dc0 MAAS admin API key (Juju -> MAAS cloud credential).** Created so the vr1-dc0 Juju controller can authenticate to the Office1 MAAS region (bootstrap + provision dc0 nodes). Per-DC credential isolation (SEC-012/-016 pattern; NEVER a cross-DC key): dedicated MAAS superuser `juju-vr1-dc0`, its API key staged at `~/vr1-dc0-creds/maas-api-key.txt` on vcloud (SEC-009, 0600), generated FROM the jumphost so it never persisted on the region, verified by FORMAT ONLY (parts=3, 70 chars), never printed/echoed/in argv. The user's password is random + UNSTORED (Juju auths via the key). GRANT: admin-scoped MAAS API (full machine/power/deploy). | 2026-07-24 driven creation (as-executed `2026-07-24-dc-maas-creds`); phase-4 Step 2.0; docs/changelog-20260724-caveman-disable.md item 7 | operator | **OPEN -- rotation obligation.** Rotate at v1 close, or immediately if it leaks or the region/jumphost is rebuilt/shared. Note it also lands in whatever Juju add-credential store + the maas-provider state of any root that consumes it (same 0600 handling). Roosevelt: per-DC cloud credential. Custody off-repo per D-069. | + +| SEC-019 | 2026-07-24 | **Dedicated dc1 MAAS admin API key (Juju -> MAAS cloud credential).** Same as SEC-018 for the vr1-dc1 Juju controller: dedicated MAAS superuser `juju-vr1-dc1`, key staged at `~/vr1-dc1-creds/maas-api-key.txt` on vcloud (0600), generated from the jumphost, format-verified (parts=3, 70 chars), never printed; random unstored password. GRANT: admin-scoped MAAS API. | 2026-07-24 driven creation (as-executed `2026-07-24-dc-maas-creds`); phase-4 Step 2.0; docs/changelog-20260724-caveman-disable.md item 7 | operator | **OPEN -- rotation obligation** (same disposition as SEC-018). Roosevelt: per-DC cloud credential. Custody off-repo per D-069. | + **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 `~/-creds/` folder on vcloud, mode 0700, files 0600 (public keys 0644). No loose env files in `~`. Sites: `~/vr1-office1-creds/` diff --git a/logs/as-executed-index.md b/logs/as-executed-index.md index dfbb420..09d22f4 100644 --- a/logs/as-executed-index.md +++ b/logs/as-executed-index.md @@ -17,3 +17,4 @@ | 2026-07-22 | dc1-deploy | jesse.austin (Claude Code lane, per-command wrap) | G12 dc1 build: apex --commit (transit /30 + rack IP, 2 objects), dc1 svc key minted, outer apply 5/0/0 exact (vvr1-dc1 + uplink), converged zero diff | | 2026-07-23 | ops-sec010-reassert | jesse.austin (Claude Code lane, per-command wrap) | queue-pass live window: SEC-010 nft re-assert all 3 hosts (4/2/2 converged); G13 close -- office1 qga channel 0/1/0 apply + 26.7.1 update + os-iperf; cache-residue delete; captures docs/audit/sec010-reassert-20260723.txt + g13-close-20260723.txt | | 2026-07-23 | stage4-carve | jesse.austin (Claude Code lane, per-command wrap) | Stage 4 carve, both DCs: dynamic ranges moved .201-.254 (D-134 amendment), 10 plane fabrics created, 90 NIC re-homes (18 nodes), 8 subnets created + 2 moved off fabric-5, 6 spaces created + 12 VLANs assigned, 18 nodes' statics + br-ex (D-133 flat); capture docs/audit/stage4-carve-verify-20260723.txt | +| 2026-07-24 | dc-maas-creds | jesse.austin (Claude Code lane, driven) | phase-4 Step 2.0 credential task: created per-DC MAAS admin service users juju-vr1-dc0 / juju-vr1-dc1 (random unstored passwords) + staged their API keys to vcloud ~/vr1-dcN-creds/maas-api-key.txt (format-verified parts=3); SEC-018/-019 opened |