Add credential approval workflow plan
This commit is contained in:
9
Makefile
9
Makefile
@@ -25,6 +25,7 @@ ARGOCD_BOOTSTRAP_DIR ?= argocd/bootstrap
|
||||
ARGOCD_REPOSITORY_SECRET ?=
|
||||
CREDENTIAL_GRANTS ?= credential-grants/catalog.yaml
|
||||
OPENBAO_TOKEN_GRANT_ARGS ?=
|
||||
OPENBAO_WORKLOAD_KV_ARGS ?=
|
||||
CREDENTIAL_HELPER_GLOBAL_ARGS ?=
|
||||
CREDENTIAL_HELPER_ARGS ?=
|
||||
CREDENTIAL_HELPER_PURPOSE ?= flex-auth-openbao-smoke
|
||||
@@ -168,6 +169,14 @@ openbao-configure-external-secrets-issue-core: ## Configure OpenBao policy/role
|
||||
OPENBAO_RELEASE=$(OPENBAO_RELEASE) ESO_NAMESPACE=$(EXTERNAL_SECRETS_NAMESPACE) \
|
||||
scripts/openbao-apply-external-secrets-issue-core.sh
|
||||
|
||||
openbao-workload-kv-lanes-dry-run: ## Dry-run OpenBao workload KV read-lane policy apply
|
||||
scripts/openbao-apply-workload-kv-lanes.sh --dry-run $(OPENBAO_WORKLOAD_KV_ARGS)
|
||||
|
||||
openbao-configure-workload-kv-lanes: ## Configure OpenBao workload KV read-lane policies
|
||||
KUBECTL='$(KUBECTL)' OPENBAO_NAMESPACE=$(OPENBAO_NAMESPACE) \
|
||||
OPENBAO_RELEASE=$(OPENBAO_RELEASE) \
|
||||
scripts/openbao-apply-workload-kv-lanes.sh $(OPENBAO_WORKLOAD_KV_ARGS)
|
||||
|
||||
openbao-validate-restore-evidence: ## Validate non-secret OpenBao restore-drill evidence JSON
|
||||
OPENBAO_RESTORE_EVIDENCE='$(OPENBAO_RESTORE_EVIDENCE)' \
|
||||
scripts/openbao-validate-restore-evidence.sh
|
||||
|
||||
236
docs/credential-change-approval.md
Normal file
236
docs/credential-change-approval.md
Normal file
@@ -0,0 +1,236 @@
|
||||
# Credential Change Approval Workflow
|
||||
|
||||
This document sketches the operator workflow we want for it-sec and credential
|
||||
changes. The goal is to remove raw OpenBao command authoring from routine human
|
||||
operation while preserving explicit human approval, auditability, and safe
|
||||
handling of secret values.
|
||||
|
||||
## Problem
|
||||
|
||||
The current workflow still asks operators to translate a reviewed intent into
|
||||
OpenBao commands by hand:
|
||||
|
||||
- create or update policies;
|
||||
- create auth roles with the right bound claims;
|
||||
- create or rotate secret paths and fields;
|
||||
- verify positive and negative access;
|
||||
- tell ops-warden or another access front door when a lane may become active.
|
||||
|
||||
That is inefficient and easy to get wrong. It is also hard to review because
|
||||
the actual unit of work is spread across chat, workplans, OpenBao UI screens,
|
||||
State Hub notes, and shell commands.
|
||||
|
||||
## Direction
|
||||
|
||||
Treat OpenBao as the enforcement and audit engine, not the primary review UI.
|
||||
Add a small approval control plane in front of it:
|
||||
|
||||
1. an agent or CLI creates a structured, non-secret credential change request;
|
||||
2. humans review the rendered proposal, risk notes, generated OpenBao plan, and
|
||||
verification plan;
|
||||
3. a human approves or denies with a comment;
|
||||
4. only approved requests can be applied by an operator-controlled helper;
|
||||
5. the helper records non-secret evidence and marks the request active,
|
||||
rejected, deactivated, rotated, or compromised.
|
||||
|
||||
This can be implemented with repo files, State Hub, and CLI/chat integration
|
||||
first. An OpenBao UI extension can come later if the workflow proves itself.
|
||||
|
||||
## Core Object
|
||||
|
||||
The canonical unit is a credential change request, abbreviated `CCR`.
|
||||
|
||||
The CCR must be non-secret. It may contain:
|
||||
|
||||
- stable request id and title;
|
||||
- requester, reviewer, approver, and applier identities;
|
||||
- target domain, tenant, workload, environment, and purpose;
|
||||
- OpenBao mount, path, field names, policy names, and auth role names;
|
||||
- exact non-secret policy HCL or generated policy references;
|
||||
- proposed auth bindings and bound claims;
|
||||
- delivery surface such as ops-warden, External Secrets, CSI, or direct caller
|
||||
fetch;
|
||||
- risk classification and approval requirements;
|
||||
- generated apply plan;
|
||||
- verification plan;
|
||||
- rollback, deactivate, rotate, and compromise response plan;
|
||||
- comments, approvals, denials, and timestamps;
|
||||
- non-secret OpenBao audit request ids or timestamps after execution.
|
||||
|
||||
It must not contain:
|
||||
|
||||
- secret values;
|
||||
- wrapped token values;
|
||||
- root, platform-admin, or issuer tokens;
|
||||
- passwords, API keys, private keys, OTP seeds, unseal shares, or recovery
|
||||
codes;
|
||||
- command output that includes secret values.
|
||||
|
||||
## State Machine
|
||||
|
||||
Suggested states:
|
||||
|
||||
```text
|
||||
draft
|
||||
proposed
|
||||
needs_changes
|
||||
approved
|
||||
denied
|
||||
apply_pending
|
||||
applied
|
||||
verified
|
||||
active
|
||||
deactivated
|
||||
rotated
|
||||
compromised
|
||||
superseded
|
||||
cancelled
|
||||
```
|
||||
|
||||
Only `approved` requests may be applied. Only `verified` requests may become
|
||||
`active`.
|
||||
|
||||
Emergency break-glass work may create a request after the fact, but it must be
|
||||
marked as break-glass, reviewed retrospectively, and linked to audit evidence.
|
||||
|
||||
## Review Surface
|
||||
|
||||
A reviewer should see a concise rendered proposal:
|
||||
|
||||
```text
|
||||
Request: whynot-design npm publish token lane
|
||||
Type: workload-kv-read
|
||||
Mount/path/field:
|
||||
platform/workloads/whynot-design/whynot-design/npm-publish
|
||||
NPM_AUTH_TOKEN
|
||||
Policy:
|
||||
workload-kv-read-whynot-design-npm-publish
|
||||
Auth binding:
|
||||
netkingdom OIDC role whynot-design-workload-kv-read
|
||||
bound claim: groups includes whynot-design
|
||||
Access front door:
|
||||
ops-warden whynot-design-npm-token
|
||||
Risk:
|
||||
grants read access to npm publish credential
|
||||
Checks:
|
||||
positive whynot fetch, negative non-whynot denial, OpenBao audit evidence
|
||||
Decision:
|
||||
approve | deny | needs changes
|
||||
Comment:
|
||||
free text
|
||||
```
|
||||
|
||||
The reviewer should not need to know the exact `bao write` syntax. They should
|
||||
be able to discuss the proposal in chat, request changes, and then make a
|
||||
formal decision.
|
||||
|
||||
## Minimal Implementation
|
||||
|
||||
Version 1 should be boring:
|
||||
|
||||
- store CCR files under `credential-change-requests/`;
|
||||
- validate CCR schema offline;
|
||||
- render a human-readable review summary;
|
||||
- generate OpenBao apply plans from approved CCRs;
|
||||
- require an approval record before apply;
|
||||
- apply only non-secret policy/auth/path metadata;
|
||||
- prompt or delegate separately for secret value entry;
|
||||
- record non-secret evidence in State Hub.
|
||||
|
||||
The CLI shape can be:
|
||||
|
||||
```bash
|
||||
scripts/credential-change.py propose workload-kv ...
|
||||
scripts/credential-change.py render CCR-YYYY-NNNN
|
||||
scripts/credential-change.py approve CCR-YYYY-NNNN --comment "..."
|
||||
scripts/credential-change.py deny CCR-YYYY-NNNN --comment "..."
|
||||
scripts/credential-change.py apply CCR-YYYY-NNNN
|
||||
scripts/credential-change.py verify CCR-YYYY-NNNN
|
||||
scripts/credential-change.py deactivate CCR-YYYY-NNNN --reason "..."
|
||||
```
|
||||
|
||||
The same operations can be exposed through chat by having the agent create the
|
||||
proposal, show the rendered summary, then call the CLI only after the human
|
||||
gives an explicit approval phrase.
|
||||
|
||||
## State Hub Role
|
||||
|
||||
State Hub should hold:
|
||||
|
||||
- request lifecycle events;
|
||||
- review comments;
|
||||
- approval/denial decisions;
|
||||
- non-secret apply and verification evidence;
|
||||
- links to workplans and CCR files.
|
||||
|
||||
State Hub should not hold secret values. It can be the first review UI because
|
||||
it already supports messages, progress, task status, and cross-repo
|
||||
coordination.
|
||||
|
||||
## OpenBao Role
|
||||
|
||||
OpenBao remains authoritative for:
|
||||
|
||||
- policy enforcement;
|
||||
- auth method configuration;
|
||||
- token issuance and revocation;
|
||||
- secret storage;
|
||||
- audit logs.
|
||||
|
||||
Where OpenBao supports non-secret metadata on secret paths or auth roles, we can
|
||||
mirror CCR ids and status labels. The workflow must not depend on OpenBao being
|
||||
the only index, because operators need to see proposed, rejected, deactivated,
|
||||
rotated, and compromised items across repos and access front doors.
|
||||
|
||||
## ops-warden Role
|
||||
|
||||
ops-warden should consume only approved and active access lanes.
|
||||
|
||||
For draft requests, ops-warden may create a draft catalog entry that points to
|
||||
the CCR, but it should not activate the entry until the CCR is verified.
|
||||
|
||||
For `warden access --fetch` / `--exec`, the catalog should include the CCR id
|
||||
and refuse active use when the CCR state is not `active`.
|
||||
|
||||
## Interactive Runbook Role
|
||||
|
||||
The interactive runbook is the operator bridge:
|
||||
|
||||
1. load a CCR;
|
||||
2. show the rendered summary and exact generated plan;
|
||||
3. confirm the request is approved;
|
||||
4. acquire operator authority through an approved path;
|
||||
5. apply the plan;
|
||||
6. ask for attended secret entry when needed;
|
||||
7. run positive and negative verification;
|
||||
8. record non-secret evidence;
|
||||
9. notify downstream front doors such as ops-warden.
|
||||
|
||||
This lets operators safely drive privileged work without needing to remember
|
||||
every OpenBao command.
|
||||
|
||||
## Compromise And Deactivation
|
||||
|
||||
Every active CCR needs a deactivate and rotate path:
|
||||
|
||||
- `deactivated`: access intentionally disabled but not necessarily compromised;
|
||||
- `rotated`: secret value replaced and old value no longer valid;
|
||||
- `compromised`: emergency state requiring immediate disablement, rotation,
|
||||
blast-radius notes, and incident follow-up.
|
||||
|
||||
The workflow must support marking an existing credential or lane as compromised
|
||||
even when the original request predates this system.
|
||||
|
||||
## Near-Term Target
|
||||
|
||||
Use the whynot-design npm token lane as the pilot:
|
||||
|
||||
1. encode the existing non-secret lane as a CCR;
|
||||
2. render it for review;
|
||||
3. approve or request changes from chat;
|
||||
4. generate/apply the OpenBao policy and auth role only after approval;
|
||||
5. provision the secret value by attended operator custody;
|
||||
6. verify and activate the ops-warden catalog entry.
|
||||
|
||||
Once that path feels good, reuse it for the sibling workload-KV lanes and the
|
||||
credential broker's OpenBao token-role gates.
|
||||
@@ -404,6 +404,10 @@ platform/operators/<purpose>
|
||||
The template policy for workload KV reads is
|
||||
`openbao/policies/workload-kv-read-template.hcl`.
|
||||
|
||||
Concrete workload access lanes used by ops-warden and similar front doors are
|
||||
tracked in `docs/workload-kv-access-lanes.md`. These docs carry non-secret
|
||||
path, field, policy, auth-role, and verification pointers only.
|
||||
|
||||
## Backup, Restore, Audit, And Monitoring
|
||||
|
||||
Before any live application secrets move into OpenBao:
|
||||
|
||||
154
docs/workload-kv-access-lanes.md
Normal file
154
docs/workload-kv-access-lanes.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# Workload KV Access Lanes
|
||||
|
||||
This document records concrete OpenBao workload KV paths that external access
|
||||
front doors can reference without storing or vending secret values themselves.
|
||||
The first lane is for ops-warden `warden access --fetch` / `--exec`.
|
||||
|
||||
## Safety Rules
|
||||
|
||||
- Do not put secret values in Git, State Hub, chat, prompts, workplans, or logs.
|
||||
- Store only non-secret pointers here: path, field name, policy name, auth role,
|
||||
flex-auth reference, and verification status.
|
||||
- ops-warden may proxy a read as the caller, but it must not hold the returned
|
||||
value beyond the caller-requested fetch/exec process.
|
||||
- Live writes require an approved OpenBao/operator path and attended handling
|
||||
of the secret value.
|
||||
|
||||
## whynot-design npm Publish Token
|
||||
|
||||
Ops-warden request:
|
||||
`551031d1-335e-4db8-9535-820fea52d0a3`
|
||||
|
||||
| Item | Value |
|
||||
| --- | --- |
|
||||
| ops-warden catalog id | `whynot-design-npm-token` |
|
||||
| KV mount | `platform` |
|
||||
| OpenBao CLI path | `platform/workloads/whynot-design/whynot-design/npm-publish` |
|
||||
| Secret field | `NPM_AUTH_TOKEN` |
|
||||
| Read policy | `workload-kv-read-whynot-design-npm-publish` |
|
||||
| Policy file | `openbao/policies/workload-kv-read-whynot-design-npm-publish.hcl` |
|
||||
| OIDC auth mount | `netkingdom` |
|
||||
| OIDC role | `whynot-design-workload-kv-read` |
|
||||
| Kubernetes auth role | `whynot-design-workload-kv-read` if an in-cluster service account consumes this lane |
|
||||
| flex-auth ref | `secret.read:whynot-design` if tenant policy requires pre-approval |
|
||||
|
||||
Expected caller login shape:
|
||||
|
||||
```bash
|
||||
bao login -method=oidc -path=netkingdom role=whynot-design-workload-kv-read
|
||||
```
|
||||
|
||||
Expected fetch shape:
|
||||
|
||||
```bash
|
||||
bao kv get -field=NPM_AUTH_TOKEN platform/workloads/whynot-design/whynot-design/npm-publish
|
||||
```
|
||||
|
||||
The fetch command returns the secret value to the authenticated caller. Run it
|
||||
only in an attended shell or through a process that consumes the value without
|
||||
logging it.
|
||||
|
||||
## OpenBao Policy
|
||||
|
||||
The source policy grants only:
|
||||
|
||||
```text
|
||||
read platform/data/workloads/whynot-design/whynot-design/npm-publish
|
||||
read platform/metadata/workloads/whynot-design/whynot-design/npm-publish
|
||||
```
|
||||
|
||||
It does not grant write, delete, patch, sudo, auth, sibling workload, or parent
|
||||
list capabilities.
|
||||
|
||||
Dry-run the policy apply path:
|
||||
|
||||
```bash
|
||||
make openbao-workload-kv-lanes-dry-run
|
||||
```
|
||||
|
||||
Apply the policy with an approved platform-admin/operator token:
|
||||
|
||||
```bash
|
||||
OPENBAO_TOKEN_FILE=~/.local/openbao/platform-admin.token \
|
||||
make openbao-configure-workload-kv-lanes
|
||||
```
|
||||
|
||||
If the OpenBao pod has an approved token-helper session, use:
|
||||
|
||||
```bash
|
||||
make openbao-configure-workload-kv-lanes OPENBAO_WORKLOAD_KV_ARGS=--use-token-helper
|
||||
```
|
||||
|
||||
Do not paste the token into shell history or logs. The helper reads a token
|
||||
from `OPENBAO_TOKEN_FILE` or an interactive hidden prompt unless
|
||||
`--use-token-helper` is set, and passes it to OpenBao through stdin.
|
||||
|
||||
## Auth Role
|
||||
|
||||
The intended OpenBao OIDC role is:
|
||||
|
||||
```text
|
||||
auth/netkingdom/role/whynot-design-workload-kv-read
|
||||
```
|
||||
|
||||
The role must attach only:
|
||||
|
||||
```text
|
||||
workload-kv-read-whynot-design-npm-publish
|
||||
```
|
||||
|
||||
Before applying the role, confirm the KeyCape/NetKingdom claim that identifies
|
||||
the whynot-design caller. The role must bind to that claim; do not create an
|
||||
unbounded OIDC role that grants this policy to every OIDC user.
|
||||
|
||||
If the consumer is an in-cluster service account instead of an OIDC caller, use
|
||||
Kubernetes auth with the same role name and bind only the approved namespace
|
||||
and service account.
|
||||
|
||||
## Secret Provisioning
|
||||
|
||||
An approved operator must create or confirm the secret with:
|
||||
|
||||
```text
|
||||
path: platform/workloads/whynot-design/whynot-design/npm-publish
|
||||
field: NPM_AUTH_TOKEN
|
||||
```
|
||||
|
||||
The value must be entered directly through OpenBao/operator custody. Record only
|
||||
non-secret evidence: actor, timestamp, path, field name, policy name, and
|
||||
verification result.
|
||||
|
||||
## Verification
|
||||
|
||||
Positive verification:
|
||||
|
||||
1. Authenticate as the whynot-design caller using the approved OIDC or
|
||||
Kubernetes auth role.
|
||||
2. Fetch the field in an attended session or through `warden access --fetch`.
|
||||
3. Record only that the fetch succeeded; do not record the value.
|
||||
|
||||
Negative verification:
|
||||
|
||||
1. Authenticate as a non-whynot identity.
|
||||
2. Confirm the same field read is denied.
|
||||
3. Record the non-secret OpenBao audit request ids or timestamps for the
|
||||
allowed and denied attempts.
|
||||
|
||||
## ops-warden Handoff
|
||||
|
||||
Send ops-warden only these pointers:
|
||||
|
||||
```text
|
||||
catalog id: whynot-design-npm-token
|
||||
mount: platform
|
||||
path: platform/workloads/whynot-design/whynot-design/npm-publish
|
||||
field: NPM_AUTH_TOKEN
|
||||
oidc login: bao login -method=oidc -path=netkingdom role=whynot-design-workload-kv-read
|
||||
policy: workload-kv-read-whynot-design-npm-publish
|
||||
policy file: openbao/policies/workload-kv-read-whynot-design-npm-publish.hcl
|
||||
flex-auth ref: secret.read:whynot-design, if tenant policy requires it
|
||||
runbook: docs/workload-kv-access-lanes.md
|
||||
```
|
||||
|
||||
Until live provisioning and verification are complete, ops-warden should keep
|
||||
the catalog entry in `draft` or equivalent non-active state.
|
||||
@@ -0,0 +1,13 @@
|
||||
# Least-privilege read policy for the whynot-design npm publish token.
|
||||
#
|
||||
# This policy intentionally grants only read access to the single KV-v2 secret
|
||||
# path used by ops-warden's caller-scoped access lane. It does not grant list
|
||||
# access to sibling workloads or mutation capabilities.
|
||||
|
||||
path "platform/data/workloads/whynot-design/whynot-design/npm-publish" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
|
||||
path "platform/metadata/workloads/whynot-design/whynot-design/npm-publish" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
137
scripts/openbao-apply-workload-kv-lanes.sh
Executable file
137
scripts/openbao-apply-workload-kv-lanes.sh
Executable file
@@ -0,0 +1,137 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
OPENBAO_NAMESPACE="${OPENBAO_NAMESPACE:-openbao}"
|
||||
OPENBAO_RELEASE="${OPENBAO_RELEASE:-openbao}"
|
||||
KUBECTL="${KUBECTL:-kubectl}"
|
||||
TOKEN_FILE="${OPENBAO_TOKEN_FILE:-}"
|
||||
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
POLICY_NAME="${WORKLOAD_KV_POLICY_NAME:-workload-kv-read-whynot-design-npm-publish}"
|
||||
POLICY_FILE="${WORKLOAD_KV_POLICY_FILE:-$REPO_DIR/openbao/policies/workload-kv-read-whynot-design-npm-publish.hcl}"
|
||||
DRY_RUN=0
|
||||
USE_TOKEN_HELPER=0
|
||||
|
||||
usage() {
|
||||
cat <<'USAGE'
|
||||
Usage: scripts/openbao-apply-workload-kv-lanes.sh [--dry-run] [--use-token-helper]
|
||||
|
||||
Applies source-owned OpenBao workload KV read-lane policies.
|
||||
|
||||
Current lane:
|
||||
- policy: workload-kv-read-whynot-design-npm-publish
|
||||
- path: platform/workloads/whynot-design/whynot-design/npm-publish
|
||||
- field: NPM_AUTH_TOKEN
|
||||
|
||||
The script reads an OpenBao operator token from OPENBAO_TOKEN_FILE or an
|
||||
interactive hidden prompt unless --dry-run or --use-token-helper is set. It
|
||||
never prints or stores the token.
|
||||
|
||||
This script intentionally does not create an OIDC role until the whynot-design
|
||||
KeyCape/NetKingdom bound claim is confirmed.
|
||||
USAGE
|
||||
}
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--dry-run)
|
||||
DRY_RUN=1
|
||||
shift
|
||||
;;
|
||||
--use-token-helper)
|
||||
USE_TOKEN_HELPER=1
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: unknown argument: $1" >&2
|
||||
usage >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
pod="${OPENBAO_RELEASE}-0"
|
||||
|
||||
read_token() {
|
||||
if [ "$DRY_RUN" -eq 1 ] || [ "$USE_TOKEN_HELPER" -eq 1 ]; then
|
||||
return
|
||||
fi
|
||||
if [ -n "$TOKEN_FILE" ]; then
|
||||
if [ ! -f "$TOKEN_FILE" ]; then
|
||||
echo "ERROR: OPENBAO_TOKEN_FILE does not exist: $TOKEN_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
head -n 1 "$TOKEN_FILE"
|
||||
return
|
||||
fi
|
||||
|
||||
local token
|
||||
read -r -s -p "OpenBao token: " token
|
||||
printf '\n' >&2
|
||||
printf '%s\n' "$token"
|
||||
}
|
||||
|
||||
remote_bao() {
|
||||
local token="$1"
|
||||
shift
|
||||
if [ "$DRY_RUN" -eq 1 ]; then
|
||||
printf 'DRY-RUN: bao %s\n' "$*"
|
||||
return 0
|
||||
fi
|
||||
if [ "$USE_TOKEN_HELPER" -eq 1 ]; then
|
||||
# shellcheck disable=SC2086
|
||||
$KUBECTL exec -i -n "$OPENBAO_NAMESPACE" "$pod" -- bao "$@"
|
||||
return
|
||||
fi
|
||||
# shellcheck disable=SC2086
|
||||
printf '%s\n' "$token" | $KUBECTL exec -i -n "$OPENBAO_NAMESPACE" "$pod" -- \
|
||||
sh -c 'read -r BAO_TOKEN; export BAO_TOKEN; exec bao "$@"' sh "$@"
|
||||
}
|
||||
|
||||
write_policy() {
|
||||
local token="$1"
|
||||
if [ ! -f "$POLICY_FILE" ]; then
|
||||
echo "ERROR: missing policy file: $POLICY_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$DRY_RUN" -eq 1 ]; then
|
||||
printf 'DRY-RUN: bao policy write %s %s\n' "$POLICY_NAME" "$POLICY_FILE"
|
||||
return 0
|
||||
fi
|
||||
if [ "$USE_TOKEN_HELPER" -eq 1 ]; then
|
||||
# shellcheck disable=SC2086
|
||||
cat "$POLICY_FILE" | $KUBECTL exec -i -n "$OPENBAO_NAMESPACE" "$pod" -- \
|
||||
bao policy write "$POLICY_NAME" -
|
||||
return
|
||||
fi
|
||||
# shellcheck disable=SC2086
|
||||
{ printf '%s\n' "$token"; cat "$POLICY_FILE"; } | \
|
||||
$KUBECTL exec -i -n "$OPENBAO_NAMESPACE" "$pod" -- \
|
||||
sh -c 'read -r BAO_TOKEN; export BAO_TOKEN; bao policy write "$1" -' sh "$POLICY_NAME"
|
||||
}
|
||||
|
||||
token="$(read_token)"
|
||||
if [ "$DRY_RUN" -eq 0 ] && [ "$USE_TOKEN_HELPER" -eq 0 ] && [ -z "$token" ]; then
|
||||
echo "ERROR: empty OpenBao token" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
remote_bao "$token" status
|
||||
write_policy "$token"
|
||||
remote_bao "$token" policy read "$POLICY_NAME"
|
||||
|
||||
cat <<'NEXT'
|
||||
|
||||
Workload KV read-lane policy apply path completed.
|
||||
|
||||
Remaining live steps:
|
||||
1. Confirm the whynot-design KeyCape/NetKingdom bound claim or service account.
|
||||
2. Create auth/netkingdom/role/whynot-design-workload-kv-read with only the
|
||||
workload-kv-read-whynot-design-npm-publish policy.
|
||||
3. Provision platform/workloads/whynot-design/whynot-design/npm-publish with
|
||||
field NPM_AUTH_TOKEN through approved OpenBao/operator custody.
|
||||
4. Run positive and negative fetch verification without printing the token.
|
||||
NEXT
|
||||
298
workplans/RAILIANCE-WP-0006-workload-kv-access-lanes.md
Normal file
298
workplans/RAILIANCE-WP-0006-workload-kv-access-lanes.md
Normal file
@@ -0,0 +1,298 @@
|
||||
---
|
||||
id: RAILIANCE-WP-0006
|
||||
type: workplan
|
||||
title: "Workload KV Access Lanes for ops-warden Fetch"
|
||||
domain: financials
|
||||
repo: railiance-platform
|
||||
status: blocked
|
||||
owner: codex
|
||||
topic_slug: railiance
|
||||
planning_priority: high
|
||||
planning_order: 6
|
||||
created: "2026-06-27"
|
||||
updated: "2026-06-27"
|
||||
depends_on_workplans:
|
||||
- RAIL-PL-WP-0002
|
||||
- RAILIANCE-WP-0004
|
||||
related_state_hub_messages:
|
||||
- "551031d1-335e-4db8-9535-820fea52d0a3"
|
||||
state_hub_workstream_id: "96c8a93d-7a5a-4fa9-8f7b-865119551da3"
|
||||
---
|
||||
|
||||
# RAILIANCE-WP-0006 - Workload KV Access Lanes for ops-warden Fetch
|
||||
|
||||
## Goal
|
||||
|
||||
Provision concrete, least-privilege OpenBao workload KV read lanes that
|
||||
`ops-warden` can expose through `warden access --fetch` / `--exec` without
|
||||
holding secret values itself.
|
||||
|
||||
The immediate request is for `whynot-design` to retrieve its npm publish token.
|
||||
The path must be concrete, policy-scoped, and documented so the ops-warden
|
||||
catalog can replace the current unresolved template path with a live
|
||||
`whynot-design-npm-token` entry.
|
||||
|
||||
No task in this workplan may paste, commit, log, or send secret values through
|
||||
Git, State Hub, chat, prompts, or workplan text.
|
||||
|
||||
## Requirements Reviewed
|
||||
|
||||
Ops-warden message `551031d1-335e-4db8-9535-820fea52d0a3` asks
|
||||
`railiance-platform` to provide non-secret pointers for:
|
||||
|
||||
- a concrete OpenBao KV path and field for `NPM_AUTH_TOKEN`;
|
||||
- the KV mount used by the path;
|
||||
- the OIDC login role for whynot-design or its operator identity;
|
||||
- a read policy scoped to whynot-design's identity/service account;
|
||||
- the flex-auth policy reference, if pre-approval is required.
|
||||
|
||||
Once these pointers are live, ops-warden will add a dedicated
|
||||
`whynot-design-npm-token` access catalog entry and a playbook, then notify
|
||||
whynot-design.
|
||||
|
||||
## Proposed Contract
|
||||
|
||||
Use the existing workload convention documented in `docs/openbao.md` and
|
||||
`docs/argocd-gitops.md`:
|
||||
|
||||
```text
|
||||
platform/workloads/<namespace>/<service-account>/<secret-name>
|
||||
```
|
||||
|
||||
For this lane, the proposed non-secret contract is:
|
||||
|
||||
| Item | Proposed value |
|
||||
| --- | --- |
|
||||
| KV mount | `platform` |
|
||||
| CLI path | `platform/workloads/whynot-design/whynot-design/npm-publish` |
|
||||
| KV-v2 policy data path | `platform/data/workloads/whynot-design/whynot-design/npm-publish` |
|
||||
| KV-v2 policy metadata path | `platform/metadata/workloads/whynot-design/whynot-design/npm-publish` |
|
||||
| Secret field | `NPM_AUTH_TOKEN` |
|
||||
| OpenBao read policy | `workload-kv-read-whynot-design-npm-publish` |
|
||||
| OIDC auth mount | `netkingdom` unless KeyCape compatibility requires `keycape` |
|
||||
| OIDC role | `whynot-design-workload-kv-read` |
|
||||
| Kubernetes auth role | `whynot-design-workload-kv-read` if an in-cluster service account consumes it |
|
||||
| flex-auth ref | `secret.read:whynot-design` if tenant policy requires pre-approval |
|
||||
|
||||
The expected caller-facing read shape is:
|
||||
|
||||
```bash
|
||||
bao login -method=oidc -path=netkingdom role=whynot-design-workload-kv-read
|
||||
bao kv get -field=NPM_AUTH_TOKEN platform/workloads/whynot-design/whynot-design/npm-publish
|
||||
```
|
||||
|
||||
The command shape is illustrative only. Verification must avoid printing the
|
||||
secret value; use attended operator checks or commands that prove read access
|
||||
without persisting the token in logs.
|
||||
|
||||
## Tasks
|
||||
|
||||
## T01 - Capture ops-warden request and path contract
|
||||
|
||||
```task
|
||||
id: RAILIANCE-WP-0006-T01
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "0c93496a-48bf-44e7-a75b-52e51e2639bc"
|
||||
```
|
||||
|
||||
Record the ops-warden request, existing workload path convention, and proposed
|
||||
whynot-design contract in this workplan.
|
||||
|
||||
Acceptance:
|
||||
|
||||
- The workplan names the concrete path, field, mount, policy, auth role, and
|
||||
optional flex-auth ref needed by ops-warden.
|
||||
- The plan distinguishes non-secret pointers from secret values.
|
||||
- The plan keeps this workload KV read lane separate from
|
||||
`RAILIANCE-WP-0005`, which tracks short-lived OpenBao token issuance for the
|
||||
ops-warden signing smoke.
|
||||
|
||||
**2026-06-27:** Reviewed the unread ops-warden request and existing
|
||||
`platform/workloads/<namespace>/<service-account>/<secret-name>` convention.
|
||||
Captured the proposed `whynot-design` npm publish lane above with no secret
|
||||
values.
|
||||
|
||||
## T02 - Add least-privilege OpenBao read policy
|
||||
|
||||
```task
|
||||
id: RAILIANCE-WP-0006-T02
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "9c06d531-2566-4767-aa2f-8339605f23d5"
|
||||
```
|
||||
|
||||
Create a concrete policy artifact for the whynot-design npm publish lane,
|
||||
derived from `openbao/policies/workload-kv-read-template.hcl` but narrowed to
|
||||
the selected `npm-publish` path.
|
||||
|
||||
Acceptance:
|
||||
|
||||
- A policy file under `openbao/policies/` defines read access to the exact
|
||||
`platform/data/workloads/whynot-design/whynot-design/npm-publish` path.
|
||||
- Metadata/list capabilities are only as broad as needed for the caller and
|
||||
ops-warden fetch UX.
|
||||
- The policy grants no write, delete, patch, sudo, auth, or unrelated workload
|
||||
capabilities.
|
||||
- The policy name matches the pointer intended for ops-warden:
|
||||
`workload-kv-read-whynot-design-npm-publish`.
|
||||
|
||||
**2026-06-27:** Added the concrete policy artifact at
|
||||
`openbao/policies/workload-kv-read-whynot-design-npm-publish.hcl`. It grants
|
||||
only `read` on the exact KV-v2 data and metadata paths for
|
||||
`platform/workloads/whynot-design/whynot-design/npm-publish`; it does not grant
|
||||
write/delete/list/sudo/auth or sibling workload access. Added
|
||||
`scripts/openbao-apply-workload-kv-lanes.sh`,
|
||||
`make openbao-workload-kv-lanes-dry-run`, and
|
||||
`make openbao-configure-workload-kv-lanes` for the source-owned policy apply
|
||||
step. Dry-run passed. A live apply attempt with
|
||||
`OPENBAO_WORKLOAD_KV_ARGS=--use-token-helper` reached unsealed OpenBao but was
|
||||
denied with `403 permission denied` while writing the policy, so live policy
|
||||
application waits on an approved platform-admin/operator token or a narrow
|
||||
token-helper capability.
|
||||
|
||||
## T03 - Define and apply auth bindings
|
||||
|
||||
```task
|
||||
id: RAILIANCE-WP-0006-T03
|
||||
status: wait
|
||||
priority: high
|
||||
state_hub_task_id: "a217371a-0f85-40c6-b691-ac67834c86b5"
|
||||
```
|
||||
|
||||
Define the auth role that lets whynot-design or an approved operator identity
|
||||
read the lane as itself.
|
||||
|
||||
Acceptance:
|
||||
|
||||
- The OIDC login role is documented as
|
||||
`bao login -method=oidc -path=netkingdom role=whynot-design-workload-kv-read`,
|
||||
or a different approved role is recorded with the reason.
|
||||
- The role attaches only the whynot-design npm publish read policy.
|
||||
- If an in-cluster whynot-design service account consumes the token, the
|
||||
Kubernetes auth role binds only the approved namespace and service account.
|
||||
- Compatibility with the legacy `keycape` auth mount is either configured or
|
||||
explicitly declined.
|
||||
|
||||
**2026-06-27:** Documented the intended OIDC role pointer as
|
||||
`auth/netkingdom/role/whynot-design-workload-kv-read` in
|
||||
`docs/workload-kv-access-lanes.md`. Live application is waiting on confirmation
|
||||
of the KeyCape/NetKingdom whynot-design bound claim or approved service-account
|
||||
subject; do not create an unbounded OIDC role.
|
||||
|
||||
## T04 - Provision the KV path without exposing the token
|
||||
|
||||
```task
|
||||
id: RAILIANCE-WP-0006-T04
|
||||
status: wait
|
||||
priority: high
|
||||
state_hub_task_id: "c43724a3-c83e-4ab6-b7d1-e427fd93a9a9"
|
||||
```
|
||||
|
||||
Have an approved operator create or confirm the OpenBao KV entry for the npm
|
||||
publish token.
|
||||
|
||||
Acceptance:
|
||||
|
||||
- The path exists at
|
||||
`platform/workloads/whynot-design/whynot-design/npm-publish`.
|
||||
- The field is named exactly `NPM_AUTH_TOKEN`.
|
||||
- The token value is entered through an approved operator/OpenBao path and is
|
||||
never written to Git, State Hub, chat, prompts, shell history, or workplan
|
||||
text.
|
||||
- Non-secret evidence records only the path, field name, actor, timestamp,
|
||||
policy name, and verification result.
|
||||
|
||||
**2026-06-27:** The concrete path and field are now documented. Live secret
|
||||
provisioning is waiting on an approved operator/OpenBao custody path for the
|
||||
actual `NPM_AUTH_TOKEN` value.
|
||||
|
||||
## T05 - Verify caller-scoped fetch behavior
|
||||
|
||||
```task
|
||||
id: RAILIANCE-WP-0006-T05
|
||||
status: wait
|
||||
priority: high
|
||||
state_hub_task_id: "dc1f470b-e78a-48a9-9957-965aed47861f"
|
||||
```
|
||||
|
||||
Prove that the authorized identity can read the token through the intended
|
||||
OpenBao path and that unauthorized identities cannot.
|
||||
|
||||
Acceptance:
|
||||
|
||||
- An approved whynot-design identity or operator role can authenticate and
|
||||
perform the fetch without unresolved `<...>` placeholders.
|
||||
- Negative verification shows a non-whynot identity cannot read the path.
|
||||
- Verification output contains no token value.
|
||||
- OpenBao audit evidence exists for the authorized read and denied read, with
|
||||
only non-secret request ids/timestamps recorded in the workplan or State Hub.
|
||||
|
||||
**2026-06-27:** Verification is waiting on live policy/role application and
|
||||
secret provisioning. The runbook requires positive and negative fetch evidence
|
||||
without printing the token value.
|
||||
|
||||
## T06 - Coordinate ops-warden catalog activation
|
||||
|
||||
```task
|
||||
id: RAILIANCE-WP-0006-T06
|
||||
status: wait
|
||||
priority: high
|
||||
state_hub_task_id: "8e84ec19-01db-4baf-a532-de87e51d4994"
|
||||
```
|
||||
|
||||
Send ops-warden the non-secret pointers needed to create and activate its
|
||||
dedicated access catalog entry.
|
||||
|
||||
Acceptance:
|
||||
|
||||
- The State Hub reply to ops-warden includes only path, field, KV mount,
|
||||
OIDC role, policy name/path, optional flex-auth ref, and runbook location.
|
||||
- Ops-warden confirms the `whynot-design-npm-token` catalog entry no longer
|
||||
contains unresolved placeholders.
|
||||
- `warden access "npm auth token" --fetch` or the agreed exact selector resolves
|
||||
to the whynot-design lane and proxies the read as the caller.
|
||||
- ops-warden confirms it holds no token value and only proxies OpenBao access.
|
||||
|
||||
**2026-06-27:** Added `docs/workload-kv-access-lanes.md` with the non-secret
|
||||
handoff payload for ops-warden and sent the pointers by State Hub message. The
|
||||
entry should remain draft/non-active until live OpenBao provisioning and
|
||||
verification complete.
|
||||
|
||||
## T07 - Decide whether to batch sibling workload-KV requests
|
||||
|
||||
```task
|
||||
id: RAILIANCE-WP-0006-T07
|
||||
status: done
|
||||
priority: medium
|
||||
state_hub_task_id: "0b3ab5f5-e933-41f2-b29a-ab4ac50593aa"
|
||||
```
|
||||
|
||||
Ops-warden noted similar still-open access lanes for
|
||||
`issue-core-ingestion-api-key` and `openrouter-llm-connect`. Decide whether to
|
||||
batch those paths in the same provisioning pass or keep this workplan scoped to
|
||||
whynot-design.
|
||||
|
||||
Acceptance:
|
||||
|
||||
- The decision is recorded without secret values.
|
||||
- If batching is approved, add concrete sub-tasks or a follow-up workplan for
|
||||
each additional lane.
|
||||
- If batching is deferred, notify ops-warden that this workplan will deliver
|
||||
whynot-design first and leave the sibling entries for separate planning.
|
||||
|
||||
**2026-06-27:** Deferred sibling lanes (`issue-core-ingestion-api-key` and
|
||||
`openrouter-llm-connect`) so the whynot-design npm token request can be serviced
|
||||
first. They should get concrete tasks or a follow-up workplan after this access
|
||||
lane pattern is validated.
|
||||
|
||||
## Exit Criteria
|
||||
|
||||
- The whynot-design npm publish token has a concrete OpenBao KV path, field,
|
||||
read policy, and auth role.
|
||||
- The authorized caller can fetch the token as itself through OpenBao and
|
||||
ops-warden without ops-warden storing the value.
|
||||
- Unauthorized reads are denied.
|
||||
- ops-warden has enough non-secret pointers to activate
|
||||
`whynot-design-npm-token`.
|
||||
- No secret values appear in Git, State Hub, chat, prompts, logs, or workplans.
|
||||
@@ -0,0 +1,252 @@
|
||||
---
|
||||
id: RAILIANCE-WP-0007
|
||||
type: workplan
|
||||
title: "Credential Change Proposal Review Workflow"
|
||||
domain: financials
|
||||
repo: railiance-platform
|
||||
status: ready
|
||||
owner: codex
|
||||
topic_slug: railiance
|
||||
planning_priority: high
|
||||
planning_order: 7
|
||||
created: "2026-06-27"
|
||||
updated: "2026-06-27"
|
||||
depends_on_workplans:
|
||||
- RAIL-PL-WP-0002
|
||||
- RAILIANCE-WP-0005
|
||||
- RAILIANCE-WP-0006
|
||||
state_hub_workstream_id: "4d7ce243-f40a-4249-a46a-a24f75d6fe4c"
|
||||
---
|
||||
|
||||
# RAILIANCE-WP-0007 - Credential Change Proposal Review Workflow
|
||||
|
||||
## Goal
|
||||
|
||||
Create a proposal -> review -> approve/deny with comment -> apply -> verify
|
||||
workflow for credential and it-sec changes, so operators do not need to author
|
||||
or mentally validate raw OpenBao commands.
|
||||
|
||||
The first target is the whynot-design npm token lane from `RAILIANCE-WP-0006`.
|
||||
The workflow should then generalize to workload KV paths, OpenBao token roles,
|
||||
ops-warden access catalog entries, External Secrets lanes, credential rotation,
|
||||
deactivation, and compromise handling.
|
||||
|
||||
## Direction
|
||||
|
||||
Do not start by extending OpenBao. Instead, build a small approval control
|
||||
plane around OpenBao:
|
||||
|
||||
- OpenBao remains the enforcement, secret storage, token, and audit engine.
|
||||
- State Hub stores non-secret request lifecycle, comments, decisions, and
|
||||
evidence.
|
||||
- Repo files store reviewable non-secret request specs and generated policy
|
||||
artifacts.
|
||||
- Agents and CLIs create proposals and render them for human review.
|
||||
- Humans approve or deny with comments.
|
||||
- Only approved requests can be applied by an operator-controlled runner or
|
||||
interactive runbook.
|
||||
|
||||
If the workflow proves valuable, a later UI or OpenBao extension can surface the
|
||||
same request index and statuses.
|
||||
|
||||
## Proposed Object
|
||||
|
||||
Introduce a non-secret Credential Change Request, or `CCR`.
|
||||
|
||||
Each CCR captures:
|
||||
|
||||
- request id, title, requester, reviewer, approver, and applier;
|
||||
- target tenant/workload/environment/purpose;
|
||||
- OpenBao mount, path, fields, policies, auth roles, and bound claims;
|
||||
- access front door such as ops-warden, External Secrets, CSI, or direct caller
|
||||
fetch;
|
||||
- risk classification and approval requirements;
|
||||
- generated apply plan and verification plan;
|
||||
- rollback, deactivate, rotate, and compromise response plan;
|
||||
- comments, decision, timestamps, and non-secret audit evidence.
|
||||
|
||||
Each CCR explicitly excludes secret values, token values, private keys,
|
||||
passwords, unseal/recovery material, and secret-bearing command output.
|
||||
|
||||
## Tasks
|
||||
|
||||
## T01 - Record the approval workflow design
|
||||
|
||||
```task
|
||||
id: RAILIANCE-WP-0007-T01
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "c82ee783-80f1-48da-a9ed-4565eac699fc"
|
||||
```
|
||||
|
||||
Document the desired operator workflow and why it should sit around OpenBao
|
||||
rather than inside the OpenBao UI initially.
|
||||
|
||||
Acceptance:
|
||||
|
||||
- The design describes the proposal, review, approval/denial, apply, verify,
|
||||
activate, deactivate, rotate, and compromised states.
|
||||
- The design names where State Hub, OpenBao, ops-warden, repo files, agents,
|
||||
and interactive runbooks fit.
|
||||
- The design keeps secret values out of State Hub, Git, chat, and prompts.
|
||||
|
||||
**2026-06-27:** Added `docs/credential-change-approval.md` with the control
|
||||
plane direction, CCR object, state machine, State Hub/OpenBao/ops-warden roles,
|
||||
interactive runbook role, and compromise/deactivation path.
|
||||
|
||||
## T02 - Define the CCR schema and storage layout
|
||||
|
||||
```task
|
||||
id: RAILIANCE-WP-0007-T02
|
||||
status: todo
|
||||
priority: high
|
||||
state_hub_task_id: "d50fb9e2-68c2-4a2b-8476-ce646d13e60a"
|
||||
```
|
||||
|
||||
Create a versioned non-secret schema for credential change requests.
|
||||
|
||||
Acceptance:
|
||||
|
||||
- A schema exists for `workload-kv-read` requests covering mount, path, fields,
|
||||
policy name, auth role, bound claims, access front door, verification plan,
|
||||
and activation conditions.
|
||||
- The schema supports decision metadata: requested, proposed, approved,
|
||||
denied, needs_changes, applied, verified, active, deactivated, rotated,
|
||||
compromised, superseded, and cancelled.
|
||||
- The schema supports comments and references State Hub ids without storing
|
||||
secrets.
|
||||
- Example CCR fixtures include the whynot-design npm token lane.
|
||||
|
||||
## T03 - Add offline validation and rendering
|
||||
|
||||
```task
|
||||
id: RAILIANCE-WP-0007-T03
|
||||
status: todo
|
||||
priority: high
|
||||
state_hub_task_id: "012f05cd-30ce-43dd-802b-4acc938db133"
|
||||
```
|
||||
|
||||
Add a helper that validates CCR files and renders human review summaries.
|
||||
|
||||
Acceptance:
|
||||
|
||||
- Invalid CCRs fail before any OpenBao apply is attempted.
|
||||
- The renderer produces a compact review block that a human can understand in
|
||||
chat or State Hub.
|
||||
- The renderer highlights risky fields: broad claims, wildcard paths,
|
||||
privileged policies, missing negative verification, and missing deactivation
|
||||
plan.
|
||||
- A secret-pattern scan rejects likely token values in CCR files.
|
||||
|
||||
## T04 - Generate OpenBao apply plans from approved CCRs
|
||||
|
||||
```task
|
||||
id: RAILIANCE-WP-0007-T04
|
||||
status: todo
|
||||
priority: high
|
||||
state_hub_task_id: "1b2e7752-815c-46f8-a2e2-212e8d04da80"
|
||||
```
|
||||
|
||||
Generate deterministic, reviewable OpenBao apply plans from CCRs.
|
||||
|
||||
Acceptance:
|
||||
|
||||
- A workload KV CCR can generate policy HCL and auth-role commands or API
|
||||
payloads.
|
||||
- The plan includes a dry-run mode and a diff against existing source
|
||||
artifacts when available.
|
||||
- Applying a plan is refused unless the CCR is approved.
|
||||
- The applier uses an approved operator authority path and does not accept raw
|
||||
tokens in argv or logs.
|
||||
|
||||
## T05 - Add chat/CLI approval commands
|
||||
|
||||
```task
|
||||
id: RAILIANCE-WP-0007-T05
|
||||
status: todo
|
||||
priority: high
|
||||
state_hub_task_id: "e6d4d2d1-1881-4db7-92f8-05e3fdb846ae"
|
||||
```
|
||||
|
||||
Make the workflow usable from chat and command line.
|
||||
|
||||
Acceptance:
|
||||
|
||||
- Operators can approve, deny, or request changes with a comment.
|
||||
- Approvals/denials are recorded as non-secret State Hub events and in the CCR
|
||||
file or linked decision record.
|
||||
- The system refuses apply when the latest human decision is denied or
|
||||
needs_changes.
|
||||
- Agents can propose changes and respond to review comments without receiving
|
||||
secret values.
|
||||
|
||||
## T06 - Build an interactive runbook for apply and verify
|
||||
|
||||
```task
|
||||
id: RAILIANCE-WP-0007-T06
|
||||
status: todo
|
||||
priority: high
|
||||
state_hub_task_id: "3c3fc38c-afa4-4367-b3e6-ba4b286ced30"
|
||||
```
|
||||
|
||||
Wrap privileged application in an operator-friendly guided runbook.
|
||||
|
||||
Acceptance:
|
||||
|
||||
- The runbook loads an approved CCR, shows the plan, asks for final attended
|
||||
confirmation, then applies policy/auth metadata.
|
||||
- Secret value entry is handled through an approved OpenBao/operator path and
|
||||
is never echoed or logged.
|
||||
- Positive and negative verification steps are guided.
|
||||
- Non-secret evidence is recorded automatically.
|
||||
|
||||
## T07 - Pilot with whynot-design and ops-warden
|
||||
|
||||
```task
|
||||
id: RAILIANCE-WP-0007-T07
|
||||
status: todo
|
||||
priority: high
|
||||
state_hub_task_id: "07a7d8bf-5528-41c8-a791-d6ccd0466a33"
|
||||
```
|
||||
|
||||
Use the existing whynot-design npm token lane as the first end-to-end pilot.
|
||||
|
||||
Acceptance:
|
||||
|
||||
- The current whynot-design lane is represented as a CCR.
|
||||
- The CCR is rendered and reviewed in chat or State Hub.
|
||||
- A human approval or denial comment is recorded.
|
||||
- If approved, the runbook applies the policy/auth metadata, guides secret
|
||||
provisioning, verifies access, and notifies ops-warden.
|
||||
- ops-warden activates its catalog entry only after CCR verification.
|
||||
|
||||
## T08 - Add deactivation, rotation, and compromise flows
|
||||
|
||||
```task
|
||||
id: RAILIANCE-WP-0007-T08
|
||||
status: todo
|
||||
priority: medium
|
||||
state_hub_task_id: "23d6ef9d-8dbc-4468-b486-5ec8ada71130"
|
||||
```
|
||||
|
||||
Support lifecycle states beyond initial creation.
|
||||
|
||||
Acceptance:
|
||||
|
||||
- Existing credentials can be imported as CCR-backed inventory without secret
|
||||
values.
|
||||
- Operators can mark a lane deactivated, rotated, or compromised with reason
|
||||
and evidence.
|
||||
- Deactivation disables the relevant access front door and auth/policy path.
|
||||
- Compromise flow records blast-radius notes and required follow-up tasks.
|
||||
|
||||
## Exit Criteria
|
||||
|
||||
- A human can review and approve or deny a credential/security change without
|
||||
writing raw OpenBao commands.
|
||||
- An approved request can be applied by an operator-controlled helper or
|
||||
interactive runbook.
|
||||
- State Hub and repo artifacts contain non-secret lifecycle, decision, and
|
||||
evidence records.
|
||||
- OpenBao remains the enforcement and audit source for actual secret access.
|
||||
- The whynot-design npm token lane can complete through this workflow.
|
||||
Reference in New Issue
Block a user