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-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-0023 | ready | — | 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-0023 | active | — | workplans/FLEX-WP-0023-operator-caller-access-path.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-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 |
@ -138,9 +138,9 @@
| 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-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-T02 | wait | — | 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-T01 | done | — | 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 | 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-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 |

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
**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`
**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
obtain this decision". Recorded as `FLEX-DEC-2026-009`; it is a gap in
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
- /opt/flex-auth/examples/secrets-engine/policy_package.md
callerAuth:
mode: warn
mode: enforce
kubernetesURL: https://10.43.0.1
binding: secrets-engine=system:serviceaccount:secrets-engine:secrets-engine
consumer:

View file

@ -46,7 +46,7 @@ admitted exactly one pod. Here the warn window protects nothing while it runs.
```task
id: FLEX-WP-0023-T01
status: todo
status: done
priority: high
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
id: FLEX-WP-0023-T02
status: wait
status: done
priority: high
state_hub_task_id: "79a8d82d-777c-5462-b49d-098f4b7a3b9c"
```
@ -110,7 +110,7 @@ isolates. Nothing is reported as verified that was not run.
```task
id: FLEX-WP-0023-T03
status: wait
status: done
priority: high
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
own record by the same argument.** Carry it into the outstanding v0.8 assent
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.