T07 generates a CCR policy through the platform generator and refuses record-evidence unless the built policy matches the CCR file. T06 stays wait on the open founder decision after a fresh can-i of yes, yes, yes. Assistant: grok Assistant-Session: 01a16071-5425-78d3-80b4-20fe2ee30f0a
166 lines
6.3 KiB
Markdown
166 lines
6.3 KiB
Markdown
---
|
|
id: MASON-WP-0015
|
|
type: workplan
|
|
title: "Restore ops-mason as the OpenBao builder: the ops-mason-construct grant"
|
|
domain: infotech
|
|
repo: ops-mason
|
|
status: active
|
|
owner: claude
|
|
topic_slug: netkingdom-security-architecture
|
|
created: "2026-10-18"
|
|
updated: "2026-10-22"
|
|
flavor: implementation
|
|
depends_on: []
|
|
state_hub_workstream_id: "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
|
|
|
|
```task
|
|
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)
|
|
|
|
```task
|
|
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
|
|
|
|
```task
|
|
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
|
|
|
|
```task
|
|
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
|
|
|
|
```task
|
|
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
|
|
|
|
```task
|
|
id: MASON-WP-0015-T06
|
|
status: wait
|
|
priority: medium
|
|
needs_human: true
|
|
decision_id: "30d29060-8d14-4a8e-9cde-34aa826eb8d1"
|
|
intervention_note: "Founder chooses MASON-IN-0006 option (a), (b), or (c). ops-mason did not choose and did not change cluster RBAC."
|
|
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. MASON-IN-0006 stays the open residual and still names options
|
|
(a), (b), and (c). This task does not choose one and does not change cluster
|
|
RBAC. It waits on founder decision
|
|
`30d29060-8d14-4a8e-9cde-34aa826eb8d1` (open, pending).
|
|
|
|
## Submit CCRs from approved plans (RPF-WP-0061)
|
|
|
|
```task
|
|
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`.
|