Change sAMAccountName env vars to userPrincipalName
and add E2E ActiveDirectory test also fixed regexes in supervisor_login_test to be anchored to the beginning and end
This commit is contained in:
parent
1c5a2b8892
commit
6f221678df
@ -298,7 +298,7 @@ func (c *activeDirectoryWatcherController) Sync(ctx controllerlib.Context) error
|
|||||||
func (c *activeDirectoryWatcherController) validateUpstream(ctx context.Context, upstream *v1alpha1.ActiveDirectoryIdentityProvider) (p provider.UpstreamLDAPIdentityProviderI, requeue bool) {
|
func (c *activeDirectoryWatcherController) validateUpstream(ctx context.Context, upstream *v1alpha1.ActiveDirectoryIdentityProvider) (p provider.UpstreamLDAPIdentityProviderI, requeue bool) {
|
||||||
spec := upstream.Spec
|
spec := upstream.Spec
|
||||||
|
|
||||||
adUpstreamImpl := activeDirectoryUpstreamGenericLDAPImpl{*upstream}
|
adUpstreamImpl := &activeDirectoryUpstreamGenericLDAPImpl{activeDirectoryIdentityProvider: *upstream}
|
||||||
|
|
||||||
config := &upstreamldap.ProviderConfig{
|
config := &upstreamldap.ProviderConfig{
|
||||||
Name: upstream.Name,
|
Name: upstream.Name,
|
||||||
@ -322,7 +322,7 @@ func (c *activeDirectoryWatcherController) validateUpstream(ctx context.Context,
|
|||||||
config.GroupAttributeParsingOverrides = map[string]func(*ldap.Entry) (string, error){defaultActiveDirectoryGroupNameAttributeName: upstreamldap.GroupSAMAccountNameWithDomainSuffix}
|
config.GroupAttributeParsingOverrides = map[string]func(*ldap.Entry) (string, error){defaultActiveDirectoryGroupNameAttributeName: upstreamldap.GroupSAMAccountNameWithDomainSuffix}
|
||||||
}
|
}
|
||||||
|
|
||||||
conditions := upstreamwatchers.ValidateGenericLDAP(ctx, &adUpstreamImpl, c.secretInformer, c.validatedSecretVersionsCache, config)
|
conditions := upstreamwatchers.ValidateGenericLDAP(ctx, adUpstreamImpl, c.secretInformer, c.validatedSecretVersionsCache, config)
|
||||||
|
|
||||||
c.updateStatus(ctx, upstream, conditions.Conditions())
|
c.updateStatus(ctx, upstream, conditions.Conditions())
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ const (
|
|||||||
ErrNoCertificates = constable.Error("no certificates found")
|
ErrNoCertificates = constable.Error("no certificates found")
|
||||||
|
|
||||||
LDAPBindAccountSecretType = corev1.SecretTypeBasicAuth
|
LDAPBindAccountSecretType = corev1.SecretTypeBasicAuth
|
||||||
TestLDAPConnectionTimeout = 90 * time.Second
|
probeLDAPTimeout = 90 * time.Second
|
||||||
|
|
||||||
// Constants related to conditions.
|
// Constants related to conditions.
|
||||||
typeBindSecretValid = "BindSecretValid"
|
typeBindSecretValid = "BindSecretValid"
|
||||||
@ -290,7 +290,7 @@ func ValidateGenericLDAP(ctx context.Context, upstream UpstreamGenericLDAPIDP, s
|
|||||||
var ldapConnectionValidCondition *v1alpha1.Condition
|
var ldapConnectionValidCondition *v1alpha1.Condition
|
||||||
var searchBaseFoundCondition *v1alpha1.Condition
|
var searchBaseFoundCondition *v1alpha1.Condition
|
||||||
if secretValidCondition.Status == v1alpha1.ConditionTrue && tlsValidCondition.Status == v1alpha1.ConditionTrue {
|
if secretValidCondition.Status == v1alpha1.ConditionTrue && tlsValidCondition.Status == v1alpha1.ConditionTrue {
|
||||||
ldapConnectionValidCondition, searchBaseFoundCondition = validateAndSetLDAPServerConnectivity(ctx, validatedSecretVersionsCache, upstream, config, currentSecretVersion)
|
ldapConnectionValidCondition, searchBaseFoundCondition = validateAndSetLDAPServerConnectivityAndSearchBase(ctx, validatedSecretVersionsCache, upstream, config, currentSecretVersion)
|
||||||
if ldapConnectionValidCondition != nil {
|
if ldapConnectionValidCondition != nil {
|
||||||
conditions.Append(ldapConnectionValidCondition, false)
|
conditions.Append(ldapConnectionValidCondition, false)
|
||||||
}
|
}
|
||||||
@ -301,10 +301,10 @@ func ValidateGenericLDAP(ctx context.Context, upstream UpstreamGenericLDAPIDP, s
|
|||||||
return conditions
|
return conditions
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateAndSetLDAPServerConnectivity(ctx context.Context, validatedSecretVersionsCache *SecretVersionCache, upstream UpstreamGenericLDAPIDP, config *upstreamldap.ProviderConfig, currentSecretVersion string) (*v1alpha1.Condition, *v1alpha1.Condition) {
|
func validateAndSetLDAPServerConnectivityAndSearchBase(ctx context.Context, validatedSecretVersionsCache *SecretVersionCache, upstream UpstreamGenericLDAPIDP, config *upstreamldap.ProviderConfig, currentSecretVersion string) (*v1alpha1.Condition, *v1alpha1.Condition) {
|
||||||
var ldapConnectionValidCondition *v1alpha1.Condition
|
var ldapConnectionValidCondition *v1alpha1.Condition
|
||||||
if !HasPreviousSuccessfulTLSConnectionConditionForCurrentSpecGenerationAndSecretVersion(validatedSecretVersionsCache, upstream.Generation(), upstream.Status().Conditions(), upstream.Name(), currentSecretVersion, config) {
|
if !HasPreviousSuccessfulTLSConnectionConditionForCurrentSpecGenerationAndSecretVersion(validatedSecretVersionsCache, upstream.Generation(), upstream.Status().Conditions(), upstream.Name(), currentSecretVersion, config) {
|
||||||
testConnectionTimeout, cancelFunc := context.WithTimeout(ctx, TestLDAPConnectionTimeout)
|
testConnectionTimeout, cancelFunc := context.WithTimeout(ctx, probeLDAPTimeout)
|
||||||
defer cancelFunc()
|
defer cancelFunc()
|
||||||
|
|
||||||
ldapConnectionValidCondition = TestConnection(testConnectionTimeout, upstream.Spec().BindSecretName(), config, currentSecretVersion)
|
ldapConnectionValidCondition = TestConnection(testConnectionTimeout, upstream.Spec().BindSecretName(), config, currentSecretVersion)
|
||||||
@ -321,7 +321,11 @@ func validateAndSetLDAPServerConnectivity(ctx context.Context, validatedSecretVe
|
|||||||
}
|
}
|
||||||
var searchBaseFoundCondition *v1alpha1.Condition
|
var searchBaseFoundCondition *v1alpha1.Condition
|
||||||
if !HasPreviousSuccessfulSearchBaseConditionForCurrentGeneration(validatedSecretVersionsCache, upstream.Generation(), upstream.Status().Conditions(), upstream.Name(), currentSecretVersion, config) {
|
if !HasPreviousSuccessfulSearchBaseConditionForCurrentGeneration(validatedSecretVersionsCache, upstream.Generation(), upstream.Status().Conditions(), upstream.Name(), currentSecretVersion, config) {
|
||||||
searchBaseFoundCondition = upstream.Spec().DetectAndSetSearchBase(ctx, config)
|
searchBaseTimeout, cancelFunc := context.WithTimeout(ctx, probeLDAPTimeout)
|
||||||
|
defer cancelFunc()
|
||||||
|
|
||||||
|
searchBaseFoundCondition = upstream.Spec().DetectAndSetSearchBase(searchBaseTimeout, config)
|
||||||
|
|
||||||
validatedSettings := validatedSecretVersionsCache.ValidatedSettingsByName[upstream.Name()]
|
validatedSettings := validatedSecretVersionsCache.ValidatedSettingsByName[upstream.Name()]
|
||||||
validatedSettings.GroupSearchBase = config.GroupSearch.Base
|
validatedSettings.GroupSearchBase = config.GroupSearch.Base
|
||||||
validatedSettings.UserSearchBase = config.UserSearch.Base
|
validatedSettings.UserSearchBase = config.UserSearch.Base
|
||||||
|
@ -660,6 +660,139 @@ func TestE2EFullIntegration(t *testing.T) {
|
|||||||
expectedGroups,
|
expectedGroups,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Add an Active Directory upstream IDP and try using it to authenticate during kubectl commands
|
||||||
|
// by interacting with the CLI's username and password prompts.
|
||||||
|
t.Run("with Supervisor ActiveDirectory upstream IDP using username and password prompts", func(t *testing.T) {
|
||||||
|
if len(env.ToolsNamespace) == 0 && !env.HasCapability(testlib.CanReachInternetLDAPPorts) {
|
||||||
|
t.Skip("Active Directory integration test requires connectivity to an LDAP server")
|
||||||
|
}
|
||||||
|
if env.SupervisorUpstreamActiveDirectory.Host == "" {
|
||||||
|
t.Skip("Active Directory hostname not specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedUsername := env.SupervisorUpstreamActiveDirectory.TestUserPrincipalNameValue
|
||||||
|
expectedGroups := env.SupervisorUpstreamActiveDirectory.TestUserIndirectGroupsSAMAccountPlusDomainNames
|
||||||
|
|
||||||
|
setupClusterForEndToEndActiveDirectoryTest(t, expectedUsername, env)
|
||||||
|
|
||||||
|
// Use a specific session cache for this test.
|
||||||
|
sessionCachePath := tempDir + "/ad-test-sessions.yaml"
|
||||||
|
|
||||||
|
kubeconfigPath := runPinnipedGetKubeconfig(t, env, pinnipedExe, tempDir, []string{
|
||||||
|
"get", "kubeconfig",
|
||||||
|
"--concierge-api-group-suffix", env.APIGroupSuffix,
|
||||||
|
"--concierge-authenticator-type", "jwt",
|
||||||
|
"--concierge-authenticator-name", authenticator.Name,
|
||||||
|
"--oidc-session-cache", sessionCachePath,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Run "kubectl get namespaces" which should trigger an LDAP-style login CLI prompt via the plugin.
|
||||||
|
start := time.Now()
|
||||||
|
kubectlCmd := exec.CommandContext(ctx, "kubectl", "get", "namespace", "--kubeconfig", kubeconfigPath)
|
||||||
|
kubectlCmd.Env = append(os.Environ(), env.ProxyEnv()...)
|
||||||
|
ptyFile, err := pty.Start(kubectlCmd)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Wait for the subprocess to print the username prompt, then type the user's username.
|
||||||
|
readFromFileUntilStringIsSeen(t, ptyFile, "Username: ")
|
||||||
|
_, err = ptyFile.WriteString(expectedUsername + "\n")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Wait for the subprocess to print the password prompt, then type the user's password.
|
||||||
|
readFromFileUntilStringIsSeen(t, ptyFile, "Password: ")
|
||||||
|
_, err = ptyFile.WriteString(env.SupervisorUpstreamActiveDirectory.TestUserPassword + "\n")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Read all output from the subprocess until EOF.
|
||||||
|
// Ignore any errors returned because there is always an error on linux.
|
||||||
|
kubectlOutputBytes, _ := ioutil.ReadAll(ptyFile)
|
||||||
|
requireKubectlGetNamespaceOutput(t, env, string(kubectlOutputBytes))
|
||||||
|
|
||||||
|
t.Logf("first kubectl command took %s", time.Since(start).String())
|
||||||
|
|
||||||
|
requireUserCanUseKubectlWithoutAuthenticatingAgain(ctx, t, env,
|
||||||
|
downstream,
|
||||||
|
kubeconfigPath,
|
||||||
|
sessionCachePath,
|
||||||
|
pinnipedExe,
|
||||||
|
expectedUsername,
|
||||||
|
expectedGroups,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Add an ActiveDirectory upstream IDP and try using it to authenticate during kubectl commands
|
||||||
|
// by passing username and password via environment variables, thus avoiding the CLI's username and password prompts.
|
||||||
|
t.Run("with Supervisor ActiveDirectory upstream IDP using PINNIPED_USERNAME and PINNIPED_PASSWORD env vars", func(t *testing.T) {
|
||||||
|
if len(env.ToolsNamespace) == 0 && !env.HasCapability(testlib.CanReachInternetLDAPPorts) {
|
||||||
|
t.Skip("ActiveDirectory integration test requires connectivity to an LDAP server")
|
||||||
|
}
|
||||||
|
|
||||||
|
if env.SupervisorUpstreamActiveDirectory.Host == "" {
|
||||||
|
t.Skip("Active Directory hostname not specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedUsername := env.SupervisorUpstreamActiveDirectory.TestUserPrincipalNameValue
|
||||||
|
expectedGroups := env.SupervisorUpstreamActiveDirectory.TestUserIndirectGroupsSAMAccountPlusDomainNames
|
||||||
|
|
||||||
|
setupClusterForEndToEndActiveDirectoryTest(t, expectedUsername, env)
|
||||||
|
|
||||||
|
// Use a specific session cache for this test.
|
||||||
|
sessionCachePath := tempDir + "/ad-test-with-env-vars-sessions.yaml"
|
||||||
|
|
||||||
|
kubeconfigPath := runPinnipedGetKubeconfig(t, env, pinnipedExe, tempDir, []string{
|
||||||
|
"get", "kubeconfig",
|
||||||
|
"--concierge-api-group-suffix", env.APIGroupSuffix,
|
||||||
|
"--concierge-authenticator-type", "jwt",
|
||||||
|
"--concierge-authenticator-name", authenticator.Name,
|
||||||
|
"--oidc-session-cache", sessionCachePath,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Set up the username and password env vars to avoid the interactive prompts.
|
||||||
|
const usernameEnvVar = "PINNIPED_USERNAME"
|
||||||
|
originalUsername, hadOriginalUsername := os.LookupEnv(usernameEnvVar)
|
||||||
|
t.Cleanup(func() {
|
||||||
|
if hadOriginalUsername {
|
||||||
|
require.NoError(t, os.Setenv(usernameEnvVar, originalUsername))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
require.NoError(t, os.Setenv(usernameEnvVar, expectedUsername))
|
||||||
|
const passwordEnvVar = "PINNIPED_PASSWORD" //nolint:gosec // this is not a credential
|
||||||
|
originalPassword, hadOriginalPassword := os.LookupEnv(passwordEnvVar)
|
||||||
|
t.Cleanup(func() {
|
||||||
|
if hadOriginalPassword {
|
||||||
|
require.NoError(t, os.Setenv(passwordEnvVar, originalPassword))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
require.NoError(t, os.Setenv(passwordEnvVar, env.SupervisorUpstreamActiveDirectory.TestUserPassword))
|
||||||
|
|
||||||
|
// Run "kubectl get namespaces" which should run an LDAP-style login without interactive prompts for username and password.
|
||||||
|
start := time.Now()
|
||||||
|
kubectlCmd := exec.CommandContext(ctx, "kubectl", "get", "namespace", "--kubeconfig", kubeconfigPath)
|
||||||
|
kubectlCmd.Env = append(os.Environ(), env.ProxyEnv()...)
|
||||||
|
ptyFile, err := pty.Start(kubectlCmd)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Read all output from the subprocess until EOF.
|
||||||
|
// Ignore any errors returned because there is always an error on linux.
|
||||||
|
kubectlOutputBytes, _ := ioutil.ReadAll(ptyFile)
|
||||||
|
requireKubectlGetNamespaceOutput(t, env, string(kubectlOutputBytes))
|
||||||
|
|
||||||
|
t.Logf("first kubectl command took %s", time.Since(start).String())
|
||||||
|
|
||||||
|
// The next kubectl command should not require auth, so we should be able to run it without these env vars.
|
||||||
|
require.NoError(t, os.Unsetenv(usernameEnvVar))
|
||||||
|
require.NoError(t, os.Unsetenv(passwordEnvVar))
|
||||||
|
|
||||||
|
requireUserCanUseKubectlWithoutAuthenticatingAgain(ctx, t, env,
|
||||||
|
downstream,
|
||||||
|
kubeconfigPath,
|
||||||
|
sessionCachePath,
|
||||||
|
pinnipedExe,
|
||||||
|
expectedUsername,
|
||||||
|
expectedGroups,
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupClusterForEndToEndLDAPTest(t *testing.T, username string, env *testlib.TestEnv) {
|
func setupClusterForEndToEndLDAPTest(t *testing.T, username string, env *testlib.TestEnv) {
|
||||||
@ -710,6 +843,39 @@ func setupClusterForEndToEndLDAPTest(t *testing.T, username string, env *testlib
|
|||||||
}, idpv1alpha1.LDAPPhaseReady)
|
}, idpv1alpha1.LDAPPhaseReady)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setupClusterForEndToEndActiveDirectoryTest(t *testing.T, username string, env *testlib.TestEnv) {
|
||||||
|
// Create a ClusterRoleBinding to give our test user from the upstream read-only access to the cluster.
|
||||||
|
testlib.CreateTestClusterRoleBinding(t,
|
||||||
|
rbacv1.Subject{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: username},
|
||||||
|
rbacv1.RoleRef{Kind: "ClusterRole", APIGroup: rbacv1.GroupName, Name: "view"},
|
||||||
|
)
|
||||||
|
testlib.WaitForUserToHaveAccess(t, username, []string{}, &authorizationv1.ResourceAttributes{
|
||||||
|
Verb: "get",
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Resource: "namespaces",
|
||||||
|
})
|
||||||
|
|
||||||
|
// Put the bind service account's info into a Secret.
|
||||||
|
bindSecret := testlib.CreateTestSecret(t, env.SupervisorNamespace, "ldap-service-account", corev1.SecretTypeBasicAuth,
|
||||||
|
map[string]string{
|
||||||
|
corev1.BasicAuthUsernameKey: env.SupervisorUpstreamActiveDirectory.BindUsername,
|
||||||
|
corev1.BasicAuthPasswordKey: env.SupervisorUpstreamActiveDirectory.BindPassword,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create upstream LDAP provider and wait for it to become ready.
|
||||||
|
testlib.CreateTestActiveDirectoryIdentityProvider(t, idpv1alpha1.ActiveDirectoryIdentityProviderSpec{
|
||||||
|
Host: env.SupervisorUpstreamActiveDirectory.Host,
|
||||||
|
TLS: &idpv1alpha1.TLSSpec{
|
||||||
|
CertificateAuthorityData: base64.StdEncoding.EncodeToString([]byte(env.SupervisorUpstreamActiveDirectory.CABundle)),
|
||||||
|
},
|
||||||
|
Bind: idpv1alpha1.ActiveDirectoryIdentityProviderBind{
|
||||||
|
SecretName: bindSecret.Name,
|
||||||
|
},
|
||||||
|
}, idpv1alpha1.ActiveDirectoryPhaseReady)
|
||||||
|
}
|
||||||
|
|
||||||
func readFromFileUntilStringIsSeen(t *testing.T, f *os.File, until string) string {
|
func readFromFileUntilStringIsSeen(t *testing.T, f *os.File, until string) string {
|
||||||
readFromFile := ""
|
readFromFile := ""
|
||||||
|
|
||||||
|
@ -69,9 +69,9 @@ func TestSupervisorLogin(t *testing.T) {
|
|||||||
},
|
},
|
||||||
requestAuthorization: requestAuthorizationUsingBrowserAuthcodeFlow,
|
requestAuthorization: requestAuthorizationUsingBrowserAuthcodeFlow,
|
||||||
// the ID token Subject should include the upstream user ID after the upstream issuer name
|
// the ID token Subject should include the upstream user ID after the upstream issuer name
|
||||||
wantDownstreamIDTokenSubjectToMatch: regexp.QuoteMeta(env.SupervisorUpstreamOIDC.Issuer+"?sub=") + ".+",
|
wantDownstreamIDTokenSubjectToMatch: "^" + regexp.QuoteMeta(env.SupervisorUpstreamOIDC.Issuer+"?sub=") + ".+",
|
||||||
// the ID token Username should include the upstream user ID after the upstream issuer name
|
// the ID token Username should include the upstream user ID after the upstream issuer name
|
||||||
wantDownstreamIDTokenUsernameToMatch: regexp.QuoteMeta(env.SupervisorUpstreamOIDC.Issuer+"?sub=") + ".+",
|
wantDownstreamIDTokenUsernameToMatch: "^" + regexp.QuoteMeta(env.SupervisorUpstreamOIDC.Issuer+"?sub=") + ".+",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "oidc with custom username and groups claim settings",
|
name: "oidc with custom username and groups claim settings",
|
||||||
@ -98,8 +98,8 @@ func TestSupervisorLogin(t *testing.T) {
|
|||||||
}, idpv1alpha1.PhaseReady)
|
}, idpv1alpha1.PhaseReady)
|
||||||
},
|
},
|
||||||
requestAuthorization: requestAuthorizationUsingBrowserAuthcodeFlow,
|
requestAuthorization: requestAuthorizationUsingBrowserAuthcodeFlow,
|
||||||
wantDownstreamIDTokenSubjectToMatch: regexp.QuoteMeta(env.SupervisorUpstreamOIDC.Issuer+"?sub=") + ".+",
|
wantDownstreamIDTokenSubjectToMatch: "^" + regexp.QuoteMeta(env.SupervisorUpstreamOIDC.Issuer+"?sub=") + ".+",
|
||||||
wantDownstreamIDTokenUsernameToMatch: regexp.QuoteMeta(env.SupervisorUpstreamOIDC.Username),
|
wantDownstreamIDTokenUsernameToMatch: "^" + regexp.QuoteMeta(env.SupervisorUpstreamOIDC.Username) + "$",
|
||||||
wantDownstreamIDTokenGroups: env.SupervisorUpstreamOIDC.ExpectedGroups,
|
wantDownstreamIDTokenGroups: env.SupervisorUpstreamOIDC.ExpectedGroups,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -132,9 +132,9 @@ func TestSupervisorLogin(t *testing.T) {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
// the ID token Subject should include the upstream user ID after the upstream issuer name
|
// the ID token Subject should include the upstream user ID after the upstream issuer name
|
||||||
wantDownstreamIDTokenSubjectToMatch: regexp.QuoteMeta(env.SupervisorUpstreamOIDC.Issuer+"?sub=") + ".+",
|
wantDownstreamIDTokenSubjectToMatch: "^" + regexp.QuoteMeta(env.SupervisorUpstreamOIDC.Issuer+"?sub=") + ".+",
|
||||||
// the ID token Username should include the upstream user ID after the upstream issuer name
|
// the ID token Username should include the upstream user ID after the upstream issuer name
|
||||||
wantDownstreamIDTokenUsernameToMatch: regexp.QuoteMeta(env.SupervisorUpstreamOIDC.Issuer+"?sub=") + ".+",
|
wantDownstreamIDTokenUsernameToMatch: "^" + regexp.QuoteMeta(env.SupervisorUpstreamOIDC.Issuer+"?sub=") + ".+",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ldap with email as username and groups names as DNs and using an LDAP provider which supports TLS",
|
name: "ldap with email as username and groups names as DNs and using an LDAP provider which supports TLS",
|
||||||
@ -193,13 +193,13 @@ func TestSupervisorLogin(t *testing.T) {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
// the ID token Subject should be the Host URL plus the value pulled from the requested UserSearch.Attributes.UID attribute
|
// the ID token Subject should be the Host URL plus the value pulled from the requested UserSearch.Attributes.UID attribute
|
||||||
wantDownstreamIDTokenSubjectToMatch: regexp.QuoteMeta(
|
wantDownstreamIDTokenSubjectToMatch: "^" + regexp.QuoteMeta(
|
||||||
"ldaps://" + env.SupervisorUpstreamLDAP.Host +
|
"ldaps://"+env.SupervisorUpstreamLDAP.Host+
|
||||||
"?base=" + url.QueryEscape(env.SupervisorUpstreamLDAP.UserSearchBase) +
|
"?base="+url.QueryEscape(env.SupervisorUpstreamLDAP.UserSearchBase)+
|
||||||
"&sub=" + base64.RawURLEncoding.EncodeToString([]byte(env.SupervisorUpstreamLDAP.TestUserUniqueIDAttributeValue)),
|
"&sub="+base64.RawURLEncoding.EncodeToString([]byte(env.SupervisorUpstreamLDAP.TestUserUniqueIDAttributeValue)),
|
||||||
),
|
) + "$",
|
||||||
// the ID token Username should have been pulled from the requested UserSearch.Attributes.Username attribute
|
// the ID token Username should have been pulled from the requested UserSearch.Attributes.Username attribute
|
||||||
wantDownstreamIDTokenUsernameToMatch: regexp.QuoteMeta(env.SupervisorUpstreamLDAP.TestUserMailAttributeValue),
|
wantDownstreamIDTokenUsernameToMatch: "^" + regexp.QuoteMeta(env.SupervisorUpstreamLDAP.TestUserMailAttributeValue) + "$",
|
||||||
wantDownstreamIDTokenGroups: env.SupervisorUpstreamLDAP.TestUserDirectGroupsDNs,
|
wantDownstreamIDTokenGroups: env.SupervisorUpstreamLDAP.TestUserDirectGroupsDNs,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -259,13 +259,13 @@ func TestSupervisorLogin(t *testing.T) {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
// the ID token Subject should be the Host URL plus the value pulled from the requested UserSearch.Attributes.UID attribute
|
// the ID token Subject should be the Host URL plus the value pulled from the requested UserSearch.Attributes.UID attribute
|
||||||
wantDownstreamIDTokenSubjectToMatch: regexp.QuoteMeta(
|
wantDownstreamIDTokenSubjectToMatch: "^" + regexp.QuoteMeta(
|
||||||
"ldaps://" + env.SupervisorUpstreamLDAP.StartTLSOnlyHost +
|
"ldaps://"+env.SupervisorUpstreamLDAP.StartTLSOnlyHost+
|
||||||
"?base=" + url.QueryEscape(env.SupervisorUpstreamLDAP.UserSearchBase) +
|
"?base="+url.QueryEscape(env.SupervisorUpstreamLDAP.UserSearchBase)+
|
||||||
"&sub=" + base64.RawURLEncoding.EncodeToString([]byte(env.SupervisorUpstreamLDAP.TestUserUniqueIDAttributeValue)),
|
"&sub="+base64.RawURLEncoding.EncodeToString([]byte(env.SupervisorUpstreamLDAP.TestUserUniqueIDAttributeValue)),
|
||||||
),
|
) + "$",
|
||||||
// the ID token Username should have been pulled from the requested UserSearch.Attributes.Username attribute
|
// the ID token Username should have been pulled from the requested UserSearch.Attributes.Username attribute
|
||||||
wantDownstreamIDTokenUsernameToMatch: regexp.QuoteMeta(env.SupervisorUpstreamLDAP.TestUserDN),
|
wantDownstreamIDTokenUsernameToMatch: "^" + regexp.QuoteMeta(env.SupervisorUpstreamLDAP.TestUserDN) + "$",
|
||||||
wantDownstreamIDTokenGroups: env.SupervisorUpstreamLDAP.TestUserDirectGroupsCNs,
|
wantDownstreamIDTokenGroups: env.SupervisorUpstreamLDAP.TestUserDirectGroupsCNs,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -372,13 +372,13 @@ func TestSupervisorLogin(t *testing.T) {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
// the ID token Subject should be the Host URL plus the value pulled from the requested UserSearch.Attributes.UID attribute
|
// the ID token Subject should be the Host URL plus the value pulled from the requested UserSearch.Attributes.UID attribute
|
||||||
wantDownstreamIDTokenSubjectToMatch: regexp.QuoteMeta(
|
wantDownstreamIDTokenSubjectToMatch: "^" + regexp.QuoteMeta(
|
||||||
"ldaps://" + env.SupervisorUpstreamActiveDirectory.Host +
|
"ldaps://"+env.SupervisorUpstreamActiveDirectory.Host+
|
||||||
"?base=" + url.QueryEscape(env.SupervisorUpstreamActiveDirectory.DefaultNamingContextSearchBase) +
|
"?base="+url.QueryEscape(env.SupervisorUpstreamActiveDirectory.DefaultNamingContextSearchBase)+
|
||||||
"&sub=" + env.SupervisorUpstreamActiveDirectory.TestUserUniqueIDAttributeValue,
|
"&sub="+env.SupervisorUpstreamActiveDirectory.TestUserUniqueIDAttributeValue,
|
||||||
),
|
) + "$",
|
||||||
// the ID token Username should have been pulled from the requested UserSearch.Attributes.Username attribute
|
// the ID token Username should have been pulled from the requested UserSearch.Attributes.Username attribute
|
||||||
wantDownstreamIDTokenUsernameToMatch: regexp.QuoteMeta(env.SupervisorUpstreamActiveDirectory.TestUserPrincipalNameValue),
|
wantDownstreamIDTokenUsernameToMatch: "^" + regexp.QuoteMeta(env.SupervisorUpstreamActiveDirectory.TestUserPrincipalNameValue) + "$",
|
||||||
wantDownstreamIDTokenGroups: env.SupervisorUpstreamActiveDirectory.TestUserIndirectGroupsSAMAccountPlusDomainNames,
|
wantDownstreamIDTokenGroups: env.SupervisorUpstreamActiveDirectory.TestUserIndirectGroupsSAMAccountPlusDomainNames,
|
||||||
}, {
|
}, {
|
||||||
name: "activedirectory with custom options",
|
name: "activedirectory with custom options",
|
||||||
@ -439,13 +439,13 @@ func TestSupervisorLogin(t *testing.T) {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
// the ID token Subject should be the Host URL plus the value pulled from the requested UserSearch.Attributes.UID attribute
|
// the ID token Subject should be the Host URL plus the value pulled from the requested UserSearch.Attributes.UID attribute
|
||||||
wantDownstreamIDTokenSubjectToMatch: regexp.QuoteMeta(
|
wantDownstreamIDTokenSubjectToMatch: "^" + regexp.QuoteMeta(
|
||||||
"ldaps://" + env.SupervisorUpstreamActiveDirectory.Host +
|
"ldaps://"+env.SupervisorUpstreamActiveDirectory.Host+
|
||||||
"?base=" + url.QueryEscape(env.SupervisorUpstreamActiveDirectory.UserSearchBase) +
|
"?base="+url.QueryEscape(env.SupervisorUpstreamActiveDirectory.UserSearchBase)+
|
||||||
"&sub=" + env.SupervisorUpstreamActiveDirectory.TestUserUniqueIDAttributeValue,
|
"&sub="+env.SupervisorUpstreamActiveDirectory.TestUserUniqueIDAttributeValue,
|
||||||
),
|
) + "$",
|
||||||
// the ID token Username should have been pulled from the requested UserSearch.Attributes.Username attribute
|
// the ID token Username should have been pulled from the requested UserSearch.Attributes.Username attribute
|
||||||
wantDownstreamIDTokenUsernameToMatch: regexp.QuoteMeta(env.SupervisorUpstreamActiveDirectory.TestUserMailAttributeValue),
|
wantDownstreamIDTokenUsernameToMatch: "^" + regexp.QuoteMeta(env.SupervisorUpstreamActiveDirectory.TestUserMailAttributeValue) + "$",
|
||||||
wantDownstreamIDTokenGroups: env.SupervisorUpstreamActiveDirectory.TestUserDirectGroupsDNs,
|
wantDownstreamIDTokenGroups: env.SupervisorUpstreamActiveDirectory.TestUserDirectGroupsDNs,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -283,7 +283,7 @@ func loadEnvVars(t *testing.T, result *TestEnv) {
|
|||||||
TestUserPassword: wantEnv("PINNIPED_TEST_AD_USER_PASSWORD", ""),
|
TestUserPassword: wantEnv("PINNIPED_TEST_AD_USER_PASSWORD", ""),
|
||||||
TestUserUniqueIDAttributeName: wantEnv("PINNIPED_TEST_AD_USER_UNIQUE_ID_ATTRIBUTE_NAME", ""),
|
TestUserUniqueIDAttributeName: wantEnv("PINNIPED_TEST_AD_USER_UNIQUE_ID_ATTRIBUTE_NAME", ""),
|
||||||
TestUserUniqueIDAttributeValue: wantEnv("PINNIPED_TEST_AD_USER_UNIQUE_ID_ATTRIBUTE_VALUE", ""),
|
TestUserUniqueIDAttributeValue: wantEnv("PINNIPED_TEST_AD_USER_UNIQUE_ID_ATTRIBUTE_VALUE", ""),
|
||||||
TestUserPrincipalNameValue: wantEnv("PINNIPED_TEST_AD_USERNAME_ATTRIBUTE_VALUE", ""),
|
TestUserPrincipalNameValue: wantEnv("PINNIPED_TEST_AD_USER_USER_PRINCIPAL_NAME", ""),
|
||||||
TestUserMailAttributeValue: wantEnv("PINNIPED_TEST_AD_USER_EMAIL_ATTRIBUTE_VALUE", ""),
|
TestUserMailAttributeValue: wantEnv("PINNIPED_TEST_AD_USER_EMAIL_ATTRIBUTE_VALUE", ""),
|
||||||
TestUserMailAttributeName: wantEnv("PINNIPED_TEST_AD_USER_EMAIL_ATTRIBUTE_NAME", ""),
|
TestUserMailAttributeName: wantEnv("PINNIPED_TEST_AD_USER_EMAIL_ATTRIBUTE_NAME", ""),
|
||||||
TestUserDirectGroupsDNs: filterEmpty(strings.Split(wantEnv("PINNIPED_TEST_AD_USER_EXPECTED_GROUPS_DN", ""), ";")),
|
TestUserDirectGroupsDNs: filterEmpty(strings.Split(wantEnv("PINNIPED_TEST_AD_USER_EXPECTED_GROUPS_DN", ""), ";")),
|
||||||
|
Loading…
Reference in New Issue
Block a user