Prepare the two approval client-side reader admissions
RPF-WP-0035-T06. Adds CCR-2026-0019 (secrets-engine) and CCR-2026-0020 (approval-engine-operator) with their exact-path read policies, reusing the existing version-1 custody from the verifier activation. No reseed, rotation, shared reader or verifier Secret reuse; both requests are in_flight and nothing is applied. The two shapes were decided by read-only survey rather than assumed. secrets-engine consumes its client secret through an operator-run CLI reading a protected file, and its namespace holds no workload, so reader 1 is an attended operator-workstation OIDC lane rather than an ESO lane; its one missing input is the operator group claim, which NetKingdom and KeyCape own. approval-engine is not deployed and no owner source names who presents the operator client, so reader 2 records the undetermined actor instead of guessing one for the widest approval scope in the pair. Both declare openbao.auth missing rather than carrying a placeholder binding. T06 moves to wait on those two owner inputs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WLUjpv3ssxNRAEPPgLFnEB Assistant: claude-code Assistant-Model: opus Assistant-Process: 1275505@bnt-lap001 Assistant-Session: 97265baa-f08f-4032-b290-a1e2965a69c5
This commit is contained in:
parent
5507fac156
commit
32d5cf0211
7 changed files with 431 additions and 1 deletions
|
|
@ -0,0 +1,158 @@
|
|||
id: CCR-2026-0019
|
||||
kind: credential-change-request
|
||||
schema_version: 1
|
||||
request_type: workload-kv-read
|
||||
title: secrets-engine client-side read of its approval client secret
|
||||
status: in_flight
|
||||
created: '2026-09-09'
|
||||
updated: '2026-09-09'
|
||||
in_flight:
|
||||
missing_fields:
|
||||
- openbao.auth
|
||||
blocking_reason: >-
|
||||
The reader is an attended operator running the secrets-engine CLI on a
|
||||
workstation, not an in-cluster identity. The auth binding is therefore
|
||||
determined in shape but not bindable: method oidc on mount netkingdom, role
|
||||
secrets-engine-approval-client-read, the three standard NetKingdom redirect
|
||||
URIs, scopes openid/profile/email/groups, user_claim sub, groups_claim
|
||||
groups, policy workload-kv-read-secrets-engine-approval-client, ttl 15m --
|
||||
with the one missing input being the exact group claim for the authorized
|
||||
operator, which NetKingdom/KeyCape own. A role cannot be created without it
|
||||
and no placeholder is recorded here. Live inspection on 2026-09-09 found namespace
|
||||
secrets-engine holding only ServiceAccount secrets-engine with no workload,
|
||||
which confirms there is no in-cluster consumer to bind instead.
|
||||
owner: railiance-platform
|
||||
requester:
|
||||
agent: claude
|
||||
reason: >-
|
||||
RPF-WP-0035-T06 residual from the completed verifier custody
|
||||
(CCR-2026-0017). The verifier copy lets KeyCape authenticate the
|
||||
secrets-engine-approval client; it does not let secrets-engine present that
|
||||
client. secrets-engine implemented the consumer on 2026-09-09
|
||||
(SECRETS-WP-0009-T03, repo revision 9eb07fd,
|
||||
secrets-engine/docs/approval-service-auth.md) and reads the value from
|
||||
SECRETS_ENGINE_APPROVAL_CLIENT_SECRET_FILE, an explicit protected file. This
|
||||
request establishes the separate exact read that fills that file. It reuses
|
||||
the existing version-1 custody and requests no reseed and no rotation.
|
||||
review:
|
||||
required: true
|
||||
required_approvers:
|
||||
- platform-operator
|
||||
- secrets-engine-owner
|
||||
comments:
|
||||
- at: '2026-09-09'
|
||||
reviewer: railiance-platform (claude)
|
||||
decision: shape_determined_actor_pending
|
||||
comment: >-
|
||||
Reader shape determined from owner source rather than assumed: the
|
||||
consumer is an operator-run CLI that exchanges the client secret for a
|
||||
short-lived token immediately before each approval request, holds it only
|
||||
in memory, and has no refresh token, renewal or fallback identity. That
|
||||
makes this an attended operator-workstation lane on the OIDC mount, not an
|
||||
External Secrets lane. The named operator group claim is the one input
|
||||
neither this repo nor secrets-engine can supply; NetKingdom/KeyCape own it.
|
||||
target:
|
||||
domain: financials
|
||||
tenant: platform
|
||||
workload: secrets-engine
|
||||
environment: production
|
||||
purpose: >-
|
||||
Let the authorized operator running the secrets-engine approval CLI fetch the
|
||||
secrets-engine-approval client secret into a protected file, without granting
|
||||
any in-cluster reader, any sibling path, or any write on the custody path.
|
||||
openbao:
|
||||
mount: platform
|
||||
kv_path: platform/workloads/secrets-engine/approval-client
|
||||
fields:
|
||||
- CLIENT_SECRET
|
||||
policy_name: workload-kv-read-secrets-engine-approval-client
|
||||
policy_file: openbao/policies/workload-kv-read-secrets-engine-approval-client.hcl
|
||||
access_frontdoor:
|
||||
type: ops-warden
|
||||
catalog_id: secrets-engine-approval-client
|
||||
selector: secrets-engine approval client secret
|
||||
command: warden access secrets-engine-approval-client --out FILE
|
||||
resolvable: false
|
||||
readiness: pending-review
|
||||
delivery:
|
||||
surface: operator-workstation
|
||||
target: >-
|
||||
Protected file consumed as SECRETS_ENGINE_APPROVAL_CLIENT_SECRET_FILE by the
|
||||
secrets-engine approval CLI: owner-only mode, outside any Git work tree,
|
||||
removed at the end of the session. No Kubernetes Secret, no ExternalSecret
|
||||
and no reuse of the sso verifier Secret keycape-secrets-engine-approval-client.
|
||||
risk:
|
||||
classification: high
|
||||
notes:
|
||||
- >-
|
||||
This is the presenting copy. Anyone holding it can obtain tokens as
|
||||
service:secrets-engine for approval:read and approval:consume until KeyCape
|
||||
disables the registration. The verifier copy admitted in CCR-2026-0017 does
|
||||
not carry that power; the two must not be conflated because they hold the
|
||||
same value.
|
||||
- >-
|
||||
A file-delivered credential outlives the process that read it. The lane
|
||||
depends on operator hygiene for removal, which is weaker than an
|
||||
ESO-delivered Secret bounded by a pod lifetime. That is a consequence of the
|
||||
consumer being a workstation CLI and is recorded rather than engineered away.
|
||||
- >-
|
||||
approval:consume is a production-effect scope. This lane grants the ability
|
||||
to present the client; it does not grant approval decisions, which remain
|
||||
with access-engine, approval-engine and the existing consume gates.
|
||||
- >-
|
||||
No reseed and no rotation. Custody is the existing version 1 from the
|
||||
verifier activation; a rotation is a distinct version-guarded operation that
|
||||
also invalidates the KeyCape verifier copy and needs both owners.
|
||||
verification:
|
||||
positive:
|
||||
- >-
|
||||
The bound operator identity reads CLIENT_SECRET from the exact path into a
|
||||
protected file with no value in chat, argv, shell history or logs.
|
||||
- >-
|
||||
The secrets-engine approval CLI exchanges it for a token with subject
|
||||
service:secrets-engine, audience approval-engine, tenant tenant:platform and
|
||||
the single requested scope, verified against live JWKS.
|
||||
negative:
|
||||
- >-
|
||||
An identity outside the confirmed group claim cannot authenticate through
|
||||
role secrets-engine-approval-client-read.
|
||||
- >-
|
||||
The role cannot read the approval-engine operator-client path, cannot list
|
||||
any parent, and cannot write or patch the custody path.
|
||||
- >-
|
||||
No in-cluster ServiceAccount, including secrets-engine/secrets-engine, gains
|
||||
a read through this lane.
|
||||
- >-
|
||||
The KeyCape verifier role cannot be substituted for this reader, and this
|
||||
reader cannot read the verifier's delivery Secret.
|
||||
activation_conditions:
|
||||
- >-
|
||||
NetKingdom/KeyCape confirm the exact group claim for the authorized operator
|
||||
and it is recorded in openbao.auth.bound_claims with
|
||||
bound_claims_confirmed true.
|
||||
- >-
|
||||
secrets-engine confirms the workstation procedure, file mode and removal step
|
||||
for SECRETS_ENGINE_APPROVAL_CLIENT_SECRET_FILE.
|
||||
- >-
|
||||
Policy and OIDC role applied under attended authority
|
||||
(openbao-platform-admin-login, founder_required) with metadata-only receipts.
|
||||
- Positive and negative results recorded with non-secret request ids.
|
||||
evidence: []
|
||||
lifecycle:
|
||||
deactivate: >-
|
||||
Detach the policy from role secrets-engine-approval-client-read and disable
|
||||
the ops-warden catalog entry. The KeyCape verifier lane and its delivery are
|
||||
unaffected.
|
||||
rotate: >-
|
||||
Shared with CCR-2026-0017: the value is one client secret. Rotation is minted
|
||||
by KeyCape and rewritten once under attended authority; both the verifier
|
||||
delivery and this reader then see the new version. No independent rotation
|
||||
exists for this lane alone.
|
||||
compromised: >-
|
||||
KeyCape disables the secrets-engine-approval registration first, since that
|
||||
is what stops token issuance, then the value is rotated and this role's
|
||||
policy detached pending review.
|
||||
state_hub:
|
||||
workplan_id: RPF-WP-0035
|
||||
task_id: RPF-WP-0035-T06
|
||||
related_request: CCR-2026-0017
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
id: CCR-2026-0020
|
||||
kind: credential-change-request
|
||||
schema_version: 1
|
||||
request_type: workload-kv-read
|
||||
title: Client-side read of the approval-engine-operator client secret
|
||||
status: in_flight
|
||||
created: '2026-09-09'
|
||||
updated: '2026-09-09'
|
||||
in_flight:
|
||||
missing_fields:
|
||||
- openbao.auth
|
||||
blocking_reason: >-
|
||||
The presenting actor is not identified by any owner source. approval-engine
|
||||
verifies this client's tokens but never presents them, and no other repo
|
||||
claims the approver surface that would. Live inspection on 2026-09-09 found
|
||||
no approval-engine namespace, workload or Service in the cluster; the owner
|
||||
deploy manifest targets namespace approval-engine and remains unapplied. An
|
||||
auth method cannot be chosen before it is known whether the presenter is an
|
||||
attended operator, an in-cluster component, or an agent surface, and the
|
||||
three imply different roles, policies and delivery.
|
||||
owner: railiance-platform
|
||||
requester:
|
||||
agent: claude
|
||||
reason: >-
|
||||
RPF-WP-0035-T06 residual from the completed verifier custody
|
||||
(CCR-2026-0018). The verifier copy lets KeyCape authenticate the
|
||||
approval-engine-operator client; something must also present it. This request
|
||||
holds the client-side reader open with the determined parts recorded and the
|
||||
undetermined parts named, rather than guessing a reader for the widest scope
|
||||
set in the pair. It reuses existing version-1 custody; no reseed, no rotation.
|
||||
review:
|
||||
required: true
|
||||
required_approvers:
|
||||
- platform-operator
|
||||
- approval-engine-owner
|
||||
comments:
|
||||
- at: '2026-09-09'
|
||||
reviewer: railiance-platform (claude)
|
||||
decision: actor_not_determined
|
||||
comment: >-
|
||||
Determined from owner source: the approval-engine-operator registration
|
||||
holds approval:create, read, approve, revoke, supersede, observe and emit,
|
||||
and explicitly not consume; approval-engine itself only verifies presented
|
||||
tokens (approval_engine/api.py identity check) and does not hold this
|
||||
client. approval-engine's own records note the engine does not restrict
|
||||
/entries by principal type, so this client can supply approver evidence
|
||||
today, and whether it should is approval doctrine owned by gate-house. The
|
||||
reader therefore cannot be named here without an owner decision, and
|
||||
naming one anyway would hand the widest approval scope to a guessed
|
||||
identity. Held in_flight deliberately.
|
||||
target:
|
||||
domain: financials
|
||||
tenant: platform
|
||||
workload: approval-engine
|
||||
environment: production
|
||||
purpose: >-
|
||||
Establish the separate exact read by which the eventual approval-engine
|
||||
operator surface obtains its client secret, once that surface is named by its
|
||||
owner.
|
||||
openbao:
|
||||
mount: platform
|
||||
kv_path: platform/workloads/approval-engine/operator-client
|
||||
fields:
|
||||
- CLIENT_SECRET
|
||||
policy_name: workload-kv-read-approval-engine-operator-client
|
||||
policy_file: openbao/policies/workload-kv-read-approval-engine-operator-client.hcl
|
||||
access_frontdoor:
|
||||
type: ops-warden
|
||||
catalog_id: approval-engine-operator-client
|
||||
selector: approval-engine operator client secret
|
||||
resolvable: false
|
||||
readiness: pending-review
|
||||
delivery:
|
||||
surface: undetermined
|
||||
target: >-
|
||||
Not determined. The delivery surface follows the actor: an attended operator
|
||||
implies a protected workstation file, an in-cluster component implies an
|
||||
ExternalSecret into the eventual approval-engine namespace, and an agent
|
||||
surface implies neither. No surface is admitted until the owner names one.
|
||||
risk:
|
||||
classification: high
|
||||
notes:
|
||||
- >-
|
||||
This is the widest scope set in the pair: create, approve, revoke and
|
||||
supersede. A holder can forge approval lifecycle actions, and because
|
||||
approval-engine records principal_type rather than restricting it, a
|
||||
non-human holder can supply approver evidence. That is why the actor is left
|
||||
unnamed rather than defaulted.
|
||||
- >-
|
||||
approval:consume is absent by design and stays absent. Adding it is a new
|
||||
lane decision, not an edit to this request.
|
||||
- >-
|
||||
The exact-path read policy is written and committed so the eventual reader
|
||||
inherits a bounded grant rather than a broad one drafted under time pressure.
|
||||
Writing the policy is not admitting a reader.
|
||||
- >-
|
||||
No reseed and no rotation; custody is the existing version 1 from the
|
||||
verifier activation.
|
||||
verification:
|
||||
positive:
|
||||
- >-
|
||||
Once the actor is named, the bound identity reads CLIENT_SECRET from the
|
||||
exact path into its admitted delivery surface with no value in chat, argv,
|
||||
shell history or logs.
|
||||
- >-
|
||||
The named surface obtains a token with subject service:approval-engine-operator,
|
||||
audience approval-engine and tenant tenant:platform, verified against live JWKS.
|
||||
negative:
|
||||
- >-
|
||||
An identity outside the confirmed binding cannot authenticate through the
|
||||
eventual role.
|
||||
- >-
|
||||
The role cannot read the secrets-engine approval-client path, cannot list any
|
||||
parent, and cannot write or patch the custody path.
|
||||
- The reader is denied approval:consume, and denial is observed rather than assumed.
|
||||
- >-
|
||||
The KeyCape verifier role cannot be substituted for this reader, and this
|
||||
reader cannot read the verifier's delivery Secret.
|
||||
activation_conditions:
|
||||
- >-
|
||||
The approval-engine owner names the presenting actor and its placement, or
|
||||
records that no client-side reader is wanted and this request is cancelled.
|
||||
- >-
|
||||
Given that actor, the auth method, mount, role, bound claims and delivery
|
||||
surface are completed and reviewed as a concrete request.
|
||||
- >-
|
||||
Policy and role applied under attended authority
|
||||
(openbao-platform-admin-login, founder_required) with metadata-only receipts.
|
||||
- Positive and negative results recorded with non-secret request ids.
|
||||
evidence: []
|
||||
lifecycle:
|
||||
deactivate: >-
|
||||
Detach the policy from the eventual role and disable the ops-warden catalog
|
||||
entry. The KeyCape verifier lane and its delivery are unaffected.
|
||||
rotate: >-
|
||||
Shared with CCR-2026-0018: one client secret, minted by KeyCape and rewritten
|
||||
once under attended authority. No independent rotation for this lane alone.
|
||||
compromised: >-
|
||||
KeyCape disables the approval-engine-operator registration first, then the
|
||||
value is rotated; emitted approval actions are referred to approval-engine
|
||||
for audit review, since rotation does not retract them.
|
||||
state_hub:
|
||||
workplan_id: RPF-WP-0035
|
||||
task_id: RPF-WP-0035-T06
|
||||
related_request: CCR-2026-0018
|
||||
Loading…
Add table
Add a link
Reference in a new issue