Enforce verified secrets-engine operator caller identity
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0726e-5232-73f2-aaca-2c05ceb62efb
This commit is contained in:
tegwick 2026-09-06 23:38:36 +02:00
parent 74216643eb
commit 6e3dfaeb41
5 changed files with 64 additions and 10 deletions

View file

@ -30,8 +30,8 @@
| workplan | FLEX-WP-0020 | proposed | — | workplans/FLEX-WP-0020-repository-identity-migration.md | | workplan | FLEX-WP-0020 | proposed | — | workplans/FLEX-WP-0020-repository-identity-migration.md |
| workplan | FLEX-WP-0021 | finished | — | workplans/FLEX-WP-0021-secrets-engine-consumer-policy-gate.md | | workplan | FLEX-WP-0021 | finished | — | workplans/FLEX-WP-0021-secrets-engine-consumer-policy-gate.md |
| workplan | FLEX-WP-0022 | proposed | — | workplans/FLEX-WP-0022-tenant-scope-coverage.md | | workplan | FLEX-WP-0022 | proposed | — | workplans/FLEX-WP-0022-tenant-scope-coverage.md |
| workplan | FLEX-WP-0023 | ready | — | workplans/FLEX-WP-0023-operator-caller-access-path.md | | workplan | FLEX-WP-0023 | active | — | workplans/FLEX-WP-0023-operator-caller-access-path.md |
| workplan | FLEX-WP-0024 | ready | — | workplans/FLEX-WP-0024-decision-envelope-authenticity.md | | workplan | FLEX-WP-0024 | active | — | workplans/FLEX-WP-0024-decision-envelope-authenticity.md |
| task | FLEX-WP-0001-T001 | done | — | workplans/FLEX-WP-0001-repo-intent-and-architecture-baseline.md | | task | FLEX-WP-0001-T001 | done | — | workplans/FLEX-WP-0001-repo-intent-and-architecture-baseline.md |
| task | FLEX-WP-0001-T002 | done | — | workplans/FLEX-WP-0001-repo-intent-and-architecture-baseline.md | | task | FLEX-WP-0001-T002 | done | — | workplans/FLEX-WP-0001-repo-intent-and-architecture-baseline.md |
| task | FLEX-WP-0001-T003 | done | — | workplans/FLEX-WP-0001-repo-intent-and-architecture-baseline.md | | task | FLEX-WP-0001-T003 | done | — | workplans/FLEX-WP-0001-repo-intent-and-architecture-baseline.md |
@ -138,9 +138,9 @@
| task | FLEX-WP-0022-T01 | todo | — | workplans/FLEX-WP-0022-tenant-scope-coverage.md | | task | FLEX-WP-0022-T01 | todo | — | workplans/FLEX-WP-0022-tenant-scope-coverage.md |
| task | FLEX-WP-0022-T02 | wait | — | workplans/FLEX-WP-0022-tenant-scope-coverage.md | | task | FLEX-WP-0022-T02 | wait | — | workplans/FLEX-WP-0022-tenant-scope-coverage.md |
| task | FLEX-WP-0022-T03 | todo | — | workplans/FLEX-WP-0022-tenant-scope-coverage.md | | task | FLEX-WP-0022-T03 | todo | — | workplans/FLEX-WP-0022-tenant-scope-coverage.md |
| task | FLEX-WP-0023-T01 | todo | — | workplans/FLEX-WP-0023-operator-caller-access-path.md | | task | FLEX-WP-0023-T01 | done | — | workplans/FLEX-WP-0023-operator-caller-access-path.md |
| task | FLEX-WP-0023-T02 | wait | — | workplans/FLEX-WP-0023-operator-caller-access-path.md | | task | FLEX-WP-0023-T02 | done | — | workplans/FLEX-WP-0023-operator-caller-access-path.md |
| task | FLEX-WP-0023-T03 | wait | — | workplans/FLEX-WP-0023-operator-caller-access-path.md | | task | FLEX-WP-0023-T03 | done | — | workplans/FLEX-WP-0023-operator-caller-access-path.md |
| task | FLEX-WP-0023-T04 | todo | — | workplans/FLEX-WP-0023-operator-caller-access-path.md | | task | FLEX-WP-0023-T04 | todo | — | workplans/FLEX-WP-0023-operator-caller-access-path.md |
| task | FLEX-WP-0023-T05 | wait | — | workplans/FLEX-WP-0023-operator-caller-access-path.md | | task | FLEX-WP-0023-T05 | wait | — | workplans/FLEX-WP-0023-operator-caller-access-path.md |
| task | FLEX-WP-0024-T01 | done | — | workplans/FLEX-WP-0024-decision-envelope-authenticity.md | | task | FLEX-WP-0024-T01 | done | — | workplans/FLEX-WP-0024-decision-envelope-authenticity.md |

View file

@ -0,0 +1,9 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: secrets-engine
namespace: secrets-engine
labels:
app.kubernetes.io/part-of: flex-auth
app.kubernetes.io/component: operator-caller
automountServiceAccountToken: false

View file

