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
95 lines
4.7 KiB
Markdown
95 lines
4.7 KiB
Markdown
# tenant-engine audit-core sender: attended seed
|
|
|
|
Status: approved, not run. Approved by Bernd Worsch (founder) on 2026-10-03
|
|
in the custodian session ("APPROVE MASON-WP-0007-T05"), covering the
|
|
three-child sequence below at the reviewed commit e7eb9db. Not run yet. 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.
|