ops-warden/wiki/NetKingdomSecurityMap.md
tegwick 7ce58ae638
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
feat: adopt security zones and explicit workload refs
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a0291a-1e87-7151-9934-fcbfe3f65eb1
2026-08-22 15:36:37 +02:00

7.9 KiB

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

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)

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.


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:

flex-auth warn-only  ->  ops-warden pre-sign gate presents its SA token
                     ->  logs clean of unauthenticated callers
                     ->  flex-auth fail-closed
                     ->  zone-specific enforce stance (flex-auth policy package)

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.

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.


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
  • wiki/AccessRouting.md — issue-vs-route role and boundary
  • wiki/CredentialRouting.md
  • wiki/PolicyGatedSigning.md (future flex-auth hook)
  • net-kingdom/docs/platform-identity-security-architecture.md