@ -1,6 +1,6 @@
# Operator caller access path # Operator caller access path
**Status:** design published, live receipts outstanding **Status:** revision 3 enforces adopted caller; positive and all four negative live checks pass
**Opened by:** `glas-harness` (`GLAS-WP-0015`, 2026-09-06), carried by `FLEX-WP-0023` **Opened by:** `glas-harness` (`GLAS-WP-0015`, 2026-09-06), carried by `FLEX-WP-0023`
**Supersedes:** the workload assumption in `FLEX-WP-0021-T04` **Supersedes:** the workload assumption in `FLEX-WP-0021-T04`
@ -206,3 +206,16 @@ So a decision record proves the *subject* was allowed. It cannot prove the
between "this decision permits the action" and "this caller was permitted to between "this decision permits the action" and "this caller was permitted to
obtain this decision". Recorded as `FLEX-DEC-2026-009`; it is a gap in obtain this decision". Recorded as `FLEX-DEC-2026-009`; it is a gap in
flex-auth's own §17 contract, not in the deployment. flex-auth's own §17 contract, not in the deployment.
## Live execution update — 2026-09-06
The earlier absent-SA and warn-mode observations above are historical design
findings. Glas created the bound identity from
`deploy/secrets-engine-operator-caller.yaml`, proved adoption with no warnings,
and upgraded the dedicated pin to Helm revision 3 / enforce. Positive request and N1N4 pass, including an actually expired issued token
(401) followed by a fresh token (200). The temporary forward is closed.
See FLEX-WP-0023 and glas-harness/docs/evidence/GLAS-WP-0015-caller-auth-2026-09-06.json.
No other consumer deployment changed. Recreate a loopback-only forward and mint
a fresh bounded token for each authorized operator session; the verification
forward is temporary and is not the runtime endpoint after cleanup.

View file

@ -12,7 +12,7 @@ args:
- --policy - --policy
- /opt/flex-auth/examples/secrets-engine/policy_package.md - /opt/flex-auth/examples/secrets-engine/policy_package.md
callerAuth: callerAuth:
mode: warn mode: enforce
kubernetesURL: https://10.43.0.1 kubernetesURL: https://10.43.0.1
binding: secrets-engine=system:serviceaccount:secrets-engine:secrets-engine binding: secrets-engine=system:serviceaccount:secrets-engine:secrets-engine
consumer: consumer:

View file

@ -46,7 +46,7 @@ admitted exactly one pod. Here the warn window protects nothing while it runs.
```task ```task
id: FLEX-WP-0023-T01 id: FLEX-WP-0023-T01
status: todo status: done
priority: high priority: high
state_hub_task_id: "10e5a40c-f142-55b9-ab15-fc77c0064ce0" state_hub_task_id: "10e5a40c-f142-55b9-ab15-fc77c0064ce0"
``` ```
@ -73,7 +73,7 @@ Gate: `kubectl -n secrets-engine create token secrets-engine --audience=flex-aut
```task ```task
id: FLEX-WP-0023-T02 id: FLEX-WP-0023-T02
status: wait status: done
priority: high priority: high
state_hub_task_id: "79a8d82d-777c-5462-b49d-098f4b7a3b9c" state_hub_task_id: "79a8d82d-777c-5462-b49d-098f4b7a3b9c"
``` ```
@ -110,7 +110,7 @@ isolates. Nothing is reported as verified that was not run.
```task ```task
id: FLEX-WP-0023-T03 id: FLEX-WP-0023-T03
status: wait status: done
priority: high priority: high
state_hub_task_id: "8117c9d8-6efa-5ccf-8ed4-4da2519c3de3" state_hub_task_id: "8117c9d8-6efa-5ccf-8ed4-4da2519c3de3"
``` ```
@ -183,3 +183,35 @@ because a decision turning on registry content must be replayable from its own
record. **A decision gated by caller authentication is not auditable from its record. **A decision gated by caller authentication is not auditable from its
own record by the same argument.** Carry it into the outstanding v0.8 assent own record by the same argument.** Carry it into the outstanding v0.8 assent
review rather than as a separate message. review rather than as a separate message.
## Operator execution from Glas — 2026-09-06
Standing production authorization applied to this bounded owner procedure.
Added deploy/secrets-engine-operator-caller.yaml and applied it after server
validation: SA secrets-engine/secrets-engine, automount disabled, no role or
role binding added. Ten-minute TokenRequest token has exact bound sub and
flex-auth audience; token values remain only in proof-process memory.
Positive adoption passed under warn with zero authentication warnings. Helm
lint/server dry-run passed; dedicated release upgraded to revision 3 with
callerAuth.mode=enforce. Correct caller gets 200 allow v2; missing token 401,
wrong principal 403, wrong audience 401. Expiry proof passed against an actually issued token: 401 after its exp
plus 65 seconds, followed by a fresh-token 200 allow v2. Other three Deployment
specs were compared and are unchanged. The temporary forward binds 127.0.0.1
and is removed when the proof finishes. Value-free receipts are in glas-harness:
docs/evidence/GLAS-WP-0015-caller-auth-2026-09-06.json.
The initial proof reader assumed JSON error responses; the server correctly
returns plain-text authentication failures. Corrected the temporary reader and
reran the checks; this was a proof-harness failure, not a production code change.
T04 caller provenance and FLEX-WP-0024 signatures remain separate open work.
An authenticated API-server port-forward authenticates the responder for this
operator path; it does not produce a signed portable decision artifact.
Final receipt: T01T03 complete; N4 expired-token 401 at epoch 1788730498,
fresh-token positive 200 at 1788730499. Temporary forward closed and proof
process exited, discarding its in-memory credentials. No port-forward remains
as an implicit runtime dependency. T04 and T05 remain open; plan stays active.