diff --git a/docs/evidence/2026-10-18-ops-mason-construct-probes.md b/docs/evidence/2026-10-18-ops-mason-construct-probes.md new file mode 100644 index 0000000..7c8e550 --- /dev/null +++ b/docs/evidence/2026-10-18-ops-mason-construct-probes.md @@ -0,0 +1,71 @@ +# MASON-WP-0015-T03 — ops-mason-construct live probes (2026-10-18) + +Token `claude-MASON-WP-0015-T03` (policies `default`, `ops-mason-construct`), +minted by the founder through `bao-session.sh build`. The probes used +throwaway objects (`workload-kv-read-mason-probe`, +`external-secrets-mason-probe`, AppRole `mason-probe`, +`platform/suppliers/mason/probe`), all deleted afterwards. This file holds +names and outcomes only; no command output was printed. + +## Run 1 — policy sha256 1ec28b30… (e7a368a) + +26/28 checks as expected. **Two failures:** a comma string +`token_policies=workload-kv-read-mason-probe,default` was accepted on both the +Kubernetes role and the AppRole role. OpenBao matched the whole string against +the `workload-kv-read-*` glob before splitting it. A JSON list was checked +element by element and refused. The login denies held: role-id, secret-id and +token create were all refused. Fixed in 482a08b with `denied_parameters` +`token_policies = ["*,*"]`. + +## Run 2 — policy sha256 969d7aae… (482a08b, as stored) + +All 31 checks as expected: + + --- allowed + PASS want=ok got=ok policy write workload-kv-read-mason-probe + PASS want=ok got=ok k8s role write (policy=workload-kv-read-mason-probe) + PASS want=ok got=ok approle role write (policy=workload-kv-read-mason-probe) + PASS want=ok got=ok kv create placeholder (cas=0) + PASS want=ok got=ok kv metadata put + PASS want=ok got=ok kv metadata read + --- must be refused + PASS want=refused got=refused (denied) kv overwrite (no cas) + PASS want=refused got=refused (denied) kv overwrite (cas=0) + PASS want=refused got=refused (denied) kv read probe value + PASS want=refused got=refused (denied) kv read real path + PASS want=refused got=refused (denied) k8s role token_policies=default + PASS want=refused got=refused (denied) k8s role legacy policies=default + PASS want=refused got=refused (denied) k8s role comma string P,default + PASS want=refused got=refused (denied) k8s role JSON list [P,default] + PASS want=refused got=refused (denied) k8s role outside prefix + PASS want=refused got=refused (denied) approle token_policies=default + PASS want=refused got=refused (denied) approle comma string P,default + PASS want=refused got=refused (denied) approle JSON list [P,default] + PASS want=refused got=refused (denied) approle role-id read + PASS want=refused got=refused (denied) approle secret-id mint + PASS want=refused got=refused (denied) token create + PASS want=refused got=refused (denied) token create orphan + PASS want=refused got=refused (denied) policy write outside prefix + PASS want=refused got=refused (denied) policy write ops-mason-construct + PASS want=refused got=refused (denied) policy write default + PASS want=refused got=refused (denied) secrets enable + PASS want=refused got=refused (denied) operators kv write + --- state after refusals + k8s role token_policies now: ['workload-kv-read-mason-probe'] + approle token_policies now: ['workload-kv-read-mason-probe'] + --- cleanup + PASS want=ok got=ok delete k8s role + PASS want=ok got=ok delete approle + PASS want=ok got=ok kv metadata delete + PASS want=ok got=ok policy delete + +Stored policy compared with the repo file: the only difference was a second +trailing newline in the file, removed so the repo file now matches the +stored text byte for byte. + +## Follow-on under the same grant + +`scripts/put-scaleway-supplier-placeholders.sh` created +`platform/suppliers/scaleway/{bootstrap,backup,mas-tem-relay}` at version 1 +with placeholder `xxx` values and custom_metadata (owner, purpose, readers). +No value was read. diff --git a/policies/ops-mason-construct.hcl b/policies/ops-mason-construct.hcl index 1f8f84c..a37b150 100644 --- a/policies/ops-mason-construct.hcl +++ b/policies/ops-mason-construct.hcl @@ -216,4 +216,3 @@ path "secret/data/*" { # Not granted, on purpose: sys/mounts/* and sys/auth/* (no new mounts or auth # methods), auth/token/revoke (other tokens), operators/ and secret/ writes, # any policy outside workload-kv-read-*, any role outside the two shapes above. - diff --git a/scripts/put-scaleway-supplier-placeholders.sh b/scripts/put-scaleway-supplier-placeholders.sh index 6f391ae..61c8766 100755 --- a/scripts/put-scaleway-supplier-placeholders.sh +++ b/scripts/put-scaleway-supplier-placeholders.sh @@ -3,9 +3,11 @@ # (supplier convention platform/suppliers//, founder # decision 2026-10-08). The founder then replaces each `xxx` in the OpenBao UI. # -# Founder act; ops-mason's survey grant cannot write. Run silently: +# Runs under the ops-mason-construct grant (BAO_TOKEN from ~/.claude-bao-token), +# or silently by the founder: # warden access openbao-platform-admin-login --exec -- \ # sh /home/worsch/ops-mason/scripts/put-scaleway-supplier-placeholders.sh +# Run 2026-10-18 under claude-MASON-WP-0015-T03: all three created at v1. # # -cas=0 refuses to write a path that already exists, so a real value is never # overwritten; a rerun fails harmlessly. No secret values pass through this script. diff --git a/workplans/MASON-WP-0015-construct-grant.md b/workplans/MASON-WP-0015-construct-grant.md index 11c0249..26331ea 100644 --- a/workplans/MASON-WP-0015-construct-grant.md +++ b/workplans/MASON-WP-0015-construct-grant.md @@ -39,7 +39,7 @@ AGENTS.md OpenBao section. ```task id: MASON-WP-0015-T02 -status: todo +status: done priority: high state_hub_task_id: "1c8893bd-8dfe-5293-87dd-8678b20e7313" ``` @@ -53,7 +53,7 @@ session can mint a token carrying it (`bao-session.sh build MASON-WP-0015-T03`). ```task id: MASON-WP-0015-T03 -status: wait +status: done priority: high state_hub_task_id: "8b512822-ace0-50b0-bf19-52985b229090" ``` @@ -68,6 +68,9 @@ outside `workload-kv-read-*` is refused. Record the results as a names-only receipt. If the glob check fails, stop and redesign the role stanzas before any build. +Done 2026-10-18: `docs/evidence/2026-10-18-ops-mason-construct-probes.md`. +Run 1 found the comma-string bypass (fixed in 482a08b); run 2 passed all 31 checks. + ## Executor and post-build check ```task