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
|
||||
description: Independently rollable flex-auth policy-decision Deployment (one consumer per release).
|
||||
type: application
|
||||
version: 0.1.0
|
||||
version: 0.2.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/part-of: flex-auth
|
||||
{{- 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 }}
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
{{- if eq (include "flex-auth.callerAuth.enabled" .) "true" }}
|
||||
serviceAccountName: {{ include "flex-auth.name" . }}
|
||||
{{- end }}
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
seccompProfile:
|
||||
|
|
@ -25,6 +28,15 @@ spec:
|
|||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
args:
|
||||
{{- 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:
|
||||
- name: http
|
||||
containerPort: {{ .Values.service.port }}
|
||||
|
|
@ -46,3 +58,25 @@ spec:
|
|||
drop:
|
||||
- ALL
|
||||
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:
|
||||
- Ingress
|
||||
- Egress
|
||||
{{- if eq (include "flex-auth.callerAuth.enabled" .) "true" }}
|
||||
egress:
|
||||
- ports:
|
||||
- port: 443
|
||||
protocol: TCP
|
||||
- port: 6443
|
||||
protocol: TCP
|
||||
{{- else }}
|
||||
egress: []
|
||||
{{- end }}
|
||||
{{- if .Values.consumer.isolated }}
|
||||
ingress: []
|
||||
{{- 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: ""
|
||||
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:
|
||||
requests:
|
||||
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
|
||||
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.
|
||||
|
||||
| File | Deployment | Consumer | Service DNS |
|
||||
|
|
@ -86,10 +92,12 @@ last-known-good digest below.
|
|||
|
||||
| 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` *(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 |
|
||||
|
||||
Rolling back the tenant-engine service to `c25fc34a…` restores fail-closed
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ spec:
|
|||
- --policy
|
||||
- /opt/flex-auth/examples/tenant-engine/policy_package.md
|
||||
- --caller-auth-mode
|
||||
- enforce
|
||||
- warn
|
||||
- --caller-kubernetes-url
|
||||
- https://10.43.0.1
|
||||
- --caller-binding
|
||||
- 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:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ spec:
|
|||
- --policy
|
||||
- /opt/flex-auth/examples/user-engine/policy_package.md
|
||||
- --caller-auth-mode
|
||||
- enforce
|
||||
- warn
|
||||
- --caller-kubernetes-url
|
||||
- https://10.43.0.1
|
||||
- --caller-binding
|
||||
- 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:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
|
|
|
|||
|
|
@ -38,9 +38,11 @@ cached across rotation.
|
|||
|
||||
Three modes support promotion: `disabled`, `warn`, and `enforce`. Warn mode
|
||||
records the same authentication failures without logging credentials. It is a
|
||||
bounded migration aid, not a conformant steady state. The reviewed desired
|
||||
manifests select `enforce`; promotion still follows FLEX-WP-0011 and requires a
|
||||
new immutable image digest plus caller rollout evidence.
|
||||
bounded migration aid, not a conformant steady state. The first production pin
|
||||
is `warn` on each independently rollable Deployment; `enforce` is the end
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ volunteer.
|
|||
| Task | |
|
||||
|---|---|
|
||||
| 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 |
|
||||
| T04 | AuthZEN endpoint — `wait`, with a written trigger |
|
||||
| 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`.
|
||||
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
|
||||
|
||||
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 |
|
||||
| --- | --- | --- |
|
||||
| `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` *(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 |
|
||||
|
|
|
|||
12
tenancy.yaml
12
tenancy.yaml
|
|
@ -40,10 +40,11 @@ tenancy:
|
|||
own inputs. Not a defect and not a target for movement.
|
||||
A: >-
|
||||
The running immutable digest still authenticates no caller, so current
|
||||
remains A0. Source and reviewed desired manifests implement A2 with an
|
||||
audience-scoped Kubernetes TokenReview choke point and exact
|
||||
protected-system-to-ServiceAccount bindings. Promotion and a live
|
||||
unbound-request probe remain under FLEX-WP-0011/FLEX-WP-0015-T02.
|
||||
remains A0. Source, overlay, and reviewed desired manifests implement
|
||||
A2 with an audience-scoped Kubernetes TokenReview choke point and exact
|
||||
protected-system-to-ServiceAccount bindings. The first production pin
|
||||
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: >-
|
||||
No tenant data at rest. Tenant scoping in decisions runs through one
|
||||
choke point (internal/decision/engine.go normalizeRequest and the
|
||||
|
|
@ -84,6 +85,7 @@ evidence:
|
|||
- "internal/callerauth/auth.go"
|
||||
- "internal/callerauth/auth_test.go"
|
||||
- "cmd/flex-auth/main_test.go"
|
||||
- "charts/flex-auth/templates/rbac.yaml"
|
||||
- "deploy/caller-auth-rbac.yaml"
|
||||
- "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
|
||||
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"
|
||||
|
|
|
|||
|
|
@ -26,14 +26,36 @@ fail() {
|
|||
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
|
||||
[[ "${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
|
||||
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 'flex-auth-reviewer' "$root/$manifest" || fail "$manifest omits the reviewer token projection"
|
||||
done
|
||||
[[ -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
|
||||
[[ "${declared_a:-0}" -lt 2 ]] || fail "A2 is declared without a caller-authentication choke point"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
name: flex-auth-local
|
||||
image:
|
||||
repository: forgejo.coulomb.social/coulomb/flex-auth
|
||||
digest: sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4
|
||||
digest: sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b
|
||||
args:
|
||||
- serve
|
||||
- --addr
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
name: flex-auth-canary
|
||||
image:
|
||||
repository: forgejo.coulomb.social/coulomb/flex-auth
|
||||
digest: sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4
|
||||
digest: sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b
|
||||
args:
|
||||
- serve
|
||||
- --addr
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
name: flex-auth-canary
|
||||
image:
|
||||
repository: forgejo.coulomb.social/coulomb/flex-auth
|
||||
digest: sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4
|
||||
digest: sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b
|
||||
args:
|
||||
- serve
|
||||
- --addr
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
# 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
|
||||
image:
|
||||
repository: forgejo.coulomb.social/coulomb/flex-auth
|
||||
digest: sha256:1bf060e61122693ce98359c167cc5fe8bdafc84e097e090eaa71af94d0f27cbc
|
||||
digest: sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b
|
||||
args:
|
||||
- serve
|
||||
- --addr
|
||||
|
|
@ -11,6 +13,10 @@ args:
|
|||
- /opt/flex-auth/examples/tenant-engine/registry_snapshot.json
|
||||
- --policy
|
||||
- /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:
|
||||
isolated: false
|
||||
namespace: tenant-engine
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
# 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
|
||||
image:
|
||||
repository: forgejo.coulomb.social/coulomb/flex-auth
|
||||
digest: sha256:1f5290376dc5fcf456dc7a785e394d8b90949dabecd1d3e856f38557149bb5f4
|
||||
digest: sha256:138aa3471c46bca6e814691fa1e6520aedda3dffd743e6b09141ab433afdb64b
|
||||
args:
|
||||
- serve
|
||||
- --addr
|
||||
|
|
@ -11,6 +13,10 @@ args:
|
|||
- /opt/flex-auth/examples/user-engine/registry_snapshot.json
|
||||
- --policy
|
||||
- /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:
|
||||
isolated: false
|
||||
namespace: user-engine
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ related_workplans:
|
|||
- FLEX-WP-0004
|
||||
- FLEX-WP-0011
|
||||
created: "2026-08-17"
|
||||
updated: "2026-08-18"
|
||||
updated: "2026-08-19"
|
||||
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
|
||||
exact `resource.system` → ServiceAccount bindings. Both check endpoints share
|
||||
the choke point; missing/mismatched identity fails 401/403 and reviewer outage
|
||||
fails 503. Unit and handler tests include the required unbound request. Desired
|
||||
manifests select enforce mode and carry narrow TokenReview RBAC. The running
|
||||
digest is unchanged, so `tenancy.current.A` honestly remains 0 while
|
||||
`tenancy.implemented.A` is 2. Source committed as `1e1e077`.
|
||||
fails 503. Unit and handler tests include the required unbound request. Source
|
||||
committed as `1e1e077`.
|
||||
|
||||
**Remaining, in this order — the sequence is a constraint, not a preference.**
|
||||
`ops-warden` ruled on rollout (2026-08-17) and `user-engine` asked for the same:
|
||||
2026-08-19 overlay outcome: the sanctioned Helm chart did not render caller
|
||||
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.
|
||||
2. Promote it in **`warn` mode**, not `enforce`. The reviewed desired manifests
|
||||
in `deploy/` select `enforce` because that is the end state — applying them
|
||||
directly is the hazard. Warn authenticates and logs failures without
|
||||
rejecting, so it is safe for an unmigrated caller.
|
||||
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.
|
||||
**Better path than a global enforce flip.** The two production Deployments
|
||||
are independently rollable (FLEX-WP-0011). USER-WP-0023-T03 only probes
|
||||
`flex-auth-user-engine`. Serializing that probe on tenant-engine's caller
|
||||
status would 401 tenant-engine writes if we enforced them together, and
|
||||
would delay user-engine A2 evidence for no safety gain. Sequence:
|
||||
|
||||
**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
|
||||
`tenant-engine` documented on 2026-08-16 as indistinguishable from a
|
||||
wrong-cluster KUBECONFIG. Promotion follows FLEX-WP-0011 staged promotion and
|
||||
the CI image build, not a hand-built image.
|
||||
wrong-cluster KUBECONFIG. Promotion follows FLEX-WP-0011 and the CI image,
|
||||
not a hand-built image.
|
||||
|
||||
`RISK-F-0001` (risk-nexus) tracks this A0 externally. Their NetworkPolicy
|
||||
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.
|
||||
|
||||
Completed 2026-08-18. `make verify-posture` checks the current/implemented
|
||||
distinction, both authenticated handlers, enforce-mode desired manifests,
|
||||
TokenReview RBAC, absence of a latent tenant-engine caller, and the stateless
|
||||
deployment assumptions behind `R: n/a`.
|
||||
distinction, both authenticated handlers, warn-or-enforce desired manifests
|
||||
and overlay pins, TokenReview RBAC, absence of a latent tenant-engine caller,
|
||||
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