From 8eb15a924fc5b39eab9a3b9154ea51109b64f5ab Mon Sep 17 00:00:00 2001 From: Ashish Amarnath Date: Tue, 9 Jul 2024 14:24:39 -0700 Subject: [PATCH] integration tests for supervisor oidc, ldap, activedirectory IDP Signed-off-by: Ashish Amarnath --- .../jwtcachefiller/jwtcachefiller.go | 4 +- test/integration/e2e_test.go | 63 ++++++++++++++++++- test/integration/supervisor_login_test.go | 16 ++--- test/testlib/client.go | 4 +- 4 files changed, 73 insertions(+), 14 deletions(-) diff --git a/internal/controller/authenticator/jwtcachefiller/jwtcachefiller.go b/internal/controller/authenticator/jwtcachefiller/jwtcachefiller.go index 952d539bd..870feb0e9 100644 --- a/internal/controller/authenticator/jwtcachefiller/jwtcachefiller.go +++ b/internal/controller/authenticator/jwtcachefiller/jwtcachefiller.go @@ -144,12 +144,12 @@ func New( controllerlib.Config{ Name: controllerName, Syncer: &jwtCacheFillerController{ + namespace: namespace, cache: cache, client: client, jwtAuthenticators: jwtAuthenticators, secretInformer: secretInformer, configMapInformer: configMapInformer, - namespace: namespace, clock: clock, log: log.WithName(controllerName), }, @@ -163,12 +163,12 @@ func New( } type jwtCacheFillerController struct { + namespace string cache *authncache.Cache jwtAuthenticators authinformers.JWTAuthenticatorInformer secretInformer corev1informers.SecretInformer configMapInformer corev1informers.ConfigMapInformer client conciergeclientset.Interface - namespace string clock clock.Clock log plog.Logger } diff --git a/test/integration/e2e_test.go b/test/integration/e2e_test.go index 66aa863a2..1a51c3a3e 100644 --- a/test/integration/e2e_test.go +++ b/test/integration/e2e_test.go @@ -115,11 +115,11 @@ func TestE2EFullIntegration_Browser(t *testing.T) { // Create a JWTAuthenticator that will validate the tokens from the downstream issuer. // If the FederationDomain is not Ready, the JWTAuthenticator cannot be ready, either. clusterAudience := "test-cluster-" + testlib.RandHex(t, 8) - authenticator := testlib.CreateTestJWTAuthenticator(topSetupCtx, t, authenticationv1alpha1.JWTAuthenticatorSpec{ + defaultJWTAuthenticatorSpec := authenticationv1alpha1.JWTAuthenticatorSpec{ Issuer: federationDomain.Spec.Issuer, Audience: clusterAudience, TLS: &authenticationv1alpha1.TLSSpec{CertificateAuthorityData: testCABundleBase64}, - }, authenticationv1alpha1.JWTAuthenticatorPhaseError) + } // Add an OIDC upstream IDP and try using it to authenticate during kubectl commands. t.Run("with Supervisor OIDC upstream IDP and browser flow with with form_post automatic authcode delivery to CLI", func(t *testing.T) { @@ -146,6 +146,7 @@ func TestE2EFullIntegration_Browser(t *testing.T) { Resource: "namespaces", }) + authenticator := testlib.CreateTestJWTAuthenticator(topSetupCtx, t, defaultJWTAuthenticatorSpec, authenticationv1alpha1.JWTAuthenticatorPhaseError) // Create upstream OIDC provider and wait for it to become ready. createdProvider := testlib.CreateTestOIDCIdentityProvider(t, idpv1alpha1.OIDCIdentityProviderSpec{ Issuer: env.SupervisorUpstreamOIDC.Issuer, @@ -232,6 +233,21 @@ func TestE2EFullIntegration_Browser(t *testing.T) { Resource: "namespaces", }) + // in this test, use a secret of type TLS to source ca bundle for the JWT authenticator + caSecret := testlib.CreateTestSecret(t, env.ConciergeNamespace, "ca-cert", corev1.SecretTypeTLS, + map[string]string{ + "ca.crt": string(testCABundlePEM), + "tls.crt": "", + "tls.key": "", + }) + jwtAuthnSpec := defaultJWTAuthenticatorSpec.DeepCopy() + jwtAuthnSpec.TLS.CertificateAuthorityData = "" + jwtAuthnSpec.TLS.CertificateAuthorityDataSource = &authenticationv1alpha1.CABundleSource{ + Kind: "Secret", + Name: caSecret.Name, + Key: "ca.crt", + } + authenticator := testlib.CreateTestJWTAuthenticator(topSetupCtx, t, *jwtAuthnSpec, authenticationv1alpha1.JWTAuthenticatorPhaseError) // Create upstream OIDC provider and wait for it to become ready. createdProvider := testlib.CreateTestOIDCIdentityProvider(t, idpv1alpha1.OIDCIdentityProviderSpec{ Issuer: env.SupervisorUpstreamOIDC.Issuer, @@ -320,6 +336,22 @@ func TestE2EFullIntegration_Browser(t *testing.T) { Resource: "namespaces", }) + // in this test, use a secret of type opaque to source ca bundle for the JWT authenticator + caSecret := testlib.CreateTestSecret(t, env.ConciergeNamespace, "ca-cert", corev1.SecretTypeOpaque, + map[string]string{ + "ca.crt": string(testCABundlePEM), + }) + t.Logf("created secret %s/%s", caSecret.Namespace, caSecret.Name) + jwtAuthnSpec := defaultJWTAuthenticatorSpec.DeepCopy() + jwtAuthnSpec.TLS.CertificateAuthorityData = "" + jwtAuthnSpec.TLS.CertificateAuthorityDataSource = &authenticationv1alpha1.CABundleSource{ + Kind: "Secret", + Name: caSecret.Name, + Key: "ca.crt", + } + + authenticator := testlib.CreateTestJWTAuthenticator(topSetupCtx, t, *jwtAuthnSpec, authenticationv1alpha1.JWTAuthenticatorPhaseError) + t.Logf("authenticator: %s/%s; concierge ns: %s", authenticator.Namespace, authenticator.Name, env.ConciergeNamespace) // Create upstream OIDC provider and wait for it to become ready. createdProvider := testlib.CreateTestOIDCIdentityProvider(t, idpv1alpha1.OIDCIdentityProviderSpec{ Issuer: env.SupervisorUpstreamOIDC.Issuer, @@ -444,6 +476,20 @@ func TestE2EFullIntegration_Browser(t *testing.T) { } } + // in this test, use a configmap to source ca bundle for the JWT authenticator + caConfigMap := testlib.CreateTestConfigMap(t, env.ConciergeNamespace, "ca-cert", + map[string]string{ + "ca.crt": string(testCABundlePEM), + }) + jwtAuthnSpec := defaultJWTAuthenticatorSpec.DeepCopy() + jwtAuthnSpec.TLS.CertificateAuthorityData = "" + jwtAuthnSpec.TLS.CertificateAuthorityDataSource = &authenticationv1alpha1.CABundleSource{ + Kind: "ConfigMap", + Name: caConfigMap.Name, + Key: "ca.crt", + } + + authenticator := testlib.CreateTestJWTAuthenticator(topSetupCtx, t, defaultJWTAuthenticatorSpec, authenticationv1alpha1.JWTAuthenticatorPhaseError) // Create upstream OIDC provider and wait for it to become ready. createdProvider := testlib.CreateTestOIDCIdentityProvider(t, idpv1alpha1.OIDCIdentityProviderSpec{ Issuer: env.SupervisorUpstreamOIDC.Issuer, @@ -574,6 +620,7 @@ func TestE2EFullIntegration_Browser(t *testing.T) { Resource: "namespaces", }) + authenticator := testlib.CreateTestJWTAuthenticator(topSetupCtx, t, defaultJWTAuthenticatorSpec, authenticationv1alpha1.JWTAuthenticatorPhaseError) // Create upstream OIDC provider and wait for it to become ready. createdProvider := testlib.CreateTestOIDCIdentityProvider(t, idpv1alpha1.OIDCIdentityProviderSpec{ Issuer: env.SupervisorUpstreamOIDC.Issuer, @@ -647,6 +694,7 @@ func TestE2EFullIntegration_Browser(t *testing.T) { tempDir := t.TempDir() // per-test tmp dir to avoid sharing files between tests + authenticator := testlib.CreateTestJWTAuthenticator(topSetupCtx, t, defaultJWTAuthenticatorSpec, authenticationv1alpha1.JWTAuthenticatorPhaseError) // Create upstream OIDC provider and wait for it to become ready. oidcIdentityProvider := testlib.CreateTestOIDCIdentityProvider(t, idpv1alpha1.OIDCIdentityProviderSpec{ Issuer: env.SupervisorUpstreamOIDC.Issuer, @@ -728,6 +776,7 @@ func TestE2EFullIntegration_Browser(t *testing.T) { expectedUsername := env.SupervisorUpstreamLDAP.TestUserMailAttributeValue expectedGroups := env.SupervisorUpstreamLDAP.TestUserDirectGroupsDNs + authenticator := testlib.CreateTestJWTAuthenticator(topSetupCtx, t, defaultJWTAuthenticatorSpec, authenticationv1alpha1.JWTAuthenticatorPhaseError) createdProvider := setupClusterForEndToEndLDAPTest(t, expectedUsername, env) testlib.WaitForFederationDomainStatusPhase(testCtx, t, federationDomain.Name, supervisorconfigv1alpha1.FederationDomainPhaseReady) testlib.WaitForJWTAuthenticatorStatusPhase(testCtx, t, authenticator.Name, authenticationv1alpha1.JWTAuthenticatorPhaseReady) @@ -787,6 +836,7 @@ func TestE2EFullIntegration_Browser(t *testing.T) { expectedUsername := env.SupervisorUpstreamLDAP.TestUserMailAttributeValue expectedGroups := env.SupervisorUpstreamLDAP.TestUserDirectGroupsDNs + authenticator := testlib.CreateTestJWTAuthenticator(topSetupCtx, t, defaultJWTAuthenticatorSpec, authenticationv1alpha1.JWTAuthenticatorPhaseError) createdProvider := setupClusterForEndToEndLDAPTest(t, expectedUsername, env) testlib.WaitForFederationDomainStatusPhase(testCtx, t, federationDomain.Name, supervisorconfigv1alpha1.FederationDomainPhaseReady) testlib.WaitForJWTAuthenticatorStatusPhase(testCtx, t, authenticator.Name, authenticationv1alpha1.JWTAuthenticatorPhaseReady) @@ -850,6 +900,7 @@ func TestE2EFullIntegration_Browser(t *testing.T) { expectedUsername := env.SupervisorUpstreamLDAP.TestUserMailAttributeValue expectedGroups := env.SupervisorUpstreamLDAP.TestUserDirectGroupsDNs + authenticator := testlib.CreateTestJWTAuthenticator(topSetupCtx, t, defaultJWTAuthenticatorSpec, authenticationv1alpha1.JWTAuthenticatorPhaseError) createdProvider := setupClusterForEndToEndLDAPTest(t, expectedUsername, env) testlib.WaitForFederationDomainStatusPhase(testCtx, t, federationDomain.Name, supervisorconfigv1alpha1.FederationDomainPhaseReady) testlib.WaitForJWTAuthenticatorStatusPhase(testCtx, t, authenticator.Name, authenticationv1alpha1.JWTAuthenticatorPhaseReady) @@ -921,6 +972,7 @@ func TestE2EFullIntegration_Browser(t *testing.T) { expectedUsername := env.SupervisorUpstreamActiveDirectory.TestUserPrincipalNameValue expectedGroups := env.SupervisorUpstreamActiveDirectory.TestUserIndirectGroupsSAMAccountPlusDomainNames + authenticator := testlib.CreateTestJWTAuthenticator(topSetupCtx, t, defaultJWTAuthenticatorSpec, authenticationv1alpha1.JWTAuthenticatorPhaseError) createdProvider := setupClusterForEndToEndActiveDirectoryTest(t, expectedUsername, env) testlib.WaitForFederationDomainStatusPhase(testCtx, t, federationDomain.Name, supervisorconfigv1alpha1.FederationDomainPhaseReady) testlib.WaitForJWTAuthenticatorStatusPhase(testCtx, t, authenticator.Name, authenticationv1alpha1.JWTAuthenticatorPhaseReady) @@ -980,6 +1032,7 @@ func TestE2EFullIntegration_Browser(t *testing.T) { expectedUsername := env.SupervisorUpstreamActiveDirectory.TestUserPrincipalNameValue expectedGroups := env.SupervisorUpstreamActiveDirectory.TestUserIndirectGroupsSAMAccountPlusDomainNames + authenticator := testlib.CreateTestJWTAuthenticator(topSetupCtx, t, defaultJWTAuthenticatorSpec, authenticationv1alpha1.JWTAuthenticatorPhaseError) createdProvider := setupClusterForEndToEndActiveDirectoryTest(t, expectedUsername, env) testlib.WaitForFederationDomainStatusPhase(testCtx, t, federationDomain.Name, supervisorconfigv1alpha1.FederationDomainPhaseReady) testlib.WaitForJWTAuthenticatorStatusPhase(testCtx, t, authenticator.Name, authenticationv1alpha1.JWTAuthenticatorPhaseReady) @@ -1053,6 +1106,7 @@ func TestE2EFullIntegration_Browser(t *testing.T) { expectedUsername := env.SupervisorUpstreamLDAP.TestUserMailAttributeValue expectedGroups := env.SupervisorUpstreamLDAP.TestUserDirectGroupsDNs + authenticator := testlib.CreateTestJWTAuthenticator(topSetupCtx, t, defaultJWTAuthenticatorSpec, authenticationv1alpha1.JWTAuthenticatorPhaseError) createdProvider := setupClusterForEndToEndLDAPTest(t, expectedUsername, env) testlib.WaitForFederationDomainStatusPhase(testCtx, t, federationDomain.Name, supervisorconfigv1alpha1.FederationDomainPhaseReady) testlib.WaitForJWTAuthenticatorStatusPhase(testCtx, t, authenticator.Name, authenticationv1alpha1.JWTAuthenticatorPhaseReady) @@ -1108,6 +1162,7 @@ func TestE2EFullIntegration_Browser(t *testing.T) { expectedUsername := env.SupervisorUpstreamActiveDirectory.TestUserPrincipalNameValue expectedGroups := env.SupervisorUpstreamActiveDirectory.TestUserIndirectGroupsSAMAccountPlusDomainNames + authenticator := testlib.CreateTestJWTAuthenticator(topSetupCtx, t, defaultJWTAuthenticatorSpec, authenticationv1alpha1.JWTAuthenticatorPhaseError) createdProvider := setupClusterForEndToEndActiveDirectoryTest(t, expectedUsername, env) testlib.WaitForFederationDomainStatusPhase(testCtx, t, federationDomain.Name, supervisorconfigv1alpha1.FederationDomainPhaseReady) testlib.WaitForJWTAuthenticatorStatusPhase(testCtx, t, authenticator.Name, authenticationv1alpha1.JWTAuthenticatorPhaseReady) @@ -1163,6 +1218,7 @@ func TestE2EFullIntegration_Browser(t *testing.T) { expectedUsername := env.SupervisorUpstreamLDAP.TestUserMailAttributeValue expectedGroups := env.SupervisorUpstreamLDAP.TestUserDirectGroupsDNs + authenticator := testlib.CreateTestJWTAuthenticator(topSetupCtx, t, defaultJWTAuthenticatorSpec, authenticationv1alpha1.JWTAuthenticatorPhaseError) createdProvider := setupClusterForEndToEndLDAPTest(t, expectedUsername, env) testlib.WaitForFederationDomainStatusPhase(testCtx, t, federationDomain.Name, supervisorconfigv1alpha1.FederationDomainPhaseReady) testlib.WaitForJWTAuthenticatorStatusPhase(testCtx, t, authenticator.Name, authenticationv1alpha1.JWTAuthenticatorPhaseReady) @@ -1253,6 +1309,7 @@ func TestE2EFullIntegration_Browser(t *testing.T) { ).Name, }, }, idpv1alpha1.GitHubPhaseReady) + authenticator := testlib.CreateTestJWTAuthenticator(topSetupCtx, t, defaultJWTAuthenticatorSpec, authenticationv1alpha1.JWTAuthenticatorPhaseError) testlib.WaitForFederationDomainStatusPhase(testCtx, t, federationDomain.Name, supervisorconfigv1alpha1.FederationDomainPhaseReady) testlib.WaitForJWTAuthenticatorStatusPhase(testCtx, t, authenticator.Name, authenticationv1alpha1.JWTAuthenticatorPhaseReady) @@ -1327,6 +1384,7 @@ func TestE2EFullIntegration_Browser(t *testing.T) { createdLDAPProvider := setupClusterForEndToEndLDAPTest(t, expectedDownstreamLDAPUsername, env) + authenticator := testlib.CreateTestJWTAuthenticator(topSetupCtx, t, defaultJWTAuthenticatorSpec, authenticationv1alpha1.JWTAuthenticatorPhaseError) // Having one IDP should put the FederationDomain into a ready state. testlib.WaitForFederationDomainStatusPhase(testCtx, t, federationDomain.Name, supervisorconfigv1alpha1.FederationDomainPhaseReady) testlib.WaitForJWTAuthenticatorStatusPhase(testCtx, t, authenticator.Name, authenticationv1alpha1.JWTAuthenticatorPhaseReady) @@ -1647,6 +1705,7 @@ func TestE2EFullIntegration_Browser(t *testing.T) { createdLDAPProvider := setupClusterForEndToEndLDAPTest(t, expectedDownstreamLDAPUsername, env) + authenticator := testlib.CreateTestJWTAuthenticator(topSetupCtx, t, defaultJWTAuthenticatorSpec, authenticationv1alpha1.JWTAuthenticatorPhaseError) // Having one IDP should put the FederationDomain into a ready state. testlib.WaitForFederationDomainStatusPhase(testCtx, t, federationDomain.Name, supervisorconfigv1alpha1.FederationDomainPhaseReady) testlib.WaitForJWTAuthenticatorStatusPhase(testCtx, t, authenticator.Name, authenticationv1alpha1.JWTAuthenticatorPhaseReady) diff --git a/test/integration/supervisor_login_test.go b/test/integration/supervisor_login_test.go index 07aa179fd..726d31813 100644 --- a/test/integration/supervisor_login_test.go +++ b/test/integration/supervisor_login_test.go @@ -322,7 +322,6 @@ func TestSupervisorLogin_Browser(t *testing.T) { regexp.QuoteMeta("&sub=") + ".+" + "$" - // TODO: update this test table to add 2 tests per IDP each to source ca bundle from secret and cm tests := []*supervisorLoginTestcase{ { name: "oidc with default username and groups claim settings", @@ -344,7 +343,8 @@ func TestSupervisorLogin_Browser(t *testing.T) { maybeSkip: skipNever, createIDP: func(t *testing.T) string { idpSpec := basicOIDCIdentityProviderSpec() - caData, _ := base64.StdEncoding.DecodeString(idpSpec.TLS.CertificateAuthorityData) + caData, err := base64.StdEncoding.DecodeString(idpSpec.TLS.CertificateAuthorityData) + require.NoError(t, err) caSecret := testlib.CreateTestSecret(t, env.SupervisorNamespace, "ca-cert", corev1.SecretTypeOpaque, map[string]string{ "ca.crt": string(caData), @@ -372,7 +372,8 @@ func TestSupervisorLogin_Browser(t *testing.T) { maybeSkip: skipNever, createIDP: func(t *testing.T) string { idpSpec := basicOIDCIdentityProviderSpec() - caData, _ := base64.StdEncoding.DecodeString(idpSpec.TLS.CertificateAuthorityData) + caData, err := base64.StdEncoding.DecodeString(idpSpec.TLS.CertificateAuthorityData) + require.NoError(t, err) caSecret := testlib.CreateTestSecret(t, env.SupervisorNamespace, "ca-cert", corev1.SecretTypeTLS, map[string]string{ "ca.crt": string(caData), @@ -402,7 +403,8 @@ func TestSupervisorLogin_Browser(t *testing.T) { maybeSkip: skipNever, createIDP: func(t *testing.T) string { idpSpec := basicOIDCIdentityProviderSpec() - caData, _ := base64.StdEncoding.DecodeString(idpSpec.TLS.CertificateAuthorityData) + caData, err := base64.StdEncoding.DecodeString(idpSpec.TLS.CertificateAuthorityData) + require.NoError(t, err) caConfigMap := testlib.CreateTestConfigMap(t, env.SupervisorNamespace, "ca-cert", map[string]string{ "ca.crt": string(caData), }) @@ -430,7 +432,8 @@ func TestSupervisorLogin_Browser(t *testing.T) { maybeSkip: skipNever, createIDP: func(t *testing.T) string { idpSpec := basicOIDCIdentityProviderSpec() - caData, _ := base64.StdEncoding.DecodeString(idpSpec.TLS.CertificateAuthorityData) + caData, err := base64.StdEncoding.DecodeString(idpSpec.TLS.CertificateAuthorityData) + require.NoError(t, err) caSecret := testlib.CreateTestSecret(t, env.SupervisorNamespace, "ca-cert", corev1.SecretTypeOpaque, map[string]string{ "ca.crt": string(caData), @@ -654,7 +657,6 @@ func TestSupervisorLogin_Browser(t *testing.T) { name: "ldap IDP using secrets of type opaque to source ca bundle and with email as username and groups names as DNs and using an LDAP provider which supports TLS", maybeSkip: skipLDAPTests, createIDP: func(t *testing.T) string { - idp, _ := createLDAPIdentityProvider(t, func(spec *idpv1alpha1.LDAPIdentityProviderSpec) { caSecret := testlib.CreateTestSecret(t, env.SupervisorNamespace, "ca-cert", corev1.SecretTypeOpaque, map[string]string{ @@ -705,7 +707,6 @@ func TestSupervisorLogin_Browser(t *testing.T) { name: "ldap IDP using secrets of type TLS to source ca bundle and with email as username and groups names as DNs and using an LDAP provider which supports TLS", maybeSkip: skipLDAPTests, createIDP: func(t *testing.T) string { - idp, _ := createLDAPIdentityProvider(t, func(spec *idpv1alpha1.LDAPIdentityProviderSpec) { caSecret := testlib.CreateTestSecret(t, env.SupervisorNamespace, "ca-cert", corev1.SecretTypeTLS, map[string]string{ @@ -758,7 +759,6 @@ func TestSupervisorLogin_Browser(t *testing.T) { name: "ldap IDP using configmaps to source ca bundle and with email as username and groups names as DNs and using an LDAP provider which supports TLS", maybeSkip: skipLDAPTests, createIDP: func(t *testing.T) string { - idp, _ := createLDAPIdentityProvider(t, func(spec *idpv1alpha1.LDAPIdentityProviderSpec) { caConfigMap := testlib.CreateTestConfigMap(t, env.SupervisorNamespace, "ca-cert", diff --git a/test/testlib/client.go b/test/testlib/client.go index 499a2127f..36f455e82 100644 --- a/test/testlib/client.go +++ b/test/testlib/client.go @@ -470,7 +470,7 @@ func CreateTestConfigMap(t *testing.T, namespace string, baseName string, string err := client.CoreV1().ConfigMaps(namespace).Delete(context.Background(), created.Name, metav1.DeleteOptions{}) require.NoError(t, err) }) - t.Logf("created test ConfigMap %s", created.Name) + t.Logf("created test ConfigMap %s/%s", created.Namespace, created.Name) return created } @@ -492,7 +492,7 @@ func CreateTestSecret(t *testing.T, namespace string, baseName string, secretTyp err := client.CoreV1().Secrets(namespace).Delete(context.Background(), created.Name, metav1.DeleteOptions{}) require.NoError(t, err) }) - t.Logf("created test Secret %s", created.Name) + t.Logf("created test Secret %s/%s", created.Namespace, created.Name) return created }