Align approval registrations to the tenant:platform decision
All checks were successful
Build and Publish Container Image / build-and-push (push) Successful in 33s
All checks were successful
Build and Publish Container Image / build-and-push (push) Successful in 33s
Operator decision 5ed3fb35-eca9-413a-82b9-95171ba85bf6 accepts tenant:platform as the platform management tenant for the Glas approval chain, requiring exact spelling across the approval store, the service-client JWT claim and the lifecycle CheckRequest. Changes the tenant field on secrets-engine-approval and approval-engine-operator only, in the registration fixture and the provisioning packet. Unrelated clients and the human directory default keep tenant:coulomb, and no audience, scope, subject, role, lifetime or MFA grant changes. Adds issuance evidence that the approval shape emits tenant:platform exactly and never an alias the caller requests, that the OpenBao client gains no cross-tenant reach, and a fixture guard pinning every reviewed client's tenant. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NV9oijZukGyGbRQGGKnK4P Assistant: claude-code Assistant-Model: opus Assistant-Process: 713576@bnt-lap001 Assistant-Session: 384c511d-9bce-4cb8-a676-2aef6c0c8df6
This commit is contained in:
parent
519e4d8ef1
commit
7a6666d1f9
8 changed files with 199 additions and 28 deletions
|
|
@ -1,4 +1,8 @@
|
|||
# Proposed non-secret admission packet. This is not executable authorization.
|
||||
# Tenant for both requests is tenant:platform per decision
|
||||
# 5ed3fb35-eca9-413a-82b9-95171ba85bf6 (landlord zone). Exact spelling required
|
||||
# across the approval store, these JWT claims and the lifecycle CheckRequest;
|
||||
# no alias to platform or tenant:coulomb.
|
||||
status: awaiting-custody-admission
|
||||
owner: key-cape
|
||||
resource_audience: approval-engine
|
||||
|
|
@ -7,7 +11,7 @@ registration_source: config/service-clients.example.yaml
|
|||
requests:
|
||||
- client_id: secrets-engine-approval
|
||||
subject: service:secrets-engine
|
||||
tenant: tenant:coulomb
|
||||
tenant: tenant:platform
|
||||
scopes: [approval:read, approval:consume]
|
||||
lifetime: 15m
|
||||
proposed_openbao_path: platform/workloads/secrets-engine/approval-client
|
||||
|
|
@ -19,7 +23,7 @@ requests:
|
|||
consumer: secrets-engine
|
||||
- client_id: approval-engine-operator
|
||||
subject: service:approval-engine-operator
|
||||
tenant: tenant:coulomb
|
||||
tenant: tenant:platform
|
||||
scopes: [approval:create, approval:read, approval:approve, approval:revoke, approval:supersede, approval:observe, approval:emit]
|
||||
lifetime: 15m
|
||||
proposed_openbao_path: platform/workloads/approval-engine/operator-client
|
||||
|
|
|
|||
|
|
@ -1,8 +1,15 @@
|
|||
# Tenant claim contract
|
||||
|
||||
Answers the tenant-alignment question in glas-harness message
|
||||
`356f6977-d361-4e3b-83ab-b2c7f4759286` (GLAS-WP-0015). It states what KeyCape
|
||||
owns and emits; it does not create a mapping between tenant vocabularies.
|
||||
States what KeyCape owns and emits for the `tenant` claim. Raised by glas-harness
|
||||
message `356f6977-d361-4e3b-83ab-b2c7f4759286` (GLAS-WP-0015) and resolved by
|
||||
operator decision `5ed3fb35-eca9-413a-82b9-95171ba85bf6` — "Use tenant:platform
|
||||
for the Glas approval dependency chain", recorded in
|
||||
`glas-harness/docs/platform-tenant-decision.md`.
|
||||
|
||||
`tenant:platform` is the platform management, administration and services tenant
|
||||
(the landlord zone). KeyCape emits it verbatim for the two approval clients and
|
||||
still creates no mapping between tenant vocabularies: no alias to `platform` or
|
||||
`tenant:coulomb`, and no implicit cross-tenant grant.
|
||||
|
||||
## What KeyCape emits
|
||||
|
||||
|
|
@ -11,39 +18,44 @@ never influenced by request parameters.
|
|||
|
||||
| Principal | Source of `tenant` | Value in the reviewed registrations |
|
||||
| --- | --- | --- |
|
||||
| Service (`client_credentials`) | The client's `tenant` field. Required by config validation — a `client_credentials` client without `serviceSubject` and `tenant` fails startup validation. | `tenant:coulomb` for all four clients in `config/service-clients.example.yaml`, including `secrets-engine-approval` and `approval-engine-operator`. |
|
||||
| Service (`client_credentials`) | The client's `tenant` field. Required by config validation — a `client_credentials` client without `serviceSubject` and `tenant` fails startup validation. | In `config/service-clients.example.yaml`: `tenant:platform` for `secrets-engine-approval` and `approval-engine-operator`; `tenant:coulomb` for `codex-railiance-platform` and `secrets-engine-openbao`. |
|
||||
| Human (`authorization_code`) | The directory user's tenant, falling back to the platform default when unset. | Directory value, else `tenant:coulomb`. |
|
||||
|
||||
`tenant`, `tenant_hint`, `audience` and `resource` request parameters cannot
|
||||
change the claim. `tenant_hint` on `/authorize` reaches registration/enrollment
|
||||
handoffs only; it is not a claim input.
|
||||
|
||||
## The three values in the request
|
||||
## The approval chain, after the decision
|
||||
|
||||
- **JWT tenant** — `tenant:coulomb`. Owned by KeyCape, emitted verbatim from the
|
||||
registration above. This is the only one of the three KeyCape owns.
|
||||
- **Approval store tenant** — `platform`. Owned by approval-engine.
|
||||
- **Policy tenant / CheckRequest tenant** — `tenant:platform`. Owned by flex-auth.
|
||||
All three layers now use one exact spelling, `tenant:platform`:
|
||||
|
||||
KeyCape performs **no** normalization, prefix-stripping or aliasing. A resource
|
||||
server comparing `tenant` must use exact string comparison, so as things stand a
|
||||
token issued to `secrets-engine-approval` (`tenant:coulomb`) does not match an
|
||||
approval store tenant `platform` or a policy tenant `tenant:platform`.
|
||||
| Layer | Value | Owner |
|
||||
| --- | --- | --- |
|
||||
| Approval store tenant | `tenant:platform` | approval-engine |
|
||||
| Service-client JWT `tenant` claim | `tenant:platform` | KeyCape (this repo) |
|
||||
| Lifecycle CheckRequest tenant | `tenant:platform` | flex-auth |
|
||||
|
||||
## What is not decided here
|
||||
KeyCape performs **no** normalization, prefix-stripping or aliasing, so a
|
||||
resource server compares `tenant` as an exact string. The previously observed
|
||||
`platform` and `tenant:coulomb` spellings are **not** accepted aliases for
|
||||
`tenant:platform`; a token carrying either must be denied by the resource server.
|
||||
|
||||
Whether these three identify the same tenant across layers is not a KeyCape
|
||||
decision, and spelling similarity is not a mapping. Two admissible resolutions
|
||||
exist, both owned outside this repository:
|
||||
## Scope of the alignment
|
||||
|
||||
1. The consuming owners accept `tenant:coulomb` as the JWT tenant and record the
|
||||
layer mapping in their own contract; KeyCape changes nothing.
|
||||
2. The owners decide the approval clients belong to a different tenant, in which
|
||||
case KeyCape changes the `tenant` field on those two registrations only, under
|
||||
an explicit decision reference, and re-issues.
|
||||
The decision changed the `tenant` field on exactly two registrations,
|
||||
`secrets-engine-approval` and `approval-engine-operator`, plus the matching
|
||||
entries in `docs/approval-engine-provisioning-request.yaml`. Deliberately
|
||||
unchanged:
|
||||
|
||||
KeyCape will not change the `tenant` value on a live registration without such a
|
||||
reference. No unilateral change to live clients or policy subjects was made.
|
||||
- `codex-railiance-platform` and `secrets-engine-openbao` keep `tenant:coulomb`.
|
||||
- Human directory resolution keeps its `tenant:coulomb` default.
|
||||
- No cross-tenant grant is implied: a `tenant:platform` token conveys no reach
|
||||
into `tenant:coulomb` resources, and audiences, scopes, subjects, roles,
|
||||
lifetimes and MFA requirements are untouched.
|
||||
|
||||
This resolves the *choice* of tenant only. Live provisioning of the two clients
|
||||
remains gated on deployment-owned custody and the separate verification gates in
|
||||
KEY-WP-0013-T02; KeyCape changed no live registration or policy subject.
|
||||
|
||||
## Evidence
|
||||
|
||||
|
|
@ -57,6 +69,20 @@ reference. No unilateral change to live clients or policy subjects was made.
|
|||
wrong-tenant denial basis for an exact-comparison resource server.
|
||||
- `TestHumanTenantClaimUsesDirectoryValueThenPlatformDefault` — human tokens carry
|
||||
the directory tenant, defaulting to `tenant:coulomb` rather than an empty claim.
|
||||
- `TestApprovalClientIssuesExactPlatformTenantAndRejectsAliases` — the
|
||||
approval-client shape issues `tenant:platform` exactly, with
|
||||
`aud=approval-engine`, even when the caller asks for `platform`,
|
||||
`tenant:coulomb` or `TENANT:PLATFORM`.
|
||||
- `TestUnrelatedServiceClientKeepsCoulombTenant` — the OpenBao login client keeps
|
||||
`tenant:coulomb` even when the request asks for `tenant:platform`, so the
|
||||
alignment grants no cross-tenant reach.
|
||||
|
||||
`src/cmd/keycape/clients_test.go`:
|
||||
|
||||
- `TestServiceRegistrationTenantsAreExactPerDecision` — loads the real
|
||||
registration fixture and pins the exact tenant of every reviewed client, so
|
||||
drift or an alias reintroduced into `config/service-clients.example.yaml` fails
|
||||
the build.
|
||||
|
||||
These are local issuance proofs. They are not live-rollout evidence; see
|
||||
`docs/approval-engine-auth-contract.md` and KEY-WP-0013-T02 for the deployment
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue