Complete user-engine runtime custody
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

This commit is contained in:
tegwick 2026-07-30 00:40:43 +02:00
parent a0bfb9c597
commit 39b71d6d96
5 changed files with 150 additions and 10 deletions

View file

@ -53,7 +53,7 @@
| task | NK-WP-0023-T02 | done | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |
| task | NK-WP-0023-T03 | done | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |
| task | NK-WP-0023-T04 | wait | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |
| task | NK-WP-0023-T05 | progress | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |
| task | NK-WP-0023-T05 | done | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |
| task | NK-WP-0023-T06 | wait | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |
| task | NK-WP-0023-T07 | done | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |
| task | NK-WP-0023-T08 | done | — | workplans/NK-WP-0023-user-engine-portal-platform-integration.md |

View file

@ -8,12 +8,20 @@
"identity_provisioner_registry_public_read": true,
"metrics_authorized": true,
"metrics_unauthorized_denied": true,
"openbao_exact_path_read": true,
"openbao_sibling_path_denied": true,
"openbao_runtime_authoritative": true,
"restore_drill_complete": true,
"restore_migration_rows": 1,
"restore_public_tables": 4,
"rollback_exercised": true,
"rollforward_restored": true,
"user_engine_offsite_age_upload": true,
"runtime_rotation_rehearsed": true,
"runtime_externalsecrets_ready": 3,
"runtime_deployments_ready_after_rotation": 2,
"provisioner_derived_tokens_equal": true,
"post_rotation_identity_reconciliation": true,
"user_engine_registry_public_read": true
},
"declared_image": "forgejo.coulomb.social/coulomb/user-engine@sha256:60f4fa1c144c8f7b9e2e74c264e4594e63ac6a0c0f75e5cf536880b8fd99fa28",

View file

@ -13,10 +13,13 @@ package read was verified without an image pull Secret; publishing still uses
the ExternalSecret-backed credential and temporary client state.
The CloudNativePG operator creates `user-engine-pg-app`, including its `uri`
field. `user-engine-runtime` contains only the generated edge marker and must
be replaced by an ExternalSecret before public exposure.
field. OpenBao is authoritative for the portal edge marker and provisioner
service token at `platform/workloads/user-engine/runtime`. The
`openbao-runtime.yaml` stores and ExternalSecrets deliver those values into the
existing namespaced Secret names without changing application interfaces.
```bash
kubectl apply -f openbao-runtime.yaml
kubectl apply -f runtime.yaml
kubectl -n user-engine rollout status deployment/user-engine
kubectl -n user-engine get cluster,pod,service,networkpolicy

View file

@ -0,0 +1,122 @@
apiVersion: external-secrets.io/v1
kind: ClusterSecretStore
metadata:
name: openbao-user-engine-runtime
labels:
app.kubernetes.io/part-of: net-kingdom-sso-mfa
net-kingdom/component: secret-delivery
spec:
conditions:
- namespaces: [user-engine]
provider:
vault:
server: https://bao.coulomb.social
path: platform
version: v2
auth:
appRole:
path: approle
roleRef:
name: openbao-user-engine-runtime-approle
namespace: external-secrets
key: role-id
secretRef:
name: openbao-user-engine-runtime-approle
namespace: external-secrets
key: secret-id
---
apiVersion: external-secrets.io/v1
kind: ClusterSecretStore
metadata:
name: openbao-sso-user-engine-runtime
labels:
app.kubernetes.io/part-of: net-kingdom-sso-mfa
net-kingdom/component: secret-delivery
spec:
conditions:
- namespaces: [sso]
provider:
vault:
server: https://bao.coulomb.social
path: platform
version: v2
auth:
appRole:
path: approle
roleRef:
name: openbao-sso-user-engine-runtime-approle
namespace: external-secrets
key: role-id
secretRef:
name: openbao-sso-user-engine-runtime-approle
namespace: external-secrets
key: secret-id
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: user-engine-runtime
namespace: user-engine
labels:
app.kubernetes.io/name: user-engine
app.kubernetes.io/part-of: user-engine
spec:
refreshInterval: 5m
secretStoreRef:
kind: ClusterSecretStore
name: openbao-user-engine-runtime
target:
name: user-engine-runtime
creationPolicy: Merge
deletionPolicy: Retain
data:
- secretKey: proxy-secret
remoteRef:
key: workloads/user-engine/runtime
property: PROXY_SECRET
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: identity-provisioner-client
namespace: user-engine
labels:
app.kubernetes.io/name: user-engine
app.kubernetes.io/part-of: user-engine
spec:
refreshInterval: 5m
secretStoreRef:
kind: ClusterSecretStore
name: openbao-user-engine-runtime
target:
name: identity-provisioner-client
creationPolicy: Merge
deletionPolicy: Retain
data:
- secretKey: token
remoteRef:
key: workloads/user-engine/runtime
property: PROVISIONER_TOKEN
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: identity-provisioner-token
namespace: sso
labels:
app.kubernetes.io/name: identity-provisioner
app.kubernetes.io/part-of: net-kingdom-sso-mfa
spec:
refreshInterval: 5m
secretStoreRef:
kind: ClusterSecretStore
name: openbao-sso-user-engine-runtime
target:
name: identity-provisioner-token
creationPolicy: Merge
deletionPolicy: Retain
data:
- secretKey: token
remoteRef:
key: workloads/user-engine/runtime
property: PROVISIONER_TOKEN

View file

@ -8,7 +8,7 @@ status: active
owner: codex
topic_slug: netkingdom
created: "2026-07-27"
updated: "2026-07-28"
updated: "2026-07-30"
depends_on:
- USER-WP-0020
- KEY-WP-0004
@ -153,7 +153,7 @@ delivery with replay and dead-letter evidence.
```task
id: NK-WP-0023-T05
status: progress
status: done
priority: high
state_hub_task_id: "4ef00e05-1259-4c76-a8ef-ec40b5facd1c"
```
@ -207,11 +207,18 @@ Nextcloud custody. The plaintext dump was removed immediately and only
non-secret sizes and the artifact name were recorded. The local isolated
restore drill already proves the same logical dump/restore path.
The final T05 custody residual is narrower: `user-engine-runtime/proxy-secret`
and `identity-provisioner-client/token` remain bootstrap Kubernetes Secrets.
They must move to an OpenBao-owned path plus ExternalSecret and a rotation
procedure. Creating that new write/custody lane requires the ops-mason
executive approval gate; registry and backup work do not remain open.
2026-07-30 completion: the approved ops-mason construction plan established
the exact OpenBao KV path `platform/workloads/user-engine/runtime`, an
exact-path read policy, and separate bounded AppRoles for the `user-engine`
and `sso` External Secrets consumers. Namespace-restricted stores and three
ExternalSecrets preserve the existing application Secret interfaces.
A coordinated rotation rehearsal changed both runtime values at the
authoritative path, waited for all three derived Secrets to converge, and
returned both Deployments to Ready. Post-rotation checks proved matching
provisioner tokens, exact-path `read`, sibling-path `deny`, and a complete
disposable provision/drift/reconcile/deprovision lifecycle. No credential
value entered recorded output. All T05 acceptance criteria are complete.
## T06 - Prove role-scoped administration and failure safety