171 lines
7.3 KiB
YAML
171 lines
7.3 KiB
YAML
id: CCR-2026-0013
|
|
kind: credential-change-request
|
|
schema_version: 1
|
|
request_type: workload-kv-read
|
|
title: Core Hub runtime API token lane
|
|
status: verified
|
|
created: '2026-08-20'
|
|
updated: '2026-08-20'
|
|
requester:
|
|
agent: codex
|
|
reason: CORE-WP-0011 and RAPP-CORE-HUB-WP-0001 relocate Core Hub production to railiance01.
|
|
The validated package requires CORE_HUB_API_TOKEN, but the value must move through
|
|
platform custody rather than a copied Kubernetes Secret or Git. This request covers
|
|
only the standing application token; PostgreSQL credentials remain dynamic database-engine
|
|
leases.
|
|
review:
|
|
required: true
|
|
required_approvers:
|
|
- platform-operator
|
|
- core-hub-owner
|
|
comments:
|
|
- at: '2026-08-20T22:02:19+00:00'
|
|
reviewer: platform operator / Core Hub owner (chat approval)
|
|
decision: approved
|
|
comment: 'State Hub decision 4f70311b-a4c4-4959-b1a1-cdd1be97d523: approved for
|
|
the governed private Core Hub relocation; static API-token custody remains separate
|
|
from dynamic PostgreSQL leases.'
|
|
- at: '2026-08-20T22:03:00+00:00'
|
|
reviewer: codex
|
|
decision: binding_confirmed
|
|
comment: Railiance01 has ServiceAccount external-secrets/external-secrets and
|
|
the External Secrets deployment uses that exact identity. The proposed Kubernetes-auth
|
|
bound claims match the live subject; store use remains independently limited
|
|
to namespace core-hub.
|
|
target:
|
|
domain: infotech
|
|
tenant: core-hub
|
|
workload: core-hub
|
|
rapp: rapp-core-hub
|
|
environment: production
|
|
purpose: Project the existing Core Hub protected-API token into the private railiance01
|
|
runtime through a namespace-limited ExternalSecret while preserving the token
|
|
across the relocation window.
|
|
openbao:
|
|
mount: platform
|
|
kv_path: platform/workloads/core-hub/runtime
|
|
fields:
|
|
- CORE_HUB_API_TOKEN
|
|
policy_name: workload-kv-read-core-hub-runtime
|
|
policy_file: openbao/policies/workload-kv-read-core-hub-runtime.hcl
|
|
auth:
|
|
method: kubernetes
|
|
mount: kubernetes
|
|
role: external-secrets-core-hub-runtime
|
|
bound_claims:
|
|
service_account_names:
|
|
- external-secrets
|
|
service_account_namespaces:
|
|
- external-secrets
|
|
bound_claims_confirmed: true
|
|
policies:
|
|
- workload-kv-read-core-hub-runtime
|
|
ttl: 15m
|
|
access_frontdoor:
|
|
type: ops-warden
|
|
catalog_id: core-hub-runtime-api-token
|
|
selector: Core Hub runtime protected API token
|
|
command: warden access core-hub-runtime-api-token --fetch CORE_HUB_API_TOKEN
|
|
resolvable: false
|
|
readiness: pending-review
|
|
delivery:
|
|
surface: external-secrets
|
|
target: ClusterSecretStore openbao-core-hub-runtime, limited to namespace core-hub,
|
|
to ExternalSecret core-hub/core-hub-api-token and Secret core-hub-api-token. The
|
|
rapp package consumes this Secret separately from runtime and migration PostgreSQL
|
|
lease Secrets.
|
|
risk:
|
|
classification: high
|
|
notes:
|
|
- The token authorizes protected Core Hub API operations and must not be printed,
|
|
placed on argv, committed, or recorded in State Hub.
|
|
- This CCR does not authorize a standing database password or a database URL in
|
|
KV. Those come from the OpenBao database engine.
|
|
- Preserve the current token during the relocation so existing protected API consumers
|
|
do not fail at the same time as the infrastructure move.
|
|
- Later rotation is coordinated with every protected API consumer because Core Hub
|
|
currently accepts one token.
|
|
verification:
|
|
positive:
|
|
- An approved core-hub ExternalSecret syncs CORE_HUB_API_TOKEN into Secret core-hub-api-token
|
|
without printing the value.
|
|
- Protected API smoke succeeds against the private shadow endpoint using an injected
|
|
token after the source database has been reconciled.
|
|
negative:
|
|
- A namespace outside core-hub cannot use openbao-core-hub-runtime.
|
|
- A token without workload-kv-read-core-hub-runtime cannot read the KV data path.
|
|
- The Core Hub workload identity cannot write or list sibling workload paths.
|
|
activation_conditions:
|
|
- Platform operator and Core Hub owner approve this CCR.
|
|
- The source token is transferred through attended operator custody without entering
|
|
logs, chat, Git, or State Hub.
|
|
- The Kubernetes auth role and policy are applied to railiance01-local OpenBao and
|
|
the bound service-account claims are verified.
|
|
- The package consumes the API-token Secret separately from dynamic database lease
|
|
Secrets.
|
|
- Positive and negative evidence is recorded with non-secret timestamps or OpenBao
|
|
audit references.
|
|
evidence:
|
|
- at: '2026-08-20T22:07:02+00:00'
|
|
actor: platform operator / Core Hub owner (chat approval)
|
|
kind: metadata_apply
|
|
result: passed
|
|
details:
|
|
- OpenBao policy and auth-role metadata apply completed without secret values
|
|
- at: '2026-08-20T22:11:45+00:00'
|
|
actor: codex
|
|
kind: secret_provisioned
|
|
result: passed
|
|
details:
|
|
- Source API token transferred directly from CoulombCore Kubernetes custody to
|
|
OpenBao KV version 1; value not printed or staged
|
|
- at: '2026-08-20T22:11:45+00:00'
|
|
actor: codex
|
|
kind: positive_verification
|
|
result: passed
|
|
details:
|
|
- Railiance01 stores Valid; API/runtime/migration ExternalSecrets SecretSynced
|
|
at 2026-08-20T22:07:42Z with expected key names only
|
|
- at: '2026-08-20T22:11:45+00:00'
|
|
actor: codex
|
|
kind: negative_verification
|
|
result: passed
|
|
details:
|
|
- Both stores rejected core-hub-denial-probe with SecretSyncedError and created
|
|
no target Secret; Kubernetes-auth token had read on exact data/metadata paths
|
|
and deny on sibling/parent paths
|
|
- at: '2026-08-20T22:11:46+00:00'
|
|
actor: codex
|
|
kind: database_role_separation
|
|
result: passed
|
|
details:
|
|
- Runtime lease connected but CREATE was denied and pg_has_role(core_hub_migrate)=false;
|
|
migration lease created and dropped bounded probe table; probe pods deleted
|
|
- at: '2026-08-20T22:45:58+00:00'
|
|
actor: codex
|
|
kind: private_shadow_verification
|
|
result: passed
|
|
details:
|
|
- 'Private railiance01 shadow: OpenBao KV and database stores Valid; least-privilege
|
|
denial and role-separation probes passed; chart 0.3.1 rotated the runtime lease
|
|
in place with Secret resourceVersion change, child PID change, stable pod UID,
|
|
container restartCount 0->0, readiness true, and 5m refresh restored; post-rotation
|
|
authenticated smoke 20260820224419-43dc05 passed all 10 checks; public Ingress
|
|
remained absent.'
|
|
lifecycle:
|
|
deactivate: Disable the front door and Kubernetes auth role, remove the ExternalSecret,
|
|
and delete the materialized Secret only after Core Hub is retired or a reviewed
|
|
fallback is active.
|
|
rotate: Coordinate a new random token with all protected API consumers, update the
|
|
OpenBao field through attended custody, wait for ESO sync, roll Core Hub and consumers,
|
|
verify protected calls, then invalidate the old token.
|
|
compromised: Disable protected writes, replace the token in OpenBao and every consumer,
|
|
roll the workload, review Core Hub protected-operation logs, and open an incident
|
|
follow-up.
|
|
state_hub:
|
|
workplan_id: RPF-WP-0021
|
|
task_id: RPF-WP-0021-T04
|
|
decision_id: 4f70311b-a4c4-4959-b1a1-cdd1be97d523
|
|
decision_api_url: http://127.0.0.1:8000/decisions/4f70311b-a4c4-4959-b1a1-cdd1be97d523
|
|
decision_dashboard_url: http://127.0.0.1:3000/decisions
|
|
decision_resolved_at: '2026-08-20T22:02:19Z'
|