WARDEN-WP-0028: tenant secrets on mount tenants/ (first lane draft)
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 3s

Adopt tenants/<tenant>/… custody (not platform/workloads). Document
onboarding, add draft binky-company-email-imap catalog entry, and mark
T01–T04/T06–T07 done. Founder Red provision remains T05.
This commit is contained in:
tegwick 2026-07-17 00:09:28 +02:00
parent b971403dad
commit 98a2339b81
7 changed files with 634 additions and 2 deletions

View file

@ -102,12 +102,16 @@ run the owner's tool as the caller and preserve owner custody.
Promotion criteria: `wiki/playbooks/catalog-lane-promotion.md`.
High-risk / agent boundary: `wiki/playbooks/agent-read-boundary.md`.
EXPOSED taint: `wiki/playbooks/exposed-taint.md` · `warden taint <id>`.
EXPOSED taint: `wiki/playbooks/exposed-taint.md` · `warden taint <id>`.
**Tenant secrets:** mount `tenants/` — path `tenants/<tenant>/<workload>/<bundle>`
(see `wiki/playbooks/tenant-secret-onboarding.md`, WARDEN-WP-0028). Not under
`platform/workloads/`.
**Draft** (hidden from default lookup until owner path ships — `warden route list --all`):
| Catalog `id` | Routing focus | Playbook |
| --- | --- | --- |
| `binky-company-email-imap` | Tenant IMAP creds on `tenants/binky/…` (provision pending) | `wiki/playbooks/binky-company-email-imap.md` |
| `object-storage-sts` | NK-WP-0007 STS vending path | `wiki/playbooks/object-storage-sts.md` |
| `database-dynamic-credentials` | OpenBao database secrets engine | `wiki/playbooks/database-dynamic-credentials.md` |

View file

@ -25,6 +25,7 @@ operator identity.
| `railiance-backup-offsite-lane` | Nextcloud upload + `AGE_PRIVATE_KEY` recovery escrow |
| `forgejo-admin-api-token` | Forgejo site-admin PAT |
| `openrouter-llm-connect` | Provider key (spend + prompt-adjacent) |
| `binky-company-email-imap` | Tenant mailbox IMAP password (`tenants/binky/…`) |
Keep this table in sync with `risk: high` rows in `registry/routing/catalog.yaml`
and path denials in `agent-high-risk-boundary.hcl`.

View file

@ -0,0 +1,103 @@
# Binky company email IMAP
Date: 2026-07-17
Catalog: `binky-company-email-imap` (status `draft` until founder provisions)
Owner: `railiance-platform` (CCR-2026-0007) · consumer need: `binky-control`
Workplan: WARDEN-WP-0028
IMAP credentials for the company mailbox (founder address) so email-connect can
run **read-only** scans for control-plane event intake.
---
## OpenBao pointers
| Field | Value |
| --- | --- |
| Mount | `tenants` |
| Path | `tenants/binky/company-email/imap` |
| Fields | `IMAP_USERNAME`, `IMAP_PASSWORD` |
| Policy | `workload-kv-read-binky-company-email-imap` |
| OIDC role | `binky-company-email-imap-workload-kv-read` (`groups=net-kingdom-admins`) |
| Risk | `high` |
Non-secret connection facts (IMAP host/port) live in email-connect / binky-control
config as host + env **names**, not passwords.
---
## Worker checklist
1. Login as caller:
```bash
bao login -method=oidc -path=netkingdom role=binky-company-email-imap-workload-kv-read
```
2. Fetch via sanctioned transport (never paste into chat):
```bash
warden access binky-company-email-imap --all --no-policy --out /tmp/imap.user
# primary field is IMAP_USERNAME; for password use --field after template support
# or:
warden access binky-company-email-imap --all --no-policy --exec -- \
env IMAP_USERNAME=… # prefer secrets-engine / dual-field exec when wired
```
Until catalog is `active` and resolvable, use bao as caller with files:
```bash
bao kv get -field=IMAP_USERNAME tenants/binky/company-email/imap > /tmp/u
bao kv get -field=IMAP_PASSWORD tenants/binky/company-email/imap > /tmp/p
chmod 600 /tmp/u /tmp/p
```
3. Run email-connect read-only scan (config uses env names only).
4. Store **metadata-only** evidence under `binky-control/mailmeta/`.
Agents (`WARDEN_AGENT_ID` set): raw value stream refused (exit 7). Use `--out` /
`--exec` / `--wrap` / `--fingerprint`.
---
## Verify (capabilities-safe)
```bash
LANE=$(bao token create -policy=workload-kv-read-binky-company-email-imap -ttl=2m -field=token)
bao token capabilities "$LANE" tenants/data/binky/company-email/imap # read
bao token revoke "$LANE"
DEFAULT=$(bao token create -policy=default -ttl=2m -field=token) # deny of create is also pass
bao token capabilities "$DEFAULT" tenants/data/binky/company-email/imap # deny
bao token revoke "$DEFAULT"
```
Never use `bao kv get` for deny tests.
---
## Founder provision (Red lane)
```bash
# values only in mode-0600 files, never argv/chat
bao kv put tenants/binky/company-email/imap \
IMAP_USERNAME=@/path/to/user.file \
IMAP_PASSWORD=@/path/to/pass.file
shred -u /path/to/user.file /path/to/pass.file
```
Then re-verify capabilities, promote catalog to `active`, set CCR
`access_frontdoor.resolvable: true` / `readiness: ready`.
## Rotation
```bash
warden rotate-guide binky-company-email-imap
```
## See also
- `binky-control/integrations/company-email-openbao.md`
- `wiki/playbooks/tenant-secret-onboarding.md`
- CCR-2026-0007 in railiance-platform

