2026-06-17 08:22:45 +02:00
# NetKingdom Security Map (ops-warden view)
Date: 2026-06-17
Condensed literacy guide for ops-warden stewards and development workers.
Canonical source remains `net-kingdom/docs/platform-identity-security-architecture.md` .
ops-warden **implements** the operational SSH lane and **documents** how the
other lanes connect.
---
## Planes
```text
Bootstrap plane railiance-infra, railiance-cluster, net-kingdom bootstrap
Platform control key-cape, flex-auth, OpenBao, Topaz, railiance-platform
Tenant plane railiance-apps, coulomb workloads, future tenants
Operational access ops-warden (SSH certs), ops-bridge (tunnels)
```
---
## Component map
| Component | Answers | Credential types | ops-warden |
| --- | --- | --- | --- |
| **key-cape** | Who are you? (lightweight IAM) | OIDC tokens, MFA | Route — do not issue |
| **Keycloak** | Who are you? (expanded IAM) | OIDC/SAML federation | Route — do not issue |
| **privacyIDEA** | MFA / step-up | OTP, hardware tokens | Route — do not issue |
| **flex-auth** | May you do this action? | Policy decisions, audit envelopes | Future SSH pre-sign; route today |
| **Topaz** | PDP runtime for flex-auth | Authorization evaluations | Route — do not issue |
| **OpenBao** | Runtime secret authority | API keys, DB creds, leases, K8s auth | SSH engine **signing backend** only |
| **ops-warden** | SSH ops access | Short-lived SSH certificates | **Own and issue** |
| **ops-bridge** | Tunnel transport | Uses certs via cert_command | Consumer |
| **railiance-infra** | Host enforcement | auth_principals, sshd | Route — deploy hosts |
| **railiance-platform** | Platform deploy | OpenBao, Postgres, ingress | Route — do not deploy from warden |
---
## Credential lanes (summary)
| Lane | Owner | Lifetime | Worker entrypoint |
| --- | --- | --- | --- |
| Identity | key-cape / Keycloak | Session / token TTL | Login / OIDC |
| Authorization | flex-auth | Per request | Policy API / embedded PEP |
| Runtime secrets | OpenBao | Lease-bound | `bao` CLI, K8s ESO, app integration |
| SSH operational | ops-warden | adm 48h / agt 24h / atm 8h | `warden sign` |
| Tunnel | ops-bridge | Session | `bridge` + cert_command |
Full routing: `wiki/CredentialRouting.md` .
---
## Trust flow (simplified)
```text
Worker request
-> Identity? key-cape / Keycloak
-> Authorized? flex-auth
-> Secret material? OpenBao
-> SSH cert? ops-warden
-> Tunnel? ops-bridge (cert from warden)
-> Host accepts? railiance-infra principals
```
OpenBao does **not** replace identity or authorization. flex-auth decides;
OpenBao stores/issues; ops-warden signs SSH certs when host reachability is
the need.
---
Answer flex-auth caller-auth question; refresh two delegation lanes
Inbox triage (ADHOC-2026-08-17), three messages, all answered and marked read.
flex-auth (FLEX-WP-0015 T02) reported that /v1/check and /v1/batch_check
authenticate no caller — any workload with cluster reach can assert any subject
and get an authoritative allow. It lands here because ops-warden owns workload
identity in this estate and its pre-sign gate is a flex-auth PEP.
Recommendation recorded in wiki/NetKingdomSecurityMap.md: Kubernetes
ServiceAccount TokenReview with a projected, audience-scoped token. Rejected the
shared-secret header — it manufactures a risk: high lane with a rotation owner
per caller on the authorization path, the exact interim-proxy debt WP-0030
exists to stop growing. Deferred mTLS pending an owner for a workload X.509 CA.
Bind `system` to the authenticated SA at auth time, but keep the resource-type
allowlist in the policy package rather than the admission layer. Warn-only
rollout; policy.enabled must not flip while /v1/check answers unauthenticated
callers. Recorded as a pattern, not a catalog entry.
Catalog delegation refreshes:
- coulomb-social-runtime-env: USER_ENGINE_PROXY_SECRET ownership settled
(decision 8fe22037, USER-WP-0021) — intended_owner stays railiance-apps,
answered clause dropped from blocked_on, consumers: [user-engine] recorded.
- rapp-qonto-keycape-client: blocked_on no longer implies an in-flight
KEY-WP-0008 dependency; the key-cape-native exchange command is unopened work.
uv run pytest -q → 338 passed, 4 deselected.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 22:55:33 +02:00
## Service-to-service caller authentication (in-cluster)
**Status:** recommended pattern, 2026-08-17. Raised by flex-auth (FLEX-WP-0015 T02):
`POST /v1/check` and `/v1/batch_check` authenticate no caller, so any workload with
network reach can assert any subject and receive an authoritative allow.
**There is no prior estate pattern for this.** What exists covers adjacent needs and
none of them covers in-cluster service→service HTTP:
| Existing mechanism | What it authenticates | Why it does not apply |
| --- | --- | --- |
| ops-warden SSH certificates | `adm` /`agt` /`atm` actors to hosts | Host reachability, not an HTTP call between pods |
| KeyCape `client_credentials` | Workload OIDC clients (`rapp-qonto-keycape-client` ) | Needs a client secret per caller — a custodied lane per consumer |
| OpenBao AppRole | Host-standing non-interactive workers | `role_id` +`secret_id` on disk; the WP-0030 register already flags AppRole as having **no owner front door** for minting or rotating |
### Recommendation: Kubernetes ServiceAccount TokenReview
Use the caller's **projected** ServiceAccount token with an explicit `audience`
(e.g. `flex-auth` ); the callee verifies it via `TokenReview` .
Why this and not the alternatives:
- **It introduces no new secret material.** A shared-secret header (flex-auth's
option (c)) would immediately become a `risk: high` credential lane with a
rotation owner, per calling system, on the authorization path — precisely the
interim-proxy debt the WP-0030 delegation register exists to stop growing.
ops-warden would end up fronting it.
- **It matches the estate's short-lived-credential doctrine.** A projected,
audience-scoped SA token has the same shape as `warden sign` output: bounded TTL,
issued by an authority, verified on use, never stored.
- **mTLS (option (b)) is the stronger end state but has no owner.** It requires an
X.509 workload CA, and no component owns one today — ops-warden issues SSH
certificates, not workload X.509. Adopting mTLS means first answering *who owns
the workload CA*, which is a permanent-ownership question, not a rollout task.
Record it as future direction; do not block on it.
Implementation notes that matter:
- Use a **projected token volume with an explicit `audience`** , not the legacy
automount token. Keep `automountServiceAccountToken: false` and add the projected
volume per Deployment. An audience-scoped token stolen from a pod cannot be
replayed against the kube-apiserver or another service.
### Authenticate *and* bind — but keep policy in the policy engine
Bind the `system` asserted in the request to the authenticated ServiceAccount and
reject a mismatch. That is identity binding, not authorization: it is cheap and it
costs nothing extra when a new consumer arrives, since a caller must have a mapping
regardless.
Do **not** put a caller allowlist for resource types ("only ops-warden may ask about
`ssh-certificate` ") in the authentication middleware. flex-auth is the estate's
policy engine; encoding that rule in its own admission layer puts authorization in
two places, where only one of them is reviewable and versioned. Express it in the
policy package.
### Rollout
Warn-only first, then fail-closed. ops-warden adopts the calling side on its own
schedule rather than in lockstep. The binding condition is sequencing, not a date:
```text
flex-auth warn-only -> ops-warden pre-sign gate presents its SA token
-> logs clean of unauthenticated callers
-> flex-auth fail-closed
2026-08-22 15:36:37 +02:00
-> zone-specific enforce stance (flex-auth policy package)
Answer flex-auth caller-auth question; refresh two delegation lanes
Inbox triage (ADHOC-2026-08-17), three messages, all answered and marked read.
flex-auth (FLEX-WP-0015 T02) reported that /v1/check and /v1/batch_check
authenticate no caller — any workload with cluster reach can assert any subject
and get an authoritative allow. It lands here because ops-warden owns workload
identity in this estate and its pre-sign gate is a flex-auth PEP.
Recommendation recorded in wiki/NetKingdomSecurityMap.md: Kubernetes
ServiceAccount TokenReview with a projected, audience-scoped token. Rejected the
shared-secret header — it manufactures a risk: high lane with a rotation owner
per caller on the authorization path, the exact interim-proxy debt WP-0030
exists to stop growing. Deferred mTLS pending an owner for a workload X.509 CA.
Bind `system` to the authenticated SA at auth time, but keep the resource-type
allowlist in the policy package rather than the admission layer. Warn-only
rollout; policy.enabled must not flip while /v1/check answers unauthenticated
callers. Recorded as a pattern, not a catalog entry.
Catalog delegation refreshes:
- coulomb-social-runtime-env: USER_ENGINE_PROXY_SECRET ownership settled
(decision 8fe22037, USER-WP-0021) — intended_owner stays railiance-apps,
answered clause dropped from blocked_on, consumers: [user-engine] recorded.
- rapp-qonto-keycape-client: blocked_on no longer implies an in-flight
KEY-WP-0008 dependency; the key-cape-native exchange command is unopened work.
uv run pytest -q → 338 passed, 4 deselected.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 22:55:33 +02:00
```
2026-08-22 15:36:37 +02:00
An enforce stance must not be assigned while `/v1/check` still answers
unauthenticated callers. ops-warden has no global enable switch or gate bypass;
it applies the compiled zone stance and its local per-zone failure mode.
Answer flex-auth caller-auth question; refresh two delegation lanes
Inbox triage (ADHOC-2026-08-17), three messages, all answered and marked read.
flex-auth (FLEX-WP-0015 T02) reported that /v1/check and /v1/batch_check
authenticate no caller — any workload with cluster reach can assert any subject
and get an authoritative allow. It lands here because ops-warden owns workload
identity in this estate and its pre-sign gate is a flex-auth PEP.
Recommendation recorded in wiki/NetKingdomSecurityMap.md: Kubernetes
ServiceAccount TokenReview with a projected, audience-scoped token. Rejected the
shared-secret header — it manufactures a risk: high lane with a rotation owner
per caller on the authorization path, the exact interim-proxy debt WP-0030
exists to stop growing. Deferred mTLS pending an owner for a workload X.509 CA.
Bind `system` to the authenticated SA at auth time, but keep the resource-type
allowlist in the policy package rather than the admission layer. Warn-only
rollout; policy.enabled must not flip while /v1/check answers unauthenticated
callers. Recorded as a pattern, not a catalog entry.
Catalog delegation refreshes:
- coulomb-social-runtime-env: USER_ENGINE_PROXY_SECRET ownership settled
(decision 8fe22037, USER-WP-0021) — intended_owner stays railiance-apps,
answered clause dropped from blocked_on, consumers: [user-engine] recorded.
- rapp-qonto-keycape-client: blocked_on no longer implies an in-flight
KEY-WP-0008 dependency; the key-cape-native exchange command is unopened work.
uv run pytest -q → 338 passed, 4 deselected.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 22:55:33 +02:00
**Division of the call:** the mechanism above is an architecture recommendation and
ops-warden's to make. Accepting the pod-spec change and the rollout timing are the
operator's.
This is a *pattern* , not a credential lane, so it gets no `registry/routing/catalog.yaml`
entry — the catalog indexes credential needs and their owners.
---
2026-06-17 08:22:45 +02:00
## NetKingdom documents to watch
| Document | Why ops-warden cares |
| --- | --- |
| `platform-identity-security-architecture.md` | Planes, secret path, SSH path |
| `responsibility-map.md` | Operational SSH dependency section |
| `platform-identity-security-architecture.md` | Operational SSH Path section |
| `platform-root-custody.md` | OpenBao ceremony — not warden's job |
| `object-storage-sts-credential-vending.md` | S3 creds — never warden |
| `canon/standards/iam-profile_v0.2.md` | Claims for future policy-gated sign |
When these change, update ops-warden wiki and `wiki/CredentialRouting.md` .
---
## Recursive platform rule
Tenant admins (including `tenant:coulomb` ) must not gain platform-root
authority. ops-warden SSH actors should use **narrow principals** for agent
and automation work — not platform-admin equivalents on hosts.
---
## See also
- `INTENT.md`
2026-06-18 20:44:53 +02:00
- `wiki/AccessRouting.md` — issue-vs-route role and boundary
2026-06-17 08:22:45 +02:00
- `wiki/CredentialRouting.md`
- `wiki/PolicyGatedSigning.md` (future flex-auth hook)
2026-08-22 15:36:37 +02:00
- `net-kingdom/docs/platform-identity-security-architecture.md`