2026-06-17 08:22:45 +02:00
# Credential Routing — NetKingdom Access Desk
Date: 2026-06-17
Use this page when a development worker (human, kaizen agent, CI job, or
custodian tool) needs **access or credentials** and is unsure which subsystem
owns the request.
2026-06-27 18:22:09 +02:00
ops-warden maintains this routing guide. It **issues SSH certificates directly** .
For every other credential type, use the routed owner path. `warden access` may
also **assist** : it renders the owner, auth method, path, and command shape and,
for `exec_capable` catalog lanes, can proxy the owner's tool **as the caller** .
That is a transparent conduit, not custody: do not paste secrets into Git,
State Hub, agent chat, or workplans.
2026-06-17 08:22:45 +02:00
---
## Quick decision tree
```text
What do you need?
|
+-- Log in as a human / get OIDC claims / MFA
| -> key-cape (lightweight) or Keycloak (expanded)
| net-kingdom/docs/platform-identity-security-architecture.md
|
+-- Permission to perform an action on a resource
| -> flex-auth (policy decision)
| flex-auth/INTENT.md
|
+-- API key, DB password, provider token, K8s secret, dynamic lease
| -> OpenBao (after flex-auth approval where policy requires it)
| railiance-platform/docs/openbao.md
2026-06-27 18:22:09 +02:00
| NEVER ops-warden as owner or store
2026-06-17 08:22:45 +02:00
|
+-- S3 / object-storage temporary credentials
| -> NK-WP-0007 vending path (flex-auth + OpenBao + storage STS)
| net-kingdom/docs/object-storage-sts-credential-vending.md
2026-06-27 18:22:09 +02:00
| NEVER ops-warden as owner or store
2026-06-17 08:22:45 +02:00
|
+-- SSH certificate for host / ops reachability (adm/agt/atm)
| -> ops-warden (warden sign / cert_command)
| wiki/OpsWardenConfig.md
|
+-- SSH tunnel / port forward (already have or will get a cert)
| -> ops-bridge
| ops-bridge tunnels.yaml + cert_command from ops-warden
|
+-- Host accepts your SSH principal / force-command on server
| -> railiance-infra Ansible
| /etc/ssh/auth_principals/, sshd hardening
```
**Under two minutes:** match your need to a branch above, open the linked doc,
2026-06-27 18:22:09 +02:00
and treat non-SSH branches as owner-routed work. `warden access` can advise or
proxy an `exec_capable` lane, but it does not make ops-warden the owner of the value.
2026-06-17 08:22:45 +02:00
---
## Routing table
| I need… | Subsystem | ops-warden role |
| --- | --- | --- |
2026-06-27 18:22:09 +02:00
| Interactive login, OIDC token, MFA | key-cape / Keycloak | Assist: advise; proxy the `login` lane when the catalog entry is `exec_capable` |
| "May I do X on resource Y?" | flex-auth (+ Topaz PDP) | Route; policy gate for SSH/access proxies where configured |
| OpenRouter / LLM provider API key | OpenBao → K8s Secret | Assist: route; proxy only as caller when the catalog lane is `exec_capable` |
| Inter-Hub operator / runtime API key | OpenBao or `0600` temp file | Assist: route/custody notes; see `wiki/InterHubBootstrapAccessLane.md` |
| Database or service password | OpenBao dynamic/KV | Assist: route; proxy only as caller when the catalog lane is `exec_capable` |
2026-06-17 08:22:45 +02:00
| Short-lived SSH cert for operator | ops-warden (`adm-*` ) | **Issue** via `warden sign` |
| Short-lived SSH cert for agent | ops-warden (`agt-*` ) | **Issue** via `warden sign` / wrapper |
| Short-lived SSH cert for CI/cron | ops-warden (`atm-*` ) | **Issue** via `warden sign` / `warden issue` |
| Tunnel to remote service | ops-bridge | Consumer of `cert_command` |
| Principal file on host | railiance-infra | Document only |
---
2026-06-18 20:44:53 +02:00
## Routing catalog index
These needs are also carried in the machine-readable pointer catalog
(`registry/routing/catalog.yaml` , surfaced via `warden route` — WARDEN-WP-0011).
2026-06-27 18:22:09 +02:00
The catalog is a **pointer-and-assist layer** : it names the owner, links the doc,
and carries secret-free handoff templates for `warden access` . Only the SSH row is
something ops-warden executes with its own authority. Non-SSH `exec_capable` rows
2026-08-15 20:54:58 +02:00
run the owner's tool as the caller and preserve owner custody. Every execution
position is classified `permanent` / `native` / `interim` (`warden route gaps`
lists the interim set — WARDEN-WP-0030).
2026-06-18 20:44:53 +02:00
| Catalog `id` | What ops-warden answers | What the worker does next |
| --- | --- | --- |
| `ssh-cert-host-access` | **Issues** the cert (`warden sign` ) | Use the cert / wire it into `cert_command` |
2026-07-01 23:16:38 +02:00
| `ops-warden-warden-sign-token` | "railiance-platform broker owns the `warden-sign` lease — use `credential exec` " | `railiance-platform/scripts/credential.py exec --grant ops-warden/warden-sign` (see playbook) |
2026-06-27 18:22:09 +02:00
| `openbao-api-key` | "OpenBao owns this — here is the path/command shape" | Call OpenBao directly, or use `warden access --fetch/--exec` as yourself when the lane is `exec_capable` |
2026-08-22 19:08:21 +02:00
| `openbao-platform-admin-login` | "This is an attended OpenBao administration identity act, not workload secret retrieval" | Use KeyCape-backed OIDC/MFA at `auth/netkingdom` , role `platform-admin` ; never substitute a workload role or root token |
2026-08-22 20:54:45 +02:00
| `openbao-shamir-recovery-ceremony` | "This is an attended trust-root ceremony, not secret provisioning" | Obtain one explicit approval and follow the railiance-platform recovery checklist with the existing out-of-band custodians; never send shares through Warden |
2026-06-18 20:44:53 +02:00
| `flex-auth-policy-check` | "flex-auth decides — here is the policy doc" | Query flex-auth / embed the PEP |
2026-06-27 18:22:09 +02:00
| `key-cape-oidc-login` | "key-cape / Keycloak owns identity" | Authenticate via IAM Profile, or use the `warden access` login lane as yourself |
2026-06-18 20:44:53 +02:00
| `ops-bridge-tunnel` | "ops-bridge owns transport — supply a `cert_command` " | Open the tunnel with ops-bridge |
| `railiance-infra-principals` | "railiance-infra deploys host principals" | Run the infra Ansible |
2026-06-18 22:34:59 +02:00
| `activity-core-issue-sink` | "activity-core + issue-core own emission — pair `ISSUE_CORE_*` env vars" | See `wiki/playbooks/activity-core-issue-sink.md` |
2026-06-25 10:27:23 +02:00
| `inter-hub-bootstrap-ssh` | "Inter-Hub bootstrap SSH envelope — attended vs unattended branches" | See `wiki/InterHubBootstrapAccessLane.md` |
2026-07-02 20:48:39 +02:00
| `issue-core-ingestion-api-key` | "railiance-platform OpenBao KV + ESO deliver `ISSUE_CORE_API_KEY` — here is the path" | ESO consumes in-cluster; `warden access issue-core-ingestion-api-key --fetch ISSUE_CORE_API_KEY` as yourself |
2026-07-16 23:26:26 +02:00
| `openrouter-llm-connect` | "railiance-platform OpenBao KV + ESO deliver `OPENROUTER_API_KEY` to activity-core" | ESO consumes in-cluster; `warden access openrouter-llm-connect --fetch OPENROUTER_API_KEY` as yourself (`risk: high` ) |
2026-07-07 22:38:45 +02:00
| `reuse-surface-hub-write-token` | "railiance-platform OpenBao KV + ESO deliver `REUSE_SURFACE_TOKEN` to reuse-surface" | ESO consumes in-cluster; `warden access reuse-surface-hub-write-token --fetch` as yourself |
2026-07-16 23:26:26 +02:00
| `railiance-backup-offsite-lane` | "railiance-platform OpenBao KV for Nextcloud WebDAV + age recovery" | `warden access railiance-backup-offsite-lane --out FILE` (`risk: high` ; agents: no raw stream) |
| `forgejo-admin-api-token` | "railiance-platform OpenBao KV for Forgejo admin PAT" | `warden access forgejo-admin-api-token --out FILE` (`risk: high` ) |
2026-07-17 00:33:20 +02:00
| `binky-company-email-imap` | "tenant IMAP on `tenants/binky/company-email/imap` (IONOS)" | `warden access binky-company-email-imap --out FILE` (`risk: high` ) |
2026-07-21 21:42:10 +02:00
| `binky-qonto-api` | "tenant Qonto API on `tenants/binky/qonto-api` (API_KEY+API_USER)" | `warden access binky-qonto-api --out FILE` (`risk: high` ) |
2026-08-23 21:43:12 +02:00
| `net-kingdom-lldap-bind-credential` | "railiance-platform custody for the LLDAP bind credential used by identity-provisioner and the privacyIDEA resolver" | Follow the owner-approved NetKingdom reconciliation runbook; lane is currently unresolved and never fetches a value |
| `net-kingdom-privacyidea-admin-token` | "railiance-platform custody for the privacyIDEA administrative token used by attended resolver reconciliation" | Follow the owner-approved NetKingdom reconciliation runbook; lane is currently unresolved and never fetches a value |
2026-06-25 10:27:23 +02:00
2026-07-16 23:26:26 +02:00
Promotion criteria: `wiki/playbooks/catalog-lane-promotion.md` .
High-risk / agent boundary: `wiki/playbooks/agent-read-boundary.md` .
2026-07-17 00:09:28 +02:00
EXPOSED taint: `wiki/playbooks/exposed-taint.md` · `warden taint <id>` .
**Tenant secrets:** mount `tenants/` — path `tenants/<tenant>/<workload>/<bundle>`
(see `wiki/playbooks/tenant-secret-onboarding.md` , WARDEN-WP-0028). Not under
`platform/workloads/` .
2026-07-01 23:32:38 +02:00
2026-06-25 10:27:23 +02:00
**Draft** (hidden from default lookup until owner path ships — `warden route list --all` ):
| Catalog `id` | Routing focus | Playbook |
| --- | --- | --- |
| `object-storage-sts` | NK-WP-0007 STS vending path | `wiki/playbooks/object-storage-sts.md` |
| `database-dynamic-credentials` | OpenBao database secrets engine | `wiki/playbooks/database-dynamic-credentials.md` |
2026-06-18 20:44:53 +02:00
2026-06-27 18:22:09 +02:00
ops-warden answers *where + who + how* . The worker still acts on the owning system.
When `warden access` proxies a non-SSH lane, it does so as the caller and stores no
value; the owner remains OpenBao, key-cape, flex-auth, or the routed subsystem.
2026-06-18 20:44:53 +02:00
---
2026-06-27 18:22:09 +02:00
## Examples — do NOT ask ops-warden to own or vend
2026-06-17 08:22:45 +02:00
| Request | Correct path |
| --- | --- |
2026-07-01 23:16:38 +02:00
| "`VAULT_TOKEN` for ops-warden production sign / policy-gate smoke" | `railiance-platform` credential broker — `warden route show ops-warden-warden-sign-token` |
2026-07-02 20:48:39 +02:00
| "Populate `OPENROUTER_API_KEY` for llm-connect" | Operator → OpenBao custody; delivery via `warden route show openrouter-llm-connect` |
2026-06-17 08:22:45 +02:00
| "Store Inter-Hub admin key for bootstrap" | Operator → OpenBao or `IHUB_OPERATOR_KEY_FILE` (`CUST-WP-0049` ) |
| "Give me Vault root token" | Break-glass ceremony → `railiance-platform/docs/openbao.md` |
| "S3 credentials for artifact upload" | NK-WP-0007 / artifact-store consumer path |
| "JWT for my app" | key-cape / Keycloak IAM Profile |
2026-06-27 18:22:09 +02:00
**No duplicate ownership.** Commands that would make warden a store, IdP, or
transport owner — `warden secret` , `warden bao` , `warden login` as an identity
service, or `warden tunnel` — do not exist. A future `warden policy` lookup, if
added by WARDEN-WP-0015, is metadata/conformance only; flex-auth remains the PDP.
The canonical anti-pattern table lives in
2026-06-18 20:44:53 +02:00
`wiki/AccessRouting.md#anti-patterns-not-coming-to-ops-warden` ; it is not
restated here.
2026-06-17 08:22:45 +02:00
---
## Examples — ops-warden IS correct
| Request | Command / pattern |
| --- | --- |
| ops-bridge tunnel needs a cert | `cert_command: warden sign <actor> --pubkey <path>` |
| Agent reaching bootstrap host | `agt-codex-interhub-bootstrap` — `wiki/InterHubBootstrapAccessLane.md` |
| Check cert expiry before shift | `warden status <actor>` |
| New tunnel actor | `warden inventory add` — `wiki/ActorInventoryPatterns.md` |
| Lab without OpenBao | `backend: local` — `wiki/OpsWardenConfig.md` |
---
## Typical flows
### Human operator → remote host
1. Identity: key-cape login if web/API access needed (optional for pure SSH).
2. SSH cert: `warden sign adm-<you> --pubkey ~/.ssh/id_ed25519.pub` .
3. Tunnel (if needed): ops-bridge with `cert_command` pointing at warden.
4. Host: principal deployed by railiance-infra.
### Kaizen / Codex agent → attended task
1. Register actor: `agt-codex-<task>` per `wiki/ActorInventoryPatterns.md` .
2. SSH cert: `WARDEN_ACTOR=... ops-ssh-wrapper ssh ...` or `warden sign` .
3. Secrets for task (API keys): OpenBao path — not warden.
4. Tunnel: ops-bridge if required.
### CI automation → scheduled job
1. Actor: `atm-<job>` with narrow principal and low TTL (≤ 8 h).
2. `warden issue atm-<job>` or sign with pre-provisioned key.
3. No long-lived keys in CI env vars.
---
## When guidance drifts
NetKingdom security architecture is canonical in `net-kingdom` . When it
changes (OpenBao, IAM Profile, new bootstrap lanes), ops-warden updates:
- This file
- `wiki/NetKingdomSecurityMap.md`
- `SCOPE.md` / `INTENT.md` as needed
Report drift via custodian workplan or State Hub message to `ops-warden` .
---
## See also
- `INTENT.md` — steward mission
2026-06-18 20:44:53 +02:00
- `wiki/AccessRouting.md` — what ops-warden issues vs routes (role and boundary)
2026-06-17 08:22:45 +02:00
- `wiki/NetKingdomSecurityMap.md` — component literacy
2026-06-27 18:22:09 +02:00
- `wiki/WorkloadSecurityPosture.md` — dev/test/prod posture, M0-M3 maturity, and blocker triage
2026-06-17 08:22:45 +02:00
- `wiki/ActorInventoryPatterns.md` — actor naming
- `wiki/OpenBaoSshEngineChecklist.md` — production SSH signing verify
2026-06-27 18:22:09 +02:00
- `net-kingdom/docs/platform-identity-security-architecture.md` — platform canon