Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -425,10 +425,17 @@ func TestClientRegistration_EndToEnd_CredentialsAuthenticate(t *testing.T) {
clusterFeatureGatesConfigMap(true),
dep,
authbridgeConfigMapForTest(clientRegistrationTestNamespace, idp.URL()),
keycloakAdminSecretForTest(clientRegistrationTestNamespace),
// keycloak-admin-secret lives in the operator namespace (not the
// agent namespace) after PR #321's security hardening. The
// reconciler reads it from there via OperatorNamespace.
keycloakAdminSecretForTest(clientRegistrationTestOperatorNS),
).Build()

r := &ClientRegistrationReconciler{Client: c, Scheme: scheme}
r := &ClientRegistrationReconciler{
Client: c,
Scheme: scheme,
OperatorNamespace: clientRegistrationTestOperatorNS,
}
res, err := r.Reconcile(ctx, req)
if err != nil || res != (ctrl.Result{}) {
t.Fatalf("Reconcile: result=%v err=%v", res, err)
Expand Down
20 changes: 18 additions & 2 deletions kagenti-operator/internal/webhook/injector/pod_mutator.go
Original file line number Diff line number Diff line change
Expand Up @@ -570,9 +570,16 @@ func perAgentConfigMapName(crName string) string {
//
// The synthesized shape matches what plugins expect:
// - jwt-validation.config.issuer from NamespaceConfig.Issuer
// (rest of the plugin's config comes from its defaults —
// (for matching the JWT `iss` claim — the PUBLIC Keycloak URL in
// split-horizon deployments). keycloak_url + keycloak_realm are
// also passed through so the plugin can derive jwks_url from the
// INTERNAL URL — the sidecar actually GETs this URL from inside
// the cluster, and the public hostname typically won't resolve
// from inside the mesh. See kagenti-extensions#383 for why the
// jwt-validation plugin needs its own copy of these fields.
// Other plugin settings fall back to their own defaults —
// audience_file=/shared/client-id.txt, bypass_paths=standard
// probes, jwks_url derived from issuer).
// probes.
// - token-exchange.config with Keycloak URL/realm, default_policy,
// and identity block keyed off ClientAuthType. File paths fall
// through to plugin defaults so operators don't have to
Expand All @@ -586,6 +593,15 @@ func synthesizePipeline(nsConfig *NamespaceConfig) map[string]interface{} {
if nsConfig.Issuer != "" {
jwtCfg["issuer"] = nsConfig.Issuer
}
// Pass keycloak_url + keycloak_realm through to jwt-validation so
// it can derive jwks_url from the internal URL rather than the
// public issuer. Mirrors the pair already handed to token-exchange.
if nsConfig.KeycloakURL != "" {
jwtCfg["keycloak_url"] = nsConfig.KeycloakURL
}
if nsConfig.KeycloakRealm != "" {
jwtCfg["keycloak_realm"] = nsConfig.KeycloakRealm
}

tokenCfg := map[string]interface{}{}
if nsConfig.KeycloakURL != "" {
Expand Down
10 changes: 10 additions & 0 deletions kagenti-operator/internal/webhook/injector/pod_mutator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,16 @@ func TestEnsurePerAgentConfigMap_EmptyBaseYAML_FallbackFromNsConfig(t *testing.T
if got, want := jwtCfg["issuer"], "http://keycloak:8080/realms/kagenti"; got != want {
t.Errorf("jwt-validation.config.issuer = %v, want %v", got, want)
}
// keycloak_url + keycloak_realm are passed to jwt-validation so the
// plugin derives jwks_url from the internal URL. Required for
// split-horizon deployments where `issuer` (public) isn't reachable
// from inside the pod. See kagenti-extensions#383.
if got, want := jwtCfg["keycloak_url"], "http://keycloak:8080"; got != want {
t.Errorf("jwt-validation.config.keycloak_url = %v, want %v", got, want)
}
if got, want := jwtCfg["keycloak_realm"], "kagenti"; got != want {
t.Errorf("jwt-validation.config.keycloak_realm = %v, want %v", got, want)
}

tokCfg := pluginConfigAt(t, cfg, "outbound", "token-exchange")
if got, want := tokCfg["keycloak_url"], "http://keycloak:8080"; got != want {
Expand Down
Loading