Add integration test for LDAP StartTLS
This commit is contained in:
parent
7e76b66639
commit
8b549f66d4
@ -333,6 +333,7 @@ export PINNIPED_TEST_SUPERVISOR_HTTP_ADDRESS="127.0.0.1:12345"
|
|||||||
export PINNIPED_TEST_SUPERVISOR_HTTPS_ADDRESS="localhost:12344"
|
export PINNIPED_TEST_SUPERVISOR_HTTPS_ADDRESS="localhost:12344"
|
||||||
export PINNIPED_TEST_PROXY=http://127.0.0.1:12346
|
export PINNIPED_TEST_PROXY=http://127.0.0.1:12346
|
||||||
export PINNIPED_TEST_LDAP_HOST=ldap.tools.svc.cluster.local
|
export PINNIPED_TEST_LDAP_HOST=ldap.tools.svc.cluster.local
|
||||||
|
export PINNIPED_TEST_LDAP_STARTTLS_ONLY_HOST=ldapstarttls.tools.svc.cluster.local
|
||||||
export PINNIPED_TEST_LDAP_LDAPS_CA_BUNDLE="${test_ca_bundle_pem}"
|
export PINNIPED_TEST_LDAP_LDAPS_CA_BUNDLE="${test_ca_bundle_pem}"
|
||||||
export PINNIPED_TEST_LDAP_BIND_ACCOUNT_USERNAME="cn=admin,dc=pinniped,dc=dev"
|
export PINNIPED_TEST_LDAP_BIND_ACCOUNT_USERNAME="cn=admin,dc=pinniped,dc=dev"
|
||||||
export PINNIPED_TEST_LDAP_BIND_ACCOUNT_PASSWORD=password
|
export PINNIPED_TEST_LDAP_BIND_ACCOUNT_PASSWORD=password
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
"go.pinniped.dev/internal/controller/supervisorconfig/upstreamwatchers"
|
"go.pinniped.dev/internal/controller/supervisorconfig/upstreamwatchers"
|
||||||
"go.pinniped.dev/internal/controllerlib"
|
"go.pinniped.dev/internal/controllerlib"
|
||||||
"go.pinniped.dev/internal/oidc/provider"
|
"go.pinniped.dev/internal/oidc/provider"
|
||||||
|
"go.pinniped.dev/internal/plog"
|
||||||
"go.pinniped.dev/internal/upstreamldap"
|
"go.pinniped.dev/internal/upstreamldap"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -266,15 +267,18 @@ func (c *ldapWatcherController) testConnection(
|
|||||||
tlsLDAPProvider := upstreamldap.New(*config)
|
tlsLDAPProvider := upstreamldap.New(*config)
|
||||||
err := tlsLDAPProvider.TestConnection(ctx)
|
err := tlsLDAPProvider.TestConnection(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
plog.InfoErr("testing LDAP connection using TLS failed, so trying again with StartTLS", err, "host", config.Host)
|
||||||
// If there was any error, try again with StartTLS instead.
|
// If there was any error, try again with StartTLS instead.
|
||||||
config.ConnectionProtocol = upstreamldap.StartTLS
|
config.ConnectionProtocol = upstreamldap.StartTLS
|
||||||
startTLSLDAPProvider := upstreamldap.New(*config)
|
startTLSLDAPProvider := upstreamldap.New(*config)
|
||||||
startTLSErr := startTLSLDAPProvider.TestConnection(ctx)
|
startTLSErr := startTLSLDAPProvider.TestConnection(ctx)
|
||||||
if startTLSErr == nil {
|
if startTLSErr == nil {
|
||||||
|
plog.Info("testing LDAP connection using StartTLS succeeded", "host", config.Host)
|
||||||
// Successfully able to fall back to using StartTLS, so clear the original
|
// Successfully able to fall back to using StartTLS, so clear the original
|
||||||
// error and consider the connection test to be successful.
|
// error and consider the connection test to be successful.
|
||||||
err = nil
|
err = nil
|
||||||
} else {
|
} else {
|
||||||
|
plog.InfoErr("testing LDAP connection using StartTLS also failed", err, "host", config.Host)
|
||||||
// Falling back to StartTLS also failed, so put TLS back into the config
|
// Falling back to StartTLS also failed, so put TLS back into the config
|
||||||
// and consider the connection test to be failed.
|
// and consider the connection test to be failed.
|
||||||
config.ConnectionProtocol = upstreamldap.TLS
|
config.ConnectionProtocol = upstreamldap.TLS
|
||||||
|
@ -69,7 +69,7 @@ func TestSupervisorLogin(t *testing.T) {
|
|||||||
wantDownstreamIDTokenGroups: env.SupervisorUpstreamOIDC.ExpectedGroups,
|
wantDownstreamIDTokenGroups: env.SupervisorUpstreamOIDC.ExpectedGroups,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ldap with email as username and groups names as DNs",
|
name: "ldap with email as username and groups names as DNs and using an LDAP provider which supports TLS",
|
||||||
createIDP: func(t *testing.T) {
|
createIDP: func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
secret := library.CreateTestSecret(t, env.SupervisorNamespace, "ldap-service-account", v1.SecretTypeBasicAuth,
|
secret := library.CreateTestSecret(t, env.SupervisorNamespace, "ldap-service-account", v1.SecretTypeBasicAuth,
|
||||||
@ -126,7 +126,7 @@ func TestSupervisorLogin(t *testing.T) {
|
|||||||
wantDownstreamIDTokenGroups: env.SupervisorUpstreamLDAP.TestUserDirectGroupsDNs,
|
wantDownstreamIDTokenGroups: env.SupervisorUpstreamLDAP.TestUserDirectGroupsDNs,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ldap with CN as username and group names as CNs", // try another variation of configuration options
|
name: "ldap with CN as username and group names as CNs and using an LDAP provider which only supports StartTLS", // try another variation of configuration options
|
||||||
createIDP: func(t *testing.T) {
|
createIDP: func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
secret := library.CreateTestSecret(t, env.SupervisorNamespace, "ldap-service-account", v1.SecretTypeBasicAuth,
|
secret := library.CreateTestSecret(t, env.SupervisorNamespace, "ldap-service-account", v1.SecretTypeBasicAuth,
|
||||||
@ -136,7 +136,7 @@ func TestSupervisorLogin(t *testing.T) {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
ldapIDP := library.CreateTestLDAPIdentityProvider(t, idpv1alpha1.LDAPIdentityProviderSpec{
|
ldapIDP := library.CreateTestLDAPIdentityProvider(t, idpv1alpha1.LDAPIdentityProviderSpec{
|
||||||
Host: env.SupervisorUpstreamLDAP.Host,
|
Host: env.SupervisorUpstreamLDAP.StartTLSOnlyHost,
|
||||||
TLS: &idpv1alpha1.TLSSpec{
|
TLS: &idpv1alpha1.TLSSpec{
|
||||||
CertificateAuthorityData: base64.StdEncoding.EncodeToString([]byte(env.SupervisorUpstreamLDAP.CABundle)),
|
CertificateAuthorityData: base64.StdEncoding.EncodeToString([]byte(env.SupervisorUpstreamLDAP.CABundle)),
|
||||||
},
|
},
|
||||||
@ -161,7 +161,7 @@ func TestSupervisorLogin(t *testing.T) {
|
|||||||
}, idpv1alpha1.LDAPPhaseReady)
|
}, idpv1alpha1.LDAPPhaseReady)
|
||||||
expectedMsg := fmt.Sprintf(
|
expectedMsg := fmt.Sprintf(
|
||||||
`successfully able to connect to "%s" and bind as user "%s" [validated with Secret "%s" at version "%s"]`,
|
`successfully able to connect to "%s" and bind as user "%s" [validated with Secret "%s" at version "%s"]`,
|
||||||
env.SupervisorUpstreamLDAP.Host, env.SupervisorUpstreamLDAP.BindUsername,
|
env.SupervisorUpstreamLDAP.StartTLSOnlyHost, env.SupervisorUpstreamLDAP.BindUsername,
|
||||||
secret.Name, secret.ResourceVersion,
|
secret.Name, secret.ResourceVersion,
|
||||||
)
|
)
|
||||||
requireSuccessfulLDAPIdentityProviderConditions(t, ldapIDP, expectedMsg)
|
requireSuccessfulLDAPIdentityProviderConditions(t, ldapIDP, expectedMsg)
|
||||||
@ -176,7 +176,7 @@ 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 + "?sub=" + env.SupervisorUpstreamLDAP.TestUserUniqueIDAttributeValue,
|
"ldaps://" + env.SupervisorUpstreamLDAP.StartTLSOnlyHost + "?sub=" + 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),
|
||||||
|
@ -437,7 +437,10 @@ func CreateTestLDAPIdentityProvider(t *testing.T, spec idpv1alpha1.LDAPIdentityP
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return result.Status.Phase == expectedPhase
|
return result.Status.Phase == expectedPhase
|
||||||
}, 60*time.Second, 1*time.Second, "expected the LDAPIdentityProvider to go into phase %s, LDAPIdentityProvider was: %s", expectedPhase, Sdump(result))
|
},
|
||||||
|
2*time.Minute, // it takes 1 minute for a failed LDAP TLS connection test to timeout before it tries using StartTLS, so wait longer than that
|
||||||
|
1*time.Second,
|
||||||
|
"expected the LDAPIdentityProvider to go into phase %s, LDAPIdentityProvider was: %s", expectedPhase, Sdump(result))
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,6 +73,7 @@ type TestOIDCUpstream struct {
|
|||||||
|
|
||||||
type TestLDAPUpstream struct {
|
type TestLDAPUpstream struct {
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
|
StartTLSOnlyHost string `json:"startTLSOnlyHost"`
|
||||||
CABundle string `json:"caBundle"`
|
CABundle string `json:"caBundle"`
|
||||||
BindUsername string `json:"bindUsername"`
|
BindUsername string `json:"bindUsername"`
|
||||||
BindPassword string `json:"bindPassword"`
|
BindPassword string `json:"bindPassword"`
|
||||||
@ -240,6 +241,7 @@ func loadEnvVars(t *testing.T, result *TestEnv) {
|
|||||||
|
|
||||||
result.SupervisorUpstreamLDAP = TestLDAPUpstream{
|
result.SupervisorUpstreamLDAP = TestLDAPUpstream{
|
||||||
Host: needEnv(t, "PINNIPED_TEST_LDAP_HOST"),
|
Host: needEnv(t, "PINNIPED_TEST_LDAP_HOST"),
|
||||||
|
StartTLSOnlyHost: needEnv(t, "PINNIPED_TEST_LDAP_STARTTLS_ONLY_HOST"),
|
||||||
CABundle: base64Decoded(t, os.Getenv("PINNIPED_TEST_LDAP_LDAPS_CA_BUNDLE")),
|
CABundle: base64Decoded(t, os.Getenv("PINNIPED_TEST_LDAP_LDAPS_CA_BUNDLE")),
|
||||||
BindUsername: needEnv(t, "PINNIPED_TEST_LDAP_BIND_ACCOUNT_USERNAME"),
|
BindUsername: needEnv(t, "PINNIPED_TEST_LDAP_BIND_ACCOUNT_USERNAME"),
|
||||||
BindPassword: needEnv(t, "PINNIPED_TEST_LDAP_BIND_ACCOUNT_PASSWORD"),
|
BindPassword: needEnv(t, "PINNIPED_TEST_LDAP_BIND_ACCOUNT_PASSWORD"),
|
||||||
|
Loading…
Reference in New Issue
Block a user