The default path is user ops-mason-builder. Token mint, pod create, and serviceaccount impersonation are no. Admin stays on the attended warden lane. Negative-scope verify treats a denied get as the proof, and the CCR test interpreter can import the platform generator. Assistant: grok Assistant-Session: 01a16071-5425-78d3-80b4-20fe2ee30f0a
7.1 KiB
| id | type | title | domain | repo | status | owner | topic_slug | created | updated | flavor | depends_on | state_hub_workstream_id |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| MASON-WP-0015 | workplan | Restore ops-mason as the OpenBao builder: the ops-mason-construct grant | infotech | ops-mason | finished | claude | netkingdom-security-architecture | 2026-10-18 | 2026-10-22 | implementation | 384b3efc-f9a5-5ea9-b224-0ce900e79804 |
ops-mason-construct grant
Decision: intakes/intakes.md MASON-IN-0005 (founder, 2026-10-18, "Build, but
never log in"). ops-mason builds structure in OpenBao; ops-warden finds and
provides it. The grant breaks the MASON-IN-0004 chain at the login step.
Review both INTENTs and draft the grant
id: MASON-WP-0015-T01
status: done
priority: high
state_hub_task_id: "55448e8c-44a0-5509-9acc-c88e65c680a0"
Reviewed ops-mason and ops-warden INTENT.md. The bodies agree (ops-mason
builds, ops-warden routes and assists); the read-only grant did not. Wrote
policies/ops-mason-construct.hcl and tests/test_construct_policy.py, added
bao-session.sh build <task>, and updated INTENT.md frontmatter and the
AGENTS.md OpenBao section.
Install the policy (founder act)
id: MASON-WP-0015-T02
status: done
priority: high
state_hub_task_id: "1c8893bd-8dfe-5293-87dd-8678b20e7313"
Same silent wrapper and hash receipt as the survey policy (AGENTS.md), with
ops-mason-construct and
/home/worsch/ops-mason/policies/ops-mason-construct.hcl. Confirm your OIDC
session can mint a token carrying it (bao-session.sh build MASON-WP-0015-T03).
Live negative and positive tests
id: MASON-WP-0015-T03
status: done
priority: high
state_hub_task_id: "8b512822-ace0-50b0-bf19-52985b229090"
Under the build grant, against throwaway names (workload-kv-read-mason-probe,
external-secrets-mason-probe, platform/suppliers/mason/probe): policy and
role create/delete succeed; a role with token_policies=default, or with
legacy policies, is refused (this confirms glob support in
allowed_parameters); role-id read, secret-id write, token create, data read,
and a write over the existing probe path are all refused; a policy write
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
id: MASON-WP-0015-T04
status: done
priority: high
state_hub_task_id: "7b7a436f-c585-5fa8-8afc-5bb033f205f8"
src/ops_mason/executor.py build_approle_kv_lane mints the role-id and
secret-id itself (lines ~420-426). Split it so that it stops after the role
definition and emits the founder delivery step. Add a post-build check that
reads each written policy and compares it with the plan's policy file
(normalising the trailing newline). Run the check in every build; a mismatch
fails the build record.
Done 2026-10-18: build_approle_kv_lane now builds structure only, and
deliver_approle_credentials handles delivery as a founder or applier step.
_verify_written_policy reads each new policy back before the role is
written. build_kubernetes_kv_lane now writes token_policies/token_ttl,
because the legacy policies is denied by ops-mason-construct. 260 tests pass.
Align ops-warden and railiance-platform references
id: MASON-WP-0015-T05
status: done
priority: medium
state_hub_task_id: "8fbac212-1b42-5e08-b65e-8217c481d995"
ops-warden registry/routing/catalog.yaml and
wiki/playbooks/openbao-structure-survey.md describe ops-mason as read-only.
The railiance-platform references are in
docs/credential-lane-designs/application-backup-delivery-2026-10-08.md and
RPF-WP-0053 and RPF-WP-0057. Message each owner with MASON-IN-0005, pointers
only. They edit their own files.
Close the Kubernetes variant
id: MASON-WP-0015-T06
status: done
priority: medium
state_hub_task_id: "feb17422-9490-51f4-a62d-55647a5f6b05"
A Kubernetes role ops-mason builds can be logged in to by anyone holding a
token for the bound ServiceAccount. Confirm that the kube identity ops-mason
applies with cannot create serviceaccounts/token or Pods in namespaces it
binds roles to (kubectl auth can-i). kubernetes_plane already refuses
the Pod and Secret kinds. Record the result in INTENT.md's
kubernetes-plane-apply entry.
Result 2026-10-18: open. The kube identity is system:admin (system:masters). It can create serviceaccounts/token, pods and impersonate, cluster-wide. Raised as MASON-IN-0006.
Result 2026-10-22, context default, captured 2026-10-21T23:55:17Z,
--all-namespaces, name-only: create serviceaccounts/token yes, create
pods yes, impersonate serviceaccounts yes. The identity is still
cluster-admin.
2026-10-22: founder Bernd Worsch chose (b) on decision
30d29060-8d14-4a8e-9cde-34aa826eb8d1. The autonomous builder gets a scoped
kube identity limited to the kinds kubernetes_plane applies. The admin
kubeconfig is reachable only through an attended warden access lane, the same
pattern as the OpenBao platform-admin login. Cluster RBAC is unchanged.
railiance-platform installs that identity. Asked in message
c3d0dc66-bd52-4d5c-a0a2-2c30cec73ab2.
2026-10-22: done. User ops-mason-builder, context default, captured
2026-10-22T06:56:46Z. create serviceaccounts --subresource=token no,
create pods no, impersonate serviceaccounts no. kubectl 1.35
parses serviceaccounts/token as a ServiceAccount named token, so that
form stays yes; the token subresource is the mint check and is no. Choice
(b) on decision 30d29060-8d14-4a8e-9cde-34aa826eb8d1. railiance-platform
commits bd6660a and e594350 hold the ClusterRole. The attended lane is
ops-warden kubernetes-railiance01-admin (537d551), resolvable before the
default path changed. The admin file stays
/home/worsch/.kube/config-railiance01 and still answers as system:admin
through that lane. The default path is the builder. Client certificate
renewal is MASON-IN-0008.
Submit CCRs from approved plans (RPF-WP-0061)
id: MASON-WP-0015-T07
status: done
priority: medium
state_hub_task_id: "ebc420c6-be1a-5abb-b766-fda0bdf2680b"
railiance-platform RPF-WP-0061 makes ops-mason the only CCR submitter
(credential-change.py submit). RPF-WP-0061-T03 and T04 are done, so this
no longer waits on them. RPF-WP-0061-T05 still waits for a first live
self-service submission; none was filed here because no approved plan is
waiting.
2026-10-22: ops-mason generates the CCR draft and its policy from the plan
through the platform generator (credential-change.py render-policy,
src/ops_mason/ccr_gate.py draft_from_plan). Plan approval is the single
hub decision recorded on the draft (state_hub.decision_id). ops-mason did
not run sync-decision; that stays a platform or founder step. Before
record-evidence, record_evidence compares the built policy text with the
CCR policy file and refuses the call unless they match, with a trailing
newline normalised. The draft, the policy, and the evidence contain no
secret value. Tests: tests/test_ccr_gate.py and tests/test_construct_policy.py.