--- id: NK-WP-0026 type: workplan title: "Promote user-engine workload identity to flex-auth" domain: infotech repo: net-kingdom status: finished owner: codex topic_slug: netkingdom created: "2026-08-18" updated: "2026-08-19" state_hub_workstream_id: "3e8965aa-494a-5dcf-a11d-b768c196c548" --- # NK-WP-0026 — user-engine caller identity rollout ```task id: NK-WP-0026-T01 status: done priority: high state_hub_task_id: "294eb50e-2d54-59f1-a793-d10e53e33020" ``` Declare a non-automounted `user-engine` ServiceAccount and a one-hour projected token with audience `flex-auth`; mount only that token into the portal. Source completed 2026-08-18. Existing NetworkPolicy already permits only the named flex-auth user-engine instance on port 8080. ```task id: NK-WP-0026-T02 status: done priority: high state_hub_task_id: "d24461e9-c378-58ac-97ed-60ad6e563d47" ``` Both sides promoted and probed. Verified live on railiance01, 2026-08-19, by net-kingdom against the cluster rather than against another repo's assertion. **Deployed digests** | Side | Object | Digest | | --- | --- | --- | | user-engine | `deploy/user-engine` (ns `user-engine`), pod `user-engine-8569d7cb87-fp7px` | `forgejo.coulomb.social/coulomb/user-engine@sha256:c501aeb204154d85017565a87fd34cff12e5c48f600d124d3f8c82f11bb9d59c` | | flex-auth | `deploy/flex-auth-user-engine` (ns `flex-auth`), pod `flex-auth-user-engine-b745b6b5c-zhsfv` | `forgejo.coulomb.social/coulomb/flex-auth@sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b` | flex-auth serves with `--caller-auth-mode enforce` and `--caller-binding user-engine=system:serviceaccount:user-engine:user-engine`. The warn stage was run on flex-auth's side under FLEX-WP-0011 / FLEX-WP-0015-T02; net-kingdom observed the end state, not the intermediate warn window. **The T01 caveat is cleared.** The old digest did not read the projected file. The deployed digest does: `user_engine/runtime.py:45` makes `USER_ENGINE_FLEX_AUTH_TOKEN_FILE` a *required* setting (`_required(...)`, so the portal cannot start without it), and `user_engine/adapters/flex_auth.py:62-68` re-reads the file **per decision** — deliberately, so projected-token rotation needs no restart — and sends it as `Authorization: Bearer`. Both were read out of the running container, not out of the source tree. **Probes** — `POST /v1/check` against `flex-auth-user-engine.flex-auth.svc.cluster.local:8080`, run from inside the workload pods so NetworkPolicy and identity are exercised as in production. All are read-only decision queries; nothing in the cluster was mutated. | Probe | Run from | Credential | Result | | --- | --- | --- | --- | | valid | `user-engine-8569d7cb87-fp7px` | the pod's own projected token, audience `flex-auth` | **HTTP 200**, `decision:d9aef25f08e17b84`, `effect: allow`, `reason: self_service`, `matched_rule: self_service`, `policy_version: v1` | | missing token | `user-engine-8569d7cb87-fp7px` | no `Authorization` header | **HTTP 401** `unauthenticated` | | wrong system | `user-engine-8569d7cb87-fp7px` | valid user-engine token, body asserting `resource.system: tenant-engine` | **HTTP 403** `forbidden` | | wrong system (network path) | `tenant-engine-6c6dcbddbb-4v26w` | tenant-engine's own projected token, against the *user-engine* PDP | connection refused — NetworkPolicy denies the cross-service path before flex-auth sees it | Note on the wrong-system probe, because it differs from what flex-auth reported. flex-auth's `tenancy.yaml` states "a token bound to the other protected system returns 403". net-kingdom could not reproduce that literal case: the tenant-engine pod cannot reach the user-engine PDP at all (Errno 111), so the 403 never arises on that path. What *is* reproducible, and is the same substitution attack, is a caller authenticated as one system asserting another system in the request body — ADR-0004's stated threat, "a caller could represent another protected system" — and that returns 403. The estate position is therefore stronger than claimed (two independent layers refuse it), but the claimed evidence is not the evidence that exists. Recorded rather than smoothed. **Manifest drift, found and closed.** `sso-mfa/k8s/user-engine/runtime.yaml` still pinned `sha256:e3b5f65b…` — the digest T01 warned must not be applied — while the cluster ran `c501aeb2…`. Anyone re-applying the repo's own manifest would have rolled the portal back to an image that does not read the token file, against a PDP now in `enforce`: every authorization call would 401 and the portal would fail closed. The manifest is now pinned to the deployed digest and `kubectl diff -f sso-mfa/k8s/user-engine/runtime.yaml` is **empty, exit 0** — declared state and live state agree. **Observation routed to flex-auth, not a blocker.** A syntactically invalid bearer token returns **HTTP 503 `caller authentication unavailable`**, not 401. ADR-0004 reserves 503 for TokenReview *unavailability* and puts invalid tokens with the 401 class. It fails closed either way, so there is no bypass, but a malformed credential is being reported as a flex-auth outage — which will mislead whoever reads the first page of an incident.