Configurable JWKS URI and in-cluster backendRef for internal JWT auth - #151
Open
tylerpotts wants to merge 2 commits into
Open
Configurable JWKS URI and in-cluster backendRef for internal JWT auth#151tylerpotts wants to merge 2 commits into
tylerpotts wants to merge 2 commits into
Conversation
…WT auth
On private-CA (BYO-cert) deployments, Envoy's JWKS fetcher cannot verify
the external Keycloak certificate: the fetch of
<issuerURL>/protocol/openid-connect/certs hairpins through the gateway,
is served the private-CA cert, and fails against Envoy's public-roots
trust. Every internal-endpoint token is then rejected with
jwt_authn_access_denied{Jwks_remote_fetch_is_failed}, observed as a
continuous ~1/sec async-fetch retry loop in the proxy logs.
Adds pack-level configuration to split key fetching from issuer
validation, mirroring the key-manager's existing external-issuer /
in-cluster-URL split:
- LLM_OIDC_JWKS_URI overrides the JWKS URL (default unchanged).
- LLM_OIDC_JWKS_BACKEND_SERVICE/NAMESPACE/PORT render a
remoteJWKS.backendRefs Service entry on the JWT SecurityPolicies, so
an http:// in-cluster Keycloak URL needs no trust material at all
while issuer keeps validating the external iss claim.
- Chart: auth.oidc.jwks.{uri,backendRef.{name,namespace,port}} plumb the
env vars, and a ReferenceGrant is rendered in the backend Service's
namespace when it differs from the release namespace (cross-namespace
SecurityPolicy backendRefs require one).
- Fixes LLM_OIDC_AUDIENCE never being rendered by the operator
Deployment template despite auth.oidc.audience existing in values.
Applies to both LLMModel and PassthroughModel policies via the shared
buildJWTSecurityPolicy. Requires Envoy Gateway >= v1.2 only when the
backendRef is configured; default rendering is byte-identical to before.
|
📄 Docs preview for |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On private-CA / BYO-cert deployments (the mode
platform.tls.secretNameexists for), the internal endpoint rejects every JWT with:with the proxy stuck in a ~1/sec async JWKS fetch retry loop. Root cause, confirmed on a live cluster (Envoy Gateway v1.6.2): the SecurityPolicy's
remoteJWKS.uriis<issuerURL>/protocol/openid-connect/certs, so Envoy resolves the external Keycloak hostname (hairpinning through its own gateway), is served the private-CA certificate, and fails TLS verification because the JWKS fetcher only trusts public roots. An in-cluster curl of the same URL fails without the CA and succeeds with-k, isolating the failure to trust, not reachability. Policy status isAcceptedthroughout; the failure is purely runtime.Fix
Split key fetching from issuer validation, mirroring the key-manager's existing external-issuer / in-cluster-URL split (
keyManager.keycloak.urlvsissuerURL):LLM_OIDC_JWKS_URI(overrides the JWKS URL; default unchanged) andLLM_OIDC_JWKS_BACKEND_SERVICE/_NAMESPACE/_PORT, which render aremoteJWKS.backendRefsService entry on the JWT SecurityPolicies. With anhttp://in-cluster Keycloak URL plus the backendRef, the key fetch needs no trust material at all, whileissuercontinues to validate the token's externalissclaim. Applies to both LLMModel and PassthroughModel policies via the sharedbuildJWTSecurityPolicy.auth.oidc.jwks.{uri,backendRef.{name,namespace,port}}plumb the env vars, and a ReferenceGrant (from:SecurityPolicyin the release namespace, to: the Service) is rendered in the backend Service's namespace when it differs from the release namespace, which cross-namespacebackendRefsrequire. The operator's ClusterRole already covers everything involved; no RBAC change.LLM_OIDC_AUDIENCEwas never rendered by the operator Deployment template even thoughauth.oidc.audienceexists in values andconfig.goreads it.Default rendering is byte-identical to before;
remoteJWKS.backendRefsrequires Envoy Gateway >= v1.2 only when the backendRef is actually configured.Example values for a private-CA cluster:
Relation to #61
This does not implement OIDC discovery (the JWKS path default is still Keycloak-shaped), but
auth.oidc.jwks.urinow also unblocks non-Keycloak providers by letting deployments state the JWKS URL explicitly. Docs updated accordingly (architecture callouts + configuration table).Testing
make testpasses (envtest suite included; reconcilers at 95.5% coverage).auth_test.go: default URI derivation with no backendRefs, URI override without backend, backendRefs rendering with and without namespace.helm lintpasses;helm templateverified for (a) defaults, byte-identical env/no ReferenceGrant, and (b) full JWKS values, correct env vars plus the ReferenceGrant in the Service's namespace.