Pin caller-auth digest in warn on independently rollable overlay pins
The sanctioned Helm chart could not promote ADR 0004 at all, and the emergency manifests selected enforce. That made a FLEX-WP-0011 apply either a no-op or a global 401. First production pin is now warn, per consumer, on CI digest sha256:138aa347… . Enforce stays a later per-consumer flip so USER-WP-0023-T03 can close without waiting on tenant-engine.
This commit is contained in:
parent
3de72fe6f5
commit
fa278674c1
22 changed files with 268 additions and 55 deletions
|
|
@ -2,5 +2,5 @@ apiVersion: v2
|
||||||
name: flex-auth
|
name: flex-auth
|
||||||
description: Independently rollable flex-auth policy-decision Deployment (one consumer per release).
|
description: Independently rollable flex-auth policy-decision Deployment (one consumer per release).
|
||||||
type: application
|
type: application
|
||||||
version: 0.1.0
|
version: 0.2.0
|
||||||
appVersion: "0.1.0"
|
appVersion: "0.1.0"
|
||||||
|
|
|
||||||
|
|
@ -18,3 +18,18 @@ app.kubernetes.io/name: {{ include "flex-auth.name" . }}
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
app.kubernetes.io/part-of: flex-auth
|
app.kubernetes.io/part-of: flex-auth
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
|
{{- define "flex-auth.callerAuth.mode" -}}
|
||||||
|
{{- $mode := "disabled" -}}
|
||||||
|
{{- if and (hasKey .Values "callerAuth") .Values.callerAuth (hasKey .Values.callerAuth "mode") .Values.callerAuth.mode -}}
|
||||||
|
{{- $mode = .Values.callerAuth.mode -}}
|
||||||
|
{{- end -}}
|
||||||
|
{{- if not (has $mode (list "disabled" "warn" "enforce")) -}}
|
||||||
|
{{- fail (printf "callerAuth.mode must be disabled, warn, or enforce; got %q" $mode) -}}
|
||||||
|
{{- end -}}
|
||||||
|
{{- $mode -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{- define "flex-auth.callerAuth.enabled" -}}
|
||||||
|
{{- if has (include "flex-auth.callerAuth.mode" .) (list "warn" "enforce") -}}true{{- else -}}false{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,9 @@ spec:
|
||||||
{{- include "flex-auth.labels" . | nindent 8 }}
|
{{- include "flex-auth.labels" . | nindent 8 }}
|
||||||
spec:
|
spec:
|
||||||
automountServiceAccountToken: false
|
automountServiceAccountToken: false
|
||||||
|
{{- if eq (include "flex-auth.callerAuth.enabled" .) "true" }}
|
||||||
|
serviceAccountName: {{ include "flex-auth.name" . }}
|
||||||
|
{{- end }}
|
||||||
securityContext:
|
securityContext:
|
||||||
runAsNonRoot: true
|
runAsNonRoot: true
|
||||||
seccompProfile:
|
seccompProfile:
|
||||||
|
|
@ -25,6 +28,15 @@ spec:
|
||||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
args:
|
args:
|
||||||
{{- toYaml .Values.args | nindent 12 }}
|
{{- toYaml .Values.args | nindent 12 }}
|
||||||
|
{{- if eq (include "flex-auth.callerAuth.enabled" .) "true" }}
|
||||||
|
{{- $binding := required "callerAuth.binding is required when callerAuth.mode is warn or enforce" .Values.callerAuth.binding }}
|
||||||
|
- --caller-auth-mode
|
||||||
|
- {{ include "flex-auth.callerAuth.mode" . | quote }}
|
||||||
|
- --caller-kubernetes-url
|
||||||
|
- {{ required "callerAuth.kubernetesURL is required when callerAuth.mode is warn or enforce" .Values.callerAuth.kubernetesURL | quote }}
|
||||||
|
- --caller-binding
|
||||||
|
- {{ $binding | quote }}
|
||||||
|
{{- end }}
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
containerPort: {{ .Values.service.port }}
|
containerPort: {{ .Values.service.port }}
|
||||||
|
|
@ -46,3 +58,25 @@ spec:
|
||||||
drop:
|
drop:
|
||||||
- ALL
|
- ALL
|
||||||
readOnlyRootFilesystem: true
|
readOnlyRootFilesystem: true
|
||||||
|
{{- if eq (include "flex-auth.callerAuth.enabled" .) "true" }}
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: {{ .Values.callerAuth.reviewer.mountPath }}
|
||||||
|
name: flex-auth-reviewer
|
||||||
|
readOnly: true
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq (include "flex-auth.callerAuth.enabled" .) "true" }}
|
||||||
|
volumes:
|
||||||
|
- name: flex-auth-reviewer
|
||||||
|
projected:
|
||||||
|
defaultMode: 0440
|
||||||
|
sources:
|
||||||
|
- serviceAccountToken:
|
||||||
|
audience: {{ .Values.callerAuth.reviewer.audience | quote }}
|
||||||
|
expirationSeconds: {{ .Values.callerAuth.reviewer.expirationSeconds }}
|
||||||
|
path: token
|
||||||
|
- configMap:
|
||||||
|
name: kube-root-ca.crt
|
||||||
|
items:
|
||||||
|
- key: ca.crt
|
||||||
|
path: ca.crt
|
||||||
|
{{- end }}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,16 @@ spec:
|
||||||
policyTypes:
|
policyTypes:
|
||||||
- Ingress
|
- Ingress
|
||||||
- Egress
|
- Egress
|
||||||
|
{{- if eq (include "flex-auth.callerAuth.enabled" .) "true" }}
|
||||||
|
egress:
|
||||||
|
- ports:
|
||||||
|
- port: 443
|
||||||
|
protocol: TCP
|
||||||
|
- port: 6443
|
||||||
|
protocol: TCP
|
||||||
|
{{- else }}
|
||||||
egress: []
|
egress: []
|
||||||
|
{{- end }}
|
||||||
{{- if .Values.consumer.isolated }}
|
{{- if .Values.consumer.isolated }}
|
||||||
ingress: []
|
ingress: []
|
||||||
{{- else }}
|
{{- else }}
|
||||||
|
|
|
||||||
30
charts/flex-auth/templates/rbac.yaml
Normal file
30
charts/flex-auth/templates/rbac.yaml
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
{{- if eq (include "flex-auth.callerAuth.enabled" .) "true" }}
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: {{ include "flex-auth.name" . }}-tokenreviewer
|
||||||
|
labels:
|
||||||
|
{{- include "flex-auth.labels" . | nindent 4 }}
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- authentication.k8s.io
|
||||||
|
resources:
|
||||||
|
- tokenreviews
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: {{ include "flex-auth.name" . }}-tokenreviewer
|
||||||
|
labels:
|
||||||
|
{{- include "flex-auth.labels" . | nindent 4 }}
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: {{ include "flex-auth.name" . }}-tokenreviewer
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: {{ include "flex-auth.name" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
{{- end }}
|
||||||
9
charts/flex-auth/templates/serviceaccount.yaml
Normal file
9
charts/flex-auth/templates/serviceaccount.yaml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{{- if eq (include "flex-auth.callerAuth.enabled" .) "true" }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: {{ include "flex-auth.name" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "flex-auth.labels" . | nindent 4 }}
|
||||||
|
automountServiceAccountToken: false
|
||||||
|
{{- end }}
|
||||||
|
|
@ -29,6 +29,18 @@ consumer:
|
||||||
namespace: ""
|
namespace: ""
|
||||||
podName: ""
|
podName: ""
|
||||||
|
|
||||||
|
# disabled keeps the image bootable without TokenReview (isolated canary).
|
||||||
|
# Production pins set warn, then enforce, independently per consumer.
|
||||||
|
callerAuth:
|
||||||
|
mode: disabled
|
||||||
|
audience: flex-auth
|
||||||
|
kubernetesURL: https://kubernetes.default.svc
|
||||||
|
binding: ""
|
||||||
|
reviewer:
|
||||||
|
mountPath: /var/run/secrets/flex-auth-reviewer
|
||||||
|
audience: https://kubernetes.default.svc
|
||||||
|
expirationSeconds: 3600
|
||||||
|
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: 25m
|
cpu: 25m
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,12 @@ emergency kubectl path recovered on 2026-08-11 from live
|
||||||
`last-applied-configuration`, kept so a rollback does not depend on a
|
`last-applied-configuration`, kept so a rollback does not depend on a
|
||||||
cluster annotation or on Helm history.
|
cluster annotation or on Helm history.
|
||||||
|
|
||||||
|
Caller authentication (FLEX-WP-0015-T02) is pinned here in **`warn`**,
|
||||||
|
matching `values/user-engine.yaml` and `values/tenant-engine.yaml`. Do not
|
||||||
|
edit these files back to `enforce` and apply them as a shortcut: that is
|
||||||
|
the hazard. Flip `callerAuth.mode` per consumer in the overlay after that
|
||||||
|
consumer's warn logs are clean, then re-render or edit only that pin.
|
||||||
|
|
||||||
Manifests for the two cluster-local flex-auth policy-decision services.
|
Manifests for the two cluster-local flex-auth policy-decision services.
|
||||||
|
|
||||||
| File | Deployment | Consumer | Service DNS |
|
| File | Deployment | Consumer | Service DNS |
|
||||||
|
|
@ -86,10 +92,12 @@ last-known-good digest below.
|
||||||
|
|
||||||
| Deployment | Last-known-good digest | Policy state |
|
| Deployment | Last-known-good digest | Policy state |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `flex-auth-tenant-engine` | `sha256:1bf060e61122693ce98359c167cc5fe8bdafc84e097e090eaa71af94d0f27cbc` | **live** — nine-action policy (FLEX-WP-0014), CI-built from `f304688` |
|
| `flex-auth-tenant-engine` | `sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b` | **pin, not live** — caller-auth **warn** (FLEX-WP-0015-T02), CI `main-3de72fe` |
|
||||||
|
| `flex-auth-tenant-engine` *(live until warn promote)* | `sha256:1bf060e61122693ce98359c167cc5fe8bdafc84e097e090eaa71af94d0f27cbc` | nine-action policy (FLEX-WP-0014), CI-built from `f304688` |
|
||||||
| `flex-auth-tenant-engine` *(previous)* | `sha256:9320df394a642eff24da8af4a0ee8886a7bb78b0f14d8ee1deeb30ea8eeeaba7` | seven-action policy, FLEX-WP-0013 restore; guardrail actions deny `unknown_action` |
|
| `flex-auth-tenant-engine` *(previous)* | `sha256:9320df394a642eff24da8af4a0ee8886a7bb78b0f14d8ee1deeb30ea8eeeaba7` | seven-action policy, FLEX-WP-0013 restore; guardrail actions deny `unknown_action` |
|
||||||
| `flex-auth-tenant-engine` *(rollback)* | `sha256:c25fc34a6cd7e64d955f8723ec70e176a583d5ae71d76280c4e2d89fba0fe0aa` | four-action policy; lifecycle actions deny `unknown_action` |
|
| `flex-auth-tenant-engine` *(rollback)* | `sha256:c25fc34a6cd7e64d955f8723ec70e176a583d5ae71d76280c4e2d89fba0fe0aa` | four-action policy; lifecycle actions deny `unknown_action` |
|
||||||
| `flex-auth-user-engine` | `sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4` | **current** — FLEX-WP-0009-T04, nine fixtures (incl. registration-applicant) verified live 2026-08-16 |
|
| `flex-auth-user-engine` | `sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b` | **pin, not live** — caller-auth **warn** (FLEX-WP-0015-T02), CI `main-3de72fe` |
|
||||||
|
| `flex-auth-user-engine` *(live until warn promote)* | `sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4` | FLEX-WP-0009-T04, nine fixtures (incl. registration-applicant) verified live 2026-08-16 |
|
||||||
| `flex-auth-user-engine` *(previous)* | `sha256:a31961c45215aa6baf3bc748c6741ab703c2c8325e61aa7983a355026195e51b` | FLEX-WP-0009-T03, six fixtures verified live 2026-08-10 |
|
| `flex-auth-user-engine` *(previous)* | `sha256:a31961c45215aa6baf3bc748c6741ab703c2c8325e61aa7983a355026195e51b` | FLEX-WP-0009-T03, six fixtures verified live 2026-08-10 |
|
||||||
|
|
||||||
Rolling back the tenant-engine service to `c25fc34a…` restores fail-closed
|
Rolling back the tenant-engine service to `c25fc34a…` restores fail-closed
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,12 @@ spec:
|
||||||
- --policy
|
- --policy
|
||||||
- /opt/flex-auth/examples/tenant-engine/policy_package.md
|
- /opt/flex-auth/examples/tenant-engine/policy_package.md
|
||||||
- --caller-auth-mode
|
- --caller-auth-mode
|
||||||
- enforce
|
- warn
|
||||||
- --caller-kubernetes-url
|
- --caller-kubernetes-url
|
||||||
- https://10.43.0.1
|
- https://10.43.0.1
|
||||||
- --caller-binding
|
- --caller-binding
|
||||||
- tenant-engine=system:serviceaccount:tenant-engine:tenant-engine
|
- tenant-engine=system:serviceaccount:tenant-engine:tenant-engine
|
||||||
image: forgejo.coulomb.social/coulomb/flex-auth@sha256:1bf060e61122693ce98359c167cc5fe8bdafc84e097e090eaa71af94d0f27cbc
|
image: forgejo.coulomb.social/coulomb/flex-auth@sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /healthz
|
path: /healthz
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,12 @@ spec:
|
||||||
- --policy
|
- --policy
|
||||||
- /opt/flex-auth/examples/user-engine/policy_package.md
|
- /opt/flex-auth/examples/user-engine/policy_package.md
|
||||||
- --caller-auth-mode
|
- --caller-auth-mode
|
||||||
- enforce
|
- warn
|
||||||
- --caller-kubernetes-url
|
- --caller-kubernetes-url
|
||||||
- https://10.43.0.1
|
- https://10.43.0.1
|
||||||
- --caller-binding
|
- --caller-binding
|
||||||
- user-engine=system:serviceaccount:user-engine:user-engine
|
- user-engine=system:serviceaccount:user-engine:user-engine
|
||||||
image: forgejo.coulomb.social/coulomb/flex-auth@sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4
|
image: forgejo.coulomb.social/coulomb/flex-auth@sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /healthz
|
path: /healthz
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,11 @@ cached across rotation.
|
||||||
|
|
||||||
Three modes support promotion: `disabled`, `warn`, and `enforce`. Warn mode
|
Three modes support promotion: `disabled`, `warn`, and `enforce`. Warn mode
|
||||||
records the same authentication failures without logging credentials. It is a
|
records the same authentication failures without logging credentials. It is a
|
||||||
bounded migration aid, not a conformant steady state. The reviewed desired
|
bounded migration aid, not a conformant steady state. The first production pin
|
||||||
manifests select `enforce`; promotion still follows FLEX-WP-0011 and requires a
|
is `warn` on each independently rollable Deployment; `enforce` is the end
|
||||||
new immutable image digest plus caller rollout evidence.
|
state and is flipped per consumer after that consumer's warn logs are clean.
|
||||||
|
Promotion follows FLEX-WP-0011. The two production pins must not be flipped
|
||||||
|
together: user-engine can enforce while tenant-engine stays in warn.
|
||||||
|
|
||||||
## Rejected alternatives
|
## Rejected alternatives
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -271,7 +271,7 @@ volunteer.
|
||||||
| Task | |
|
| Task | |
|
||||||
|---|---|
|
|---|---|
|
||||||
| T01 | Publish the posture vector and this review; reply to `rapp-postgres` |
|
| T01 | Publish the posture vector and this review; reply to `rapp-postgres` |
|
||||||
| T02 | **Close the A0**: TokenReview source/desired state done; immutable promotion pending |
|
| T02 | **Close the A0**: TokenReview source + warn-first overlay pin done; operator promote-then-per-consumer-enforce pending |
|
||||||
| T03 | Deleted the unused tenant-engine live-roles adapter |
|
| T03 | Deleted the unused tenant-engine live-roles adapter |
|
||||||
| T04 | AuthZEN endpoint — `wait`, with a written trigger |
|
| T04 | AuthZEN endpoint — `wait`, with a written trigger |
|
||||||
| T05 | `make verify-posture` guards declaration/source/deployment drift |
|
| T05 | `make verify-posture` guards declaration/source/deployment drift |
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,32 @@ $RAILIANCE rollback . --apply --approval-id <state-hub-id> --revision <helm-rev>
|
||||||
The canary Service is `flex-auth-canary.flex-auth.svc.cluster.local:8080`.
|
The canary Service is `flex-auth-canary.flex-auth.svc.cluster.local:8080`.
|
||||||
Production consumers keep calling their own Service names.
|
Production consumers keep calling their own Service names.
|
||||||
|
|
||||||
|
## Caller-auth promotion (FLEX-WP-0015-T02)
|
||||||
|
|
||||||
|
The two production pins are independently rollable. Do not flip both to
|
||||||
|
`enforce` in one apply. The first pin of digest
|
||||||
|
`sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b`
|
||||||
|
is **warn** on each consumer.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Warn pin (safe if a caller still sends no token)
|
||||||
|
helm upgrade --install flex-auth-user-engine charts/flex-auth \
|
||||||
|
--namespace flex-auth -f values/user-engine.yaml --wait --timeout 2m
|
||||||
|
helm upgrade --install flex-auth-tenant-engine charts/flex-auth \
|
||||||
|
--namespace flex-auth -f values/tenant-engine.yaml --wait --timeout 2m
|
||||||
|
|
||||||
|
# Confirm warn logs: "caller authentication warning:" must be absent for a
|
||||||
|
# migrated caller. user-engine is migrated; tenant-engine live status is
|
||||||
|
# unconfirmed. Isolated canary keeps callerAuth.mode=disabled.
|
||||||
|
|
||||||
|
# Then set values/user-engine.yaml callerAuth.mode: enforce and upgrade only
|
||||||
|
# that release. USER-WP-0023-T03 runs only after that flip. tenant-engine
|
||||||
|
# stays warn until its logs are clean.
|
||||||
|
```
|
||||||
|
|
||||||
|
Emergency kubectl path is also warn. Applying it in enforce is the hazard
|
||||||
|
the warn pin exists to prevent.
|
||||||
|
|
||||||
## Rolling a production pin
|
## Rolling a production pin
|
||||||
|
|
||||||
Policy is baked into the image. Do not build images on a workstation.
|
Policy is baked into the image. Do not build images on a workstation.
|
||||||
|
|
@ -76,8 +102,10 @@ or re-apply the last-known-good digest in `deploy/README.md`.
|
||||||
|
|
||||||
| Deployment | Last-known-good digest | Policy state |
|
| Deployment | Last-known-good digest | Policy state |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `flex-auth-tenant-engine` | `sha256:1bf060e61122693ce98359c167cc5fe8bdafc84e097e090eaa71af94d0f27cbc` | **live** — nine-action policy (FLEX-WP-0014), CI-built from `f304688` |
|
| `flex-auth-tenant-engine` | `sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b` | **pin, not live** — caller-auth warn (FLEX-WP-0015-T02), CI `main-3de72fe` |
|
||||||
|
| `flex-auth-tenant-engine` *(live until warn promote)* | `sha256:1bf060e61122693ce98359c167cc5fe8bdafc84e097e090eaa71af94d0f27cbc` | nine-action policy (FLEX-WP-0014), CI-built from `f304688` |
|
||||||
| `flex-auth-tenant-engine` *(previous)* | `sha256:9320df394a642eff24da8af4a0ee8886a7bb78b0f14d8ee1deeb30ea8eeeaba7` | seven-action policy, FLEX-WP-0013 restore |
|
| `flex-auth-tenant-engine` *(previous)* | `sha256:9320df394a642eff24da8af4a0ee8886a7bb78b0f14d8ee1deeb30ea8eeeaba7` | seven-action policy, FLEX-WP-0013 restore |
|
||||||
| `flex-auth-tenant-engine` *(rollback)* | `sha256:c25fc34a6cd7e64d955f8723ec70e176a583d5ae71d76280c4e2d89fba0fe0aa` | four-action policy; lifecycle actions deny `unknown_action` |
|
| `flex-auth-tenant-engine` *(rollback)* | `sha256:c25fc34a6cd7e64d955f8723ec70e176a583d5ae71d76280c4e2d89fba0fe0aa` | four-action policy; lifecycle actions deny `unknown_action` |
|
||||||
| `flex-auth-user-engine` | `sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4` | FLEX-WP-0009-T04, nine fixtures, live 2026-08-16 |
|
| `flex-auth-user-engine` | `sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b` | **pin, not live** — caller-auth warn (FLEX-WP-0015-T02), CI `main-3de72fe` |
|
||||||
|
| `flex-auth-user-engine` *(live until warn promote)* | `sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4` | FLEX-WP-0009-T04, nine fixtures, live 2026-08-16 |
|
||||||
| `flex-auth-user-engine` *(previous)* | `sha256:a31961c45215aa6baf3bc748c6741ab703c2c8325e61aa7983a355026195e51b` | FLEX-WP-0009-T03, six fixtures |
|
| `flex-auth-user-engine` *(previous)* | `sha256:a31961c45215aa6baf3bc748c6741ab703c2c8325e61aa7983a355026195e51b` | FLEX-WP-0009-T03, six fixtures |
|
||||||
|
|
|
||||||
12
tenancy.yaml
12
tenancy.yaml
|
|
@ -40,10 +40,11 @@ tenancy:
|
||||||
own inputs. Not a defect and not a target for movement.
|
own inputs. Not a defect and not a target for movement.
|
||||||
A: >-
|
A: >-
|
||||||
The running immutable digest still authenticates no caller, so current
|
The running immutable digest still authenticates no caller, so current
|
||||||
remains A0. Source and reviewed desired manifests implement A2 with an
|
remains A0. Source, overlay, and reviewed desired manifests implement
|
||||||
audience-scoped Kubernetes TokenReview choke point and exact
|
A2 with an audience-scoped Kubernetes TokenReview choke point and exact
|
||||||
protected-system-to-ServiceAccount bindings. Promotion and a live
|
protected-system-to-ServiceAccount bindings. The first production pin
|
||||||
unbound-request probe remain under FLEX-WP-0011/FLEX-WP-0015-T02.
|
is warn, independently per consumer, under FLEX-WP-0011/FLEX-WP-0015-T02.
|
||||||
|
Current moves to A2 only after enforce and a live unbound-request probe.
|
||||||
E: >-
|
E: >-
|
||||||
No tenant data at rest. Tenant scoping in decisions runs through one
|
No tenant data at rest. Tenant scoping in decisions runs through one
|
||||||
choke point (internal/decision/engine.go normalizeRequest and the
|
choke point (internal/decision/engine.go normalizeRequest and the
|
||||||
|
|
@ -84,6 +85,7 @@ evidence:
|
||||||
- "internal/callerauth/auth.go"
|
- "internal/callerauth/auth.go"
|
||||||
- "internal/callerauth/auth_test.go"
|
- "internal/callerauth/auth_test.go"
|
||||||
- "cmd/flex-auth/main_test.go"
|
- "cmd/flex-auth/main_test.go"
|
||||||
|
- "charts/flex-auth/templates/rbac.yaml"
|
||||||
- "deploy/caller-auth-rbac.yaml"
|
- "deploy/caller-auth-rbac.yaml"
|
||||||
- "docs/adr/0004-inbound-caller-authentication.md"
|
- "docs/adr/0004-inbound-caller-authentication.md"
|
||||||
deployment: "deploy/flex-auth-user-engine.yaml, deploy/flex-auth-tenant-engine.yaml"
|
deployment: "values/user-engine.yaml, values/tenant-engine.yaml, deploy/flex-auth-user-engine.yaml, deploy/flex-auth-tenant-engine.yaml"
|
||||||
|
|
|
||||||
|
|
@ -12,4 +12,21 @@ for values in values/stage1.yaml values/stage2-canary.yaml values/stage3-product
|
||||||
helm template flex-auth charts/flex-auth -f "${values}" --namespace flex-auth >/dev/null
|
helm template flex-auth charts/flex-auth -f "${values}" --namespace flex-auth >/dev/null
|
||||||
done
|
done
|
||||||
|
|
||||||
|
user_render="$(helm template flex-auth-user-engine charts/flex-auth -f values/user-engine.yaml --namespace flex-auth)"
|
||||||
|
echo "$user_render" | grep -q -- '--caller-auth-mode' || { echo "user-engine render omits caller-auth-mode" >&2; exit 1; }
|
||||||
|
echo "$user_render" | grep -A1 -- '--caller-auth-mode' | grep -q warn || { echo "user-engine first pin must be warn" >&2; exit 1; }
|
||||||
|
echo "$user_render" | grep -q tokenreviews || { echo "user-engine render omits TokenReview RBAC" >&2; exit 1; }
|
||||||
|
echo "$user_render" | grep -q flex-auth-reviewer || { echo "user-engine render omits reviewer projection" >&2; exit 1; }
|
||||||
|
|
||||||
|
tenant_render="$(helm template flex-auth-tenant-engine charts/flex-auth -f values/tenant-engine.yaml --namespace flex-auth)"
|
||||||
|
echo "$tenant_render" | grep -A1 -- '--caller-auth-mode' | grep -q warn || { echo "tenant-engine first pin must be warn" >&2; exit 1; }
|
||||||
|
echo "$tenant_render" | grep -q 'tenant-engine=system:serviceaccount:tenant-engine:tenant-engine' \
|
||||||
|
|| { echo "tenant-engine render omits its exact binding" >&2; exit 1; }
|
||||||
|
|
||||||
|
canary_render="$(helm template flex-auth-canary charts/flex-auth -f values/stage2-canary.yaml --namespace flex-auth)"
|
||||||
|
if echo "$canary_render" | grep -q tokenreviews; then
|
||||||
|
echo "isolated canary must not create TokenReview RBAC" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
echo "stage1 overlay render ok"
|
echo "stage1 overlay render ok"
|
||||||
|
|
|
||||||
|
|
@ -26,14 +26,36 @@ fail() {
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
caller_mode_from_manifest() {
|
||||||
|
awk '
|
||||||
|
$0 ~ /--caller-auth-mode/ { getline; gsub(/^[[:space:]-]+/, ""); print; exit }
|
||||||
|
' "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
caller_mode_from_values() {
|
||||||
|
awk '
|
||||||
|
$1 == "callerAuth:" { in_block=1; next }
|
||||||
|
in_block && /^[^[:space:]#]/ { exit }
|
||||||
|
in_block && $1 == "mode:" { print $2; exit }
|
||||||
|
' "$1"
|
||||||
|
}
|
||||||
|
|
||||||
if grep -q 'authenticator.Authorize' "$main"; then
|
if grep -q 'authenticator.Authorize' "$main"; then
|
||||||
[[ "${declared_a:-0}" -ge 2 ]] || fail "caller authentication exists but current/implemented A is below 2"
|
[[ "${declared_a:-0}" -ge 2 ]] || fail "caller authentication exists but current/implemented A is below 2"
|
||||||
for manifest in deploy/flex-auth-user-engine.yaml deploy/flex-auth-tenant-engine.yaml; do
|
for manifest in deploy/flex-auth-user-engine.yaml deploy/flex-auth-tenant-engine.yaml; do
|
||||||
grep -q -- '--caller-auth-mode' "$root/$manifest" || fail "$manifest omits caller auth mode"
|
grep -q -- '--caller-auth-mode' "$root/$manifest" || fail "$manifest omits caller auth mode"
|
||||||
grep -q 'enforce' "$root/$manifest" || fail "$manifest does not select enforce mode"
|
mode="$(caller_mode_from_manifest "$root/$manifest")"
|
||||||
|
[[ "$mode" == "warn" || "$mode" == "enforce" ]] || fail "$manifest caller-auth-mode is ${mode:-empty}, not warn or enforce"
|
||||||
grep -q -- '--caller-binding' "$root/$manifest" || fail "$manifest omits the exact system binding"
|
grep -q -- '--caller-binding' "$root/$manifest" || fail "$manifest omits the exact system binding"
|
||||||
|
grep -q 'flex-auth-reviewer' "$root/$manifest" || fail "$manifest omits the reviewer token projection"
|
||||||
done
|
done
|
||||||
[[ -f "$root/deploy/caller-auth-rbac.yaml" ]] || fail "TokenReview RBAC manifest is absent"
|
[[ -f "$root/deploy/caller-auth-rbac.yaml" ]] || fail "TokenReview RBAC manifest is absent"
|
||||||
|
grep -q 'tokenreviews' "$root/charts/flex-auth/templates/rbac.yaml" || fail "overlay TokenReview RBAC template is absent"
|
||||||
|
for values in values/user-engine.yaml values/tenant-engine.yaml; do
|
||||||
|
mode="$(caller_mode_from_values "$root/$values")"
|
||||||
|
[[ "$mode" == "warn" || "$mode" == "enforce" ]] || fail "$values callerAuth.mode is ${mode:-empty}, not warn or enforce"
|
||||||
|
grep -q 'binding:' "$root/$values" || fail "$values omits callerAuth.binding"
|
||||||
|
done
|
||||||
else
|
else
|
||||||
[[ "${declared_a:-0}" -lt 2 ]] || fail "A2 is declared without a caller-authentication choke point"
|
[[ "${declared_a:-0}" -lt 2 ]] || fail "A2 is declared without a caller-authentication choke point"
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
name: flex-auth-local
|
name: flex-auth-local
|
||||||
image:
|
image:
|
||||||
repository: forgejo.coulomb.social/coulomb/flex-auth
|
repository: forgejo.coulomb.social/coulomb/flex-auth
|
||||||
digest: sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4
|
digest: sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b
|
||||||
args:
|
args:
|
||||||
- serve
|
- serve
|
||||||
- --addr
|
- --addr
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
name: flex-auth-canary
|
name: flex-auth-canary
|
||||||
image:
|
image:
|
||||||
repository: forgejo.coulomb.social/coulomb/flex-auth
|
repository: forgejo.coulomb.social/coulomb/flex-auth
|
||||||
digest: sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4
|
digest: sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b
|
||||||
args:
|
args:
|
||||||
- serve
|
- serve
|
||||||
- --addr
|
- --addr
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
name: flex-auth-canary
|
name: flex-auth-canary
|
||||||
image:
|
image:
|
||||||
repository: forgejo.coulomb.social/coulomb/flex-auth
|
repository: forgejo.coulomb.social/coulomb/flex-auth
|
||||||
digest: sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4
|
digest: sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b
|
||||||
args:
|
args:
|
||||||
- serve
|
- serve
|
||||||
- --addr
|
- --addr
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
# Production pin for the tenant-engine policy service. Independently rollable.
|
# Production pin for the tenant-engine policy service. Independently rollable.
|
||||||
|
# Warn is safe whether or not the live tenant-engine client already sends a
|
||||||
|
# token. Do not flip this pin to enforce until its warn logs are clean.
|
||||||
name: flex-auth-tenant-engine
|
name: flex-auth-tenant-engine
|
||||||
image:
|
image:
|
||||||
repository: forgejo.coulomb.social/coulomb/flex-auth
|
repository: forgejo.coulomb.social/coulomb/flex-auth
|
||||||
digest: sha256:1bf060e61122693ce98359c167cc5fe8bdafc84e097e090eaa71af94d0f27cbc
|
digest: sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b
|
||||||
args:
|
args:
|
||||||
- serve
|
- serve
|
||||||
- --addr
|
- --addr
|
||||||
|
|
@ -11,6 +13,10 @@ args:
|
||||||
- /opt/flex-auth/examples/tenant-engine/registry_snapshot.json
|
- /opt/flex-auth/examples/tenant-engine/registry_snapshot.json
|
||||||
- --policy
|
- --policy
|
||||||
- /opt/flex-auth/examples/tenant-engine/policy_package.md
|
- /opt/flex-auth/examples/tenant-engine/policy_package.md
|
||||||
|
callerAuth:
|
||||||
|
mode: warn
|
||||||
|
kubernetesURL: https://10.43.0.1
|
||||||
|
binding: tenant-engine=system:serviceaccount:tenant-engine:tenant-engine
|
||||||
consumer:
|
consumer:
|
||||||
isolated: false
|
isolated: false
|
||||||
namespace: tenant-engine
|
namespace: tenant-engine
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
# Production pin for the user-engine policy service. Independently rollable.
|
# Production pin for the user-engine policy service. Independently rollable.
|
||||||
|
# First caller-auth pin is warn (FLEX-WP-0015-T02). Flip mode to enforce only
|
||||||
|
# after warn logs are clean of unauthenticated callers for this consumer.
|
||||||
name: flex-auth-user-engine
|
name: flex-auth-user-engine
|
||||||
image:
|
image:
|
||||||
repository: forgejo.coulomb.social/coulomb/flex-auth
|
repository: forgejo.coulomb.social/coulomb/flex-auth
|
||||||
digest: sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4
|
digest: sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b
|
||||||
args:
|
args:
|
||||||
- serve
|
- serve
|
||||||
- --addr
|
- --addr
|
||||||
|
|
@ -11,6 +13,10 @@ args:
|
||||||
- /opt/flex-auth/examples/user-engine/registry_snapshot.json
|
- /opt/flex-auth/examples/user-engine/registry_snapshot.json
|
||||||
- --policy
|
- --policy
|
||||||
- /opt/flex-auth/examples/user-engine/policy_package.md
|
- /opt/flex-auth/examples/user-engine/policy_package.md
|
||||||
|
callerAuth:
|
||||||
|
mode: warn
|
||||||
|
kubernetesURL: https://10.43.0.1
|
||||||
|
binding: user-engine=system:serviceaccount:user-engine:user-engine
|
||||||
consumer:
|
consumer:
|
||||||
isolated: false
|
isolated: false
|
||||||
namespace: user-engine
|
namespace: user-engine
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ related_workplans:
|
||||||
- FLEX-WP-0004
|
- FLEX-WP-0004
|
||||||
- FLEX-WP-0011
|
- FLEX-WP-0011
|
||||||
created: "2026-08-17"
|
created: "2026-08-17"
|
||||||
updated: "2026-08-18"
|
updated: "2026-08-19"
|
||||||
state_hub_workstream_id: "31846b19-c2a3-428e-950b-5985bc9146eb"
|
state_hub_workstream_id: "31846b19-c2a3-428e-950b-5985bc9146eb"
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -110,38 +110,50 @@ Ship through the FLEX-WP-0011 staged-promotion path, not by direct apply.
|
||||||
ServiceAccount TokenReview with a separately projected reviewer identity and
|
ServiceAccount TokenReview with a separately projected reviewer identity and
|
||||||
exact `resource.system` → ServiceAccount bindings. Both check endpoints share
|
exact `resource.system` → ServiceAccount bindings. Both check endpoints share
|
||||||
the choke point; missing/mismatched identity fails 401/403 and reviewer outage
|
the choke point; missing/mismatched identity fails 401/403 and reviewer outage
|
||||||
fails 503. Unit and handler tests include the required unbound request. Desired
|
fails 503. Unit and handler tests include the required unbound request. Source
|
||||||
manifests select enforce mode and carry narrow TokenReview RBAC. The running
|
committed as `1e1e077`.
|
||||||
digest is unchanged, so `tenancy.current.A` honestly remains 0 while
|
|
||||||
`tenancy.implemented.A` is 2. Source committed as `1e1e077`.
|
|
||||||
|
|
||||||
**Remaining, in this order — the sequence is a constraint, not a preference.**
|
2026-08-19 overlay outcome: the sanctioned Helm chart did not render caller
|
||||||
`ops-warden` ruled on rollout (2026-08-17) and `user-engine` asked for the same:
|
auth at all, so a FLEX-WP-0011 pin of the new digest would have stayed
|
||||||
|
`disabled`. That is now wired. Desired emergency manifests and production
|
||||||
|
values select **`warn`**, not `enforce` — applying the previous enforce
|
||||||
|
manifests was the hazard. CI image `sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b`
|
||||||
|
(`main-3de72fe`, built 2026-08-18T13:25Z) contains the TokenReview flags.
|
||||||
|
The running cluster digest is still unchanged, so `tenancy.current.A`
|
||||||
|
remains 0 while `tenancy.implemented.A` is 2.
|
||||||
|
|
||||||
1. Build and pin a new immutable digest carrying the caller-auth code.
|
**Better path than a global enforce flip.** The two production Deployments
|
||||||
2. Promote it in **`warn` mode**, not `enforce`. The reviewed desired manifests
|
are independently rollable (FLEX-WP-0011). USER-WP-0023-T03 only probes
|
||||||
in `deploy/` select `enforce` because that is the end state — applying them
|
`flex-auth-user-engine`. Serializing that probe on tenant-engine's caller
|
||||||
directly is the hazard. Warn authenticates and logs failures without
|
status would 401 tenant-engine writes if we enforced them together, and
|
||||||
rejecting, so it is safe for an unmigrated caller.
|
would delay user-engine A2 evidence for no safety gain. Sequence:
|
||||||
3. Confirm the warn logs are clean of unauthenticated callers. `user-engine` is
|
|
||||||
migrated and deployed as of 2026-08-18 (image `sha256:c501aeb2…`, token at
|
|
||||||
`/var/run/secrets/flex-auth-caller/token`). `tenant-engine`'s caller status
|
|
||||||
is **unconfirmed — asked 2026-08-18**; promoting `enforce` while their
|
|
||||||
client sends no token 401s every check and blocks their write paths.
|
|
||||||
`ops-warden` adopts the calling side on its own schedule.
|
|
||||||
4. Flip to `enforce`, then capture the live negative probe. `user-engine` has
|
|
||||||
the three assertions written and ready in their
|
|
||||||
`docs/flex-auth-caller-identity.md`; they deliberately have not run it,
|
|
||||||
because against an unenforced digest "no token returns 401" comes back as a
|
|
||||||
normal decision and would record as false evidence.
|
|
||||||
5. Only then may `policy.enabled` flip anywhere — `ops-warden` names that the
|
|
||||||
real deadline, and it is the same gate as FLEX-WP-0007.
|
|
||||||
|
|
||||||
**Operator gate.** Steps 1–4 need cluster credentials this session does not
|
1. Pin the caller-auth digest in overlay + emergency manifests — **done
|
||||||
|
2026-08-19**, first mode `warn` on both consumers.
|
||||||
|
2. Operator: promote each pin in warn via `helm upgrade --install
|
||||||
|
flex-auth-<consumer> charts/flex-auth --namespace flex-auth -f
|
||||||
|
values/<consumer>.yaml`. Isolated canary may boot the same digest with
|
||||||
|
caller-auth disabled. Do not `kubectl apply` an enforce manifest.
|
||||||
|
3. Confirm warn logs per consumer. `user-engine` is migrated and deployed
|
||||||
|
as of 2026-08-18 (image `sha256:c501aeb2…`, token at
|
||||||
|
`/var/run/secrets/flex-auth-caller/token`). `tenant-engine` source and
|
||||||
|
desired manifests already project that token and send it; live digest
|
||||||
|
is still unconfirmed. Warn is safe either way. `ops-warden` adopts the
|
||||||
|
calling side on its own schedule.
|
||||||
|
4. Flip **user-engine only** to `enforce` (`callerAuth.mode: enforce` in
|
||||||
|
`values/user-engine.yaml`, same digest). Then capture the live negative
|
||||||
|
probe from a user-engine pod. The three assertions are already written
|
||||||
|
in user-engine `docs/flex-auth-caller-identity.md`; they must not run
|
||||||
|
against warn, because "no token returns 401" would still be a decision.
|
||||||
|
5. Flip tenant-engine to enforce only after its warn logs are clean.
|
||||||
|
6. Only then may `policy.enabled` flip anywhere — `ops-warden` names that
|
||||||
|
the real deadline, and it is the same gate as FLEX-WP-0007.
|
||||||
|
|
||||||
|
**Operator gate.** Steps 2–5 need cluster credentials this session does not
|
||||||
have: `kubectl` returns `Unauthorized` and the context is `default`, which
|
have: `kubectl` returns `Unauthorized` and the context is `default`, which
|
||||||
`tenant-engine` documented on 2026-08-16 as indistinguishable from a
|
`tenant-engine` documented on 2026-08-16 as indistinguishable from a
|
||||||
wrong-cluster KUBECONFIG. Promotion follows FLEX-WP-0011 staged promotion and
|
wrong-cluster KUBECONFIG. Promotion follows FLEX-WP-0011 and the CI image,
|
||||||
the CI image build, not a hand-built image.
|
not a hand-built image.
|
||||||
|
|
||||||
`RISK-F-0001` (risk-nexus) tracks this A0 externally. Their NetworkPolicy
|
`RISK-F-0001` (risk-nexus) tracks this A0 externally. Their NetworkPolicy
|
||||||
question was answered 2026-08-18: both Deployments carry an ingress policy
|
question was answered 2026-08-18: both Deployments carry an ingress policy
|
||||||
|
|
@ -218,6 +230,7 @@ correct-looking responses, exactly like the two silent pin rollbacks the
|
||||||
estate has already been bitten by.
|
estate has already been bitten by.
|
||||||
|
|
||||||
Completed 2026-08-18. `make verify-posture` checks the current/implemented
|
Completed 2026-08-18. `make verify-posture` checks the current/implemented
|
||||||
distinction, both authenticated handlers, enforce-mode desired manifests,
|
distinction, both authenticated handlers, warn-or-enforce desired manifests
|
||||||
TokenReview RBAC, absence of a latent tenant-engine caller, and the stateless
|
and overlay pins, TokenReview RBAC, absence of a latent tenant-engine caller,
|
||||||
deployment assumptions behind `R: n/a`.
|
and the stateless deployment assumptions behind `R: n/a`. First production
|
||||||
|
pin is warn; enforce is the end state, flipped per consumer.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue