diff options
Diffstat (limited to 'internal/authentication/ldap_user_provider_test.go')
| -rw-r--r-- | internal/authentication/ldap_user_provider_test.go | 238 |
1 files changed, 222 insertions, 16 deletions
diff --git a/internal/authentication/ldap_user_provider_test.go b/internal/authentication/ldap_user_provider_test.go index 5913df0d2..8602bd8b1 100644 --- a/internal/authentication/ldap_user_provider_test.go +++ b/internal/authentication/ldap_user_provider_test.go @@ -2,6 +2,7 @@ package authentication import ( "errors" + "fmt" "testing" "github.com/go-ldap/ldap/v3" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/authelia/authelia/internal/configuration/schema" + "github.com/authelia/authelia/internal/utils" ) func TestShouldCreateRawConnectionWhenSchemeIsLDAP(t *testing.T) { @@ -19,7 +21,7 @@ func TestShouldCreateRawConnectionWhenSchemeIsLDAP(t *testing.T) { mockFactory := NewMockLDAPConnectionFactory(ctrl) mockConn := NewMockLDAPConnection(ctrl) - ldapClient := NewLDAPUserProviderWithFactory( + ldapClient := newLDAPUserProvider( schema.LDAPAuthenticationBackendConfiguration{ URL: "ldap://127.0.0.1:389", }, @@ -46,7 +48,7 @@ func TestShouldCreateTLSConnectionWhenSchemeIsLDAPS(t *testing.T) { mockFactory := NewMockLDAPConnectionFactory(ctrl) mockConn := NewMockLDAPConnection(ctrl) - ldapClient := NewLDAPUserProviderWithFactory( + ldapClient := newLDAPUserProvider( schema.LDAPAuthenticationBackendConfiguration{ URL: "ldaps://127.0.0.1:389", }, @@ -72,7 +74,7 @@ func TestEscapeSpecialCharsFromUserInput(t *testing.T) { mockFactory := NewMockLDAPConnectionFactory(ctrl) - ldapClient := NewLDAPUserProviderWithFactory( + ldapClient := newLDAPUserProvider( schema.LDAPAuthenticationBackendConfiguration{ URL: "ldaps://127.0.0.1:389", }, @@ -103,7 +105,7 @@ func TestEscapeSpecialCharsInGroupsFilter(t *testing.T) { mockFactory := NewMockLDAPConnectionFactory(ctrl) - ldapClient := NewLDAPUserProviderWithFactory( + ldapClient := newLDAPUserProvider( schema.LDAPAuthenticationBackendConfiguration{ URL: "ldaps://127.0.0.1:389", GroupsFilter: "(|(member={dn})(uid={username})(uid={input}))", @@ -125,6 +127,210 @@ func TestEscapeSpecialCharsInGroupsFilter(t *testing.T) { assert.Equal(t, "(|(member=cn=john \\28external\\29,dc=example,dc=com)(uid=john)(uid=john\\#\\=\\28abc\\,def\\29))", filter) } +type ExtendedSearchRequestMatcher struct { + filter string + baseDN string + scope int + derefAliases int + typesOnly bool + attributes []string +} + +func NewExtendedSearchRequestMatcher(filter, base string, scope, derefAliases int, typesOnly bool, attributes []string) *ExtendedSearchRequestMatcher { + return &ExtendedSearchRequestMatcher{filter, base, scope, derefAliases, typesOnly, attributes} +} + +func (e *ExtendedSearchRequestMatcher) Matches(x interface{}) bool { + sr := x.(*ldap.SearchRequest) + + if e.filter != sr.Filter || e.baseDN != sr.BaseDN || e.scope != sr.Scope || e.derefAliases != sr.DerefAliases || + e.typesOnly != sr.TypesOnly || utils.IsStringSlicesDifferent(e.attributes, sr.Attributes) { + return false + } + + return true +} + +func (e *ExtendedSearchRequestMatcher) String() string { + return fmt.Sprintf("baseDN: %s, filter %s", e.baseDN, e.filter) +} + +func TestShouldCheckLDAPServerExtensions(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockFactory := NewMockLDAPConnectionFactory(ctrl) + mockConn := NewMockLDAPConnection(ctrl) + + ldapClient := newLDAPUserProvider( + schema.LDAPAuthenticationBackendConfiguration{ + URL: "ldap://127.0.0.1:389", + User: "cn=admin,dc=example,dc=com", + UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))", + UsernameAttribute: "uid", + MailAttribute: "mail", + DisplayNameAttribute: "displayname", + Password: "password", + AdditionalUsersDN: "ou=users", + BaseDN: "dc=example,dc=com", + }, + nil, + mockFactory) + + mockFactory.EXPECT(). + DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()). + Return(mockConn, nil) + + mockConn.EXPECT(). + Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")). + Return(nil) + + mockConn.EXPECT(). + Search(NewExtendedSearchRequestMatcher("(objectClass=*)", "", ldap.ScopeBaseObject, ldap.NeverDerefAliases, false, []string{ldapSupportedExtensionAttribute})). + Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: "", + Attributes: []*ldap.EntryAttribute{ + { + Name: ldapSupportedExtensionAttribute, + Values: []string{ldapOIDPasswdModifyExtension}, + }, + }, + }, + }, + }, nil) + + err := ldapClient.checkServer() + assert.NoError(t, err) + + assert.True(t, ldapClient.supportExtensionPasswdModify) +} + +func TestShouldNotEnablePasswdModifyExtension(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockFactory := NewMockLDAPConnectionFactory(ctrl) + mockConn := NewMockLDAPConnection(ctrl) + + ldapClient := newLDAPUserProvider( + schema.LDAPAuthenticationBackendConfiguration{ + URL: "ldap://127.0.0.1:389", + User: "cn=admin,dc=example,dc=com", + UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))", + UsernameAttribute: "uid", + MailAttribute: "mail", + DisplayNameAttribute: "displayname", + Password: "password", + AdditionalUsersDN: "ou=users", + BaseDN: "dc=example,dc=com", + }, + nil, + mockFactory) + + mockFactory.EXPECT(). + DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()). + Return(mockConn, nil) + + mockConn.EXPECT(). + Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")). + Return(nil) + + mockConn.EXPECT(). + Search(NewExtendedSearchRequestMatcher("(objectClass=*)", "", ldap.ScopeBaseObject, ldap.NeverDerefAliases, false, []string{ldapSupportedExtensionAttribute})). + Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: "", + Attributes: []*ldap.EntryAttribute{ + { + Name: ldapSupportedExtensionAttribute, + Values: []string{}, + }, + }, + }, + }, + }, nil) + + err := ldapClient.checkServer() + assert.NoError(t, err) + + assert.False(t, ldapClient.supportExtensionPasswdModify) +} + +func TestShouldReturnCheckServerConnectError(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockFactory := NewMockLDAPConnectionFactory(ctrl) + mockConn := NewMockLDAPConnection(ctrl) + + ldapClient := newLDAPUserProvider( + schema.LDAPAuthenticationBackendConfiguration{ + URL: "ldap://127.0.0.1:389", + User: "cn=admin,dc=example,dc=com", + UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))", + UsernameAttribute: "uid", + MailAttribute: "mail", + DisplayNameAttribute: "displayname", + Password: "password", + AdditionalUsersDN: "ou=users", + BaseDN: "dc=example,dc=com", + }, + nil, + mockFactory) + + mockFactory.EXPECT(). + DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()). + Return(mockConn, errors.New("could not connect")) + + err := ldapClient.checkServer() + assert.EqualError(t, err, "could not connect") + + assert.False(t, ldapClient.supportExtensionPasswdModify) +} + +func TestShouldReturnCheckServerSearchError(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockFactory := NewMockLDAPConnectionFactory(ctrl) + mockConn := NewMockLDAPConnection(ctrl) + + ldapClient := newLDAPUserProvider( + schema.LDAPAuthenticationBackendConfiguration{ + URL: "ldap://127.0.0.1:389", + User: "cn=admin,dc=example,dc=com", + UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))", + UsernameAttribute: "uid", + MailAttribute: "mail", + DisplayNameAttribute: "displayname", + Password: "password", + AdditionalUsersDN: "ou=users", + BaseDN: "dc=example,dc=com", + }, + nil, + mockFactory) + + mockFactory.EXPECT(). + DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()). + Return(mockConn, nil) + + mockConn.EXPECT(). + Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")). + Return(nil) + + mockConn.EXPECT(). + Search(NewExtendedSearchRequestMatcher("(objectClass=*)", "", ldap.ScopeBaseObject, ldap.NeverDerefAliases, false, []string{ldapSupportedExtensionAttribute})). + Return(nil, errors.New("could not perform the search")) + + err := ldapClient.checkServer() + assert.EqualError(t, err, "could not perform the search") + + assert.False(t, ldapClient.supportExtensionPasswdModify) +} + type SearchRequestMatcher struct { expected string } @@ -149,7 +355,7 @@ func TestShouldEscapeUserInput(t *testing.T) { mockFactory := NewMockLDAPConnectionFactory(ctrl) mockConn := NewMockLDAPConnection(ctrl) - ldapClient := NewLDAPUserProviderWithFactory( + ldapClient := newLDAPUserProvider( schema.LDAPAuthenticationBackendConfiguration{ URL: "ldap://127.0.0.1:389", User: "cn=admin,dc=example,dc=com", @@ -181,7 +387,7 @@ func TestShouldCombineUsernameFilterAndUsersFilter(t *testing.T) { mockFactory := NewMockLDAPConnectionFactory(ctrl) mockConn := NewMockLDAPConnection(ctrl) - ldapClient := NewLDAPUserProviderWithFactory( + ldapClient := newLDAPUserProvider( schema.LDAPAuthenticationBackendConfiguration{ URL: "ldap://127.0.0.1:389", User: "cn=admin,dc=example,dc=com", @@ -226,7 +432,7 @@ func TestShouldNotCrashWhenGroupsAreNotRetrievedFromLDAP(t *testing.T) { mockFactory := NewMockLDAPConnectionFactory(ctrl) mockConn := NewMockLDAPConnection(ctrl) - ldapClient := NewLDAPUserProviderWithFactory( + ldapClient := newLDAPUserProvider( schema.LDAPAuthenticationBackendConfiguration{ URL: "ldap://127.0.0.1:389", User: "cn=admin,dc=example,dc=com", @@ -297,7 +503,7 @@ func TestShouldNotCrashWhenEmailsAreNotRetrievedFromLDAP(t *testing.T) { mockFactory := NewMockLDAPConnectionFactory(ctrl) mockConn := NewMockLDAPConnection(ctrl) - ldapClient := NewLDAPUserProviderWithFactory( + ldapClient := newLDAPUserProvider( schema.LDAPAuthenticationBackendConfiguration{ URL: "ldap://127.0.0.1:389", User: "cn=admin,dc=example,dc=com", @@ -357,7 +563,7 @@ func TestShouldReturnUsernameFromLDAP(t *testing.T) { mockFactory := NewMockLDAPConnectionFactory(ctrl) mockConn := NewMockLDAPConnection(ctrl) - ldapClient := NewLDAPUserProviderWithFactory( + ldapClient := newLDAPUserProvider( schema.LDAPAuthenticationBackendConfiguration{ URL: "ldap://127.0.0.1:389", User: "cn=admin,dc=example,dc=com", @@ -428,7 +634,7 @@ func TestShouldUpdateUserPassword(t *testing.T) { mockFactory := NewMockLDAPConnectionFactory(ctrl) mockConn := NewMockLDAPConnection(ctrl) - ldapClient := NewLDAPUserProviderWithFactory( + ldapClient := newLDAPUserProvider( schema.LDAPAuthenticationBackendConfiguration{ URL: "ldap://127.0.0.1:389", User: "cn=admin,dc=example,dc=com", @@ -495,7 +701,7 @@ func TestShouldCheckValidUserPassword(t *testing.T) { mockFactory := NewMockLDAPConnectionFactory(ctrl) mockConn := NewMockLDAPConnection(ctrl) - ldapClient := NewLDAPUserProviderWithFactory( + ldapClient := newLDAPUserProvider( schema.LDAPAuthenticationBackendConfiguration{ URL: "ldap://127.0.0.1:389", User: "cn=admin,dc=example,dc=com", @@ -563,7 +769,7 @@ func TestShouldCheckInvalidUserPassword(t *testing.T) { mockFactory := NewMockLDAPConnectionFactory(ctrl) mockConn := NewMockLDAPConnection(ctrl) - ldapClient := NewLDAPUserProviderWithFactory( + ldapClient := newLDAPUserProvider( schema.LDAPAuthenticationBackendConfiguration{ URL: "ldap://127.0.0.1:389", User: "cn=admin,dc=example,dc=com", @@ -631,7 +837,7 @@ func TestShouldCallStartTLSWhenEnabled(t *testing.T) { mockFactory := NewMockLDAPConnectionFactory(ctrl) mockConn := NewMockLDAPConnection(ctrl) - ldapClient := NewLDAPUserProviderWithFactory( + ldapClient := newLDAPUserProvider( schema.LDAPAuthenticationBackendConfiguration{ URL: "ldap://127.0.0.1:389", User: "cn=admin,dc=example,dc=com", @@ -705,7 +911,7 @@ func TestShouldParseDynamicConfiguration(t *testing.T) { mockFactory := NewMockLDAPConnectionFactory(ctrl) - ldapClient := NewLDAPUserProviderWithFactory( + ldapClient := newLDAPUserProvider( schema.LDAPAuthenticationBackendConfiguration{ URL: "ldap://127.0.0.1:389", User: "cn=admin,dc=example,dc=com", @@ -736,7 +942,7 @@ func TestShouldCallStartTLSWithInsecureSkipVerifyWhenSkipVerifyTrue(t *testing.T mockFactory := NewMockLDAPConnectionFactory(ctrl) mockConn := NewMockLDAPConnection(ctrl) - ldapClient := NewLDAPUserProviderWithFactory( + ldapClient := newLDAPUserProvider( schema.LDAPAuthenticationBackendConfiguration{ URL: "ldap://127.0.0.1:389", User: "cn=admin,dc=example,dc=com", @@ -814,7 +1020,7 @@ func TestShouldReturnLDAPSAlreadySecuredWhenStartTLSAttempted(t *testing.T) { mockFactory := NewMockLDAPConnectionFactory(ctrl) mockConn := NewMockLDAPConnection(ctrl) - ldapClient := NewLDAPUserProviderWithFactory( + ldapClient := newLDAPUserProvider( schema.LDAPAuthenticationBackendConfiguration{ URL: "ldaps://127.0.0.1:389", User: "cn=admin,dc=example,dc=com", |
