From 8fc4d1997be9aa4d70c4c5d0fd633e77102bb32d Mon Sep 17 00:00:00 2001 From: Bryce Palmer Date: Fri, 14 Aug 2026 14:26:25 -0400 Subject: [PATCH] bugfix: external-oidc: omit client-credential TLS generated config when empty Signed-off-by: Bryce Palmer --- .../generation/oauthapiserver/generate.go | 15 +-- .../oauthapiserver/generate_test.go | 110 ++++++++++++++++++ 2 files changed, 116 insertions(+), 9 deletions(-) diff --git a/pkg/controllers/externaloidc/generation/oauthapiserver/generate.go b/pkg/controllers/externaloidc/generation/oauthapiserver/generate.go index f78c0016b9..5d6dd2c1cf 100644 --- a/pkg/controllers/externaloidc/generation/oauthapiserver/generate.go +++ b/pkg/controllers/externaloidc/generation/oauthapiserver/generate.go @@ -887,14 +887,13 @@ func generateExternalClaimsSourceAuthenticationClientCredential(clientCredential return nil, fmt.Errorf("generating scopes: %w", err) } - var certificateAuthority *string - if len(clientCredentialConfig.TLS.CertificateAuthority.Name) > 0 { - ca, err := getCertificateAuthorityFromConfigMap(clientCredentialConfig.TLS.CertificateAuthority.Name, cmLister) + zeroValueExternalSourceTLS := configv1.ExternalSourceTLS{} + var tls *authenticationv1alpha1.TLS + if clientCredentialConfig.TLS != zeroValueExternalSourceTLS { + tls, err = generateExternalClaimsSourceTLS(clientCredentialConfig.TLS, cmLister) if err != nil { - return nil, fmt.Errorf("getting certificate authority: %w", err) + return nil, err } - - certificateAuthority = &ca } return &authenticationv1alpha1.ClientCredentialConfig{ @@ -902,9 +901,7 @@ func generateExternalClaimsSourceAuthenticationClientCredential(clientCredential ClientSecret: clientSecret, TokenEndpoint: clientCredentialConfig.TokenEndpoint, Scopes: scopes, - TLS: &authenticationv1alpha1.TLS{ - CertificateAuthority: certificateAuthority, - }, + TLS: tls, }, nil } diff --git a/pkg/controllers/externaloidc/generation/oauthapiserver/generate_test.go b/pkg/controllers/externaloidc/generation/oauthapiserver/generate_test.go index e30303c97b..a06cb0b970 100644 --- a/pkg/controllers/externaloidc/generation/oauthapiserver/generate_test.go +++ b/pkg/controllers/externaloidc/generation/oauthapiserver/generate_test.go @@ -1604,6 +1604,116 @@ func TestAuthenticationConfigurationGeneratorGenerateAuthenticationConfiguration }, ), }, + { + name: "valid auth config with external claims source using client credential auth with nil TLS config", + caBundleConfigMap: &baseCABundleConfigMap, + configMapIndexer: func() cache.Indexer { + idx := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{}) + idx.Add(&corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "ext-source-ca-bundle", + Namespace: configNamespace, + }, + Data: map[string]string{ + "ca-bundle.crt": testCertData, + }, + }) + return idx + }(), + secretIndexer: func() cache.Indexer { + idx := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{}) + idx.Add(&corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "client-secret-ref", + Namespace: configNamespace, + }, + Data: map[string][]byte{ + "client-secret": []byte("my-secret-value"), + }, + }) + return idx + }(), + auth: *authWithUpdates(baseAuthResource, []func(auth *configv1.Authentication){ + func(auth *configv1.Authentication) { + for i := range auth.Spec.OIDCProviders { + auth.Spec.OIDCProviders[i].Issuer.URL = "https://example.com" + auth.Spec.OIDCProviders[i].ExternalClaimsSources = []configv1.ExternalClaimsSource{ + { + Authentication: configv1.ExternalSourceAuthentication{ + Type: configv1.ExternalSourceAuthenticationTypeClientCredential, + ClientCredential: configv1.ClientCredentialConfig{ + ClientID: "my-client-id", + ClientSecret: configv1.ClientSecretSecretReference{ + Name: "client-secret-ref", + }, + TokenEndpoint: "https://idp.example.com/oauth2/token", + Scopes: []configv1.OAuth2Scope{"openid", "profile"}, + }, + }, + TLS: configv1.ExternalSourceTLS{ + CertificateAuthority: configv1.ExternalSourceCertificateAuthorityConfigMapReference{ + Name: "ext-source-ca-bundle", + }, + }, + URL: configv1.SourceURL{ + Hostname: "claims.example.com", + PathExpression: "claims.sub", + }, + Mappings: []configv1.SourcedClaimMapping{ + { + Name: "custom_claim", + Expression: "response.custom_claim", + }, + }, + }, + } + } + }, + }), + expectedAuthConfig: authConfigWithUpdates(baseAuthConfig, []func(authConfig *authenticationv1alpha1.AuthenticationConfiguration){ + func(authConfig *authenticationv1alpha1.AuthenticationConfiguration) { + for i := range authConfig.JWT { + authConfig.JWT[i].Issuer.URL = "https://example.com" + authConfig.JWT[i].ExternalClaimsSources = []authenticationv1alpha1.ExternalClaimsSource{ + { + Authentication: &authenticationv1alpha1.Authentication{ + Type: ptr.To(authenticationv1alpha1.AuthenticationTypeClientCredential), + ClientCredential: &authenticationv1alpha1.ClientCredentialConfig{ + ClientID: "my-client-id", + ClientSecret: "my-secret-value", + TokenEndpoint: "https://idp.example.com/oauth2/token", + Scopes: []string{"openid", "profile"}, + }, + }, + TLS: &authenticationv1alpha1.TLS{ + CertificateAuthority: ptr.To(testCertData), + }, + URL: &authenticationv1alpha1.SourceURL{ + Hostname: ptr.To("claims.example.com"), + PathExpression: ptr.To("claims.sub"), + }, + Mappings: []authenticationv1alpha1.SourcedClaimMapping{ + { + Name: ptr.To("custom_claim"), + Expression: ptr.To("response.custom_claim"), + }, + }, + }, + } + } + }, + }), + expectError: false, + featureGates: featuregates.NewFeatureGate( + []configv1.FeatureGateName{ + features.FeatureGateExternalOIDCExternalClaimsSourcing, + }, + []configv1.FeatureGateName{ + features.FeatureGateExternalOIDCWithAdditionalClaimMappings, + features.FeatureGateExternalOIDCWithUpstreamParity, + }, + ), + }, { name: "auth config with external claims source with unknown auth type, error", caBundleConfigMap: &baseCABundleConfigMap,