CUST-WP-0075: tenant-engine sender seed helper; re-qualify RPF-WP-0035-T02/T08
- scripts/tenant_engine_audit_core_sender_seed.py: silent attended row-7 seed for MASON-WP-0007-T05 (wrap-migrate technique, CAS 0, never overwrites, metadata-only --dry-run, documented exit codes), with offline fake-bao tests. - Lane review doc with the exact founder sequence and the read-only ESO token-create can-i check for MASON-WP-0007-T06. - RPF-WP-0035-T02: SECRETS-WP-0007-T04 is done; real blocker is live KeyCape registration and client custody of secrets-engine-openbao (blocked_on key-cape). Design stays proposed. - RPF-WP-0035-T08: receiver rollout with evidence_kind already accepted 2026-09-11; moved the misplaced D1 correction note here from T02. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 3775@bnt-lap001 Assistant-Session: cfacb6a5-ad5b-4f79-ac67-053e3b0d34a3
This commit is contained in:
parent
401765f184
commit
e7eb9db57e
6 changed files with 512 additions and 3 deletions
|
|
@ -120,3 +120,12 @@ then perform the positive/negative/expiry/use-limit/revocation checks above.
|
|||
Do not print login responses. Publish the consumer contract only after those
|
||||
checks pass. A conflicting existing mount/role requires review, not overwrite.
|
||||
No service-client secret is created, moved or requested by this source return.
|
||||
|
||||
## Gate check — 2026-10-03 (CUST-WP-0075)
|
||||
|
||||
Still proposed. SECRETS-WP-0007-T04 is done (2026-09-27), so the gate named
|
||||
above is open, but the "before writing" preconditions are not: KeyCape has not
|
||||
claimed a live registration of `secrets-engine-openbao`, and its client-credential
|
||||
custody has no owning task (KeyCape contract: "a separate approved custody
|
||||
action"). No reviewed child is written. RPF-WP-0035-T02 waits on key-cape naming
|
||||
that task.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
# tenant-engine audit-core sender: attended seed
|
||||
|
||||
Status: ready for review, not run. Owner: railiance-platform (OpenBao side) for
|
||||
ops-mason MASON-WP-0007-T05 (plan row 7). Intake RPF-IN-0002. Prepared
|
||||
2026-10-03 under CUST-WP-0075.
|
||||
|
||||
## What the founder approves
|
||||
|
||||
One attended sitting, run from a railiance-platform checkout at the reviewed
|
||||
commit, with these three children in order. Each child prints nothing; read
|
||||
warden's printed line, not its exit code (orientation §5).
|
||||
|
||||
```sh
|
||||
cd ~/railiance-platform
|
||||
export BAO_ADDR=http://127.0.0.1:18200 VAULT_ADDR=http://127.0.0.1:18200
|
||||
|
||||
# 1. policy + Kubernetes-auth role (commit 8c44256). Exit 3 = existing object differs.
|
||||
warden access openbao-platform-admin-login --exec -- \
|
||||
sh scripts/openbao-tenant-engine-audit-core-sender-eso-attended.sh
|
||||
|
||||
# 2. seed dry-run: KV metadata only, no value read or written.
|
||||
warden access openbao-platform-admin-login --exec -- \
|
||||
python3 scripts/tenant_engine_audit_core_sender_seed.py --dry-run \
|
||||
--confirm 'SEED tenant-engine audit-core-sender' \
|
||||
--receipt docs/evidence/tenant-engine-sender-seed-dry-run.json
|
||||
|
||||
# 3. seed: only if step 2's receipt says outcome dry_run_would_write (exit 0).
|
||||
warden access openbao-platform-admin-login --exec -- \
|
||||
python3 scripts/tenant_engine_audit_core_sender_seed.py \
|
||||
--confirm 'SEED tenant-engine audit-core-sender' \
|
||||
--receipt docs/evidence/tenant-engine-sender-seed.json
|
||||
```
|
||||
|
||||
Each `warden access` is its own login. Receipts are created mode 0600, refused
|
||||
if the file exists, and hold only paths, versions, booleans and an outcome
|
||||
code. Commit them as evidence.
|
||||
|
||||
## What the seed does
|
||||
|
||||
`scripts/tenant_engine_audit_core_sender_seed.py` is the user-engine /
|
||||
audit-core wrap-migrate technique (ops-mason
|
||||
`plans/user-engine-openbao-runtime-custody.md` §6; audit-core runbook,
|
||||
"wrap-migrated on 2026-08-14"): one platform-admin process reads the source and
|
||||
writes the target, and the value travels only through process memory and the
|
||||
`bao` child's stdin. Never argv, stdout, stderr, a file or the receipt.
|
||||
|
||||
1. Refuses unless `--confirm` is exact, HOME is a warden attended envelope, no
|
||||
`BAO_TOKEN`/`VAULT_TOKEN` is set, and the identity has `platform-admin` and
|
||||
not `root`.
|
||||
2. Reads `platform/workloads/audit-core/senders` (KV v2, field `senders.json`)
|
||||
and selects the one row named `tenant-engine`. Refuses if the row is
|
||||
missing or duplicated, holds zero or more than one token (a rotation
|
||||
overlap is in progress: finish it first), or is not write-only
|
||||
(`may_write` true, `may_read` false).
|
||||
3. If `platform/workloads/tenant-engine/audit-core-sender` exists: exit 0 when
|
||||
it holds exactly `{token: <that token>}`, otherwise exit 3. Never overwrites.
|
||||
4. Otherwise writes `{token}` with `cas=0`, reads it back (must be version 1 and
|
||||
equal), and checks that the registry version did not move during the run.
|
||||
|
||||
The registry is never written. Exit codes: 0 ok (written or already
|
||||
identical; dry-run: would write), 1 contained internal error, 2 precondition
|
||||
refused before any write, 3 target exists and differs, 4 write failed,
|
||||
5 verify failed, 6 dry-run found the target already present.
|
||||
|
||||
Tests: `tests/test_tenant_engine_audit_core_sender_seed.py` runs the helper as
|
||||
a subprocess against a fake `bao` and asserts empty stdout/stderr, the token
|
||||
never in `bao` argv or the receipt, CAS 0, idempotence, refusal of a differing
|
||||
or deleted target, every precondition, and distinct write/verify codes.
|
||||
|
||||
## Operator check for MASON-WP-0007-T06 (read-only, not run)
|
||||
|
||||
Before the tenant-engine ClusterSecretStore goes live, the ESO controller must
|
||||
be allowed to create ServiceAccount tokens in `tenant-engine`. Confirm the node
|
||||
IP is `92.205.62.239` first (`kubectl get nodes -o wide`), then:
|
||||
|
||||
```sh
|
||||
kubectl auth can-i create serviceaccounts --subresource=token \
|
||||
-n tenant-engine --as=system:serviceaccount:external-secrets:external-secrets
|
||||
```
|
||||
|
||||
`yes` is required. This is a SubjectAccessReview: it reads no object. A `no`
|
||||
is a railiance-cluster RBAC matter, not a reason to widen the OpenBao role.
|
||||
|
||||
## Follow-ups outside the seed
|
||||
|
||||
- `openbao/policies/agent-high-risk-boundary.hcl` denies coding agents the
|
||||
sender registry, but not the new
|
||||
`platform/{data,metadata}/workloads/tenant-engine/audit-core-sender` paths.
|
||||
Adding those deny lines is a separate reviewed policy change.
|
||||
- Rotation stays overlap-first (plan §4): rotate in the registry, finish the
|
||||
overlap so the sender holds one token, then re-seed. Because this helper
|
||||
never overwrites, a rotated token needs a reviewed CAS-update variant. That
|
||||
variant is not built.
|
||||
Loading…
Add table
Add a link
Reference in a new issue