fix(oauth2-proxy): poll keycloak over the backchannel in wait-for-keycloak - #3467
fix(oauth2-proxy): poll keycloak over the backchannel in wait-for-keycloak#3467aweingarten wants to merge 5 commits into
Conversation
…cloak The `wait-for-keycloak` init container polls the public issuer URL (`https://keycloak.<domainSuffix>/realms/otomi`) with a plain `curlimages/curl`. It is sidecar-less by definition, which means it hits two walls the mesh would otherwise hide: - the host is an Istio ServiceEntry with no in-cluster DNS record, so sidecar-less pods can't resolve it at all; - when it does resolve, the Otomi-signed wildcard cert isn't trusted by a vanilla curl image, so it exits 60 (self-signed certificate in certificate chain). Either way the container loops forever and oauth2-proxy never starts, with no chart value exposing the image, a CA mount, or the curl args to work around it. Point the poll at `_derived.oidcBaseUrlBackchannel` — the in-cluster `http://keycloak-keycloakx-http.keycloak:8080/realms/otomi` URL that already exists for exactly this purpose and is used by kubernetes-gateways for its JWKS endpoint. Plain HTTP to a ClusterIP Service: nothing to resolve through the mesh, nothing to trust. The gate itself is unchanged — both URLs return 200 only once the otomi realm is being served, so this changes the route, not the condition. Refs linode#3388, linode#3420
|
The public URL check here isn't just "is Keycloak up", its an end-to-end smoke test (DNS, cert, ingress) gating oauth2-proxy, which is the platform's SSO entrypoint. Switching to oidcBaseUrlBackchannel fixes the sidecar-less DNS/TLS failure, but it also means the gate now passes even when the public path is broken. That defeats the point of gating on it in the first place. If the goal is just don't crashloop forever, maybe worth keeping the public URL but adding CA trust + in-mesh DNS path (mount platform CA, skip the ServiceEntry issue) instead of swapping to backchannel. Otherwise, we lose the one check that verifies real users can actually reach Keycloak. Alternative: make this configurable instead of picking one. Add a value (default true = current public-url behavior) so people who want the real e2e check keep it, and people hitting the DNS/ServiceEntry issue can opt into backchannel. Still need the CA trust fix for the public path though, otherwise the flag is pointless for anyone who leaves it on. |
There was a problem hiding this comment.
Pull request overview
This PR fixes oauth2-proxy startup failures caused by the wait-for-keycloak init container polling Keycloak via the public issuer URL from a sidecar-less pod (where ServiceEntry DNS and custom CA trust can break the curl check). It switches the poll target to the existing backchannel in-cluster URL so the init container can reliably reach Keycloak and unblock oauth2-proxy.
Changes:
- Update
wait-for-keycloakinit container to poll_derived.oidcBaseUrlBackchannelinstead of_derived.oidcBaseUrl. - Add inline template comments documenting why the backchannel URL is required for this sidecar-less init container.
📌 Summary
Fixes #3388 — the oauth2-proxy item (and, for this container, the resolution failure in #3420).
The
wait-for-keycloakinit container polls the public issuer URL with a vanillacurlimages/curl:The oauth2-proxy pod is explicitly sidecar-less (
sidecar.istio.io/inject: "false"), so that URL is reached without the mesh, and it hits one of two walls depending on the deployment:self-signed certificate in certificate chain).Either way the container loops forever and oauth2-proxy never starts. No chart value exposes the init image, a CA mount, or the curl args, so there's no supported way out.
Worth noting the asymmetry this creates: oauth2-proxy's own config already tolerates the untrusted CA —
ssl_insecure_skip_verify = {{ $v._derived.untrustedCA }}— so the gate is currently stricter than the app it gates.The fix points the poll at
_derived.oidcBaseUrlBackchannel(http://keycloak-keycloakx-http.keycloak:8080/realms/otomi), which already exists for exactly this purpose and is used by kubernetes-gateways for its JWKS endpoint. Plain HTTP to a ClusterIP Service: nothing to resolve through the mesh, nothing to trust.🔍 Reviewer Notes
otomirealm is being served; only the route changes. It does not verify the public ingress path — but the init container never usefully verified that either, since it fails on DNS/TLS before reaching Keycloak.--cacert, following thecustom-caSecret pattern in argocd-raw/gitea-raw). Mounting a CA fixes the TLS half but leaves the DNS half, and it adds a Secret + volume + mount where a value that already exists does the whole job. Happy to switch if you'd rather the gate stay on the public URL.otomi.git; Lokiobject_store/schemaConfignot settable through_rawValues) are untouched here — they're independent and larger. Splitting that issue may be worthwhile.curlimages/curl:latestwith no value to override it. That part of the Charts hardcode values that can't be overridden via apl-values #3388 ask stands; it seemed better as its own change.Template-only change.
validate-templates/lint:hfneedhelmfile, which I don't have locally — leaving those to CI.🧹 Checklist
validate-templates