View file

@ -87,10 +87,11 @@ out on the OpenBao-delivered value, positive + negative verification audit-logge
---
## Draft lanes (2026-07-16)
## Draft lanes (2026-07-17)
| Catalog `id` | Blocker |
| --- | --- |
| `binky-company-email-imap` | Founder Red provision of IMAP values (CCR-2026-0007 applied; mount/policy/role live) |
| `object-storage-sts` | NK-WP-0007 vending path not production-exercised |
| `database-dynamic-credentials` | OpenBao database engine role paths TBD per workload |
@ -98,6 +99,9 @@ out on the OpenBao-delivered value, positive + negative verification audit-logge
capabilities-safe re-verify (WP-0026 T07); primary field `NC_WEBDAV_TOKEN`;
`risk: high` + EXPOSED taint on version 2 (operator may rotate optionally).
**Tenant path (WP-0028):** new client secrets use mount `tenants/`, not
`platform/workloads/`. See `wiki/playbooks/tenant-secret-onboarding.md`.
Re-run promotion when the owning repo closes the blocker; do not promote on
playbook prose alone.

View file

@ -0,0 +1,81 @@
# Tenant secret onboarding
Date: 2026-07-17
Workplan: WARDEN-WP-0028
How to add a **client/tenant** commercial secret to NetKingdom OpenBao so
ops-warden can route it and consumers can use it without pasting values into
Git, State Hub, or chat.
---
## Path convention
```text
mount: tenants # dedicated KV v2 mount (not platform/)
path: tenants/<tenant>/<workload>/<bundle>
```
| Segment | Meaning | Example |
| --- | --- | --- |
| `tenant` | Stable client slug | `binky` |
| `workload` | Capability / system | `company-email` |
| `bundle` | One purpose / one CCR | `imap` |
**Do not** put new client secrets under `platform/workloads/…` (fleet/platform
services) or invent `secret/prod/…` as the production home.
First worked lane: `tenants/binky/company-email/imap` (CCR-2026-0007).
---
## Ownership
| Step | Owner |
| --- | --- |
| Business need, non-secret host facts, consumer config | Tenant control repo (e.g. `binky-control`) |
| CCR, policy HCL, OIDC role, mount hygiene | `railiance-platform` |
| Catalog front door + playbook + rotation guide | `ops-warden` |
| Value provision (Red) | Human founder/operator |
| Optional exec wrapper | `secrets-engine` (same path only) |
---
## Checklist
1. **Slug + fields** — pick `tenant`/`workload`/`bundle` and field names (no values).
2. **CCR**`railiance-platform/credential-change-requests/CCR-YYYY-NNNN-….yaml`
- `openbao.mount: tenants`
- `openbao.kv_path: tenants/<tenant>/<workload>/<bundle>`
- `policy_name` starts with `workload-kv-read-`
- OIDC role ends with `-workload-kv-read`
- `risk` high for mailbox/admin/recovery-class secrets
3. **Policy file** — exact `tenants/data/…` + `tenants/metadata/…` read only.
4. **Applier dry-run**`scripts/credential-change.py applier-dry-run <CCR>`
5. **Approve + apply metadata** — policy + OIDC role; **no** secret write in apply.
6. **ops-warden catalog** — draft entry with `risk: high`, rotation block, concrete
`fetch_command` for primary field; playbook under `wiki/playbooks/`.
7. **Founder provision**`bao kv put tenants/… FIELD=@file` (mode 0600 file) or
secrets-engine provision; never chat/Git.
8. **Verify capabilities-safe**`bao token capabilities` allow/deny; never
`kv get` for deny tests (WP-0026).
9. **Promote** catalog `draft``active` when resolvable; update CCR readiness.
10. **Agent boundary** — add exact data `deny` + metadata `read` to
`agent-high-risk-boundary` for high-risk lanes.
---
## Worker fetch (after active)
```bash
bao login -method=oidc -path=netkingdom role=<lane>-workload-kv-read
warden access <catalog-id> --no-policy --out /tmp/secret.file # mode 0600
# agents: never raw --fetch stream; WARDEN_AGENT_ID + risk=high → exit 7
```
## See also
- `wiki/playbooks/binky-company-email-imap.md`
- `wiki/playbooks/catalog-lane-promotion.md`
- `wiki/playbooks/agent-read-boundary.md`
- `railiance-platform/docs/credential-change-approval.md`