summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Elliott <james-d-elliott@users.noreply.github.com>2025-02-23 19:05:57 +1100
committerGitHub <noreply@github.com>2025-02-23 08:05:57 +0000
commit0af038e0ced689db90da480876a0bb26d78c6fb9 (patch)
tree5d97fe07636fcc5f7c6d87d6535bc5e1f0a9f2eb
parent197b45521f5e3799d0b9ef1ec0000d4f83abdee9 (diff)
feat(authentication): ldap connection pooling (#7217)
This implements optional LDAP connection pooling to optimize the speed of LDAP transactions. Signed-off-by: James Elliott <james-d-elliott@users.noreply.github.com>
-rw-r--r--config.template.yml15
-rw-r--r--docs/content/configuration/first-factor/ldap.md34
-rw-r--r--docs/content/integration/openid-connect/stirling-pdf/index.md2
-rw-r--r--docs/content/reference/guides/authentication-method-references.md2
-rw-r--r--docs/content/reference/guides/webauthn.md2
-rw-r--r--docs/data/configkeys.json20
-rw-r--r--docs/static/schemas/latest/json-schema/configuration.json43
-rw-r--r--docs/static/schemas/v4.38/json-schema/configuration.json43
-rw-r--r--docs/static/schemas/v4.39/json-schema/configuration.json43
-rw-r--r--internal/authentication/file_user_provider.go7
-rw-r--r--internal/authentication/file_user_provider_test.go3
-rw-r--r--internal/authentication/gen.go3
-rw-r--r--internal/authentication/ldap_client_dialer.go31
-rw-r--r--internal/authentication/ldap_client_dialer_test.go61
-rw-r--r--internal/authentication/ldap_client_factory.go312
-rw-r--r--internal/authentication/ldap_client_factory_config.go27
-rw-r--r--internal/authentication/ldap_client_factory_mock_test.go59
-rw-r--r--internal/authentication/ldap_client_mock_test.go264
-rw-r--r--internal/authentication/ldap_user_provider.go168
-rw-r--r--internal/authentication/ldap_user_provider_lifecycle.go (renamed from internal/authentication/ldap_user_provider_startup.go)20
-rw-r--r--internal/authentication/ldap_user_provider_test.go4285
-rw-r--r--internal/authentication/types.go46
-rw-r--r--internal/authentication/user_provider.go1
-rw-r--r--internal/commands/services.go4
-rw-r--r--internal/configuration/config.template.yml15
-rw-r--r--internal/configuration/schema/authentication.go14
-rw-r--r--internal/configuration/schema/keys.go4
-rw-r--r--internal/configuration/validator/authentication.go14
-rw-r--r--internal/configuration/validator/authentication_test.go15
-rw-r--r--internal/mocks/gen.go4
-rw-r--r--internal/mocks/user_provider.go14
-rw-r--r--internal/suites/ActiveDirectory/configuration.yml5
-rw-r--r--internal/suites/LDAP/configuration.yml5
-rw-r--r--internal/utils/crypto.go4
34 files changed, 3276 insertions, 2313 deletions
diff --git a/config.template.yml b/config.template.yml
index a3181081d..2e01b7a15 100644
--- a/config.template.yml
+++ b/config.template.yml
@@ -459,6 +459,7 @@ identity_validation:
## Use StartTLS with the LDAP connection.
# start_tls: false
+ ## TLS configuration.
# tls:
## The server subject name to check the servers certificate against during the validation process.
## This option is not required if the certificate has a SAN which matches the address options hostname.
@@ -495,6 +496,20 @@ identity_validation:
# ...
# -----END RSA PRIVATE KEY-----
+ ## Connection Pooling configuration.
+ # pooling:
+ ## Enable Pooling.
+ # enable: false
+
+ ## Pool count.
+ # count: 5
+
+ ## Retries to obtain a connection during the timeout.
+ # retries: 2
+
+ ## Timeout before the attempt to obtain a connection fails.
+ # timeout: '10 seconds'
+
## The distinguished name of the container searched for objects in the directory information tree.
## See also: additional_users_dn, additional_groups_dn.
# base_dn: 'dc=example,dc=com'
diff --git a/docs/content/configuration/first-factor/ldap.md b/docs/content/configuration/first-factor/ldap.md
index 3d2043f5f..6730e302c 100644
--- a/docs/content/configuration/first-factor/ldap.md
+++ b/docs/content/configuration/first-factor/ldap.md
@@ -50,6 +50,11 @@ authentication_backend:
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
+ pooling:
+ enable: false
+ count: 5
+ retries: 2
+ timeout: '10 seconds'
base_dn: '{{< sitevar name="domain" format="dn" nojs="DC=example,DC=com" >}}'
additional_users_dn: 'OU=users'
users_filter: '(&({username_attribute}={input})(objectClass=person))'
@@ -155,6 +160,35 @@ By default Authelia uses the system certificate trust for TLS certificate verifi
this.
+### pooling
+
+The connection pooling configuration.
+
+#### enable
+
+{{< confkey type="boolean" default="false" required="no" >}}
+
+Enables the connection pooling functionality.
+
+#### count
+
+{{< confkey type="integer" default="5" required="no" >}}
+
+The number of open connections to be available in the pool at any given time.
+
+#### retries
+
+{{< confkey type="integer" default="2" required="no" >}}
+
+The number of attempts to obtain a free connecting that are made within the timeout period. This effectively splits the
+timeout into chunks.
+
+#### timeout
+
+{{< confkey type="string,integer" syntax="duration" default="5 seconds" required="no" >}}
+
+The amount of time that we wait for a connection to become free in the pool before giving up and failing with an error.
+
### base_dn
{{< confkey type="string" required="situational" >}}
diff --git a/docs/content/integration/openid-connect/stirling-pdf/index.md b/docs/content/integration/openid-connect/stirling-pdf/index.md
index 36c5ae29b..912c95391 100644
--- a/docs/content/integration/openid-connect/stirling-pdf/index.md
+++ b/docs/content/integration/openid-connect/stirling-pdf/index.md
@@ -2,7 +2,7 @@
title: "Stirling-PDF"
description: "Integrating Stirling-PDF with the Authelia OpenID Connect 1.0 Provider."
summary: ""
-date: 2025-02-23T17:51:47+10:00
+date: 2025-02-23T04:38:52+00:00
draft: false
images: []
weight: 620
diff --git a/docs/content/reference/guides/authentication-method-references.md b/docs/content/reference/guides/authentication-method-references.md
index 6470e680e..c00d35fdc 100644
--- a/docs/content/reference/guides/authentication-method-references.md
+++ b/docs/content/reference/guides/authentication-method-references.md
@@ -2,7 +2,7 @@
title: "Authentication Method Reference Values"
description: "This guide shows a list of Authentication Method Reference Values based on RFC8176 and how they are implemented within Authelia"
summary: "This guide shows a list of other frequently asked question documents as well as some general ones."
-date: 2025-01-27T09:23:06+11:00
+date: 2025-02-23T16:08:49+11:00
draft: false
images: []
weight: 220
diff --git a/docs/content/reference/guides/webauthn.md b/docs/content/reference/guides/webauthn.md
index 71e8d9e57..2ff01c566 100644
--- a/docs/content/reference/guides/webauthn.md
+++ b/docs/content/reference/guides/webauthn.md
@@ -2,7 +2,7 @@
title: "WebAuthn"
description: "A reference guide on various WebAuthn features and topics"
summary: "This section contains reference documentation for Authelia's WebAuthn implementation and capabilities."
-date: 2025-01-27T09:23:06+11:00
+date: 2025-02-23T16:08:49+11:00
draft: false
images: []
weight: 220
diff --git a/docs/data/configkeys.json b/docs/data/configkeys.json
index 9f3f8de57..a93d83920 100644
--- a/docs/data/configkeys.json
+++ b/docs/data/configkeys.json
@@ -305,6 +305,26 @@
"env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_TLS_CERTIFICATE_CHAIN_FILE"
},
{
+ "path": "authentication_backend.ldap.pooling.enable",
+ "secret": false,
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_POOLING_ENABLE"
+ },
+ {
+ "path": "authentication_backend.ldap.pooling.count",
+ "secret": false,
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_POOLING_COUNT"
+ },
+ {
+ "path": "authentication_backend.ldap.pooling.retries",
+ "secret": false,
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_POOLING_RETRIES"
+ },
+ {
+ "path": "authentication_backend.ldap.pooling.timeout",
+ "secret": false,
+ "env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_POOLING_TIMEOUT"
+ },
+ {
"path": "authentication_backend.ldap.base_dn",
"secret": false,
"env": "AUTHELIA_AUTHENTICATION_BACKEND_LDAP_BASE_DN"
diff --git a/docs/static/schemas/latest/json-schema/configuration.json b/docs/static/schemas/latest/json-schema/configuration.json
index 0bbeac431..a6d722ba3 100644
--- a/docs/static/schemas/latest/json-schema/configuration.json
+++ b/docs/static/schemas/latest/json-schema/configuration.json
@@ -713,6 +713,11 @@
"title": "TLS",
"description": "The LDAP directory server TLS connection properties."
},
+ "pooling": {
+ "$ref": "#/$defs/AuthenticationBackendLDAPPooling",
+ "title": "Pooling",
+ "description": "The LDAP Connection Pooling properties."
+ },
"base_dn": {
"type": "string",
"title": "Base DN",
@@ -821,6 +826,44 @@
"type": "object",
"description": "AuthenticationBackendLDAPAttributes represents the configuration related to LDAP server attributes."
},
+ "AuthenticationBackendLDAPPooling": {
+ "properties": {
+ "enable": {
+ "type": "boolean",
+ "title": "Enable",
+ "description": "Enable LDAP connection pooling.",
+ "default": false
+ },
+ "count": {
+ "type": "integer",
+ "title": "Count",
+ "description": "The number of connections to keep open for LDAP connection pooling.",
+ "default": 5
+ },
+ "retries": {
+ "type": "integer",
+ "title": "Retries",
+ "description": "The number of attempts to retrieve a connection from the pool during the timeout.",
+ "default": 2
+ },
+ "timeout": {
+ "oneOf": [
+ {
+ "type": "string",
+ "pattern": "^\\d+\\s*(y|M|w|d|h|m|s|ms|((year|month|week|day|hour|minute|second|millisecond)s?))(\\s*\\d+\\s*(y|M|w|d|h|m|s|ms|((year|month|week|day|hour|minute|second|millisecond)s?)))*$"
+ },
+ {
+ "type": "integer",
+ "description": "The duration in seconds"
+ }
+ ],
+ "title": "Timeout",
+ "description": "The duration of time to wait for a connection to become available in the connection pool."
+ }
+ },
+ "additionalProperties": false,
+ "type": "object"
+ },
"AuthenticationBackendPasswordReset": {
"properties": {
"disable": {
diff --git a/docs/static/schemas/v4.38/json-schema/configuration.json b/docs/static/schemas/v4.38/json-schema/configuration.json
index 0bbeac431..a6d722ba3 100644
--- a/docs/static/schemas/v4.38/json-schema/configuration.json
+++ b/docs/static/schemas/v4.38/json-schema/configuration.json
@@ -713,6 +713,11 @@
"title": "TLS",
"description": "The LDAP directory server TLS connection properties."
},
+ "pooling": {
+ "$ref": "#/$defs/AuthenticationBackendLDAPPooling",
+ "title": "Pooling",
+ "description": "The LDAP Connection Pooling properties."
+ },
"base_dn": {
"type": "string",
"title": "Base DN",
@@ -821,6 +826,44 @@
"type": "object",
"description": "AuthenticationBackendLDAPAttributes represents the configuration related to LDAP server attributes."
},
+ "AuthenticationBackendLDAPPooling": {
+ "properties": {
+ "enable": {
+ "type": "boolean",
+ "title": "Enable",
+ "description": "Enable LDAP connection pooling.",
+ "default": false
+ },
+ "count": {
+ "type": "integer",
+ "title": "Count",
+ "description": "The number of connections to keep open for LDAP connection pooling.",
+ "default": 5
+ },
+ "retries": {
+ "type": "integer",
+ "title": "Retries",
+ "description": "The number of attempts to retrieve a connection from the pool during the timeout.",
+ "default": 2
+ },
+ "timeout": {
+ "oneOf": [
+ {
+ "type": "string",
+ "pattern": "^\\d+\\s*(y|M|w|d|h|m|s|ms|((year|month|week|day|hour|minute|second|millisecond)s?))(\\s*\\d+\\s*(y|M|w|d|h|m|s|ms|((year|month|week|day|hour|minute|second|millisecond)s?)))*$"
+ },
+ {
+ "type": "integer",
+ "description": "The duration in seconds"
+ }
+ ],
+ "title": "Timeout",
+ "description": "The duration of time to wait for a connection to become available in the connection pool."
+ }
+ },
+ "additionalProperties": false,
+ "type": "object"
+ },
"AuthenticationBackendPasswordReset": {
"properties": {
"disable": {
diff --git a/docs/static/schemas/v4.39/json-schema/configuration.json b/docs/static/schemas/v4.39/json-schema/configuration.json
index 221ec38d6..39d9ad7d4 100644
--- a/docs/static/schemas/v4.39/json-schema/configuration.json
+++ b/docs/static/schemas/v4.39/json-schema/configuration.json
@@ -734,6 +734,11 @@
"title": "TLS",
"description": "The LDAP directory server TLS connection properties."
},
+ "pooling": {
+ "$ref": "#/$defs/AuthenticationBackendLDAPPooling",
+ "title": "Pooling",
+ "description": "The LDAP Connection Pooling properties."
+ },
"base_dn": {
"type": "string",
"title": "Base DN",
@@ -968,6 +973,44 @@
"additionalProperties": false,
"type": "object"
},
+ "AuthenticationBackendLDAPPooling": {
+ "properties": {
+ "enable": {
+ "type": "boolean",
+ "title": "Enable",
+ "description": "Enable LDAP connection pooling.",
+ "default": false
+ },
+ "count": {
+ "type": "integer",
+ "title": "Count",
+ "description": "The number of connections to keep open for LDAP connection pooling.",
+ "default": 5
+ },
+ "retries": {
+ "type": "integer",
+ "title": "Retries",
+ "description": "The number of attempts to retrieve a connection from the pool during the timeout.",
+ "default": 2
+ },
+ "timeout": {
+ "oneOf": [
+ {
+ "type": "string",
+ "pattern": "^\\d+\\s*(y|M|w|d|h|m|s|ms|((year|month|week|day|hour|minute|second|millisecond)s?))(\\s*\\d+\\s*(y|M|w|d|h|m|s|ms|((year|month|week|day|hour|minute|second|millisecond)s?)))*$"
+ },
+ {
+ "type": "integer",
+ "description": "The duration in seconds"
+ }
+ ],
+ "title": "Timeout",
+ "description": "The duration of time to wait for a connection to become available in the connection pool."
+ }
+ },
+ "additionalProperties": false,
+ "type": "object"
+ },
"AuthenticationBackendPasswordReset": {
"properties": {
"disable": {
diff --git a/internal/authentication/file_user_provider.go b/internal/authentication/file_user_provider.go
index 02e0faa81..0dd84e085 100644
--- a/internal/authentication/file_user_provider.go
+++ b/internal/authentication/file_user_provider.go
@@ -25,7 +25,7 @@ type FileUserProvider struct {
config *schema.AuthenticationBackendFile
hash algorithm.Hash
database FileUserProviderDatabase
- mutex *sync.Mutex
+ mutex sync.Mutex
timeoutReload time.Time
}
@@ -33,7 +33,6 @@ type FileUserProvider struct {
func NewFileUserProvider(config *schema.AuthenticationBackendFile) (provider *FileUserProvider) {
return &FileUserProvider{
config: config,
- mutex: &sync.Mutex{},
timeoutReload: time.Now().Add(-1 * time.Second),
database: NewFileUserDatabase(config.Path, config.Search.Email, config.Search.CaseInsensitive, getExtra(config)),
}
@@ -77,6 +76,10 @@ func (p *FileUserProvider) Reload() (reloaded bool, err error) {
return true, nil
}
+func (p *FileUserProvider) Shutdown() (err error) {
+ return nil
+}
+
// CheckUserPassword checks if provided password matches for the given user.
func (p *FileUserProvider) CheckUserPassword(username string, password string) (match bool, err error) {
var details FileUserDatabaseUserDetails
diff --git a/internal/authentication/file_user_provider_test.go b/internal/authentication/file_user_provider_test.go
index 1da33a389..0925d893f 100644
--- a/internal/authentication/file_user_provider_test.go
+++ b/internal/authentication/file_user_provider_test.go
@@ -86,7 +86,6 @@ func TestShouldNotPanicOnNilDB(t *testing.T) {
provider := &FileUserProvider{
config: &schema.AuthenticationBackendFile{Path: f, Password: schema.DefaultPasswordConfig},
- mutex: &sync.Mutex{},
timeoutReload: time.Now().Add(-1 * time.Second),
}
@@ -102,7 +101,7 @@ func TestShouldHandleBadConfig(t *testing.T) {
provider := &FileUserProvider{
config: &schema.AuthenticationBackendFile{Path: f, Password: schema.DefaultPasswordConfig, ExtraAttributes: map[string]schema.AuthenticationBackendExtraAttribute{"example": {ValueType: "integer"}}},
- mutex: &sync.Mutex{},
+ mutex: sync.Mutex{},
timeoutReload: time.Now().Add(-1 * time.Second),
}
diff --git a/internal/authentication/gen.go b/internal/authentication/gen.go
index 3e92fd178..c908f02d7 100644
--- a/internal/authentication/gen.go
+++ b/internal/authentication/gen.go
@@ -3,7 +3,8 @@ package authentication
// This file is used to generate mocks. You can generate all mocks using the
// command `go generate github.com/authelia/authelia/v4/internal/authentication`.
-//go:generate mockgen -package authentication -destination ldap_client_mock_test.go -mock_names LDAPClient=MockLDAPClient github.com/authelia/authelia/v4/internal/authentication LDAPClient
+//go:generate mockgen -package authentication -destination ldap_client_mock_test.go -mock_names Client=MockLDAPClient github.com/go-ldap/ldap/v3 Client
+//go:generate mockgen -package authentication -destination ldap_client_dialer_test.go -mock_names LDAPClientDialer=MockLDAPClientDialer github.com/authelia/authelia/v4/internal/authentication LDAPClientDialer
//go:generate mockgen -package authentication -destination ldap_client_factory_mock_test.go -mock_names LDAPClientFactory=MockLDAPClientFactory github.com/authelia/authelia/v4/internal/authentication LDAPClientFactory
//go:generate mockgen -package authentication -destination file_user_provider_database_mock_test.go -mock_names FileUserProviderDatabase=MockFileUserDatabase github.com/authelia/authelia/v4/internal/authentication FileUserProviderDatabase
//go:generate mockgen -package authentication -destination file_user_provider_hash_mock_test.go -mock_names Hash=MockHash github.com/go-crypt/crypt/algorithm Hash
diff --git a/internal/authentication/ldap_client_dialer.go b/internal/authentication/ldap_client_dialer.go
new file mode 100644
index 000000000..4577e2eae
--- /dev/null
+++ b/internal/authentication/ldap_client_dialer.go
@@ -0,0 +1,31 @@
+package authentication
+
+import (
+ "fmt"
+
+ "github.com/go-ldap/ldap/v3"
+)
+
+// LDAPClientDialer is an abstract type that dials a ldap.Client.
+type LDAPClientDialer interface {
+ // DialURL takes a single address and dials it returning the ldap.Client.
+ DialURL(addr string, opts ...ldap.DialOpt) (client ldap.Client, err error)
+}
+
+// NewLDAPClientDialerStandard returns a new *LDAPClientDialerStandard.
+func NewLDAPClientDialerStandard() *LDAPClientDialerStandard {
+ return &LDAPClientDialerStandard{}
+}
+
+// LDAPClientDialerStandard is a concrete type that dials a ldap.Client and returns it, implementing the
+// LDAPClientDialer.
+type LDAPClientDialerStandard struct{}
+
+// DialURL takes a single address and dials it returning the ldap.Client.
+func (d *LDAPClientDialerStandard) DialURL(addr string, opts ...ldap.DialOpt) (client ldap.Client, err error) {
+ if client, err = ldap.DialURL(addr, opts...); err != nil {
+ return nil, fmt.Errorf("failed to dial LDAP server at %s: %w", addr, err)
+ }
+
+ return client, nil
+}
diff --git a/internal/authentication/ldap_client_dialer_test.go b/internal/authentication/ldap_client_dialer_test.go
new file mode 100644
index 000000000..40228a8ea
--- /dev/null
+++ b/internal/authentication/ldap_client_dialer_test.go
@@ -0,0 +1,61 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: github.com/authelia/authelia/v4/internal/authentication (interfaces: LDAPClientDialer)
+//
+// Generated by this command:
+//
+// mockgen -package authentication -destination ldap_client_dialer_test.go -mock_names LDAPClientDialer=MockLDAPClientDialer github.com/authelia/authelia/v4/internal/authentication LDAPClientDialer
+//
+
+// Package authentication is a generated GoMock package.
+package authentication
+
+import (
+ reflect "reflect"
+
+ ldap "github.com/go-ldap/ldap/v3"
+ gomock "go.uber.org/mock/gomock"
+)
+
+// MockLDAPClientDialer is a mock of LDAPClientDialer interface.
+type MockLDAPClientDialer struct {
+ ctrl *gomock.Controller
+ recorder *MockLDAPClientDialerMockRecorder
+ isgomock struct{}
+}
+
+// MockLDAPClientDialerMockRecorder is the mock recorder for MockLDAPClientDialer.
+type MockLDAPClientDialerMockRecorder struct {
+ mock *MockLDAPClientDialer
+}
+
+// NewMockLDAPClientDialer creates a new mock instance.
+func NewMockLDAPClientDialer(ctrl *gomock.Controller) *MockLDAPClientDialer {
+ mock := &MockLDAPClientDialer{ctrl: ctrl}
+ mock.recorder = &MockLDAPClientDialerMockRecorder{mock}
+ return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockLDAPClientDialer) EXPECT() *MockLDAPClientDialerMockRecorder {
+ return m.recorder
+}
+
+// DialURL mocks base method.
+func (m *MockLDAPClientDialer) DialURL(addr string, opts ...ldap.DialOpt) (ldap.Client, error) {
+ m.ctrl.T.Helper()
+ varargs := []any{addr}
+ for _, a := range opts {
+ varargs = append(varargs, a)
+ }
+ ret := m.ctrl.Call(m, "DialURL", varargs...)
+ ret0, _ := ret[0].(ldap.Client)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// DialURL indicates an expected call of DialURL.
+func (mr *MockLDAPClientDialerMockRecorder) DialURL(addr any, opts ...any) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ varargs := append([]any{addr}, opts...)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DialURL", reflect.TypeOf((*MockLDAPClientDialer)(nil).DialURL), varargs...)
+}
diff --git a/internal/authentication/ldap_client_factory.go b/internal/authentication/ldap_client_factory.go
index d360f05b3..9bb55502c 100644
--- a/internal/authentication/ldap_client_factory.go
+++ b/internal/authentication/ldap_client_factory.go
@@ -1,18 +1,314 @@
package authentication
import (
+ "context"
+ "crypto/tls"
+ "crypto/x509"
+ "errors"
+ "fmt"
+ "net"
+ "sync"
+ "time"
+
"github.com/go-ldap/ldap/v3"
+
+ "github.com/authelia/authelia/v4/internal/configuration/schema"
+ "github.com/authelia/authelia/v4/internal/utils"
)
-// ProductionLDAPClientFactory the production implementation of an ldap connection factory.
-type ProductionLDAPClientFactory struct{}
+// LDAPClientFactory an interface describing factories that produce LDAPConnection implementations.
+type LDAPClientFactory interface {
+ Initialize() (err error)
+ GetClient(opts ...LDAPClientFactoryOption) (client ldap.Client, err error)
+ ReleaseClient(client ldap.Client) (err error)
+ Close() (err error)
+}
+
+// NewStandardLDAPClientFactory create a concrete ldap connection factory.
+func NewStandardLDAPClientFactory(config *schema.AuthenticationBackendLDAP, certs *x509.CertPool, dialer LDAPClientDialer) LDAPClientFactory {
+ if dialer == nil {
+ dialer = &LDAPClientDialerStandard{}
+ }
+
+ tlsc := utils.NewTLSConfig(config.TLS, certs)
+
+ opts := []ldap.DialOpt{
+ ldap.DialWithDialer(&net.Dialer{Timeout: config.Timeout}),
+ ldap.DialWithTLSConfig(tlsc),
+ }
+
+ return &StandardLDAPClientFactory{
+ config: config,
+ tls: tlsc,
+ opts: opts,
+ dialer: dialer,
+ }
+}
+
+// StandardLDAPClientFactory the production implementation of an ldap connection factory.
+type StandardLDAPClientFactory struct {
+ config *schema.AuthenticationBackendLDAP
+ tls *tls.Config
+ opts []ldap.DialOpt
+ dialer LDAPClientDialer
+}
+
+func (f *StandardLDAPClientFactory) Initialize() (err error) {
+ return nil
+}
+
+func (f *StandardLDAPClientFactory) GetClient(opts ...LDAPClientFactoryOption) (client ldap.Client, err error) {
+ return getLDAPClient(f.config.Address.String(), f.config.User, f.config.Password, f.dialer, f.tls, f.config.StartTLS, f.opts, opts...)
+}
+
+func (f *StandardLDAPClientFactory) ReleaseClient(client ldap.Client) (err error) {
+ if err = client.Close(); err != nil {
+ return fmt.Errorf("error occurred closing LDAP client: %w", err)
+ }
+
+ return nil
+}
-// NewProductionLDAPClientFactory create a concrete ldap connection factory.
-func NewProductionLDAPClientFactory() *ProductionLDAPClientFactory {
- return &ProductionLDAPClientFactory{}
+func (f *StandardLDAPClientFactory) Close() (err error) {
+ return nil
}
-// DialURL creates a client from an LDAP URL when successful.
-func (f *ProductionLDAPClientFactory) DialURL(addr string, opts ...ldap.DialOpt) (client LDAPClient, err error) {
- return ldap.DialURL(addr, opts...)
+// NewPooledLDAPClientFactory is a decorator for a LDAPClientFactory that performs pooling.
+func NewPooledLDAPClientFactory(config *schema.AuthenticationBackendLDAP, certs *x509.CertPool, dialer LDAPClientDialer) (factory LDAPClientFactory) {
+ if dialer == nil {
+ dialer = &LDAPClientDialerStandard{}
+ }
+
+ tlsc := utils.NewTLSConfig(config.TLS, certs)
+
+ opts := []ldap.DialOpt{
+ ldap.DialWithDialer(&net.Dialer{Timeout: config.Timeout}),
+ ldap.DialWithTLSConfig(tlsc),
+ }
+
+ if config.Pooling.Count <= 0 {
+ config.Pooling.Count = 3
+ }
+
+ if config.Pooling.Retries <= 0 {
+ config.Pooling.Retries = 3
+ }
+
+ if config.Pooling.Timeout <= 0 {
+ config.Pooling.Timeout = time.Second
+ }
+
+ sleep := config.Pooling.Timeout / time.Duration(config.Pooling.Retries)
+
+ return &PooledLDAPClientFactory{
+ config: config,
+ tls: tlsc,
+ opts: opts,
+ dialer: dialer,
+ sleep: sleep,
+ }
+}
+
+// PooledLDAPClientFactory is a LDAPClientFactory that takes another LDAPClientFactory and pools the
+// factory generated connections using a channel for thread safety.
+type PooledLDAPClientFactory struct {
+ config *schema.AuthenticationBackendLDAP
+ tls *tls.Config
+ opts []ldap.DialOpt
+ dialer LDAPClientDialer
+
+ pool chan *LDAPClientPooled
+ mu sync.Mutex
+
+ sleep time.Duration
+
+ closing bool
+}
+
+func (f *PooledLDAPClientFactory) Initialize() (err error) {
+ f.mu.Lock()
+
+ defer f.mu.Unlock()
+
+ if f.pool != nil {
+ return nil
+ }
+
+ f.pool = make(chan *LDAPClientPooled, f.config.Pooling.Count)
+
+ var (
+ errs []error
+ client *LDAPClientPooled
+ )
+
+ for i := 0; i < f.config.Pooling.Count; i++ {
+ if client, err = f.new(); err != nil {
+ errs = append(errs, err)
+
+ continue
+ }
+
+ f.pool <- client
+ }
+
+ if len(errs) == f.config.Pooling.Count {
+ return fmt.Errorf("errors occurred initializing the client pool: no connections could be established")
+ }
+
+ return nil
+}
+
+// GetClient opens new client using the pool.
+func (f *PooledLDAPClientFactory) GetClient(opts ...LDAPClientFactoryOption) (conn ldap.Client, err error) {
+ if len(opts) != 0 {
+ return getLDAPClient(f.config.Address.String(), f.config.User, f.config.Password, f.dialer, f.tls, f.config.StartTLS, f.opts, opts...)
+ }
+
+ return f.acquire(context.Background())
+}
+
+// The new function creates a pool based client. This function is not thread safe.
+func (f *PooledLDAPClientFactory) new() (pooled *LDAPClientPooled, err error) {
+ var client ldap.Client
+
+ if client, err = getLDAPClient(f.config.Address.String(), f.config.User, f.config.Password, f.dialer, f.tls, f.config.StartTLS, f.opts); err != nil {
+ return nil, fmt.Errorf("error occurred establishing new client for the pool: %w", err)
+ }
+
+ return &LDAPClientPooled{Client: client}, nil
+}
+
+// ReleaseClient returns a client using the pool or closes it.
+func (f *PooledLDAPClientFactory) ReleaseClient(client ldap.Client) (err error) {
+ f.mu.Lock()
+
+ defer f.mu.Unlock()
+
+ if f.closing {
+ return client.Close()
+ }
+
+ if pool, ok := client.(*LDAPClientPooled); !ok || cap(f.pool) == len(f.pool) {
+ // Prevent extra or non-pool connections from being returned into the pool.
+ return client.Close()
+ } else {
+ f.pool <- pool
+ }
+
+ return nil
+}
+
+func (f *PooledLDAPClientFactory) acquire(ctx context.Context) (client *LDAPClientPooled, err error) {
+ f.mu.Lock()
+
+ defer f.mu.Unlock()
+
+ if f.closing {
+ return nil, fmt.Errorf("error acquiring client: the pool is closed")
+ }
+
+ if cap(f.pool) != f.config.Pooling.Count {
+ if err = f.Initialize(); err != nil {
+ return nil, err
+ }
+ }
+
+ ctx, cancel := context.WithTimeout(ctx, f.config.Pooling.Timeout)
+ defer cancel()
+
+ select {
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ case client = <-f.pool:
+ if client.IsClosing() || client.Client == nil {
+ for {
+ select {
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ default:
+ if client, err = f.new(); err != nil {
+ time.Sleep(f.sleep)
+
+ continue
+ }
+
+ return client, nil
+ }
+ }
+ }
+
+ return client, nil
+ }
+}
+
+func (f *PooledLDAPClientFactory) Close() (err error) {
+ f.mu.Lock()
+
+ defer f.mu.Unlock()
+
+ f.closing = true
+
+ close(f.pool)
+
+ var errs []error
+
+ for client := range f.pool {
+ if client.IsClosing() {
+ continue
+ }
+
+ if err = client.Close(); err != nil {
+ errs = append(errs, err)
+ }
+ }
+
+ if len(errs) > 0 {
+ return fmt.Errorf("errors occurred closing the client pool: %w", errors.Join(errs...))
+ }
+
+ return nil
+}
+
+// LDAPClientPooled is a decorator for the ldap.Client which handles the pooling functionality. i.e. prevents the client
+// from being closed and instead relinquishes the connection back to the pool.
+type LDAPClientPooled struct {
+ ldap.Client
+}
+
+func getLDAPClient(address, username, password string, dialer LDAPClientDialer, tls *tls.Config, startTLS bool, dialerOpts []ldap.DialOpt, opts ...LDAPClientFactoryOption) (client ldap.Client, err error) {
+ config := &LDAPClientFactoryOptions{
+ Address: address,
+ Username: username,
+ Password: password,
+ }
+
+ for _, opt := range opts {
+ opt(config)
+ }
+
+ if client, err = dialer.DialURL(config.Address, dialerOpts...); err != nil {
+ return nil, fmt.Errorf("error occurred dialing address: %w", err)
+ }
+
+ if tls != nil && startTLS {
+ if err = client.StartTLS(tls); err != nil {
+ _ = client.Close()
+
+ return nil, fmt.Errorf("error occurred performing starttls: %w", err)
+ }
+ }
+
+ if config.Password == "" {
+ err = client.UnauthenticatedBind(config.Username)
+ } else {
+ err = client.Bind(config.Username, config.Password)
+ }
+
+ if err != nil {
+ _ = client.Close()
+
+ return nil, fmt.Errorf("error occurred performing bind: %w", err)
+ }
+
+ return client, nil
}
diff --git a/internal/authentication/ldap_client_factory_config.go b/internal/authentication/ldap_client_factory_config.go
new file mode 100644
index 000000000..c66222c79
--- /dev/null
+++ b/internal/authentication/ldap_client_factory_config.go
@@ -0,0 +1,27 @@
+package authentication
+
+type LDAPClientFactoryOptions struct {
+ Address string
+ Username string
+ Password string
+}
+
+type LDAPClientFactoryOption func(*LDAPClientFactoryOptions)
+
+func WithAddress(address string) func(*LDAPClientFactoryOptions) {
+ return func(settings *LDAPClientFactoryOptions) {
+ settings.Address = address
+ }
+}
+
+func WithUsername(username string) func(*LDAPClientFactoryOptions) {
+ return func(settings *LDAPClientFactoryOptions) {
+ settings.Username = username
+ }
+}
+
+func WithPassword(password string) func(*LDAPClientFactoryOptions) {
+ return func(settings *LDAPClientFactoryOptions) {
+ settings.Password = password
+ }
+}
diff --git a/internal/authentication/ldap_client_factory_mock_test.go b/internal/authentication/ldap_client_factory_mock_test.go
index f8ce5bb81..fe0a8c2e4 100644
--- a/internal/authentication/ldap_client_factory_mock_test.go
+++ b/internal/authentication/ldap_client_factory_mock_test.go
@@ -40,22 +40,63 @@ func (m *MockLDAPClientFactory) EXPECT() *MockLDAPClientFactoryMockRecorder {
return m.recorder
}
-// DialURL mocks base method.
-func (m *MockLDAPClientFactory) DialURL(addr string, opts ...ldap.DialOpt) (LDAPClient, error) {
+// Close mocks base method.
+func (m *MockLDAPClientFactory) Close() error {
m.ctrl.T.Helper()
- varargs := []any{addr}
+ ret := m.ctrl.Call(m, "Close")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// Close indicates an expected call of Close.
+func (mr *MockLDAPClientFactoryMockRecorder) Close() *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockLDAPClientFactory)(nil).Close))
+}
+
+// GetClient mocks base method.
+func (m *MockLDAPClientFactory) GetClient(opts ...LDAPClientFactoryOption) (ldap.Client, error) {
+ m.ctrl.T.Helper()
+ varargs := []any{}
for _, a := range opts {
varargs = append(varargs, a)
}
- ret := m.ctrl.Call(m, "DialURL", varargs...)
- ret0, _ := ret[0].(LDAPClient)
+ ret := m.ctrl.Call(m, "GetClient", varargs...)
+ ret0, _ := ret[0].(ldap.Client)
ret1, _ := ret[1].(error)
return ret0, ret1
}
-// DialURL indicates an expected call of DialURL.
-func (mr *MockLDAPClientFactoryMockRecorder) DialURL(addr any, opts ...any) *gomock.Call {
+// GetClient indicates an expected call of GetClient.
+func (mr *MockLDAPClientFactoryMockRecorder) GetClient(opts ...any) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetClient", reflect.TypeOf((*MockLDAPClientFactory)(nil).GetClient), opts...)
+}
+
+// Initialize mocks base method.
+func (m *MockLDAPClientFactory) Initialize() error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "Initialize")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// Initialize indicates an expected call of Initialize.
+func (mr *MockLDAPClientFactoryMockRecorder) Initialize() *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Initialize", reflect.TypeOf((*MockLDAPClientFactory)(nil).Initialize))
+}
+
+// ReleaseClient mocks base method.
+func (m *MockLDAPClientFactory) ReleaseClient(client ldap.Client) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "ReleaseClient", client)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// ReleaseClient indicates an expected call of ReleaseClient.
+func (mr *MockLDAPClientFactoryMockRecorder) ReleaseClient(client any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- varargs := append([]any{addr}, opts...)
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DialURL", reflect.TypeOf((*MockLDAPClientFactory)(nil).DialURL), varargs...)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReleaseClient", reflect.TypeOf((*MockLDAPClientFactory)(nil).ReleaseClient), client)
}
diff --git a/internal/authentication/ldap_client_mock_test.go b/internal/authentication/ldap_client_mock_test.go
index 3a492be2e..055beecbe 100644
--- a/internal/authentication/ldap_client_mock_test.go
+++ b/internal/authentication/ldap_client_mock_test.go
@@ -1,15 +1,16 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: github.com/authelia/authelia/v4/internal/authentication (interfaces: LDAPClient)
+// Source: github.com/go-ldap/ldap/v3 (interfaces: Client)
//
// Generated by this command:
//
-// mockgen -package authentication -destination ldap_client_mock_test.go -mock_names LDAPClient=MockLDAPClient github.com/authelia/authelia/v4/internal/authentication LDAPClient
+// mockgen -package authentication -destination ldap_client_mock_test.go -mock_names Client=MockLDAPClient github.com/go-ldap/ldap/v3 Client
//
// Package authentication is a generated GoMock package.
package authentication
import (
+ context "context"
tls "crypto/tls"
reflect "reflect"
time "time"
@@ -18,7 +19,7 @@ import (
gomock "go.uber.org/mock/gomock"
)
-// MockLDAPClient is a mock of LDAPClient interface.
+// MockLDAPClient is a mock of Client interface.
type MockLDAPClient struct {
ctrl *gomock.Controller
recorder *MockLDAPClientMockRecorder
@@ -43,17 +44,17 @@ func (m *MockLDAPClient) EXPECT() *MockLDAPClientMockRecorder {
}
// Add mocks base method.
-func (m *MockLDAPClient) Add(request *ldap.AddRequest) error {
+func (m *MockLDAPClient) Add(arg0 *ldap.AddRequest) error {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "Add", request)
+ ret := m.ctrl.Call(m, "Add", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// Add indicates an expected call of Add.
-func (mr *MockLDAPClientMockRecorder) Add(request any) *gomock.Call {
+func (mr *MockLDAPClientMockRecorder) Add(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Add", reflect.TypeOf((*MockLDAPClient)(nil).Add), request)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Add", reflect.TypeOf((*MockLDAPClient)(nil).Add), arg0)
}
// Bind mocks base method.
@@ -100,160 +101,146 @@ func (mr *MockLDAPClientMockRecorder) Compare(dn, attribute, value any) *gomock.
}
// Del mocks base method.
-func (m *MockLDAPClient) Del(request *ldap.DelRequest) error {
+func (m *MockLDAPClient) Del(arg0 *ldap.DelRequest) error {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "Del", request)
+ ret := m.ctrl.Call(m, "Del", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// Del indicates an expected call of Del.
-func (mr *MockLDAPClientMockRecorder) Del(request any) *gomock.Call {
+func (mr *MockLDAPClientMockRecorder) Del(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Del", reflect.TypeOf((*MockLDAPClient)(nil).Del), request)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Del", reflect.TypeOf((*MockLDAPClient)(nil).Del), arg0)
}
-// DigestMD5Bind mocks base method.
-func (m *MockLDAPClient) DigestMD5Bind(request *ldap.DigestMD5BindRequest) (*ldap.DigestMD5BindResult, error) {
+// DirSync mocks base method.
+func (m *MockLDAPClient) DirSync(searchRequest *ldap.SearchRequest, flags, maxAttrCount int64, cookie []byte) (*ldap.SearchResult, error) {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "DigestMD5Bind", request)
- ret0, _ := ret[0].(*ldap.DigestMD5BindResult)
+ ret := m.ctrl.Call(m, "DirSync", searchRequest, flags, maxAttrCount, cookie)
+ ret0, _ := ret[0].(*ldap.SearchResult)
ret1, _ := ret[1].(error)
return ret0, ret1
}
-// DigestMD5Bind indicates an expected call of DigestMD5Bind.
-func (mr *MockLDAPClientMockRecorder) DigestMD5Bind(request any) *gomock.Call {
+// DirSync indicates an expected call of DirSync.
+func (mr *MockLDAPClientMockRecorder) DirSync(searchRequest, flags, maxAttrCount, cookie any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DigestMD5Bind", reflect.TypeOf((*MockLDAPClient)(nil).DigestMD5Bind), request)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DirSync", reflect.TypeOf((*MockLDAPClient)(nil).DirSync), searchRequest, flags, maxAttrCount, cookie)
}
-// ExternalBind mocks base method.
-func (m *MockLDAPClient) ExternalBind() error {
+// DirSyncAsync mocks base method.
+func (m *MockLDAPClient) DirSyncAsync(ctx context.Context, searchRequest *ldap.SearchRequest, bufferSize int, flags, maxAttrCount int64, cookie []byte) ldap.Response {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "ExternalBind")
- ret0, _ := ret[0].(error)
+ ret := m.ctrl.Call(m, "DirSyncAsync", ctx, searchRequest, bufferSize, flags, maxAttrCount, cookie)
+ ret0, _ := ret[0].(ldap.Response)
return ret0
}
-// ExternalBind indicates an expected call of ExternalBind.
-func (mr *MockLDAPClientMockRecorder) ExternalBind() *gomock.Call {
+// DirSyncAsync indicates an expected call of DirSyncAsync.
+func (mr *MockLDAPClientMockRecorder) DirSyncAsync(ctx, searchRequest, bufferSize, flags, maxAttrCount, cookie any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExternalBind", reflect.TypeOf((*MockLDAPClient)(nil).ExternalBind))
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DirSyncAsync", reflect.TypeOf((*MockLDAPClient)(nil).DirSyncAsync), ctx, searchRequest, bufferSize, flags, maxAttrCount, cookie)
}
-// IsClosing mocks base method.
-func (m *MockLDAPClient) IsClosing() bool {
+// Extended mocks base method.
+func (m *MockLDAPClient) Extended(arg0 *ldap.ExtendedRequest) (*ldap.ExtendedResponse, error) {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "IsClosing")
- ret0, _ := ret[0].(bool)
- return ret0
+ ret := m.ctrl.Call(m, "Extended", arg0)
+ ret0, _ := ret[0].(*ldap.ExtendedResponse)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
}
-// IsClosing indicates an expected call of IsClosing.
-func (mr *MockLDAPClientMockRecorder) IsClosing() *gomock.Call {
+// Extended indicates an expected call of Extended.
+func (mr *MockLDAPClientMockRecorder) Extended(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsClosing", reflect.TypeOf((*MockLDAPClient)(nil).IsClosing))
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Extended", reflect.TypeOf((*MockLDAPClient)(nil).Extended), arg0)
}
-// MD5Bind mocks base method.
-func (m *MockLDAPClient) MD5Bind(host, username, password string) error {
+// ExternalBind mocks base method.
+func (m *MockLDAPClient) ExternalBind() error {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "MD5Bind", host, username, password)
+ ret := m.ctrl.Call(m, "ExternalBind")
ret0, _ := ret[0].(error)
return ret0
}
-// MD5Bind indicates an expected call of MD5Bind.
-func (mr *MockLDAPClientMockRecorder) MD5Bind(host, username, password any) *gomock.Call {
+// ExternalBind indicates an expected call of ExternalBind.
+func (mr *MockLDAPClientMockRecorder) ExternalBind() *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MD5Bind", reflect.TypeOf((*MockLDAPClient)(nil).MD5Bind), host, username, password)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExternalBind", reflect.TypeOf((*MockLDAPClient)(nil).ExternalBind))
}
-// Modify mocks base method.
-func (m *MockLDAPClient) Modify(request *ldap.ModifyRequest) error {
+// GetLastError mocks base method.
+func (m *MockLDAPClient) GetLastError() error {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "Modify", request)
+ ret := m.ctrl.Call(m, "GetLastError")
ret0, _ := ret[0].(error)
return ret0
}
-// Modify indicates an expected call of Modify.
-func (mr *MockLDAPClientMockRecorder) Modify(request any) *gomock.Call {
+// GetLastError indicates an expected call of GetLastError.
+func (mr *MockLDAPClientMockRecorder) GetLastError() *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Modify", reflect.TypeOf((*MockLDAPClient)(nil).Modify), request)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLastError", reflect.TypeOf((*MockLDAPClient)(nil).GetLastError))
}
-// ModifyDN mocks base method.
-func (m_2 *MockLDAPClient) ModifyDN(m *ldap.ModifyDNRequest) error {
- m_2.ctrl.T.Helper()
- ret := m_2.ctrl.Call(m_2, "ModifyDN", m)
- ret0, _ := ret[0].(error)
- return ret0
-}
-
-// ModifyDN indicates an expected call of ModifyDN.
-func (mr *MockLDAPClientMockRecorder) ModifyDN(m any) *gomock.Call {
- mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ModifyDN", reflect.TypeOf((*MockLDAPClient)(nil).ModifyDN), m)
-}
-
-// ModifyWithResult mocks base method.
-func (m *MockLDAPClient) ModifyWithResult(request *ldap.ModifyRequest) (*ldap.ModifyResult, error) {
+// IsClosing mocks base method.
+func (m *MockLDAPClient) IsClosing() bool {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "ModifyWithResult", request)
- ret0, _ := ret[0].(*ldap.ModifyResult)
- ret1, _ := ret[1].(error)
- return ret0, ret1
+ ret := m.ctrl.Call(m, "IsClosing")
+ ret0, _ := ret[0].(bool)
+ return ret0
}
-// ModifyWithResult indicates an expected call of ModifyWithResult.
-func (mr *MockLDAPClientMockRecorder) ModifyWithResult(request any) *gomock.Call {
+// IsClosing indicates an expected call of IsClosing.
+func (mr *MockLDAPClientMockRecorder) IsClosing() *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ModifyWithResult", reflect.TypeOf((*MockLDAPClient)(nil).ModifyWithResult), request)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsClosing", reflect.TypeOf((*MockLDAPClient)(nil).IsClosing))
}
-// NTLMBind mocks base method.
-func (m *MockLDAPClient) NTLMBind(domain, username, password string) error {
+// Modify mocks base method.
+func (m *MockLDAPClient) Modify(arg0 *ldap.ModifyRequest) error {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "NTLMBind", domain, username, password)
+ ret := m.ctrl.Call(m, "Modify", arg0)
ret0, _ := ret[0].(error)
return ret0
}
-// NTLMBind indicates an expected call of NTLMBind.
-func (mr *MockLDAPClientMockRecorder) NTLMBind(domain, username, password any) *gomock.Call {
+// Modify indicates an expected call of Modify.
+func (mr *MockLDAPClientMockRecorder) Modify(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NTLMBind", reflect.TypeOf((*MockLDAPClient)(nil).NTLMBind), domain, username, password)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Modify", reflect.TypeOf((*MockLDAPClient)(nil).Modify), arg0)
}
-// NTLMBindWithHash mocks base method.
-func (m *MockLDAPClient) NTLMBindWithHash(domain, username, hash string) error {
+// ModifyDN mocks base method.
+func (m *MockLDAPClient) ModifyDN(arg0 *ldap.ModifyDNRequest) error {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "NTLMBindWithHash", domain, username, hash)
+ ret := m.ctrl.Call(m, "ModifyDN", arg0)
ret0, _ := ret[0].(error)
return ret0
}
-// NTLMBindWithHash indicates an expected call of NTLMBindWithHash.
-func (mr *MockLDAPClientMockRecorder) NTLMBindWithHash(domain, username, hash any) *gomock.Call {
+// ModifyDN indicates an expected call of ModifyDN.
+func (mr *MockLDAPClientMockRecorder) ModifyDN(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NTLMBindWithHash", reflect.TypeOf((*MockLDAPClient)(nil).NTLMBindWithHash), domain, username, hash)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ModifyDN", reflect.TypeOf((*MockLDAPClient)(nil).ModifyDN), arg0)
}
-// NTLMChallengeBind mocks base method.
-func (m *MockLDAPClient) NTLMChallengeBind(request *ldap.NTLMBindRequest) (*ldap.NTLMBindResult, error) {
+// ModifyWithResult mocks base method.
+func (m *MockLDAPClient) ModifyWithResult(arg0 *ldap.ModifyRequest) (*ldap.ModifyResult, error) {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "NTLMChallengeBind", request)
- ret0, _ := ret[0].(*ldap.NTLMBindResult)
+ ret := m.ctrl.Call(m, "ModifyWithResult", arg0)
+ ret0, _ := ret[0].(*ldap.ModifyResult)
ret1, _ := ret[1].(error)
return ret0, ret1
}
-// NTLMChallengeBind indicates an expected call of NTLMChallengeBind.
-func (mr *MockLDAPClientMockRecorder) NTLMChallengeBind(request any) *gomock.Call {
+// ModifyWithResult indicates an expected call of ModifyWithResult.
+func (mr *MockLDAPClientMockRecorder) ModifyWithResult(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NTLMChallengeBind", reflect.TypeOf((*MockLDAPClient)(nil).NTLMChallengeBind), request)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ModifyWithResult", reflect.TypeOf((*MockLDAPClient)(nil).ModifyWithResult), arg0)
}
// NTLMUnauthenticatedBind mocks base method.
@@ -271,89 +258,129 @@ func (mr *MockLDAPClientMockRecorder) NTLMUnauthenticatedBind(domain, username a
}
// PasswordModify mocks base method.
-func (m *MockLDAPClient) PasswordModify(request *ldap.PasswordModifyRequest) (*ldap.PasswordModifyResult, error) {
+func (m *MockLDAPClient) PasswordModify(arg0 *ldap.PasswordModifyRequest) (*ldap.PasswordModifyResult, error) {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "PasswordModify", request)
+ ret := m.ctrl.Call(m, "PasswordModify", arg0)
ret0, _ := ret[0].(*ldap.PasswordModifyResult)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// PasswordModify indicates an expected call of PasswordModify.
-func (mr *MockLDAPClientMockRecorder) PasswordModify(request any) *gomock.Call {
+func (mr *MockLDAPClientMockRecorder) PasswordModify(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PasswordModify", reflect.TypeOf((*MockLDAPClient)(nil).PasswordModify), request)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PasswordModify", reflect.TypeOf((*MockLDAPClient)(nil).PasswordModify), arg0)
}
// Search mocks base method.
-func (m *MockLDAPClient) Search(request *ldap.SearchRequest) (*ldap.SearchResult, error) {
+func (m *MockLDAPClient) Search(arg0 *ldap.SearchRequest) (*ldap.SearchResult, error) {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "Search", request)
+ ret := m.ctrl.Call(m, "Search", arg0)
ret0, _ := ret[0].(*ldap.SearchResult)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Search indicates an expected call of Search.
-func (mr *MockLDAPClientMockRecorder) Search(request any) *gomock.Call {
+func (mr *MockLDAPClientMockRecorder) Search(arg0 any) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Search", reflect.TypeOf((*MockLDAPClient)(nil).Search), arg0)
+}
+
+// SearchAsync mocks base method.
+func (m *MockLDAPClient) SearchAsync(ctx context.Context, searchRequest *ldap.SearchRequest, bufferSize int) ldap.Response {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "SearchAsync", ctx, searchRequest, bufferSize)
+ ret0, _ := ret[0].(ldap.Response)
+ return ret0
+}
+
+// SearchAsync indicates an expected call of SearchAsync.
+func (mr *MockLDAPClientMockRecorder) SearchAsync(ctx, searchRequest, bufferSize any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Search", reflect.TypeOf((*MockLDAPClient)(nil).Search), request)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchAsync", reflect.TypeOf((*MockLDAPClient)(nil).SearchAsync), ctx, searchRequest, bufferSize)
}
// SearchWithPaging mocks base method.
-func (m *MockLDAPClient) SearchWithPaging(request *ldap.SearchRequest, pagingSize uint32) (*ldap.SearchResult, error) {
+func (m *MockLDAPClient) SearchWithPaging(searchRequest *ldap.SearchRequest, pagingSize uint32) (*ldap.SearchResult, error) {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "SearchWithPaging", request, pagingSize)
+ ret := m.ctrl.Call(m, "SearchWithPaging", searchRequest, pagingSize)
ret0, _ := ret[0].(*ldap.SearchResult)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SearchWithPaging indicates an expected call of SearchWithPaging.
-func (mr *MockLDAPClientMockRecorder) SearchWithPaging(request, pagingSize any) *gomock.Call {
+func (mr *MockLDAPClientMockRecorder) SearchWithPaging(searchRequest, pagingSize any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchWithPaging", reflect.TypeOf((*MockLDAPClient)(nil).SearchWithPaging), request, pagingSize)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchWithPaging", reflect.TypeOf((*MockLDAPClient)(nil).SearchWithPaging), searchRequest, pagingSize)
}
// SetTimeout mocks base method.
-func (m *MockLDAPClient) SetTimeout(timeout time.Duration) {
+func (m *MockLDAPClient) SetTimeout(arg0 time.Duration) {
m.ctrl.T.Helper()
- m.ctrl.Call(m, "SetTimeout", timeout)
+ m.ctrl.Call(m, "SetTimeout", arg0)
}
// SetTimeout indicates an expected call of SetTimeout.
-func (mr *MockLDAPClientMockRecorder) SetTimeout(timeout any) *gomock.Call {
+func (mr *MockLDAPClientMockRecorder) SetTimeout(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetTimeout", reflect.TypeOf((*MockLDAPClient)(nil).SetTimeout), timeout)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetTimeout", reflect.TypeOf((*MockLDAPClient)(nil).SetTimeout), arg0)
}
// SimpleBind mocks base method.
-func (m *MockLDAPClient) SimpleBind(request *ldap.SimpleBindRequest) (*ldap.SimpleBindResult, error) {
+func (m *MockLDAPClient) SimpleBind(arg0 *ldap.SimpleBindRequest) (*ldap.SimpleBindResult, error) {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "SimpleBind", request)
+ ret := m.ctrl.Call(m, "SimpleBind", arg0)
ret0, _ := ret[0].(*ldap.SimpleBindResult)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SimpleBind indicates an expected call of SimpleBind.
-func (mr *MockLDAPClientMockRecorder) SimpleBind(request any) *gomock.Call {
+func (mr *MockLDAPClientMockRecorder) SimpleBind(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SimpleBind", reflect.TypeOf((*MockLDAPClient)(nil).SimpleBind), request)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SimpleBind", reflect.TypeOf((*MockLDAPClient)(nil).SimpleBind), arg0)
+}
+
+// Start mocks base method.
+func (m *MockLDAPClient) Start() {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "Start")
+}
+
+// Start indicates an expected call of Start.
+func (mr *MockLDAPClientMockRecorder) Start() *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*MockLDAPClient)(nil).Start))
}
// StartTLS mocks base method.
-func (m *MockLDAPClient) StartTLS(config *tls.Config) error {
+func (m *MockLDAPClient) StartTLS(arg0 *tls.Config) error {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "StartTLS", config)
+ ret := m.ctrl.Call(m, "StartTLS", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// StartTLS indicates an expected call of StartTLS.
-func (mr *MockLDAPClientMockRecorder) StartTLS(config any) *gomock.Call {
+func (mr *MockLDAPClientMockRecorder) StartTLS(arg0 any) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartTLS", reflect.TypeOf((*MockLDAPClient)(nil).StartTLS), arg0)
+}
+
+// Syncrepl mocks base method.
+func (m *MockLDAPClient) Syncrepl(ctx context.Context, searchRequest *ldap.SearchRequest, bufferSize int, mode ldap.ControlSyncRequestMode, cookie []byte, reloadHint bool) ldap.Response {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "Syncrepl", ctx, searchRequest, bufferSize, mode, cookie, reloadHint)
+ ret0, _ := ret[0].(ldap.Response)
+ return ret0
+}
+
+// Syncrepl indicates an expected call of Syncrepl.
+func (mr *MockLDAPClientMockRecorder) Syncrepl(ctx, searchRequest, bufferSize, mode, cookie, reloadHint any) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartTLS", reflect.TypeOf((*MockLDAPClient)(nil).StartTLS), config)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Syncrepl", reflect.TypeOf((*MockLDAPClient)(nil).Syncrepl), ctx, searchRequest, bufferSize, mode, cookie, reloadHint)
}
// TLSConnectionState mocks base method.
@@ -398,18 +425,3 @@ func (mr *MockLDAPClientMockRecorder) Unbind() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unbind", reflect.TypeOf((*MockLDAPClient)(nil).Unbind))
}
-
-// WhoAmI mocks base method.
-func (m *MockLDAPClient) WhoAmI(controls []ldap.Control) (*ldap.WhoAmIResult, error) {
- m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "WhoAmI", controls)
- ret0, _ := ret[0].(*ldap.WhoAmIResult)
- ret1, _ := ret[1].(error)
- return ret0, ret1
-}
-
-// WhoAmI indicates an expected call of WhoAmI.
-func (mr *MockLDAPClientMockRecorder) WhoAmI(controls any) *gomock.Call {
- mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WhoAmI", reflect.TypeOf((*MockLDAPClient)(nil).WhoAmI), controls)
-}
diff --git a/internal/authentication/ldap_user_provider.go b/internal/authentication/ldap_user_provider.go
index 66687e1a1..905bf07e8 100644
--- a/internal/authentication/ldap_user_provider.go
+++ b/internal/authentication/ldap_user_provider.go
@@ -1,10 +1,8 @@
package authentication
import (
- "crypto/tls"
"crypto/x509"
"fmt"
- "net"
"net/url"
"strconv"
"strings"
@@ -21,11 +19,9 @@ import (
// LDAPUserProvider is a UserProvider that connects to LDAP servers like ActiveDirectory, OpenLDAP, OpenDJ, FreeIPA, etc.
type LDAPUserProvider struct {
- config schema.AuthenticationBackendLDAP
- tlsConfig *tls.Config
- dialOpts []ldap.DialOpt
- log *logrus.Logger
- factory LDAPClientFactory
+ config *schema.AuthenticationBackendLDAP
+ log *logrus.Logger
+ factory LDAPClientFactory
clock clock.Provider
@@ -53,37 +49,27 @@ type LDAPUserProvider struct {
groupsFilterReplacementsMemberOfRDN bool
}
-// NewLDAPUserProvider creates a new instance of LDAPUserProvider with the ProductionLDAPClientFactory.
-func NewLDAPUserProvider(config schema.AuthenticationBackend, certPool *x509.CertPool) (provider *LDAPUserProvider) {
- provider = NewLDAPUserProviderWithFactory(*config.LDAP, config.PasswordReset.Disable, certPool, NewProductionLDAPClientFactory())
-
- return provider
-}
-
-// NewLDAPUserProviderWithFactory creates a new instance of LDAPUserProvider with the specified LDAPClientFactory.
-func NewLDAPUserProviderWithFactory(config schema.AuthenticationBackendLDAP, disableResetPassword bool, certPool *x509.CertPool, factory LDAPClientFactory) (provider *LDAPUserProvider) {
- if config.TLS == nil {
- config.TLS = schema.DefaultLDAPAuthenticationBackendConfigurationImplementationCustom.TLS
+// NewLDAPUserProvider creates a new instance of LDAPUserProvider with the StandardLDAPClientFactory.
+func NewLDAPUserProvider(config schema.AuthenticationBackend, certs *x509.CertPool) (provider *LDAPUserProvider) {
+ if config.LDAP.TLS == nil {
+ config.LDAP.TLS = schema.DefaultLDAPAuthenticationBackendConfigurationImplementationCustom.TLS
}
- tlsConfig := utils.NewTLSConfig(config.TLS, certPool)
+ var factory LDAPClientFactory
- var dialOpts = []ldap.DialOpt{
- ldap.DialWithDialer(&net.Dialer{Timeout: config.Timeout}),
- }
-
- if tlsConfig != nil {
- dialOpts = append(dialOpts, ldap.DialWithTLSConfig(tlsConfig))
+ if config.LDAP.Pooling.Enable {
+ factory = NewPooledLDAPClientFactory(config.LDAP, certs, nil)
+ } else {
+ factory = NewStandardLDAPClientFactory(config.LDAP, certs, nil)
}
- if factory == nil {
- factory = NewProductionLDAPClientFactory()
- }
+ return NewLDAPUserProviderWithFactory(config.LDAP, config.PasswordReset.Disable, factory)
+}
+// NewLDAPUserProviderWithFactory creates a new instance of LDAPUserProvider with the specified LDAPClientFactory.
+func NewLDAPUserProviderWithFactory(config *schema.AuthenticationBackendLDAP, disableResetPassword bool, factory LDAPClientFactory) (provider *LDAPUserProvider) {
provider = &LDAPUserProvider{
config: config,
- tlsConfig: tlsConfig,
- dialOpts: dialOpts,
log: logging.Logger(),
factory: factory,
disableResetPassword: disableResetPassword,
@@ -99,25 +85,33 @@ func NewLDAPUserProviderWithFactory(config schema.AuthenticationBackendLDAP, dis
// CheckUserPassword checks if provided password matches for the given user.
func (p *LDAPUserProvider) CheckUserPassword(username string, password string) (valid bool, err error) {
var (
- client, clientUser LDAPClient
- profile *ldapUserProfile
+ client, uclient ldap.Client
+ profile *ldapUserProfile
)
- if client, err = p.connect(); err != nil {
+ if client, err = p.factory.GetClient(); err != nil {
return false, err
}
- defer client.Close()
+ defer func() {
+ if err := p.factory.ReleaseClient(client); err != nil {
+ p.log.WithError(err).Warn("Error occurred releasing the LDAP client")
+ }
+ }()
if profile, err = p.getUserProfile(client, username); err != nil {
return false, err
}
- if clientUser, err = p.connectCustom(p.config.Address.String(), profile.DN, password, p.config.StartTLS, p.dialOpts...); err != nil {
+ if uclient, err = p.factory.GetClient(WithUsername(profile.DN), WithPassword(password)); err != nil {
return false, fmt.Errorf("authentication failed. Cause: %w", err)
}
- defer clientUser.Close()
+ defer func() {
+ if err := p.factory.ReleaseClient(uclient); err != nil {
+ p.log.WithError(err).Warn("Error occurred releasing the LDAP client")
+ }
+ }()
return true, nil
}
@@ -125,15 +119,19 @@ func (p *LDAPUserProvider) CheckUserPassword(username string, password string) (
// GetDetails retrieve the groups a user belongs to.
func (p *LDAPUserProvider) GetDetails(username string) (details *UserDetails, err error) {
var (
- client LDAPClient
+ client ldap.Client
profile *ldapUserProfile
)
- if client, err = p.connect(); err != nil {
+ if client, err = p.factory.GetClient(); err != nil {
return nil, err
}
- defer client.Close()
+ defer func() {
+ if err := p.factory.ReleaseClient(client); err != nil {
+ p.log.WithError(err).Warn("Error occurred releasing the LDAP client")
+ }
+ }()
if profile, err = p.getUserProfile(client, username); err != nil {
return nil, err
@@ -158,11 +156,11 @@ func (p *LDAPUserProvider) GetDetails(username string) (details *UserDetails, er
// GetDetailsExtended retrieves the UserDetailsExtended values.
func (p *LDAPUserProvider) GetDetailsExtended(username string) (details *UserDetailsExtended, err error) {
var (
- client LDAPClient
+ client ldap.Client
profile *ldapUserProfileExtended
)
- if client, err = p.connect(); err != nil {
+ if client, err = p.factory.GetClient(); err != nil {
return nil, err
}
@@ -243,15 +241,19 @@ func (p *LDAPUserProvider) GetDetailsExtended(username string) (details *UserDet
// UpdatePassword update the password of the given user.
func (p *LDAPUserProvider) UpdatePassword(username, password string) (err error) {
var (
- client LDAPClient
+ client ldap.Client
profile *ldapUserProfile
)
- if client, err = p.connect(); err != nil {
+ if client, err = p.factory.GetClient(); err != nil {
return fmt.Errorf("unable to update password. Cause: %w", err)
}
- defer client.Close()
+ defer func() {
+ if err := p.factory.ReleaseClient(client); err != nil {
+ p.log.WithError(err).Warn("Error occurred releasing the LDAP client")
+ }
+ }()
if profile, err = p.getUserProfile(client, username); err != nil {
return fmt.Errorf("unable to update password. Cause: %w", err)
@@ -297,39 +299,7 @@ func (p *LDAPUserProvider) UpdatePassword(username, password string) (err error)
return nil
}
-func (p *LDAPUserProvider) connect() (client LDAPClient, err error) {
- return p.connectCustom(p.config.Address.String(), p.config.User, p.config.Password, p.config.StartTLS, p.dialOpts...)
-}
-
-func (p *LDAPUserProvider) connectCustom(url, username, password string, startTLS bool, opts ...ldap.DialOpt) (client LDAPClient, err error) {
- if client, err = p.factory.DialURL(url, opts...); err != nil {
- return nil, fmt.Errorf("dial failed with error: %w", err)
- }
-
- if startTLS {
- if err = client.StartTLS(p.tlsConfig); err != nil {
- client.Close()
-
- return nil, fmt.Errorf("starttls failed with error: %w", err)
- }
- }
-
- if password == "" {
- err = client.UnauthenticatedBind(username)
- } else {
- err = client.Bind(username, password)
- }
-
- if err != nil {
- client.Close()
-
- return nil, fmt.Errorf("bind failed with error: %w", err)
- }
-
- return client, nil
-}
-
-func (p *LDAPUserProvider) search(client LDAPClient, request *ldap.SearchRequest) (result *ldap.SearchResult, err error) {
+func (p *LDAPUserProvider) search(client ldap.Client, request *ldap.SearchRequest) (result *ldap.SearchResult, err error) {
if result, err = client.Search(request); err != nil {
if referral, ok := p.getReferral(err); ok {
if result == nil {
@@ -357,15 +327,19 @@ func (p *LDAPUserProvider) search(client LDAPClient, request *ldap.SearchRequest
func (p *LDAPUserProvider) searchReferral(referral string, request *ldap.SearchRequest, searchResult *ldap.SearchResult) (err error) {
var (
- client LDAPClient
+ client ldap.Client
result *ldap.SearchResult
)
- if client, err = p.connectCustom(referral, p.config.User, p.config.Password, p.config.StartTLS, p.dialOpts...); err != nil {
+ if client, err = p.factory.GetClient(WithAddress(referral)); err != nil {
return fmt.Errorf("error occurred connecting to referred LDAP server '%s': %w", referral, err)
}
- defer client.Close()
+ defer func() {
+ if err := p.factory.ReleaseClient(client); err != nil {
+ p.log.WithError(err).Warn("Error occurred releasing the LDAP client")
+ }
+ }()
if result, err = client.Search(request); err != nil {
return fmt.Errorf("error occurred performing search on referred LDAP server '%s': %w", referral, err)
@@ -390,7 +364,7 @@ func (p *LDAPUserProvider) searchReferrals(request *ldap.SearchRequest, result *
return nil
}
-func (p *LDAPUserProvider) getUserProfile(client LDAPClient, username string) (profile *ldapUserProfile, err error) {
+func (p *LDAPUserProvider) getUserProfile(client ldap.Client, username string) (profile *ldapUserProfile, err error) {
// Search for the given username.
request := ldap.NewSearchRequest(
p.usersBaseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases,
@@ -463,7 +437,7 @@ func (p *LDAPUserProvider) getUserProfileResultToProfile(username string, entry
return &userProfile, nil
}
-func (p *LDAPUserProvider) getUserProfileExtended(client LDAPClient, username string) (profile *ldapUserProfileExtended, err error) {
+func (p *LDAPUserProvider) getUserProfileExtended(client ldap.Client, username string) (profile *ldapUserProfileExtended, err error) {
// Search for the given username.
request := ldap.NewSearchRequest(
p.usersBaseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases,
@@ -552,7 +526,7 @@ func (p *LDAPUserProvider) getUserProfileResultToProfileExtended(username string
return &userProfile, nil
}
-func (p *LDAPUserProvider) getUserGroups(client LDAPClient, username string, profile *ldapUserProfile) (groups []string, err error) {
+func (p *LDAPUserProvider) getUserGroups(client ldap.Client, username string, profile *ldapUserProfile) (groups []string, err error) {
request := ldap.NewSearchRequest(
p.groupsBaseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases,
0, 0, false, p.resolveGroupsFilter(username, profile), p.groupsAttributes, nil,
@@ -577,7 +551,7 @@ func (p *LDAPUserProvider) getUserGroups(client LDAPClient, username string, pro
}
}
-func (p *LDAPUserProvider) getUserGroupsRequestFilter(client LDAPClient, username string, _ *ldapUserProfile, request *ldap.SearchRequest) (groups []string, err error) {
+func (p *LDAPUserProvider) getUserGroupsRequestFilter(client ldap.Client, username string, _ *ldapUserProfile, request *ldap.SearchRequest) (groups []string, err error) {
var result *ldap.SearchResult
if result, err = p.search(client, request); err != nil {
@@ -593,7 +567,7 @@ func (p *LDAPUserProvider) getUserGroupsRequestFilter(client LDAPClient, usernam
return groups, nil
}
-func (p *LDAPUserProvider) getUserGroupsRequestMemberOf(client LDAPClient, username string, profile *ldapUserProfile, request *ldap.SearchRequest) (groups []string, err error) {
+func (p *LDAPUserProvider) getUserGroupsRequestMemberOf(client ldap.Client, username string, profile *ldapUserProfile, request *ldap.SearchRequest) (groups []string, err error) {
var result *ldap.SearchResult
if result, err = p.search(client, request); err != nil {
@@ -733,7 +707,7 @@ func (p *LDAPUserProvider) resolveGroupsFilter(input string, profile *ldapUserPr
return filter
}
-func (p *LDAPUserProvider) modify(client LDAPClient, modifyRequest *ldap.ModifyRequest) (err error) {
+func (p *LDAPUserProvider) modify(client ldap.Client, modifyRequest *ldap.ModifyRequest) (err error) {
if err = client.Modify(modifyRequest); err != nil {
var (
referral string
@@ -747,15 +721,19 @@ func (p *LDAPUserProvider) modify(client LDAPClient, modifyRequest *ldap.ModifyR
p.log.Debugf("Attempting Modify on referred URL %s", referral)
var (
- clientRef LDAPClient
+ clientRef ldap.Client
errRef error
)
- if clientRef, errRef = p.connectCustom(referral, p.config.User, p.config.Password, p.config.StartTLS, p.dialOpts...); errRef != nil {
+ if clientRef, errRef = p.factory.GetClient(WithAddress(referral)); errRef != nil {
return fmt.Errorf("error occurred connecting to referred LDAP server '%s': %+v. Original Error: %w", referral, errRef, err)
}
- defer clientRef.Close()
+ defer func() {
+ if err := p.factory.ReleaseClient(clientRef); err != nil {
+ p.log.WithError(err).Warn("Error occurred releasing the LDAP client")
+ }
+ }()
if errRef = clientRef.Modify(modifyRequest); errRef != nil {
return fmt.Errorf("error occurred performing modify on referred LDAP server '%s': %+v. Original Error: %w", referral, errRef, err)
@@ -767,7 +745,7 @@ func (p *LDAPUserProvider) modify(client LDAPClient, modifyRequest *ldap.ModifyR
return nil
}
-func (p *LDAPUserProvider) pwdModify(client LDAPClient, pwdModifyRequest *ldap.PasswordModifyRequest) (err error) {
+func (p *LDAPUserProvider) pwdModify(client ldap.Client, pwdModifyRequest *ldap.PasswordModifyRequest) (err error) {
if _, err = client.PasswordModify(pwdModifyRequest); err != nil {
var (
referral string
@@ -781,15 +759,19 @@ func (p *LDAPUserProvider) pwdModify(client LDAPClient, pwdModifyRequest *ldap.P
p.log.Debugf("Attempting PwdModify ExOp (1.3.6.1.4.1.4203.1.11.1) on referred URL %s", referral)
var (
- clientRef LDAPClient
+ clientRef ldap.Client
errRef error
)
- if clientRef, errRef = p.connectCustom(referral, p.config.User, p.config.Password, p.config.StartTLS, p.dialOpts...); errRef != nil {
+ if clientRef, errRef = p.factory.GetClient(WithAddress(referral)); errRef != nil {
return fmt.Errorf("error occurred connecting to referred LDAP server '%s': %+v. Original Error: %w", referral, errRef, err)
}
- defer clientRef.Close()
+ defer func() {
+ if err := p.factory.ReleaseClient(clientRef); err != nil {
+ p.log.WithError(err).Warn("Error occurred releasing the LDAP client")
+ }
+ }()
if _, errRef = clientRef.PasswordModify(pwdModifyRequest); errRef != nil {
return fmt.Errorf("error occurred performing password modify on referred LDAP server '%s': %+v. Original Error: %w", referral, errRef, err)
diff --git a/internal/authentication/ldap_user_provider_startup.go b/internal/authentication/ldap_user_provider_lifecycle.go
index 20d7e7653..73dceaa6a 100644
--- a/internal/authentication/ldap_user_provider_startup.go
+++ b/internal/authentication/ldap_user_provider_lifecycle.go
@@ -10,15 +10,27 @@ import (
"github.com/authelia/authelia/v4/internal/utils"
)
+func (p *LDAPUserProvider) Shutdown() (err error) {
+ return p.factory.Close()
+}
+
// StartupCheck implements the startup check provider interface.
func (p *LDAPUserProvider) StartupCheck() (err error) {
- var client LDAPClient
+ if err = p.factory.Initialize(); err != nil {
+ return err
+ }
+
+ var client ldap.Client
- if client, err = p.connect(); err != nil {
+ if client, err = p.factory.GetClient(); err != nil {
return err
}
- defer client.Close()
+ defer func() {
+ if err := p.factory.ReleaseClient(client); err != nil {
+ p.log.WithError(err).Warn("Error occurred releasing the LDAP client")
+ }
+ }()
if p.features, err = p.getServerSupportedFeatures(client); err != nil {
return err
@@ -40,7 +52,7 @@ func (p *LDAPUserProvider) StartupCheck() (err error) {
return nil
}
-func (p *LDAPUserProvider) getServerSupportedFeatures(client LDAPClient) (features LDAPSupportedFeatures, err error) {
+func (p *LDAPUserProvider) getServerSupportedFeatures(client ldap.Client) (features LDAPSupportedFeatures, err error) {
var (
request *ldap.SearchRequest
result *ldap.SearchResult
diff --git a/internal/authentication/ldap_user_provider_test.go b/internal/authentication/ldap_user_provider_test.go
index 04a37e5f2..3975faa39 100644
--- a/internal/authentication/ldap_user_provider_test.go
+++ b/internal/authentication/ldap_user_provider_test.go
@@ -25,42 +25,35 @@ func TestNewLDAPUserProvider(t *testing.T) {
assert.NotNil(t, provider)
}
-func TestNewLDAPUserProviderWithFactoryWithoutFactory(t *testing.T) {
- provider := NewLDAPUserProviderWithFactory(schema.AuthenticationBackendLDAP{}, false, nil, nil)
-
- assert.NotNil(t, provider)
-
- assert.IsType(t, &ProductionLDAPClientFactory{}, provider.factory)
-}
-
func TestShouldCreateRawConnectionWhenSchemeIsLDAP(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
+ factory := NewStandardLDAPClientFactory(config, nil, mockDialer)
mockClient := NewMockLDAPClient(ctrl)
provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- },
+ config,
false,
- nil,
- mockFactory)
+ factory)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ dialURL := mockDialer.EXPECT().DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).Return(mockClient, nil)
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- gomock.InOrder(dialURL, connBind)
+ gomock.InOrder(dialURL, clientBind)
- _, err := provider.connect()
+ _, err := provider.factory.GetClient()
require.NoError(t, err)
}
@@ -69,30 +62,29 @@ func TestShouldCreateTLSConnectionWhenSchemeIsLDAPS(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPSAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
+ factory := NewStandardLDAPClientFactory(config, nil, mockDialer)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPSAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- },
- false,
- nil,
- mockFactory)
+ provider := NewLDAPUserProviderWithFactory(config, false, factory)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldaps://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ dialURL := mockDialer.EXPECT().DialURL("ldaps://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- gomock.InOrder(dialURL, connBind)
+ gomock.InOrder(dialURL, clientBind)
- _, err := provider.connect()
+ _, err := provider.factory.GetClient()
require.NoError(t, err)
}
@@ -120,16 +112,16 @@ func TestEscapeSpecialCharsInGroupsFilter(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPSAddress,
+ GroupsFilter: "(|(member={dn})(uid={username})(uid={input}))",
+ }
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPSAddress,
- GroupsFilter: "(|(member={dn})(uid={username})(uid={input}))",
- },
- false,
- nil,
- mockFactory)
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
+ factory := NewStandardLDAPClientFactory(config, nil, mockDialer)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, factory)
profile := ldapUserProfile{
DN: "cn=john (external),dc=example,dc=com",
@@ -149,7 +141,15 @@ func TestResolveGroupsFilter(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPSAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
+ factory := NewStandardLDAPClientFactory(config, nil, mockDialer)
testCases := []struct {
name string
@@ -207,11 +207,7 @@ func TestResolveGroupsFilter(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
- provider := NewLDAPUserProviderWithFactory(
- tc.have,
- false,
- nil,
- mockFactory)
+ provider := NewLDAPUserProviderWithFactory(&tc.have, false, factory)
assert.Equal(t, tc.expected, provider.resolveGroupsFilter("", tc.profile))
})
@@ -305,13 +301,12 @@ func TestShouldCheckLDAPEpochFilters(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
+ &schema.AuthenticationBackendLDAP{
UsersFilter: tc.have.users,
Attributes: tc.have.attr,
BaseDN: "dc=example,dc=com",
},
false,
- nil,
mockFactory)
assert.Equal(t, tc.expected.dtgeneralized, provider.usersFilterReplacementDateTimeGeneralized)
@@ -325,33 +320,102 @@ func TestShouldCheckLDAPServerExtensions(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ Password: "password",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
+ factory := NewStandardLDAPClientFactory(config, nil, mockDialer)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
+ provider := NewLDAPUserProviderWithFactory(config, false, factory)
+
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ clientBind := mockClient.EXPECT().
+ Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
+ Return(nil)
+
+ searchOIDs := mockClient.EXPECT().
+ Search(NewExtendedSearchRequestMatcher("(objectClass=*)", "", ldap.ScopeBaseObject, ldap.NeverDerefAliases, false, []string{ldapSupportedExtensionAttribute, ldapSupportedControlAttribute})).
+ Return(&ldap.SearchResult{
+ Entries: []*ldap.Entry{
+ {
+ DN: "",
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: ldapSupportedExtensionAttribute,
+ Values: []string{ldapOIDExtensionPwdModifyExOp, ldapOIDExtensionTLS},
+ },
+ {
+ Name: ldapSupportedControlAttribute,
+ Values: []string{},
+ },
+ },
+ },
},
- Password: "password",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
+ }, nil)
+
+ clientClose := mockClient.EXPECT().Close()
+
+ gomock.InOrder(dialURL, clientBind, searchOIDs, clientClose)
+
+ err := provider.StartupCheck()
+ assert.NoError(t, err)
+
+ assert.True(t, provider.features.Extensions.PwdModifyExOp)
+ assert.True(t, provider.features.Extensions.TLS)
+
+ assert.False(t, provider.features.ControlTypes.MsftPwdPolHints)
+ assert.False(t, provider.features.ControlTypes.MsftPwdPolHintsDeprecated)
+}
+
+func TestShouldCheckLDAPServerExtensionsPooled(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
},
- false,
- nil,
- mockFactory)
+ Password: "password",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ Pooling: schema.AuthenticationBackendLDAPPooling{
+ Count: 1,
+ },
+ }
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ mockDialer := NewMockLDAPClientDialer(ctrl)
- connBind := mockClient.EXPECT().
+ factory := NewPooledLDAPClientFactory(config, nil, mockDialer)
+
+ mockClient := NewMockLDAPClient(ctrl)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, factory)
+
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -375,9 +439,14 @@ func TestShouldCheckLDAPServerExtensions(t *testing.T) {
},
}, nil)
- connClose := mockClient.EXPECT().Close()
-
- gomock.InOrder(dialURL, connBind, searchOIDs, connClose)
+ gomock.InOrder(
+ dialURL,
+ clientBind,
+ mockClient.EXPECT().IsClosing().Return(false),
+ searchOIDs,
+ mockClient.EXPECT().IsClosing().Return(false),
+ mockClient.EXPECT().Close().Return(fmt.Errorf("close error")),
+ )
err := provider.StartupCheck()
assert.NoError(t, err)
@@ -387,39 +456,105 @@ func TestShouldCheckLDAPServerExtensions(t *testing.T) {
assert.False(t, provider.features.ControlTypes.MsftPwdPolHints)
assert.False(t, provider.features.ControlTypes.MsftPwdPolHintsDeprecated)
+
+ assert.EqualError(t, provider.Shutdown(), "errors occurred closing the client pool: close error")
}
func TestShouldNotCheckLDAPServerExtensionsWhenRootDSEReturnsMoreThanOneEntry(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ Password: "password",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
+
+ clientBind := mockClient.EXPECT().
+ Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
+ Return(nil)
+
+ searchOIDs := mockClient.EXPECT().
+ Search(NewExtendedSearchRequestMatcher("(objectClass=*)", "", ldap.ScopeBaseObject, ldap.NeverDerefAliases, false, []string{ldapSupportedExtensionAttribute, ldapSupportedControlAttribute})).
+ Return(&ldap.SearchResult{
+ Entries: []*ldap.Entry{
+ {
+ DN: "",
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: ldapSupportedExtensionAttribute,
+ Values: []string{ldapOIDExtensionPwdModifyExOp, ldapOIDExtensionTLS},
+ },
+ {
+ Name: ldapSupportedControlAttribute,
+ Values: []string{},
+ },
+ },
+ },
+ {},
},
- Password: "password",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
+ }, nil)
+
+ clientClose := mockClient.EXPECT().Close()
+
+ gomock.InOrder(dialURL, clientBind, searchOIDs, clientClose)
+
+ err := provider.StartupCheck()
+ assert.NoError(t, err)
+
+ assert.False(t, provider.features.Extensions.PwdModifyExOp)
+ assert.False(t, provider.features.Extensions.TLS)
+
+ assert.False(t, provider.features.ControlTypes.MsftPwdPolHints)
+ assert.False(t, provider.features.ControlTypes.MsftPwdPolHintsDeprecated)
+}
+
+func TestShouldNotCheckLDAPServerExtensionsWhenRootDSEReturnsMoreThanOneEntryPooled(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
},
- false,
- nil,
- mockFactory)
+ Password: "password",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ Pooling: schema.AuthenticationBackendLDAPPooling{Count: 1},
+ }
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ mockDialer := NewMockLDAPClientDialer(ctrl)
- connBind := mockClient.EXPECT().
+ mockClient := NewMockLDAPClient(ctrl)
+
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewPooledLDAPClientFactory(config, nil, mockDialer))
+
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -444,9 +579,97 @@ func TestShouldNotCheckLDAPServerExtensionsWhenRootDSEReturnsMoreThanOneEntry(t
},
}, nil)
- connClose := mockClient.EXPECT().Close()
+ gomock.InOrder(
+ dialURL,
+ clientBind,
+ mockClient.EXPECT().IsClosing().Return(false),
+ searchOIDs,
+ mockClient.EXPECT().IsClosing().Return(false),
+ mockClient.EXPECT().Close().Return(nil),
+ )
+
+ err := provider.StartupCheck()
+ assert.NoError(t, err)
+
+ assert.False(t, provider.features.Extensions.PwdModifyExOp)
+ assert.False(t, provider.features.Extensions.TLS)
+
+ assert.False(t, provider.features.ControlTypes.MsftPwdPolHints)
+ assert.False(t, provider.features.ControlTypes.MsftPwdPolHintsDeprecated)
+
+ assert.NoError(t, provider.Shutdown())
+}
+
+func TestShouldNotCheckLDAPServerExtensionsWhenRootDSEReturnsMoreThanOneEntryPooledClosing(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ Password: "password",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ Pooling: schema.AuthenticationBackendLDAPPooling{Count: 1},
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
+ mockClient := NewMockLDAPClient(ctrl)
+ mockClientSecond := NewMockLDAPClient(ctrl)
+
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ dialURLSecond := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClientSecond, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewPooledLDAPClientFactory(config, nil, mockDialer))
+
+ clientBind := mockClient.EXPECT().
+ Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
+ Return(nil)
- gomock.InOrder(dialURL, connBind, searchOIDs, connClose)
+ clientBindSecond := mockClientSecond.EXPECT().
+ Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
+ Return(nil)
+
+ searchOIDs := mockClientSecond.EXPECT().
+ Search(NewExtendedSearchRequestMatcher("(objectClass=*)", "", ldap.ScopeBaseObject, ldap.NeverDerefAliases, false, []string{ldapSupportedExtensionAttribute, ldapSupportedControlAttribute})).
+ Return(&ldap.SearchResult{
+ Entries: []*ldap.Entry{
+ {
+ DN: "",
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: ldapSupportedExtensionAttribute,
+ Values: []string{ldapOIDExtensionPwdModifyExOp, ldapOIDExtensionTLS},
+ },
+ {
+ Name: ldapSupportedControlAttribute,
+ Values: []string{},
+ },
+ },
+ },
+ {},
+ },
+ }, nil)
+
+ gomock.InOrder(
+ dialURL,
+ clientBind,
+ mockClient.EXPECT().IsClosing().Return(true),
+ dialURLSecond,
+ clientBindSecond,
+ searchOIDs,
+ mockClientSecond.EXPECT().IsClosing().Return(false),
+ mockClientSecond.EXPECT().Close().Return(nil),
+ )
err := provider.StartupCheck()
assert.NoError(t, err)
@@ -456,39 +679,104 @@ func TestShouldNotCheckLDAPServerExtensionsWhenRootDSEReturnsMoreThanOneEntry(t
assert.False(t, provider.features.ControlTypes.MsftPwdPolHints)
assert.False(t, provider.features.ControlTypes.MsftPwdPolHintsDeprecated)
+
+ assert.NoError(t, provider.Shutdown())
}
func TestShouldCheckLDAPServerControlTypes(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ Password: "password",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
+
+ clientBind := mockClient.EXPECT().
+ Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
+ Return(nil)
+
+ searchOIDs := mockClient.EXPECT().
+ Search(NewExtendedSearchRequestMatcher("(objectClass=*)", "", ldap.ScopeBaseObject, ldap.NeverDerefAliases, false, []string{ldapSupportedExtensionAttribute, ldapSupportedControlAttribute})).
+ Return(&ldap.SearchResult{
+ Entries: []*ldap.Entry{
+ {
+ DN: "",
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: ldapSupportedExtensionAttribute,
+ Values: []string{},
+ },
+ {
+ Name: ldapSupportedControlAttribute,
+ Values: []string{ldapOIDControlMsftServerPolicyHints, ldapOIDControlMsftServerPolicyHintsDeprecated},
+ },
+ },
+ },
},
- Password: "password",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
+ }, nil)
+
+ clientClose := mockClient.EXPECT().Close()
+
+ gomock.InOrder(dialURL, clientBind, searchOIDs, clientClose)
+
+ err := provider.StartupCheck()
+ assert.NoError(t, err)
+
+ assert.False(t, provider.features.Extensions.PwdModifyExOp)
+ assert.False(t, provider.features.Extensions.TLS)
+
+ assert.True(t, provider.features.ControlTypes.MsftPwdPolHints)
+ assert.True(t, provider.features.ControlTypes.MsftPwdPolHintsDeprecated)
+}
+
+func TestShouldCheckLDAPServerControlTypesPooled(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
},
- false,
- nil,
- mockFactory)
+ Password: "password",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ Pooling: schema.AuthenticationBackendLDAPPooling{Count: 1},
+ }
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ mockDialer := NewMockLDAPClientDialer(ctrl)
- connBind := mockClient.EXPECT().
+ mockClient := NewMockLDAPClient(ctrl)
+
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewPooledLDAPClientFactory(config, nil, mockDialer))
+
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -512,9 +800,16 @@ func TestShouldCheckLDAPServerControlTypes(t *testing.T) {
},
}, nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
- gomock.InOrder(dialURL, connBind, searchOIDs, connClose)
+ gomock.InOrder(
+ dialURL,
+ clientBind,
+ mockClient.EXPECT().IsClosing().Return(false),
+ searchOIDs,
+ mockClient.EXPECT().IsClosing().Return(false),
+ clientClose,
+ )
err := provider.StartupCheck()
assert.NoError(t, err)
@@ -524,39 +819,38 @@ func TestShouldCheckLDAPServerControlTypes(t *testing.T) {
assert.True(t, provider.features.ControlTypes.MsftPwdPolHints)
assert.True(t, provider.features.ControlTypes.MsftPwdPolHintsDeprecated)
+
+ assert.NoError(t, provider.Shutdown())
}
func TestShouldNotEnablePasswdModifyExtensionOrControlTypes(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ Password: "password",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- Password: "password",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -580,52 +874,123 @@ func TestShouldNotEnablePasswdModifyExtensionOrControlTypes(t *testing.T) {
},
}, nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
- gomock.InOrder(dialURL, connBind, searchOIDs, connClose)
+ gomock.InOrder(dialURL, clientBind, searchOIDs, clientClose)
- err := provider.StartupCheck()
- assert.NoError(t, err)
+ assert.NoError(t, provider.StartupCheck())
assert.False(t, provider.features.Extensions.PwdModifyExOp)
assert.False(t, provider.features.Extensions.TLS)
assert.False(t, provider.features.ControlTypes.MsftPwdPolHints)
assert.False(t, provider.features.ControlTypes.MsftPwdPolHintsDeprecated)
+
+ assert.NoError(t, provider.Shutdown())
}
-func TestShouldReturnCheckServerConnectError(t *testing.T) {
+func TestShouldNotEnablePasswdModifyExtensionOrControlTypesPooled(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ Password: "password",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ Pooling: schema.AuthenticationBackendLDAPPooling{
+ Count: 1,
+ },
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewPooledLDAPClientFactory(config, nil, mockDialer))
+
+ clientBind := mockClient.EXPECT().
+ Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
+ Return(nil)
+
+ searchOIDs := mockClient.EXPECT().
+ Search(NewExtendedSearchRequestMatcher("(objectClass=*)", "", ldap.ScopeBaseObject, ldap.NeverDerefAliases, false, []string{ldapSupportedExtensionAttribute, ldapSupportedControlAttribute})).
+ Return(&ldap.SearchResult{
+ Entries: []*ldap.Entry{
+ {
+ DN: "",
+ Attributes: []*ldap.EntryAttribute{
+ {
+ Name: ldapSupportedExtensionAttribute,
+ Values: []string{},
+ },
+ {
+ Name: ldapSupportedControlAttribute,
+ Values: []string{},
+ },
+ },
+ },
},
- Password: "password",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
+ }, nil)
+
+ clientClose := mockClient.EXPECT().Close()
+
+ gomock.InOrder(
+ dialURL,
+ clientBind,
+ mockClient.EXPECT().IsClosing().Return(false),
+ searchOIDs,
+ mockClient.EXPECT().IsClosing().Return(false),
+ clientClose,
+ )
+
+ assert.NoError(t, provider.StartupCheck())
+
+ assert.False(t, provider.features.Extensions.PwdModifyExOp)
+ assert.False(t, provider.features.Extensions.TLS)
+
+ assert.False(t, provider.features.ControlTypes.MsftPwdPolHints)
+ assert.False(t, provider.features.ControlTypes.MsftPwdPolHintsDeprecated)
+
+ assert.NoError(t, provider.Shutdown())
+}
+
+func TestShouldReturnCheckServerConnectError(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
},
- false,
- nil,
- mockFactory)
+ Password: "password",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
- mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, errors.New("could not connect"))
+ mockDialer := NewMockLDAPClientDialer(ctrl)
- err := provider.StartupCheck()
- assert.EqualError(t, err, "dial failed with error: could not connect")
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
+
+ mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(nil, errors.New("could not connect"))
+
+ assert.EqualError(t, provider.StartupCheck(), "error occurred dialing address: could not connect")
assert.False(t, provider.features.Extensions.PwdModifyExOp)
}
@@ -634,33 +999,76 @@ func TestShouldReturnCheckServerSearchError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ Password: "password",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- Password: "password",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
+
+ clientBind := mockClient.EXPECT().
+ Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
+ Return(nil)
+
+ searchOIDs := mockClient.EXPECT().
+ Search(NewExtendedSearchRequestMatcher("(objectClass=*)", "", ldap.ScopeBaseObject, ldap.NeverDerefAliases, false, []string{ldapSupportedExtensionAttribute, ldapSupportedControlAttribute})).
+ Return(nil, errors.New("could not perform the search"))
+
+ clientClose := mockClient.EXPECT().Close()
+
+ gomock.InOrder(dialURL, clientBind, searchOIDs, clientClose)
+
+ err := provider.StartupCheck()
+ assert.EqualError(t, err, "error occurred during RootDSE search: could not perform the search")
+
+ assert.False(t, provider.features.Extensions.PwdModifyExOp)
+}
+
+func TestShouldReturnCheckServerSearchErrorPooled(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
},
- false,
- nil,
- mockFactory)
+ Password: "password",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ Pooling: schema.AuthenticationBackendLDAPPooling{Count: 1},
+ }
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ mockDialer := NewMockLDAPClientDialer(ctrl)
- connBind := mockClient.EXPECT().
+ mockClient := NewMockLDAPClient(ctrl)
+
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewPooledLDAPClientFactory(config, nil, mockDialer))
+
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -668,48 +1076,98 @@ func TestShouldReturnCheckServerSearchError(t *testing.T) {
Search(NewExtendedSearchRequestMatcher("(objectClass=*)", "", ldap.ScopeBaseObject, ldap.NeverDerefAliases, false, []string{ldapSupportedExtensionAttribute, ldapSupportedControlAttribute})).
Return(nil, errors.New("could not perform the search"))
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
- gomock.InOrder(dialURL, connBind, searchOIDs, connClose)
+ gomock.InOrder(
+ dialURL,
+ clientBind,
+ mockClient.EXPECT().IsClosing().Return(false),
+ searchOIDs,
+ mockClient.EXPECT().IsClosing().Return(false),
+ clientClose,
+ )
err := provider.StartupCheck()
assert.EqualError(t, err, "error occurred during RootDSE search: could not perform the search")
assert.False(t, provider.features.Extensions.PwdModifyExOp)
+
+ assert.NoError(t, provider.Shutdown())
}
func TestShouldPermitRootDSEFailure(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ PermitFeatureDetectionFailure: true,
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ Password: "password",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- PermitFeatureDetectionFailure: true,
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- Password: "password",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
+
+ clientBind := mockClient.EXPECT().
+ Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
+ Return(nil)
+
+ searchOIDs := mockClient.EXPECT().
+ Search(NewExtendedSearchRequestMatcher("(objectClass=*)", "", ldap.ScopeBaseObject, ldap.NeverDerefAliases, false, []string{ldapSupportedExtensionAttribute, ldapSupportedControlAttribute})).
+ Return(nil, errors.New("could not perform the search"))
+
+ clientClose := mockClient.EXPECT().Close()
+
+ gomock.InOrder(dialURL, clientBind, searchOIDs, clientClose)
+
+ assert.NoError(t, provider.StartupCheck())
+}
+
+func TestShouldPermitRootDSEFailurePooled(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+
+ config := &schema.AuthenticationBackendLDAP{
+ PermitFeatureDetectionFailure: true,
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
},
- false,
- nil,
- mockFactory)
+ Password: "password",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ Pooling: schema.AuthenticationBackendLDAPPooling{Count: 1},
+ }
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ mockDialer := NewMockLDAPClientDialer(ctrl)
- connBind := mockClient.EXPECT().
+ mockClient := NewMockLDAPClient(ctrl)
+
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewPooledLDAPClientFactory(config, nil, mockDialer))
+
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -717,12 +1175,19 @@ func TestShouldPermitRootDSEFailure(t *testing.T) {
Search(NewExtendedSearchRequestMatcher("(objectClass=*)", "", ldap.ScopeBaseObject, ldap.NeverDerefAliases, false, []string{ldapSupportedExtensionAttribute, ldapSupportedControlAttribute})).
Return(nil, errors.New("could not perform the search"))
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
- gomock.InOrder(dialURL, connBind, searchOIDs, connClose)
+ gomock.InOrder(
+ dialURL,
+ clientBind,
+ mockClient.EXPECT().IsClosing().Return(false),
+ searchOIDs,
+ mockClient.EXPECT().IsClosing().Return(false),
+ clientClose,
+ )
- err := provider.StartupCheck()
- assert.NoError(t, err)
+ assert.NoError(t, provider.StartupCheck())
+ assert.NoError(t, provider.Shutdown())
}
type SearchRequestMatcher struct {
@@ -750,7 +1215,7 @@ func TestShouldEscapeUserInput(t *testing.T) {
mockClient := NewMockLDAPClient(ctrl)
provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
+ &schema.AuthenticationBackendLDAP{
Address: testLDAPAddress,
User: "cn=admin,dc=example,dc=com",
UsersFilter: "(|({username_attribute}={input})({mail_attribute}={input}))",
@@ -766,7 +1231,6 @@ func TestShouldEscapeUserInput(t *testing.T) {
PermitReferrals: true,
},
false,
- nil,
mockFactory)
mockClient.EXPECT().
@@ -783,35 +1247,32 @@ func TestShouldReturnEmailWhenAttributeSameAsUsername(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "mail",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "(&({username_attribute}={input})(objectClass=inetOrgPerson))",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "mail",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "(&({username_attribute}={input})(objectClass=inetOrgPerson))",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- assert.Equal(t, []string{"mail", "displayName", "memberOf"}, provider.usersAttributes)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ assert.Equal(t, []string{"mail", "displayName", "memberOf"}, provider.usersAttributes)
- bind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -835,9 +1296,9 @@ func TestShouldReturnEmailWhenAttributeSameAsUsername(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, bind, search)
+ gomock.InOrder(dialURL, clientBind, search)
- client, err := provider.connect()
+ client, err := provider.factory.GetClient()
assert.NoError(t, err)
profile, err := provider.getUserProfile(client, "john@example.com")
@@ -857,35 +1318,32 @@ func TestShouldReturnUsernameAndBlankDisplayNameWhenAttributesTheSame(t *testing
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "uid",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "(&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=inetOrgPerson))",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "uid",
- MemberOf: "memberOf",
- },
- UsersFilter: "(&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=inetOrgPerson))",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- assert.Equal(t, []string{"uid", "mail", "memberOf"}, provider.usersAttributes)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ assert.Equal(t, []string{"uid", "mail", "memberOf"}, provider.usersAttributes)
- bind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -909,9 +1367,9 @@ func TestShouldReturnUsernameAndBlankDisplayNameWhenAttributesTheSame(t *testing
},
}, nil)
- gomock.InOrder(dialURL, bind, search)
+ gomock.InOrder(dialURL, clientBind, search)
- client, err := provider.connect()
+ client, err := provider.factory.GetClient()
assert.NoError(t, err)
profile, err := provider.getUserProfile(client, "john@example.com")
@@ -931,35 +1389,32 @@ func TestShouldReturnBlankEmailAndDisplayNameWhenAttrsLenZero(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "(&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=inetOrgPerson))",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "(&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=inetOrgPerson))",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- assert.Equal(t, []string{"uid", "mail", "displayName", "memberOf"}, provider.usersAttributes)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ assert.Equal(t, []string{"uid", "mail", "displayName", "memberOf"}, provider.usersAttributes)
- bind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -991,9 +1446,9 @@ func TestShouldReturnBlankEmailAndDisplayNameWhenAttrsLenZero(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, bind, search)
+ gomock.InOrder(dialURL, clientBind, search)
- client, err := provider.connect()
+ client, err := provider.factory.GetClient()
assert.NoError(t, err)
profile, err := provider.getUserProfile(client, "john@example.com")
@@ -1016,7 +1471,7 @@ func TestShouldCombineUsernameFilterAndUsersFilter(t *testing.T) {
mockClient := NewMockLDAPClient(ctrl)
provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
+ &schema.AuthenticationBackendLDAP{
Address: testLDAPAddress,
User: "cn=admin,dc=example,dc=com",
UsersFilter: "(&({username_attribute}={input})(&(objectCategory=person)(objectClass=user)))",
@@ -1032,7 +1487,6 @@ func TestShouldCombineUsernameFilterAndUsersFilter(t *testing.T) {
PermitReferrals: true,
},
false,
- nil,
mockFactory)
assert.Equal(t, []string{"uid", "mail", "displayName", "memberOf"}, provider.usersAttributes)
@@ -1092,39 +1546,36 @@ func TestShouldNotCrashWhenGroupsAreNotRetrievedFromLDAP(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ GroupName: "cn",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- GroupName: "cn",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchGroups := mockClient.EXPECT().
Search(gomock.Any()).
@@ -1154,7 +1605,7 @@ func TestShouldNotCrashWhenGroupsAreNotRetrievedFromLDAP(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, connBind, searchProfile, searchGroups, connClose)
+ gomock.InOrder(dialURL, clientBind, searchProfile, searchGroups, clientClose)
details, err := provider.GetDetails("john")
require.NoError(t, err)
@@ -1169,99 +1620,100 @@ func TestLDAPUserProvider_GetDetailsExtended_ShouldPass(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
- mockClient := NewMockLDAPClient(ctrl)
-
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- StreetAddress: "street",
- FamilyName: "sn",
- MiddleName: "middle",
- GivenName: "givenName",
- Nickname: "nickname",
- Gender: "gender",
- Birthdate: "birthDate",
- Website: "website",
- Profile: "profile",
- Picture: "picture",
- ZoneInfo: "zoneinfo",
- Locale: "locale",
- PhoneNumber: "phone",
- PhoneExtension: "ext",
- Locality: "locality",
- Region: "region",
- PostalCode: "postCode",
- Country: "c",
- Extra: map[string]schema.AuthenticationBackendLDAPAttributesAttribute{
- "exampleStr": {
- AuthenticationBackendExtraAttribute: schema.AuthenticationBackendExtraAttribute{
- MultiValued: false,
- ValueType: ValueTypeString,
- },
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ StreetAddress: "street",
+ FamilyName: "sn",
+ MiddleName: "middle",
+ GivenName: "givenName",
+ Nickname: "nickname",
+ Gender: "gender",
+ Birthdate: "birthDate",
+ Website: "website",
+ Profile: "profile",
+ Picture: "picture",
+ ZoneInfo: "zoneinfo",
+ Locale: "locale",
+ PhoneNumber: "phone",
+ PhoneExtension: "ext",
+ Locality: "locality",
+ Region: "region",
+ PostalCode: "postCode",
+ Country: "c",
+ Extra: map[string]schema.AuthenticationBackendLDAPAttributesAttribute{
+ "exampleStr": {
+ AuthenticationBackendExtraAttribute: schema.AuthenticationBackendExtraAttribute{
+ MultiValued: false,
+ ValueType: ValueTypeString,
},
- "exampleStrMV": {
- AuthenticationBackendExtraAttribute: schema.AuthenticationBackendExtraAttribute{
- MultiValued: true,
- ValueType: ValueTypeString,
- },
+ },
+ "exampleStrMV": {
+ AuthenticationBackendExtraAttribute: schema.AuthenticationBackendExtraAttribute{
+ MultiValued: true,
+ ValueType: ValueTypeString,
},
- "exampleInt": {
- Name: "exampleIntChangedAttributeName",
- AuthenticationBackendExtraAttribute: schema.AuthenticationBackendExtraAttribute{
- MultiValued: false,
- ValueType: ValueTypeInteger,
- },
+ },
+ "exampleInt": {
+ Name: "exampleIntChangedAttributeName",
+ AuthenticationBackendExtraAttribute: schema.AuthenticationBackendExtraAttribute{
+ MultiValued: false,
+ ValueType: ValueTypeInteger,
},
- "exampleIntMV": {
- AuthenticationBackendExtraAttribute: schema.AuthenticationBackendExtraAttribute{
- MultiValued: true,
- ValueType: ValueTypeInteger,
- },
+ },
+ "exampleIntMV": {
+ AuthenticationBackendExtraAttribute: schema.AuthenticationBackendExtraAttribute{
+ MultiValued: true,
+ ValueType: ValueTypeInteger,
},
- "exampleBool": {
- AuthenticationBackendExtraAttribute: schema.AuthenticationBackendExtraAttribute{
- MultiValued: false,
- ValueType: ValueTypeBoolean,
- },
+ },
+ "exampleBool": {
+ AuthenticationBackendExtraAttribute: schema.AuthenticationBackendExtraAttribute{
+ MultiValued: false,
+ ValueType: ValueTypeBoolean,
},
- "exampleBoolMV": {
- AuthenticationBackendExtraAttribute: schema.AuthenticationBackendExtraAttribute{
- MultiValued: true,
- ValueType: ValueTypeBoolean,
- },
+ },
+ "exampleBoolMV": {
+ AuthenticationBackendExtraAttribute: schema.AuthenticationBackendExtraAttribute{
+ MultiValued: true,
+ ValueType: ValueTypeBoolean,
},
- "exampleEmptyStringInt": {
- AuthenticationBackendExtraAttribute: schema.AuthenticationBackendExtraAttribute{
- MultiValued: false,
- ValueType: ValueTypeInteger,
- },
+ },
+ "exampleEmptyStringInt": {
+ AuthenticationBackendExtraAttribute: schema.AuthenticationBackendExtraAttribute{
+ MultiValued: false,
+ ValueType: ValueTypeInteger,
},
- "exampleEmptyStringBoolean": {
- AuthenticationBackendExtraAttribute: schema.AuthenticationBackendExtraAttribute{
- MultiValued: false,
- ValueType: ValueTypeBoolean,
- },
+ },
+ "exampleEmptyStringBoolean": {
+ AuthenticationBackendExtraAttribute: schema.AuthenticationBackendExtraAttribute{
+ MultiValued: false,
+ ValueType: ValueTypeBoolean,
},
},
},
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
},
- false,
- nil,
- mockFactory)
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ factory := NewStandardLDAPClientFactory(config, nil, mockDialer)
- dialURL := mockFactory.EXPECT().
+ provider := NewLDAPUserProviderWithFactory(config, false, factory)
+
+ mockClient := NewMockLDAPClient(ctrl)
+
+ dialURL := mockDialer.EXPECT().
DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
Return(mockClient, nil)
@@ -1487,39 +1939,40 @@ func TestLDAPUserProvider_GetDetailsExtended_ShouldParseError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
- mockClient := NewMockLDAPClient(ctrl)
+ mockDialer := NewMockLDAPClientDialer(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- StreetAddress: "street",
- Extra: map[string]schema.AuthenticationBackendLDAPAttributesAttribute{
- "example": {
- AuthenticationBackendExtraAttribute: schema.AuthenticationBackendExtraAttribute{
- MultiValued: tc.multiValued,
- ValueType: tc.valueType,
- },
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ StreetAddress: "street",
+ Extra: map[string]schema.AuthenticationBackendLDAPAttributesAttribute{
+ "example": {
+ AuthenticationBackendExtraAttribute: schema.AuthenticationBackendExtraAttribute{
+ MultiValued: tc.multiValued,
+ ValueType: tc.valueType,
},
},
},
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
},
- false,
- nil,
- mockFactory)
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ factory := NewStandardLDAPClientFactory(config, nil, mockDialer)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, factory)
- dialURL := mockFactory.EXPECT().
+ mockClient := NewMockLDAPClient(ctrl)
+
+ dialURL := mockDialer.EXPECT().
DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
Return(mockClient, nil)
@@ -1578,31 +2031,32 @@ func TestLDAPUserProvider_GetDetailsExtended_ShouldErrorBadPictureURL(t *testing
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
- mockClient := NewMockLDAPClient(ctrl)
-
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- Picture: "photoURL",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ Picture: "photoURL",
},
- false,
- nil,
- mockFactory)
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ factory := NewStandardLDAPClientFactory(config, nil, mockDialer)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, factory)
- dialURL := mockFactory.EXPECT().
+ mockClient := NewMockLDAPClient(ctrl)
+
+ dialURL := mockDialer.EXPECT().
DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
Return(mockClient, nil)
@@ -1657,31 +2111,32 @@ func TestLDAPUserProvider_GetDetailsExtended_ShouldErrorBadProfileURL(t *testing
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
- mockClient := NewMockLDAPClient(ctrl)
-
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- Profile: "profile",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ Profile: "profile",
},
- false,
- nil,
- mockFactory)
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ factory := NewStandardLDAPClientFactory(config, nil, mockDialer)
- dialURL := mockFactory.EXPECT().
+ provider := NewLDAPUserProviderWithFactory(config, false, factory)
+
+ mockClient := NewMockLDAPClient(ctrl)
+
+ dialURL := mockDialer.EXPECT().
DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
Return(mockClient, nil)
@@ -1736,31 +2191,32 @@ func TestLDAPUserProvider_GetDetailsExtended_ShouldErrorBadWebsiteURL(t *testing
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
- mockClient := NewMockLDAPClient(ctrl)
-
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- Website: "www",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ Website: "www",
},
- false,
- nil,
- mockFactory)
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ factory := NewStandardLDAPClientFactory(config, nil, mockDialer)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, factory)
+
+ mockClient := NewMockLDAPClient(ctrl)
- dialURL := mockFactory.EXPECT().
+ dialURL := mockDialer.EXPECT().
DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
Return(mockClient, nil)
@@ -1815,31 +2271,32 @@ func TestLDAPUserProvider_GetDetailsExtended_ShouldErrorBadLocale(t *testing.T)
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
- mockClient := NewMockLDAPClient(ctrl)
-
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- Locale: "locale",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ Locale: "locale",
},
- false,
- nil,
- mockFactory)
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ factory := NewStandardLDAPClientFactory(config, nil, mockDialer)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, factory)
+
+ mockClient := NewMockLDAPClient(ctrl)
- dialURL := mockFactory.EXPECT().
+ dialURL := mockDialer.EXPECT().
DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
Return(mockClient, nil)
@@ -1894,44 +2351,41 @@ func TestLDAPUserProvider_GetDetails_ShouldReturnOnUserError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
Return(nil, fmt.Errorf("failed to search"))
- gomock.InOrder(dialURL, connBind, searchProfile, connClose)
+ gomock.InOrder(dialURL, clientBind, searchProfile, clientClose)
details, err := provider.GetDetails("john")
assert.Nil(t, details)
@@ -1942,30 +2396,31 @@ func TestLDAPUserProvider_GetDetailsExtendedShouldReturnOnBindError(t *testing.T
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
- mockClient := NewMockLDAPClient(ctrl)
-
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
},
- false,
- nil,
- mockFactory)
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ factory := NewStandardLDAPClientFactory(config, nil, mockDialer)
- dialURL := mockFactory.EXPECT().
+ provider := NewLDAPUserProviderWithFactory(config, false, factory)
+
+ mockClient := NewMockLDAPClient(ctrl)
+
+ dialURL := mockDialer.EXPECT().
DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
Return(mockClient, nil)
@@ -1979,36 +2434,36 @@ func TestLDAPUserProvider_GetDetailsExtendedShouldReturnOnBindError(t *testing.T
details, err := provider.GetDetailsExtended("john")
assert.Nil(t, details)
- assert.EqualError(t, err, "bind failed with error: bad bind")
+ assert.EqualError(t, err, "error occurred performing bind: bad bind")
}
func TestLDAPUserProvider_GetDetailsExtendedShouldReturnOnDialError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
-
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
},
- false,
- nil,
- mockFactory)
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ factory := NewStandardLDAPClientFactory(config, nil, mockDialer)
- dialURL := mockFactory.EXPECT().
+ provider := NewLDAPUserProviderWithFactory(config, false, factory)
+
+ dialURL := mockDialer.EXPECT().
DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
Return(nil, fmt.Errorf("failed to dial"))
@@ -2016,37 +2471,37 @@ func TestLDAPUserProvider_GetDetailsExtendedShouldReturnOnDialError(t *testing.T
details, err := provider.GetDetailsExtended("john")
assert.Nil(t, details)
- assert.EqualError(t, err, "dial failed with error: failed to dial")
+ assert.EqualError(t, err, "error occurred dialing address: failed to dial")
}
func TestLDAPUserProvider_GetDetailsExtendedShouldReturnOnUserError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
+ factory := NewStandardLDAPClientFactory(config, nil, mockDialer)
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
- },
- false,
- nil,
- mockFactory)
+ provider := NewLDAPUserProviderWithFactory(config, false, factory)
- dialURL := mockFactory.EXPECT().
+ dialURL := mockDialer.EXPECT().
DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
Return(mockClient, nil)
@@ -2071,38 +2526,35 @@ func TestLDAPUserProvider_GetDetails_ShouldReturnOnGroupsError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchGroups := mockClient.EXPECT().
Search(gomock.Any()).
@@ -2132,7 +2584,7 @@ func TestLDAPUserProvider_GetDetails_ShouldReturnOnGroupsError(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, connBind, searchProfile, searchGroups, connClose)
+ gomock.InOrder(dialURL, clientBind, searchProfile, searchGroups, clientClose)
details, err := provider.GetDetails("john")
@@ -2144,37 +2596,34 @@ func TestShouldNotCrashWhenEmailsAreNotRetrievedFromLDAP(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ GroupName: "displayName",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- GroupName: "displayName",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchGroups := mockClient.EXPECT().
Search(gomock.Any()).
@@ -2196,7 +2645,7 @@ func TestShouldNotCrashWhenEmailsAreNotRetrievedFromLDAP(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, connBind, searchProfile, searchGroups, connClose)
+ gomock.InOrder(dialURL, clientBind, searchProfile, searchGroups, clientClose)
details, err := provider.GetDetails("john")
require.NoError(t, err)
@@ -2210,37 +2659,34 @@ func TestShouldUnauthenticatedBind(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ GroupName: "displayName",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- GroupName: "displayName",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
UnauthenticatedBind(gomock.Eq("cn=admin,dc=example,dc=com")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchGroups := mockClient.EXPECT().
Search(gomock.Any()).
@@ -2262,7 +2708,7 @@ func TestShouldUnauthenticatedBind(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, connBind, searchProfile, searchGroups, connClose)
+ gomock.InOrder(dialURL, clientBind, searchProfile, searchGroups, clientClose)
details, err := provider.GetDetails("john")
require.NoError(t, err)
@@ -2276,38 +2722,35 @@ func TestShouldReturnUsernameFromLDAP(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ GroupName: "cn",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- GroupName: "cn",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchGroups := mockClient.EXPECT().
Search(gomock.Any()).
@@ -2337,7 +2780,7 @@ func TestShouldReturnUsernameFromLDAP(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, connBind, searchProfile, searchGroups, connClose)
+ gomock.InOrder(dialURL, clientBind, searchProfile, searchGroups, clientClose)
details, err := provider.GetDetails("john")
require.NoError(t, err)
@@ -2352,40 +2795,37 @@ func TestShouldReturnUsernameFromLDAPSearchModeMemberOfRDN(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ GroupName: "cn",
+ },
+ GroupSearchMode: "memberof",
+ UsersFilter: "uid={input}",
+ GroupsFilter: "(|{memberof:rdn})",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "DC=example,DC=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- GroupName: "cn",
- },
- GroupSearchMode: "memberof",
- UsersFilter: "uid={input}",
- GroupsFilter: "(|{memberof:rdn})",
- AdditionalUsersDN: "ou=users",
- BaseDN: "DC=example,DC=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
requestGroups := ldap.NewSearchRequest(
provider.groupsBaseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases,
@@ -2427,7 +2867,7 @@ func TestShouldReturnUsernameFromLDAPSearchModeMemberOfRDN(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, connBind, searchProfile, searchGroups, connClose)
+ gomock.InOrder(dialURL, clientBind, searchProfile, searchGroups, clientClose)
details, err := provider.GetDetails("john")
require.NoError(t, err)
@@ -2442,41 +2882,38 @@ func TestShouldReturnUsernameFromLDAPSearchModeMemberOfDN(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "CN=Administrator,CN=Users,DC=example,DC=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ DistinguishedName: "distinguishedName",
+ Username: "sAMAccountName",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ GroupName: "cn",
+ },
+ GroupSearchMode: "memberof",
+ UsersFilter: "sAMAccountName={input}",
+ GroupsFilter: "(|{memberof:dn})",
+ AdditionalUsersDN: "CN=users",
+ BaseDN: "DC=example,DC=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "CN=Administrator,CN=Users,DC=example,DC=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- DistinguishedName: "distinguishedName",
- Username: "sAMAccountName",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- GroupName: "cn",
- },
- GroupSearchMode: "memberof",
- UsersFilter: "sAMAccountName={input}",
- GroupsFilter: "(|{memberof:dn})",
- AdditionalUsersDN: "CN=users",
- BaseDN: "DC=example,DC=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("CN=Administrator,CN=Users,DC=example,DC=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
requestGroups := ldap.NewSearchRequest(
provider.groupsBaseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases,
@@ -2515,7 +2952,7 @@ func TestShouldReturnUsernameFromLDAPSearchModeMemberOfDN(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, connBind, searchProfile, searchGroups, connClose)
+ gomock.InOrder(dialURL, clientBind, searchProfile, searchGroups, clientClose)
details, err := provider.GetDetails("john")
require.NoError(t, err)
@@ -2530,41 +2967,38 @@ func TestShouldReturnErrSearchMemberOf(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "CN=Administrator,CN=Users,DC=example,DC=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ DistinguishedName: "distinguishedName",
+ Username: "sAMAccountName",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ GroupName: "cn",
+ },
+ GroupSearchMode: "memberof",
+ UsersFilter: "sAMAccountName={input}",
+ GroupsFilter: "(|{memberof:dn})",
+ AdditionalUsersDN: "CN=users",
+ BaseDN: "DC=example,DC=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "CN=Administrator,CN=Users,DC=example,DC=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- DistinguishedName: "distinguishedName",
- Username: "sAMAccountName",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- GroupName: "cn",
- },
- GroupSearchMode: "memberof",
- UsersFilter: "sAMAccountName={input}",
- GroupsFilter: "(|{memberof:dn})",
- AdditionalUsersDN: "CN=users",
- BaseDN: "DC=example,DC=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("CN=Administrator,CN=Users,DC=example,DC=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
requestGroups := ldap.NewSearchRequest(
provider.groupsBaseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases,
@@ -2603,7 +3037,7 @@ func TestShouldReturnErrSearchMemberOf(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, connBind, searchProfile, searchGroups, connClose)
+ gomock.InOrder(dialURL, clientBind, searchProfile, searchGroups, clientClose)
details, err := provider.GetDetails("john")
assert.Nil(t, details)
@@ -2614,41 +3048,38 @@ func TestShouldReturnErrUnknownSearchMode(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "CN=Administrator,CN=Users,DC=example,DC=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ DistinguishedName: "distinguishedName",
+ Username: "sAMAccountName",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ GroupName: "cn",
+ },
+ GroupSearchMode: "bad",
+ UsersFilter: "sAMAccountName={input}",
+ GroupsFilter: "(|{memberof:dn})",
+ AdditionalUsersDN: "CN=users",
+ BaseDN: "DC=example,DC=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "CN=Administrator,CN=Users,DC=example,DC=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- DistinguishedName: "distinguishedName",
- Username: "sAMAccountName",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- GroupName: "cn",
- },
- GroupSearchMode: "bad",
- UsersFilter: "sAMAccountName={input}",
- GroupsFilter: "(|{memberof:dn})",
- AdditionalUsersDN: "CN=users",
- BaseDN: "DC=example,DC=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("CN=Administrator,CN=Users,DC=example,DC=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
@@ -2678,7 +3109,7 @@ func TestShouldReturnErrUnknownSearchMode(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, connBind, searchProfile, connClose)
+ gomock.InOrder(dialURL, clientBind, searchProfile, clientClose)
details, err := provider.GetDetails("john")
assert.Nil(t, details)
@@ -2690,41 +3121,38 @@ func TestShouldSkipEmptyAttributesSearchModeMemberOf(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "CN=Administrator,CN=Users,DC=example,DC=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ DistinguishedName: "distinguishedName",
+ Username: "sAMAccountName",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ GroupName: "cn",
+ },
+ GroupSearchMode: "memberof",
+ UsersFilter: "sAMAccountName={input}",
+ GroupsFilter: "(|{memberof:dn})",
+ AdditionalUsersDN: "CN=users",
+ BaseDN: "DC=example,DC=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "CN=Administrator,CN=Users,DC=example,DC=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- DistinguishedName: "distinguishedName",
- Username: "sAMAccountName",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- GroupName: "cn",
- },
- GroupSearchMode: "memberof",
- UsersFilter: "sAMAccountName={input}",
- GroupsFilter: "(|{memberof:dn})",
- AdditionalUsersDN: "CN=users",
- BaseDN: "DC=example,DC=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("CN=Administrator,CN=Users,DC=example,DC=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
@@ -2792,7 +3220,7 @@ func TestShouldSkipEmptyAttributesSearchModeMemberOf(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, connBind, searchProfile, searchGroups, connClose)
+ gomock.InOrder(dialURL, clientBind, searchProfile, searchGroups, clientClose)
details, err := provider.GetDetails("john")
@@ -2804,41 +3232,38 @@ func TestShouldSkipEmptyAttributesSearchModeFilter(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "CN=Administrator,CN=Users,DC=example,DC=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ DistinguishedName: "distinguishedName",
+ Username: "sAMAccountName",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ GroupName: "cn",
+ },
+ GroupSearchMode: "filter",
+ UsersFilter: "sAMAccountName={input}",
+ GroupsFilter: "(|{memberof:dn})",
+ AdditionalUsersDN: "CN=users",
+ BaseDN: "DC=example,DC=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "CN=Administrator,CN=Users,DC=example,DC=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- DistinguishedName: "distinguishedName",
- Username: "sAMAccountName",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- GroupName: "cn",
- },
- GroupSearchMode: "filter",
- UsersFilter: "sAMAccountName={input}",
- GroupsFilter: "(|{memberof:dn})",
- AdditionalUsersDN: "CN=users",
- BaseDN: "DC=example,DC=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("CN=Administrator,CN=Users,DC=example,DC=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
@@ -2906,7 +3331,7 @@ func TestShouldSkipEmptyAttributesSearchModeFilter(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, connBind, searchProfile, searchGroups, connClose)
+ gomock.InOrder(dialURL, clientBind, searchProfile, searchGroups, clientClose)
details, err := provider.GetDetails("john")
@@ -2918,39 +3343,36 @@ func TestShouldSkipEmptyGroupsResultMemberOf(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ GroupName: "cn",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- GroupName: "cn",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchGroups := mockClient.EXPECT().
Search(gomock.Any()).
@@ -2984,7 +3406,7 @@ func TestShouldSkipEmptyGroupsResultMemberOf(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, connBind, searchProfile, searchGroups, connClose)
+ gomock.InOrder(dialURL, clientBind, searchProfile, searchGroups, clientClose)
details, err := provider.GetDetails("john")
require.NoError(t, err)
@@ -2998,41 +3420,38 @@ func TestShouldReturnUsernameFromLDAPWithReferralsInErrorAndResult(t *testing.T)
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ GroupName: "cn",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
mockClientReferral := NewMockLDAPClient(ctrl)
mockClientReferralAlt := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- GroupName: "cn",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchGroups := mockClient.EXPECT().
Search(gomock.Any()).
@@ -3045,15 +3464,13 @@ func TestShouldReturnUsernameFromLDAPWithReferralsInErrorAndResult(t *testing.T)
Referrals: []string{"ldap://192.168.0.1"},
}, &ldap.Error{ResultCode: ldap.LDAPResultReferral, Err: errors.New("referral"), Packet: &testBERPacketReferral})
- dialURLReferral := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://192.168.0.1"), gomock.Any()).
- Return(mockClientReferral, nil)
+ dialURLReferral := mockDialer.EXPECT().DialURL("ldap://192.168.0.1", gomock.Any()).Return(mockClientReferral, nil)
- connBindReferral := mockClientReferral.EXPECT().
+ clientBindReferral := mockClientReferral.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connCloseReferral := mockClientReferral.EXPECT().Close()
+ clientCloseReferral := mockClientReferral.EXPECT().Close()
searchProfileReferral := mockClientReferral.EXPECT().
Search(gomock.Any()).
@@ -3079,15 +3496,13 @@ func TestShouldReturnUsernameFromLDAPWithReferralsInErrorAndResult(t *testing.T)
},
}, nil)
- dialURLReferralAlt := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://192.168.0.1"), gomock.Any()).
- Return(mockClientReferralAlt, nil)
+ dialURLReferralAlt := mockDialer.EXPECT().DialURL("ldap://192.168.0.1", gomock.Any()).Return(mockClientReferralAlt, nil)
- connBindReferralAlt := mockClientReferralAlt.EXPECT().
+ clientBindReferralAlt := mockClientReferralAlt.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connCloseReferralAlt := mockClientReferralAlt.EXPECT().Close()
+ clientCloseReferralAlt := mockClientReferralAlt.EXPECT().Close()
searchProfileReferralAlt := mockClientReferralAlt.EXPECT().
Search(gomock.Any()).
@@ -3113,7 +3528,7 @@ func TestShouldReturnUsernameFromLDAPWithReferralsInErrorAndResult(t *testing.T)
},
}, nil)
- gomock.InOrder(dialURL, connBind, searchProfile, dialURLReferral, connBindReferral, searchProfileReferral, connCloseReferral, dialURLReferralAlt, connBindReferralAlt, searchProfileReferralAlt, connCloseReferralAlt, searchGroups, connClose)
+ gomock.InOrder(dialURL, clientBind, searchProfile, dialURLReferral, clientBindReferral, searchProfileReferral, clientCloseReferral, dialURLReferralAlt, clientBindReferralAlt, searchProfileReferralAlt, clientCloseReferralAlt, searchGroups, clientClose)
details, err := provider.GetDetails("john")
require.NoError(t, err)
@@ -3128,40 +3543,37 @@ func TestShouldReturnUsernameFromLDAPWithReferralsInErrorAndNoResult(t *testing.
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ GroupName: "cn",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
mockClientReferral := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- GroupName: "cn",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchGroups := mockClient.EXPECT().
Search(gomock.Any()).
@@ -3171,15 +3583,13 @@ func TestShouldReturnUsernameFromLDAPWithReferralsInErrorAndNoResult(t *testing.
Search(gomock.Any()).
Return(nil, &ldap.Error{ResultCode: ldap.LDAPResultReferral, Err: errors.New("referral"), Packet: &testBERPacketReferral})
- dialURLReferral := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://192.168.0.1"), gomock.Any()).
- Return(mockClientReferral, nil)
+ dialURLReferral := mockDialer.EXPECT().DialURL("ldap://192.168.0.1", gomock.Any()).Return(mockClientReferral, nil)
- connBindReferral := mockClientReferral.EXPECT().
+ clientBindReferral := mockClientReferral.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connCloseReferral := mockClientReferral.EXPECT().Close()
+ clientCloseReferral := mockClientReferral.EXPECT().Close()
searchProfileReferral := mockClientReferral.EXPECT().
Search(gomock.Any()).
@@ -3205,7 +3615,7 @@ func TestShouldReturnUsernameFromLDAPWithReferralsInErrorAndNoResult(t *testing.
},
}, nil)
- gomock.InOrder(dialURL, connBind, searchProfile, dialURLReferral, connBindReferral, searchProfileReferral, connCloseReferral, searchGroups, connClose)
+ gomock.InOrder(dialURL, clientBind, searchProfile, dialURLReferral, clientBindReferral, searchProfileReferral, clientCloseReferral, searchGroups, clientClose)
details, err := provider.GetDetails("john")
require.NoError(t, err)
@@ -3220,114 +3630,104 @@ func TestShouldReturnDialErrDuringReferralSearchUsernameFromLDAPWithReferralsInE
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ GroupName: "cn",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- GroupName: "cn",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
Return(nil, &ldap.Error{ResultCode: ldap.LDAPResultReferral, Err: errors.New("referral"), Packet: &testBERPacketReferral})
- dialURLReferral := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://192.168.0.1"), gomock.Any()).
- Return(nil, fmt.Errorf("failed to connect"))
+ dialURLReferral := mockDialer.EXPECT().DialURL("ldap://192.168.0.1", gomock.Any()).Return(nil, fmt.Errorf("failed to connect"))
- gomock.InOrder(dialURL, connBind, searchProfile, dialURLReferral, connClose)
+ gomock.InOrder(dialURL, clientBind, searchProfile, dialURLReferral, clientClose)
details, err := provider.GetDetails("john")
assert.Nil(t, details)
- assert.EqualError(t, err, "cannot find user DN of user 'john'. Cause: error occurred connecting to referred LDAP server 'ldap://192.168.0.1': dial failed with error: failed to connect")
+ assert.EqualError(t, err, "cannot find user DN of user 'john'. Cause: error occurred connecting to referred LDAP server 'ldap://192.168.0.1': error occurred dialing address: failed to connect")
}
func TestShouldReturnSearchErrDuringReferralSearchUsernameFromLDAPWithReferralsInErrorAndNoResult(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ GroupName: "cn",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
mockClientReferral := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- GroupName: "cn",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
Return(nil, &ldap.Error{ResultCode: ldap.LDAPResultReferral, Err: errors.New("referral"), Packet: &testBERPacketReferral})
- dialURLReferral := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://192.168.0.1"), gomock.Any()).
- Return(mockClientReferral, nil)
+ dialURLReferral := mockDialer.EXPECT().DialURL("ldap://192.168.0.1", gomock.Any()).Return(mockClientReferral, nil)
- connBindReferral := mockClientReferral.EXPECT().
+ clientBindReferral := mockClientReferral.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connCloseReferral := mockClientReferral.EXPECT().Close()
+ clientCloseReferral := mockClientReferral.EXPECT().Close()
searchProfileReferral := mockClientReferral.EXPECT().
Search(gomock.Any()).
Return(nil, fmt.Errorf("not found"))
- gomock.InOrder(dialURL, connBind, searchProfile, dialURLReferral, connBindReferral, searchProfileReferral, connCloseReferral, connClose)
+ gomock.InOrder(dialURL, clientBind, searchProfile, dialURLReferral, clientBindReferral, searchProfileReferral, clientCloseReferral, clientClose)
details, err := provider.GetDetails("john")
@@ -3339,45 +3739,42 @@ func TestShouldNotReturnUsernameFromLDAPWithReferralsInErrorAndReferralsNotPermi
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ GroupName: "cn",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: false,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- GroupName: "cn",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: false,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
Return(nil, &ldap.Error{ResultCode: ldap.LDAPResultReferral, Err: errors.New("referral"), Packet: &testBERPacketReferral})
- gomock.InOrder(dialURL, connBind, searchProfile, connClose)
+ gomock.InOrder(dialURL, clientBind, searchProfile, clientClose)
details, err := provider.GetDetails("john")
assert.EqualError(t, err, "cannot find user DN of user 'john'. Cause: LDAP Result Code 10 \"Referral\": referral")
@@ -3388,40 +3785,37 @@ func TestShouldReturnUsernameFromLDAPWithReferralsErr(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ GroupName: "cn",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
mockClientReferral := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- GroupName: "cn",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchGroups := mockClient.EXPECT().
Search(gomock.Any()).
@@ -3431,15 +3825,13 @@ func TestShouldReturnUsernameFromLDAPWithReferralsErr(t *testing.T) {
Search(gomock.Any()).
Return(&ldap.SearchResult{}, &ldap.Error{ResultCode: ldap.LDAPResultReferral, Err: errors.New("referral"), Packet: &testBERPacketReferral})
- dialURLReferral := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://192.168.0.1"), gomock.Any()).
- Return(mockClientReferral, nil)
+ dialURLReferral := mockDialer.EXPECT().DialURL("ldap://192.168.0.1", gomock.Any()).Return(mockClientReferral, nil)
- connBindReferral := mockClientReferral.EXPECT().
+ clientBindReferral := mockClientReferral.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connCloseReferral := mockClientReferral.EXPECT().Close()
+ clientCloseReferral := mockClientReferral.EXPECT().Close()
searchProfileReferral := mockClientReferral.EXPECT().
Search(gomock.Any()).
@@ -3465,7 +3857,7 @@ func TestShouldReturnUsernameFromLDAPWithReferralsErr(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, connBind, searchProfile, dialURLReferral, connBindReferral, searchProfileReferral, connCloseReferral, searchGroups, connClose)
+ gomock.InOrder(dialURL, clientBind, searchProfile, dialURLReferral, clientBindReferral, searchProfileReferral, clientCloseReferral, searchGroups, clientClose)
details, err := provider.GetDetails("john")
require.NoError(t, err)
@@ -3480,34 +3872,33 @@ func TestShouldNotUpdateUserPasswordConnect(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: false,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: false,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(nil, errors.New("tcp timeout"))
- dialURLOIDs := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBindOIDs := mockClient.EXPECT().
+ dialURLOIDs := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ clientBindOIDs := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -3531,53 +3922,46 @@ func TestShouldNotUpdateUserPasswordConnect(t *testing.T) {
},
}, nil)
- connCloseOIDs := mockClient.EXPECT().Close()
+ clientCloseOIDs := mockClient.EXPECT().Close()
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(nil, errors.New("tcp timeout"))
+ gomock.InOrder(dialURLOIDs, clientBindOIDs, searchOIDs, clientCloseOIDs, dialURL)
- gomock.InOrder(dialURLOIDs, connBindOIDs, searchOIDs, connCloseOIDs, dialURL)
+ require.NoError(t, provider.StartupCheck())
- err := provider.StartupCheck()
- require.NoError(t, err)
-
- err = provider.UpdatePassword("john", "password")
- assert.EqualError(t, err, "unable to update password. Cause: dial failed with error: tcp timeout")
+ assert.EqualError(t, provider.UpdatePassword("john", "password"), "unable to update password. Cause: error occurred dialing address: tcp timeout")
}
func TestShouldNotUpdateUserPasswordGetDetails(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: false,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: false,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURLOIDs := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBindOIDs := mockClient.EXPECT().
+ dialURLOIDs := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ clientBindOIDs := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -3601,56 +3985,51 @@ func TestShouldNotUpdateUserPasswordGetDetails(t *testing.T) {
},
}, nil)
- connCloseOIDs := mockClient.EXPECT().Close()
+ clientCloseOIDs := mockClient.EXPECT().Close()
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
-
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
Return(nil, &ldap.Error{ResultCode: ldap.LDAPResultProtocolError, Err: errors.New("permission error")})
- gomock.InOrder(dialURLOIDs, connBindOIDs, searchOIDs, connCloseOIDs, dialURL, connBind, searchProfile, connClose)
+ gomock.InOrder(dialURLOIDs, clientBindOIDs, searchOIDs, clientCloseOIDs, dialURL, clientBind, searchProfile, clientClose)
- err := provider.StartupCheck()
- require.NoError(t, err)
+ require.NoError(t, provider.StartupCheck())
- err = provider.UpdatePassword("john", "password")
- assert.EqualError(t, err, "unable to update password. Cause: cannot find user DN of user 'john'. Cause: LDAP Result Code 2 \"Protocol Error\": permission error")
+ assert.EqualError(t, provider.UpdatePassword("john", "password"), "unable to update password. Cause: cannot find user DN of user 'john'. Cause: LDAP Result Code 2 \"Protocol Error\": permission error")
}
func TestShouldUpdateUserPassword(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
modifyRequest := ldap.NewModifyRequest(
"uid=test,dc=example,dc=com",
@@ -3659,11 +4038,9 @@ func TestShouldUpdateUserPassword(t *testing.T) {
modifyRequest.Replace(ldapAttributeUserPassword, []string{"password"})
- dialURLOIDs := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ dialURLOIDs := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- connBindOIDs := mockClient.EXPECT().
+ clientBindOIDs := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -3687,17 +4064,13 @@ func TestShouldUpdateUserPassword(t *testing.T) {
},
}, nil)
- connCloseOIDs := mockClient.EXPECT().Close()
+ clientCloseOIDs := mockClient.EXPECT().Close()
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
-
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
@@ -3727,7 +4100,7 @@ func TestShouldUpdateUserPassword(t *testing.T) {
Modify(modifyRequest).
Return(nil)
- gomock.InOrder(dialURLOIDs, connBindOIDs, searchOIDs, connCloseOIDs, dialURL, connBind, searchProfile, modify, connClose)
+ gomock.InOrder(dialURLOIDs, clientBindOIDs, searchOIDs, clientCloseOIDs, dialURL, clientBind, searchProfile, modify, clientClose)
err := provider.StartupCheck()
require.NoError(t, err)
@@ -3740,28 +4113,29 @@ func TestShouldUpdateUserPasswordMSAD(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Implementation: "activedirectory",
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Implementation: "activedirectory",
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
modifyRequest := ldap.NewModifyRequest(
"uid=test,dc=example,dc=com",
@@ -3771,11 +4145,9 @@ func TestShouldUpdateUserPasswordMSAD(t *testing.T) {
pwdEncoded, _ := encodingUTF16LittleEndian.NewEncoder().String(fmt.Sprintf("\"%s\"", "password"))
modifyRequest.Replace(ldapAttributeUnicodePwd, []string{pwdEncoded})
- dialURLOIDs := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ dialURLOIDs := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- connBindOIDs := mockClient.EXPECT().
+ clientBindOIDs := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -3799,17 +4171,13 @@ func TestShouldUpdateUserPasswordMSAD(t *testing.T) {
},
}, nil)
- connCloseOIDs := mockClient.EXPECT().Close()
-
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ clientCloseOIDs := mockClient.EXPECT().Close()
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
@@ -3839,7 +4207,7 @@ func TestShouldUpdateUserPasswordMSAD(t *testing.T) {
Modify(modifyRequest).
Return(nil)
- gomock.InOrder(dialURLOIDs, connBindOIDs, searchOIDs, connCloseOIDs, dialURL, connBind, searchProfile, modify, connClose)
+ gomock.InOrder(dialURLOIDs, clientBindOIDs, searchOIDs, clientCloseOIDs, dialURL, clientBind, searchProfile, modify, clientClose)
err := provider.StartupCheck()
require.NoError(t, err)
@@ -3852,30 +4220,31 @@ func TestShouldUpdateUserPasswordMSADWithReferrals(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Implementation: "activedirectory",
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
mockClientReferral := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Implementation: "activedirectory",
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
modifyRequest := ldap.NewModifyRequest(
"uid=test,dc=example,dc=com",
@@ -3885,11 +4254,9 @@ func TestShouldUpdateUserPasswordMSADWithReferrals(t *testing.T) {
pwdEncoded, _ := encodingUTF16LittleEndian.NewEncoder().String(fmt.Sprintf("\"%s\"", "password"))
modifyRequest.Replace(ldapAttributeUnicodePwd, []string{pwdEncoded})
- dialURLOIDs := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ dialURLOIDs := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- connBindOIDs := mockClient.EXPECT().
+ clientBindOIDs := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -3913,17 +4280,13 @@ func TestShouldUpdateUserPasswordMSADWithReferrals(t *testing.T) {
},
}, nil)
- connCloseOIDs := mockClient.EXPECT().Close()
+ clientCloseOIDs := mockClient.EXPECT().Close()
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
-
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
@@ -3957,21 +4320,19 @@ func TestShouldUpdateUserPasswordMSADWithReferrals(t *testing.T) {
Packet: &testBERPacketReferral,
})
- dialURLReferral := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://192.168.0.1"), gomock.Any()).
- Return(mockClientReferral, nil)
+ dialURLReferral := mockDialer.EXPECT().DialURL("ldap://192.168.0.1", gomock.Any()).Return(mockClientReferral, nil)
- connBindReferral := mockClientReferral.EXPECT().
+ clientBindReferral := mockClientReferral.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connCloseReferral := mockClientReferral.EXPECT().Close()
+ clientCloseReferral := mockClientReferral.EXPECT().Close()
modifyReferral := mockClientReferral.EXPECT().
Modify(modifyRequest).
Return(nil)
- gomock.InOrder(dialURLOIDs, connBindOIDs, searchOIDs, connCloseOIDs, dialURL, connBind, searchProfile, modify, dialURLReferral, connBindReferral, modifyReferral, connCloseReferral, connClose)
+ gomock.InOrder(dialURLOIDs, clientBindOIDs, searchOIDs, clientCloseOIDs, dialURL, clientBind, searchProfile, modify, dialURLReferral, clientBindReferral, modifyReferral, clientCloseReferral, clientClose)
err := provider.StartupCheck()
require.NoError(t, err)
@@ -3984,29 +4345,30 @@ func TestShouldUpdateUserPasswordMSADWithReferralsWithReferralConnectErr(t *test
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Implementation: "activedirectory",
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Implementation: "activedirectory",
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
modifyRequest := ldap.NewModifyRequest(
"uid=test,dc=example,dc=com",
@@ -4016,11 +4378,9 @@ func TestShouldUpdateUserPasswordMSADWithReferralsWithReferralConnectErr(t *test
pwdEncoded, _ := encodingUTF16LittleEndian.NewEncoder().String(fmt.Sprintf("\"%s\"", "password"))
modifyRequest.Replace(ldapAttributeUnicodePwd, []string{pwdEncoded})
- dialURLOIDs := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ dialURLOIDs := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- connBindOIDs := mockClient.EXPECT().
+ clientBindOIDs := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -4044,17 +4404,13 @@ func TestShouldUpdateUserPasswordMSADWithReferralsWithReferralConnectErr(t *test
},
}, nil)
- connCloseOIDs := mockClient.EXPECT().Close()
-
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ clientCloseOIDs := mockClient.EXPECT().Close()
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
@@ -4088,47 +4444,46 @@ func TestShouldUpdateUserPasswordMSADWithReferralsWithReferralConnectErr(t *test
Packet: &testBERPacketReferral,
})
- dialURLReferral := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://192.168.0.1"), gomock.Any()).
- Return(nil, errors.New("tcp timeout"))
+ dialURLReferral := mockDialer.EXPECT().DialURL("ldap://192.168.0.1", gomock.Any()).Return(nil, errors.New("tcp timeout"))
- gomock.InOrder(dialURLOIDs, connBindOIDs, searchOIDs, connCloseOIDs, dialURL, connBind, searchProfile, modify, dialURLReferral, connClose)
+ gomock.InOrder(dialURLOIDs, clientBindOIDs, searchOIDs, clientCloseOIDs, dialURL, clientBind, searchProfile, modify, dialURLReferral, clientClose)
err := provider.StartupCheck()
require.NoError(t, err)
err = provider.UpdatePassword("john", "password")
- assert.EqualError(t, err, "unable to update password. Cause: error occurred connecting to referred LDAP server 'ldap://192.168.0.1': dial failed with error: tcp timeout. Original Error: LDAP Result Code 10 \"Referral\": error occurred")
+ assert.EqualError(t, err, "unable to update password. Cause: error occurred connecting to referred LDAP server 'ldap://192.168.0.1': error occurred dialing address: tcp timeout. Original Error: LDAP Result Code 10 \"Referral\": error occurred")
}
func TestShouldUpdateUserPasswordMSADWithReferralsWithReferralModifyErr(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Implementation: "activedirectory",
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
mockClientReferral := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Implementation: "activedirectory",
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
modifyRequest := ldap.NewModifyRequest(
"uid=test,dc=example,dc=com",
@@ -4138,11 +4493,9 @@ func TestShouldUpdateUserPasswordMSADWithReferralsWithReferralModifyErr(t *testi
pwdEncoded, _ := encodingUTF16LittleEndian.NewEncoder().String(fmt.Sprintf("\"%s\"", "password"))
modifyRequest.Replace(ldapAttributeUnicodePwd, []string{pwdEncoded})
- dialURLOIDs := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ dialURLOIDs := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- connBindOIDs := mockClient.EXPECT().
+ clientBindOIDs := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -4166,17 +4519,13 @@ func TestShouldUpdateUserPasswordMSADWithReferralsWithReferralModifyErr(t *testi
},
}, nil)
- connCloseOIDs := mockClient.EXPECT().Close()
-
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ clientCloseOIDs := mockClient.EXPECT().Close()
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
@@ -4210,15 +4559,13 @@ func TestShouldUpdateUserPasswordMSADWithReferralsWithReferralModifyErr(t *testi
Packet: &testBERPacketReferral,
})
- dialURLReferral := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://192.168.0.1"), gomock.Any()).
- Return(mockClientReferral, nil)
+ dialURLReferral := mockDialer.EXPECT().DialURL("ldap://192.168.0.1", gomock.Any()).Return(mockClientReferral, nil)
- connBindReferral := mockClientReferral.EXPECT().
+ clientBindReferral := mockClientReferral.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connCloseReferral := mockClientReferral.EXPECT().Close()
+ clientCloseReferral := mockClientReferral.EXPECT().Close()
modifyReferral := mockClientReferral.EXPECT().
Modify(modifyRequest).
@@ -4228,7 +4575,7 @@ func TestShouldUpdateUserPasswordMSADWithReferralsWithReferralModifyErr(t *testi
Packet: &testBERPacketReferral,
})
- gomock.InOrder(dialURLOIDs, connBindOIDs, searchOIDs, connCloseOIDs, dialURL, connBind, searchProfile, modify, dialURLReferral, connBindReferral, modifyReferral, connCloseReferral, connClose)
+ gomock.InOrder(dialURLOIDs, clientBindOIDs, searchOIDs, clientCloseOIDs, dialURL, clientBind, searchProfile, modify, dialURLReferral, clientBindReferral, modifyReferral, clientCloseReferral, clientClose)
err := provider.StartupCheck()
require.NoError(t, err)
@@ -4241,29 +4588,30 @@ func TestShouldUpdateUserPasswordMSADWithoutReferrals(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Implementation: "activedirectory",
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: false,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Implementation: "activedirectory",
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: false,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
modifyRequest := ldap.NewModifyRequest(
"uid=test,dc=example,dc=com",
@@ -4273,11 +4621,9 @@ func TestShouldUpdateUserPasswordMSADWithoutReferrals(t *testing.T) {
pwdEncoded, _ := encodingUTF16LittleEndian.NewEncoder().String(fmt.Sprintf("\"%s\"", "password"))
modifyRequest.Replace(ldapAttributeUnicodePwd, []string{pwdEncoded})
- dialURLOIDs := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ dialURLOIDs := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- connBindOIDs := mockClient.EXPECT().
+ clientBindOIDs := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -4301,17 +4647,13 @@ func TestShouldUpdateUserPasswordMSADWithoutReferrals(t *testing.T) {
},
}, nil)
- connCloseOIDs := mockClient.EXPECT().Close()
-
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ clientCloseOIDs := mockClient.EXPECT().Close()
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
@@ -4345,7 +4687,7 @@ func TestShouldUpdateUserPasswordMSADWithoutReferrals(t *testing.T) {
Packet: &testBERPacketReferral,
})
- gomock.InOrder(dialURLOIDs, connBindOIDs, searchOIDs, connCloseOIDs, dialURL, connBind, searchProfile, modify, connClose)
+ gomock.InOrder(dialURLOIDs, clientBindOIDs, searchOIDs, clientCloseOIDs, dialURL, clientBind, searchProfile, modify, clientClose)
err := provider.StartupCheck()
require.NoError(t, err)
@@ -4358,27 +4700,28 @@ func TestShouldUpdateUserPasswordPasswdModifyExtension(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
pwdModifyRequest := ldap.NewPasswordModifyRequest(
"uid=test,dc=example,dc=com",
@@ -4386,11 +4729,9 @@ func TestShouldUpdateUserPasswordPasswdModifyExtension(t *testing.T) {
"password",
)
- dialURLOIDs := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ dialURLOIDs := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- connBindOIDs := mockClient.EXPECT().
+ clientBindOIDs := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -4414,17 +4755,13 @@ func TestShouldUpdateUserPasswordPasswdModifyExtension(t *testing.T) {
},
}, nil)
- connCloseOIDs := mockClient.EXPECT().Close()
+ clientCloseOIDs := mockClient.EXPECT().Close()
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
-
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
@@ -4454,7 +4791,7 @@ func TestShouldUpdateUserPasswordPasswdModifyExtension(t *testing.T) {
PasswordModify(pwdModifyRequest).
Return(nil, nil)
- gomock.InOrder(dialURLOIDs, connBindOIDs, searchOIDs, connCloseOIDs, dialURL, connBind, searchProfile, passwdModify, connClose)
+ gomock.InOrder(dialURLOIDs, clientBindOIDs, searchOIDs, clientCloseOIDs, dialURL, clientBind, searchProfile, passwdModify, clientClose)
err := provider.StartupCheck()
require.NoError(t, err)
@@ -4467,29 +4804,30 @@ func TestShouldUpdateUserPasswordPasswdModifyExtensionWithReferrals(t *testing.T
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
mockClientReferral := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
pwdModifyRequest := ldap.NewPasswordModifyRequest(
"uid=test,dc=example,dc=com",
@@ -4497,11 +4835,9 @@ func TestShouldUpdateUserPasswordPasswdModifyExtensionWithReferrals(t *testing.T
"password",
)
- dialURLOIDs := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ dialURLOIDs := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- connBindOIDs := mockClient.EXPECT().
+ clientBindOIDs := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -4525,17 +4861,13 @@ func TestShouldUpdateUserPasswordPasswdModifyExtensionWithReferrals(t *testing.T
},
}, nil)
- connCloseOIDs := mockClient.EXPECT().Close()
+ clientCloseOIDs := mockClient.EXPECT().Close()
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
-
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
@@ -4571,21 +4903,19 @@ func TestShouldUpdateUserPasswordPasswdModifyExtensionWithReferrals(t *testing.T
Packet: &testBERPacketReferral,
})
- dialURLReferral := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://192.168.0.1"), gomock.Any()).
- Return(mockClientReferral, nil)
+ dialURLReferral := mockDialer.EXPECT().DialURL("ldap://192.168.0.1", gomock.Any()).Return(mockClientReferral, nil)
- connBindReferral := mockClientReferral.EXPECT().
+ clientBindReferral := mockClientReferral.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connCloseReferral := mockClientReferral.EXPECT().Close()
+ clientCloseReferral := mockClientReferral.EXPECT().Close()
passwdModifyReferral := mockClientReferral.EXPECT().
PasswordModify(pwdModifyRequest).
Return(&ldap.PasswordModifyResult{}, nil)
- gomock.InOrder(dialURLOIDs, connBindOIDs, searchOIDs, connCloseOIDs, dialURL, connBind, searchProfile, passwdModify, dialURLReferral, connBindReferral, passwdModifyReferral, connCloseReferral, connClose)
+ gomock.InOrder(dialURLOIDs, clientBindOIDs, searchOIDs, clientCloseOIDs, dialURL, clientBind, searchProfile, passwdModify, dialURLReferral, clientBindReferral, passwdModifyReferral, clientCloseReferral, clientClose)
err := provider.StartupCheck()
require.NoError(t, err)
@@ -4598,28 +4928,29 @@ func TestShouldUpdateUserPasswordPasswdModifyExtensionWithoutReferrals(t *testin
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: false,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: false,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
pwdModifyRequest := ldap.NewPasswordModifyRequest(
"uid=test,dc=example,dc=com",
@@ -4627,11 +4958,9 @@ func TestShouldUpdateUserPasswordPasswdModifyExtensionWithoutReferrals(t *testin
"password",
)
- dialURLOIDs := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ dialURLOIDs := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- connBindOIDs := mockClient.EXPECT().
+ clientBindOIDs := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -4655,17 +4984,13 @@ func TestShouldUpdateUserPasswordPasswdModifyExtensionWithoutReferrals(t *testin
},
}, nil)
- connCloseOIDs := mockClient.EXPECT().Close()
+ clientCloseOIDs := mockClient.EXPECT().Close()
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
-
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
@@ -4701,7 +5026,7 @@ func TestShouldUpdateUserPasswordPasswdModifyExtensionWithoutReferrals(t *testin
Packet: &testBERPacketReferral,
})
- gomock.InOrder(dialURLOIDs, connBindOIDs, searchOIDs, connCloseOIDs, dialURL, connBind, searchProfile, passwdModify, connClose)
+ gomock.InOrder(dialURLOIDs, clientBindOIDs, searchOIDs, clientCloseOIDs, dialURL, clientBind, searchProfile, passwdModify, clientClose)
err := provider.StartupCheck()
require.NoError(t, err)
@@ -4714,28 +5039,29 @@ func TestShouldUpdateUserPasswordPasswdModifyExtensionWithReferralsReferralConne
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
pwdModifyRequest := ldap.NewPasswordModifyRequest(
"uid=test,dc=example,dc=com",
@@ -4743,11 +5069,9 @@ func TestShouldUpdateUserPasswordPasswdModifyExtensionWithReferralsReferralConne
"password",
)
- dialURLOIDs := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ dialURLOIDs := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- connBindOIDs := mockClient.EXPECT().
+ clientBindOIDs := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -4771,17 +5095,13 @@ func TestShouldUpdateUserPasswordPasswdModifyExtensionWithReferralsReferralConne
},
}, nil)
- connCloseOIDs := mockClient.EXPECT().Close()
+ clientCloseOIDs := mockClient.EXPECT().Close()
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
-
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
@@ -4817,46 +5137,45 @@ func TestShouldUpdateUserPasswordPasswdModifyExtensionWithReferralsReferralConne
Packet: &testBERPacketReferral,
})
- dialURLReferral := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://192.168.0.1"), gomock.Any()).
- Return(nil, errors.New("tcp timeout"))
+ dialURLReferral := mockDialer.EXPECT().DialURL("ldap://192.168.0.1", gomock.Any()).Return(nil, errors.New("tcp timeout"))
- gomock.InOrder(dialURLOIDs, connBindOIDs, searchOIDs, connCloseOIDs, dialURL, connBind, searchProfile, passwdModify, dialURLReferral, connClose)
+ gomock.InOrder(dialURLOIDs, clientBindOIDs, searchOIDs, clientCloseOIDs, dialURL, clientBind, searchProfile, passwdModify, dialURLReferral, clientClose)
err := provider.StartupCheck()
require.NoError(t, err)
err = provider.UpdatePassword("john", "password")
- assert.EqualError(t, err, "unable to update password. Cause: error occurred connecting to referred LDAP server 'ldap://192.168.0.1': dial failed with error: tcp timeout. Original Error: LDAP Result Code 10 \"Referral\": error occurred")
+ assert.EqualError(t, err, "unable to update password. Cause: error occurred connecting to referred LDAP server 'ldap://192.168.0.1': error occurred dialing address: tcp timeout. Original Error: LDAP Result Code 10 \"Referral\": error occurred")
}
func TestShouldUpdateUserPasswordPasswdModifyExtensionWithReferralsReferralPasswordModifyErr(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ PermitReferrals: true,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
mockClientReferral := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- PermitReferrals: true,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
pwdModifyRequest := ldap.NewPasswordModifyRequest(
"uid=test,dc=example,dc=com",
@@ -4864,11 +5183,9 @@ func TestShouldUpdateUserPasswordPasswdModifyExtensionWithReferralsReferralPassw
"password",
)
- dialURLOIDs := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ dialURLOIDs := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- connBindOIDs := mockClient.EXPECT().
+ clientBindOIDs := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -4892,17 +5209,13 @@ func TestShouldUpdateUserPasswordPasswdModifyExtensionWithReferralsReferralPassw
},
}, nil)
- connCloseOIDs := mockClient.EXPECT().Close()
-
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ clientCloseOIDs := mockClient.EXPECT().Close()
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
@@ -4938,15 +5251,13 @@ func TestShouldUpdateUserPasswordPasswdModifyExtensionWithReferralsReferralPassw
Packet: &testBERPacketReferral,
})
- dialURLReferral := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://192.168.0.1"), gomock.Any()).
- Return(mockClientReferral, nil)
+ dialURLReferral := mockDialer.EXPECT().DialURL("ldap://192.168.0.1", gomock.Any()).Return(mockClientReferral, nil)
- connBindReferral := mockClientReferral.EXPECT().
+ clientBindReferral := mockClientReferral.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connCloseReferral := mockClientReferral.EXPECT().Close()
+ clientCloseReferral := mockClientReferral.EXPECT().Close()
passwdModifyReferral := mockClientReferral.EXPECT().
PasswordModify(pwdModifyRequest).
@@ -4956,7 +5267,7 @@ func TestShouldUpdateUserPasswordPasswdModifyExtensionWithReferralsReferralPassw
Packet: &testBERPacketReferral,
})
- gomock.InOrder(dialURLOIDs, connBindOIDs, searchOIDs, connCloseOIDs, dialURL, connBind, searchProfile, passwdModify, dialURLReferral, connBindReferral, passwdModifyReferral, connCloseReferral, connClose)
+ gomock.InOrder(dialURLOIDs, clientBindOIDs, searchOIDs, clientCloseOIDs, dialURL, clientBind, searchProfile, passwdModify, dialURLReferral, clientBindReferral, passwdModifyReferral, clientCloseReferral, clientClose)
err := provider.StartupCheck()
require.NoError(t, err)
@@ -4969,29 +5280,30 @@ func TestShouldUpdateUserPasswordActiveDirectoryWithServerPolicyHints(t *testing
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Implementation: "activedirectory",
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ DistinguishedName: "distinguishedName",
+ Username: "sAMAccountName",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "cn={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Implementation: "activedirectory",
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- DistinguishedName: "distinguishedName",
- Username: "sAMAccountName",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "cn={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
utf16 := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM)
pwdEncoded, _ := utf16.NewEncoder().String("\"password\"")
@@ -5003,11 +5315,9 @@ func TestShouldUpdateUserPasswordActiveDirectoryWithServerPolicyHints(t *testing
modifyRequest.Replace("unicodePwd", []string{pwdEncoded})
- dialURLOIDs := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ dialURLOIDs := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- connBindOIDs := mockClient.EXPECT().
+ clientBindOIDs := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -5031,17 +5341,13 @@ func TestShouldUpdateUserPasswordActiveDirectoryWithServerPolicyHints(t *testing
},
}, nil)
- connCloseOIDs := mockClient.EXPECT().Close()
+ clientCloseOIDs := mockClient.EXPECT().Close()
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
-
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
@@ -5071,7 +5377,7 @@ func TestShouldUpdateUserPasswordActiveDirectoryWithServerPolicyHints(t *testing
Modify(modifyRequest).
Return(nil)
- gomock.InOrder(dialURLOIDs, connBindOIDs, searchOIDs, connCloseOIDs, dialURL, connBind, searchProfile, passwdModify, connClose)
+ gomock.InOrder(dialURLOIDs, clientBindOIDs, searchOIDs, clientCloseOIDs, dialURL, clientBind, searchProfile, passwdModify, clientClose)
err := provider.StartupCheck()
require.NoError(t, err)
@@ -5084,29 +5390,30 @@ func TestShouldUpdateUserPasswordActiveDirectoryWithServerPolicyHintsDeprecated(
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Implementation: "activedirectory",
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ DistinguishedName: "distinguishedName",
+ Username: "sAMAccountName",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "cn={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Implementation: "activedirectory",
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- DistinguishedName: "distinguishedName",
- Username: "sAMAccountName",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "cn={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
utf16 := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM)
pwdEncoded, _ := utf16.NewEncoder().String("\"password\"")
@@ -5118,11 +5425,9 @@ func TestShouldUpdateUserPasswordActiveDirectoryWithServerPolicyHintsDeprecated(
modifyRequest.Replace("unicodePwd", []string{pwdEncoded})
- dialURLOIDs := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ dialURLOIDs := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- connBindOIDs := mockClient.EXPECT().
+ clientBindOIDs := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -5146,17 +5451,13 @@ func TestShouldUpdateUserPasswordActiveDirectoryWithServerPolicyHintsDeprecated(
},
}, nil)
- connCloseOIDs := mockClient.EXPECT().Close()
-
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ clientCloseOIDs := mockClient.EXPECT().Close()
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
@@ -5186,7 +5487,7 @@ func TestShouldUpdateUserPasswordActiveDirectoryWithServerPolicyHintsDeprecated(
Modify(modifyRequest).
Return(nil)
- gomock.InOrder(dialURLOIDs, connBindOIDs, searchOIDs, connCloseOIDs, dialURL, connBind, searchProfile, passwdModify, connClose)
+ gomock.InOrder(dialURLOIDs, clientBindOIDs, searchOIDs, clientCloseOIDs, dialURL, clientBind, searchProfile, passwdModify, clientClose)
err := provider.StartupCheck()
require.NoError(t, err)
@@ -5199,29 +5500,30 @@ func TestShouldUpdateUserPasswordActiveDirectory(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Implementation: "activedirectory",
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ DistinguishedName: "distinguishedName",
+ Username: "sAMAccountName",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "cn={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Implementation: "activedirectory",
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- DistinguishedName: "distinguishedName",
- Username: "sAMAccountName",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "cn={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
utf16 := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM)
pwdEncoded, _ := utf16.NewEncoder().String("\"password\"")
@@ -5233,11 +5535,9 @@ func TestShouldUpdateUserPasswordActiveDirectory(t *testing.T) {
modifyRequest.Replace("unicodePwd", []string{pwdEncoded})
- dialURLOIDs := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ dialURLOIDs := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- connBindOIDs := mockClient.EXPECT().
+ clientBindOIDs := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -5261,17 +5561,13 @@ func TestShouldUpdateUserPasswordActiveDirectory(t *testing.T) {
},
}, nil)
- connCloseOIDs := mockClient.EXPECT().Close()
-
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ clientCloseOIDs := mockClient.EXPECT().Close()
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
@@ -5301,7 +5597,7 @@ func TestShouldUpdateUserPasswordActiveDirectory(t *testing.T) {
Modify(modifyRequest).
Return(nil)
- gomock.InOrder(dialURLOIDs, connBindOIDs, searchOIDs, connCloseOIDs, dialURL, connBind, searchProfile, passwdModify, connClose)
+ gomock.InOrder(dialURLOIDs, clientBindOIDs, searchOIDs, clientCloseOIDs, dialURL, clientBind, searchProfile, passwdModify, clientClose)
err := provider.StartupCheck()
require.NoError(t, err)
@@ -5314,28 +5610,29 @@ func TestShouldUpdateUserPasswordBasic(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Implementation: "custom",
+ Address: testLDAPAddress,
+ User: "uid=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Implementation: "custom",
- Address: testLDAPAddress,
- User: "uid=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
+
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
modifyRequest := ldap.NewModifyRequest(
"uid=test,dc=example,dc=com",
@@ -5344,11 +5641,9 @@ func TestShouldUpdateUserPasswordBasic(t *testing.T) {
modifyRequest.Replace("userPassword", []string{"password"})
- dialURLOIDs := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ dialURLOIDs := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- connBindOIDs := mockClient.EXPECT().
+ clientBindOIDs := mockClient.EXPECT().
Bind(gomock.Eq("uid=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -5372,17 +5667,13 @@ func TestShouldUpdateUserPasswordBasic(t *testing.T) {
},
}, nil)
- connCloseOIDs := mockClient.EXPECT().Close()
+ clientCloseOIDs := mockClient.EXPECT().Close()
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
-
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("uid=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchProfile := mockClient.EXPECT().
Search(gomock.Any()).
@@ -5412,7 +5703,7 @@ func TestShouldUpdateUserPasswordBasic(t *testing.T) {
Modify(modifyRequest).
Return(nil)
- gomock.InOrder(dialURLOIDs, connBindOIDs, searchOIDs, connCloseOIDs, dialURL, connBind, searchProfile, passwdModify, connClose)
+ gomock.InOrder(dialURLOIDs, clientBindOIDs, searchOIDs, clientCloseOIDs, dialURL, clientBind, searchProfile, passwdModify, clientClose)
err := provider.StartupCheck()
require.NoError(t, err)
@@ -5425,33 +5716,30 @@ func TestShouldReturnErrorWhenMultipleUsernameAttributes(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- bind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -5479,9 +5767,9 @@ func TestShouldReturnErrorWhenMultipleUsernameAttributes(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, bind, search)
+ gomock.InOrder(dialURL, clientBind, search)
- client, err := provider.connect()
+ client, err := provider.factory.GetClient()
assert.NoError(t, err)
profile, err := provider.getUserProfile(client, "john")
@@ -5494,33 +5782,30 @@ func TestShouldReturnErrorWhenZeroUsernameAttributes(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- bind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -5548,9 +5833,9 @@ func TestShouldReturnErrorWhenZeroUsernameAttributes(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, bind, search)
+ gomock.InOrder(dialURL, clientBind, search)
- client, err := provider.connect()
+ client, err := provider.factory.GetClient()
assert.NoError(t, err)
profile, err := provider.getUserProfile(client, "john")
@@ -5563,33 +5848,30 @@ func TestShouldReturnErrorWhenUsernameAttributeNotReturned(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- bind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -5613,9 +5895,9 @@ func TestShouldReturnErrorWhenUsernameAttributeNotReturned(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, bind, search)
+ gomock.InOrder(dialURL, clientBind, search)
- client, err := provider.connect()
+ client, err := provider.factory.GetClient()
assert.NoError(t, err)
profile, err := provider.getUserProfile(client, "john")
@@ -5628,33 +5910,30 @@ func TestShouldReturnErrorWhenMultipleUsersFound(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "(|(uid={input})(uid=*))",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "(|(uid={input})(uid=*))",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- bind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -5699,9 +5978,9 @@ func TestShouldReturnErrorWhenMultipleUsersFound(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, bind, search)
+ gomock.InOrder(dialURL, clientBind, search)
- client, err := provider.connect()
+ client, err := provider.factory.GetClient()
assert.NoError(t, err)
profile, err := provider.getUserProfile(client, "john")
@@ -5714,33 +5993,30 @@ func TestShouldReturnErrorWhenNoDN(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "(|(uid={input})(uid=*))",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "(|(uid={input})(uid=*))",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- bind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
@@ -5768,9 +6044,9 @@ func TestShouldReturnErrorWhenNoDN(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, bind, search)
+ gomock.InOrder(dialURL, clientBind, search)
- client, err := provider.connect()
+ client, err := provider.factory.GetClient()
assert.NoError(t, err)
profile, err := provider.getUserProfile(client, "john")
@@ -5783,32 +6059,29 @@ func TestShouldCheckValidUserPassword(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
gomock.InOrder(
- mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil),
+ mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil),
mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil),
@@ -5835,9 +6108,7 @@ func TestShouldCheckValidUserPassword(t *testing.T) {
},
},
}, nil),
- mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil),
+ mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil),
mockClient.EXPECT().
Bind(gomock.Eq("uid=test,dc=example,dc=com"), gomock.Eq("password")).
Return(nil),
@@ -5854,74 +6125,68 @@ func TestShouldNotCheckValidUserPasswordWithConnectError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- bind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(&ldap.Error{ResultCode: ldap.LDAPResultInvalidCredentials, Err: errors.New("invalid username or password")})
- gomock.InOrder(dialURL, bind, mockClient.EXPECT().Close())
+ gomock.InOrder(dialURL, clientBind, mockClient.EXPECT().Close())
valid, err := provider.CheckUserPassword("john", "password")
assert.False(t, valid)
- assert.EqualError(t, err, "bind failed with error: LDAP Result Code 49 \"Invalid Credentials\": invalid username or password")
+ assert.EqualError(t, err, "error occurred performing bind: LDAP Result Code 49 \"Invalid Credentials\": invalid username or password")
}
func TestShouldNotCheckValidUserPasswordWithGetProfileError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
gomock.InOrder(
- mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil),
+ mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil),
mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil),
@@ -5941,32 +6206,29 @@ func TestShouldCheckInvalidUserPassword(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- },
- false,
- nil,
- mockFactory)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
gomock.InOrder(
- mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil),
+ mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil),
mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil),
@@ -5993,9 +6255,7 @@ func TestShouldCheckInvalidUserPassword(t *testing.T) {
},
},
}, nil),
- mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil),
+ mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil),
mockClient.EXPECT().
Bind(gomock.Eq("uid=test,dc=example,dc=com"), gomock.Eq("password")).
Return(errors.New("invalid username or password")),
@@ -6005,49 +6265,47 @@ func TestShouldCheckInvalidUserPassword(t *testing.T) {
valid, err := provider.CheckUserPassword("john", "password")
assert.False(t, valid)
- require.EqualError(t, err, "authentication failed. Cause: bind failed with error: invalid username or password")
+ require.EqualError(t, err, "authentication failed. Cause: error occurred performing bind: invalid username or password")
}
func TestShouldCallStartTLSWhenEnabled(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ GroupName: "cn",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ TLS: schema.DefaultLDAPAuthenticationBackendConfigurationImplementationCustom.TLS,
+ StartTLS: true,
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- GroupName: "cn",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- StartTLS: true,
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
- connBind := mockClient.EXPECT().
+ connStartTLS := mockClient.EXPECT().
+ StartTLS(gomock.Any())
+
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
- connStartTLS := mockClient.EXPECT().
- StartTLS(provider.tlsConfig)
-
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchGroups := mockClient.EXPECT().
Search(gomock.Any()).
@@ -6077,7 +6335,7 @@ func TestShouldCallStartTLSWhenEnabled(t *testing.T) {
},
}, nil)
- gomock.InOrder(dialURL, connStartTLS, connBind, searchProfile, searchGroups, connClose)
+ gomock.InOrder(dialURL, connStartTLS, clientBind, searchProfile, searchGroups, clientClose)
details, err := provider.GetDetails("john")
require.NoError(t, err)
@@ -6095,7 +6353,7 @@ func TestShouldParseDynamicConfiguration(t *testing.T) {
mockFactory := NewMockLDAPClientFactory(ctrl)
provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
+ &schema.AuthenticationBackendLDAP{
Address: testLDAPAddress,
User: "cn=admin,dc=example,dc=com",
Password: "password",
@@ -6113,7 +6371,6 @@ func TestShouldParseDynamicConfiguration(t *testing.T) {
StartTLS: true,
},
false,
- nil,
mockFactory)
provider.clock = clock.NewFixed(time.Unix(1670250519, 0))
@@ -6139,49 +6396,46 @@ func TestShouldCallStartTLSWithInsecureSkipVerifyWhenSkipVerifyTrue(t *testing.T
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ GroupName: "cn",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ StartTLS: true,
+ TLS: &schema.TLS{
+ SkipVerify: true,
+ },
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- GroupName: "cn",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- StartTLS: true,
- TLS: &schema.TLS{
- SkipVerify: true,
- },
- },
- false,
- nil,
- mockFactory)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
assert.False(t, provider.groupsFilterReplacementInput)
assert.False(t, provider.groupsFilterReplacementUsername)
assert.False(t, provider.groupsFilterReplacementDN)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldap://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ dialURL := mockDialer.EXPECT().DialURL("ldap://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- connBind := mockClient.EXPECT().
+ clientBind := mockClient.EXPECT().
Bind(gomock.Eq("cn=admin,dc=example,dc=com"), gomock.Eq("password")).
Return(nil)
connStartTLS := mockClient.EXPECT().
- StartTLS(provider.tlsConfig)
+ StartTLS(gomock.Not(gomock.Nil()))
- connClose := mockClient.EXPECT().Close()
+ clientClose := mockClient.EXPECT().Close()
searchGroups := mockClient.EXPECT().
Search(gomock.Any()).
@@ -6215,7 +6469,7 @@ func TestShouldCallStartTLSWithInsecureSkipVerifyWhenSkipVerifyTrue(t *testing.T
},
}, nil)
- gomock.InOrder(dialURL, connStartTLS, connBind, searchProfile, searchGroups, connClose)
+ gomock.InOrder(dialURL, connStartTLS, clientBind, searchProfile, searchGroups, clientClose)
details, err := provider.GetDetails("john")
require.NoError(t, err)
@@ -6230,42 +6484,39 @@ func TestShouldReturnLDAPSAlreadySecuredWhenStartTLSAttempted(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- mockFactory := NewMockLDAPClientFactory(ctrl)
+ config := &schema.AuthenticationBackendLDAP{
+ Address: testLDAPSAddress,
+ User: "cn=admin,dc=example,dc=com",
+ Password: "password",
+ Attributes: schema.AuthenticationBackendLDAPAttributes{
+ Username: "uid",
+ Mail: "mail",
+ DisplayName: "displayName",
+ MemberOf: "memberOf",
+ },
+ UsersFilter: "uid={input}",
+ AdditionalUsersDN: "ou=users",
+ BaseDN: "dc=example,dc=com",
+ StartTLS: true,
+ TLS: &schema.TLS{
+ SkipVerify: true,
+ },
+ }
+
+ mockDialer := NewMockLDAPClientDialer(ctrl)
+
mockClient := NewMockLDAPClient(ctrl)
- provider := NewLDAPUserProviderWithFactory(
- schema.AuthenticationBackendLDAP{
- Address: testLDAPSAddress,
- User: "cn=admin,dc=example,dc=com",
- Password: "password",
- Attributes: schema.AuthenticationBackendLDAPAttributes{
- Username: "uid",
- Mail: "mail",
- DisplayName: "displayName",
- MemberOf: "memberOf",
- },
- UsersFilter: "uid={input}",
- AdditionalUsersDN: "ou=users",
- BaseDN: "dc=example,dc=com",
- StartTLS: true,
- TLS: &schema.TLS{
- SkipVerify: true,
- },
- },
- false,
- nil,
- mockFactory)
+ dialURL := mockDialer.EXPECT().DialURL("ldaps://127.0.0.1:389", gomock.Any()).Return(mockClient, nil)
- dialURL := mockFactory.EXPECT().
- DialURL(gomock.Eq("ldaps://127.0.0.1:389"), gomock.Any()).
- Return(mockClient, nil)
+ provider := NewLDAPUserProviderWithFactory(config, false, NewStandardLDAPClientFactory(config, nil, mockDialer))
connStartTLS := mockClient.EXPECT().
- StartTLS(provider.tlsConfig).
+ StartTLS(gomock.Not(gomock.Nil())).
Return(errors.New("LDAP Result Code 200 \"Network Error\": ldap: already encrypted"))
gomock.InOrder(dialURL, connStartTLS, mockClient.EXPECT().Close())
_, err := provider.GetDetails("john")
- assert.EqualError(t, err, "starttls failed with error: LDAP Result Code 200 \"Network Error\": ldap: already encrypted")
+ assert.EqualError(t, err, "error occurred performing starttls: LDAP Result Code 200 \"Network Error\": ldap: already encrypted")
}
diff --git a/internal/authentication/types.go b/internal/authentication/types.go
index d1853d5f3..145a83818 100644
--- a/internal/authentication/types.go
+++ b/internal/authentication/types.go
@@ -1,59 +1,13 @@
package authentication
import (
- "crypto/tls"
"fmt"
"net/mail"
"net/url"
- "time"
- "github.com/go-ldap/ldap/v3"
"golang.org/x/text/language"
)
-// LDAPClientFactory an interface of factory of LDAP clients.
-type LDAPClientFactory interface {
- DialURL(addr string, opts ...ldap.DialOpt) (client LDAPClient, err error)
-}
-
-// LDAPClient is a cut down version of the ldap.Client interface with just the methods we use.
-//
-// Methods added to this interface that have a direct correlation with one from ldap.Client should have the same signature.
-type LDAPClient interface {
- Close() (err error)
- IsClosing() bool
- SetTimeout(timeout time.Duration)
-
- TLSConnectionState() (state tls.ConnectionState, ok bool)
- StartTLS(config *tls.Config) (err error)
-
- Unbind() (err error)
- Bind(username, password string) (err error)
- SimpleBind(request *ldap.SimpleBindRequest) (result *ldap.SimpleBindResult, err error)
- MD5Bind(host string, username string, password string) (err error)
- DigestMD5Bind(request *ldap.DigestMD5BindRequest) (result *ldap.DigestMD5BindResult, err error)
- UnauthenticatedBind(username string) (err error)
- ExternalBind() (err error)
- NTLMBind(domain string, username string, password string) (err error)
- NTLMUnauthenticatedBind(domain string, username string) (err error)
- NTLMBindWithHash(domain string, username string, hash string) (err error)
- NTLMChallengeBind(request *ldap.NTLMBindRequest) (result *ldap.NTLMBindResult, err error)
-
- Modify(request *ldap.ModifyRequest) (err error)
- ModifyWithResult(request *ldap.ModifyRequest) (result *ldap.ModifyResult, err error)
- ModifyDN(m *ldap.ModifyDNRequest) (err error)
- PasswordModify(request *ldap.PasswordModifyRequest) (result *ldap.PasswordModifyResult, err error)
-
- Add(request *ldap.AddRequest) (err error)
- Del(request *ldap.DelRequest) (err error)
-
- Search(request *ldap.SearchRequest) (result *ldap.SearchResult, err error)
- SearchWithPaging(request *ldap.SearchRequest, pagingSize uint32) (result *ldap.SearchResult, err error)
- Compare(dn string, attribute string, value string) (same bool, err error)
-
- WhoAmI(controls []ldap.Control) (result *ldap.WhoAmIResult, err error)
-}
-
// UserDetails represent the details retrieved for a given user.
type UserDetails struct {
Username string
diff --git a/internal/authentication/user_provider.go b/internal/authentication/user_provider.go
index f6c63ca57..516345d15 100644
--- a/internal/authentication/user_provider.go
+++ b/internal/authentication/user_provider.go
@@ -13,4 +13,5 @@ type UserProvider interface {
GetDetails(username string) (details *UserDetails, err error)
GetDetailsExtended(username string) (details *UserDetailsExtended, err error)
UpdatePassword(username, newPassword string) (err error)
+ Shutdown() (err error)
}
diff --git a/internal/commands/services.go b/internal/commands/services.go
index 332a29357..18598b488 100644
--- a/internal/commands/services.go
+++ b/internal/commands/services.go
@@ -447,6 +447,10 @@ func servicesRun(ctx ServiceCtx) {
var err error
+ if err = ctx.GetProviders().UserProvider.Shutdown(); err != nil {
+ ctx.GetLogger().WithError(err).Error("Error occurred closing authentication connections")
+ }
+
if err = ctx.GetProviders().StorageProvider.Close(); err != nil {
ctx.GetLogger().WithError(err).Error("Error occurred closing database connections")
}
diff --git a/internal/configuration/config.template.yml b/internal/configuration/config.template.yml
index a3181081d..2e01b7a15 100644
--- a/internal/configuration/config.template.yml
+++ b/internal/configuration/config.template.yml
@@ -459,6 +459,7 @@ identity_validation:
## Use StartTLS with the LDAP connection.
# start_tls: false
+ ## TLS configuration.
# tls:
## The server subject name to check the servers certificate against during the validation process.
## This option is not required if the certificate has a SAN which matches the address options hostname.
@@ -495,6 +496,20 @@ identity_validation:
# ...
# -----END RSA PRIVATE KEY-----
+ ## Connection Pooling configuration.
+ # pooling:
+ ## Enable Pooling.
+ # enable: false
+
+ ## Pool count.
+ # count: 5
+
+ ## Retries to obtain a connection during the timeout.
+ # retries: 2
+
+ ## Timeout before the attempt to obtain a connection fails.
+ # timeout: '10 seconds'
+
## The distinguished name of the container searched for objects in the directory information tree.
## See also: additional_users_dn, additional_groups_dn.
# base_dn: 'dc=example,dc=com'
diff --git a/internal/configuration/schema/authentication.go b/internal/configuration/schema/authentication.go
index 4ebfb680f..010262abf 100644
--- a/internal/configuration/schema/authentication.go
+++ b/internal/configuration/schema/authentication.go
@@ -127,6 +127,8 @@ type AuthenticationBackendLDAP struct {
StartTLS bool `koanf:"start_tls" json:"start_tls" jsonschema:"default=false,title=StartTLS" jsonschema_description:"Enables the use of StartTLS."`
TLS *TLS `koanf:"tls" json:"tls" jsonschema:"title=TLS" jsonschema_description:"The LDAP directory server TLS connection properties."`
+ Pooling AuthenticationBackendLDAPPooling `koanf:"pooling" json:"pooling" jsonschema:"title=Pooling" jsonschema_description:"The LDAP Connection Pooling properties."`
+
BaseDN string `koanf:"base_dn" json:"base_dn" jsonschema:"title=Base DN" jsonschema_description:"The base for all directory server operations."`
AdditionalUsersDN string `koanf:"additional_users_dn" json:"additional_users_dn" jsonschema:"title=Additional User Base" jsonschema_description:"The base in addition to the Base DN for all directory server operations for users."`
@@ -146,6 +148,13 @@ type AuthenticationBackendLDAP struct {
Password string `koanf:"password" json:"password" jsonschema:"title=Password" jsonschema_description:"The password for LDAP authenticated binding."`
}
+type AuthenticationBackendLDAPPooling struct {
+ Enable bool `koanf:"enable" json:"enable" jsonschema:"title=Enable,default=false" jsonschema_description:"Enable LDAP connection pooling."`
+ Count int `koanf:"count" json:"count" jsonschema:"title=Count,default=5" jsonschema_description:"The number of connections to keep open for LDAP connection pooling."`
+ Retries int `koanf:"retries" json:"retries" jsonschema:"title=Retries,default=2" jsonschema_description:"The number of attempts to retrieve a connection from the pool during the timeout."`
+ Timeout time.Duration `koanf:"timeout" json:"timeout" jsonschema:"title=Timeout,default=10 seconds" jsonschema_description:"The duration of time to wait for a connection to become available in the connection pool."`
+}
+
// AuthenticationBackendLDAPAttributes represents the configuration related to LDAP server attributes.
type AuthenticationBackendLDAPAttributes struct {
DistinguishedName string `koanf:"distinguished_name" json:"distinguished_name" jsonschema:"title=Attribute: Distinguished Name" jsonschema_description:"The directory server attribute which contains the distinguished name for all objects."`
@@ -243,6 +252,11 @@ var DefaultLDAPAuthenticationBackendConfigurationImplementationCustom = Authenti
GroupName: ldapAttrCommonName,
},
Timeout: time.Second * 5,
+ Pooling: AuthenticationBackendLDAPPooling{
+ Count: 5,
+ Retries: 2,
+ Timeout: time.Second * 10,
+ },
TLS: &TLS{
MinimumVersion: TLSVersion{tls.VersionTLS12},
},
diff --git a/internal/configuration/schema/keys.go b/internal/configuration/schema/keys.go
index b065409ae..f2efaca93 100644
--- a/internal/configuration/schema/keys.go
+++ b/internal/configuration/schema/keys.go
@@ -197,6 +197,10 @@ var Keys = []string{
"authentication_backend.ldap.tls.server_name",
"authentication_backend.ldap.tls.private_key",
"authentication_backend.ldap.tls.certificate_chain",
+ "authentication_backend.ldap.pooling.enable",
+ "authentication_backend.ldap.pooling.count",
+ "authentication_backend.ldap.pooling.retries",
+ "authentication_backend.ldap.pooling.timeout",
"authentication_backend.ldap.base_dn",
"authentication_backend.ldap.additional_users_dn",
"authentication_backend.ldap.users_filter",
diff --git a/internal/configuration/validator/authentication.go b/internal/configuration/validator/authentication.go
index e53c7695d..c0dde8a26 100644
--- a/internal/configuration/validator/authentication.go
+++ b/internal/configuration/validator/authentication.go
@@ -349,6 +349,20 @@ func validateLDAPAuthenticationBackend(config *schema.AuthenticationBackend, val
validator.Push(fmt.Errorf(errFmtLDAPAuthBackendTLSConfigInvalid, err))
}
+ if config.LDAP.Pooling.Enable {
+ if config.LDAP.Pooling.Count < 1 {
+ config.LDAP.Pooling.Count = schema.DefaultLDAPAuthenticationBackendConfigurationImplementationCustom.Pooling.Count
+ }
+
+ if config.LDAP.Pooling.Retries < 1 {
+ config.LDAP.Pooling.Retries = schema.DefaultLDAPAuthenticationBackendConfigurationImplementationCustom.Pooling.Retries
+ }
+
+ if config.LDAP.Pooling.Timeout < 1 {
+ config.LDAP.Pooling.Timeout = schema.DefaultLDAPAuthenticationBackendConfigurationImplementationCustom.Pooling.Timeout
+ }
+ }
+
if strings.Contains(config.LDAP.UsersFilter, "{0}") {
validator.Push(fmt.Errorf(errFmtLDAPAuthBackendFilterReplacedPlaceholders, "users_filter", "{0}", "{input}"))
}
diff --git a/internal/configuration/validator/authentication_test.go b/internal/configuration/validator/authentication_test.go
index c1ee3fe14..1fe5e2937 100644
--- a/internal/configuration/validator/authentication_test.go
+++ b/internal/configuration/validator/authentication_test.go
@@ -608,9 +608,22 @@ func (suite *LDAPAuthenticationBackendSuite) TestShouldValidateDefaultImplementa
suite.Equal(schema.LDAPImplementationCustom, suite.config.LDAP.Implementation)
- suite.Equal(suite.config.LDAP.Attributes.Username, schema.DefaultLDAPAuthenticationBackendConfigurationImplementationCustom.Attributes.Username)
+ suite.Equal(schema.DefaultLDAPAuthenticationBackendConfigurationImplementationCustom.Attributes.Username, suite.config.LDAP.Attributes.Username)
suite.Len(suite.validator.Warnings(), 0)
suite.Len(suite.validator.Errors(), 0)
+
+ suite.Equal(0, suite.config.LDAP.Pooling.Retries)
+ suite.Equal(0, suite.config.LDAP.Pooling.Count)
+ suite.Equal(time.Duration(0), suite.config.LDAP.Pooling.Timeout)
+}
+
+func (suite *LDAPAuthenticationBackendSuite) TestShouldValidateDefaultPooling() {
+ suite.config.LDAP.Pooling.Enable = true
+ ValidateAuthenticationBackend(&suite.config, suite.validator)
+
+ suite.Equal(schema.DefaultLDAPAuthenticationBackendConfigurationImplementationCustom.Pooling.Retries, suite.config.LDAP.Pooling.Retries)
+ suite.Equal(schema.DefaultLDAPAuthenticationBackendConfigurationImplementationCustom.Pooling.Count, suite.config.LDAP.Pooling.Count)
+ suite.Equal(schema.DefaultLDAPAuthenticationBackendConfigurationImplementationCustom.Pooling.Timeout, suite.config.LDAP.Pooling.Timeout)
}
func (suite *LDAPAuthenticationBackendSuite) TestShouldRaiseErrorWhenImplementationIsInvalidMSAD() {
diff --git a/internal/mocks/gen.go b/internal/mocks/gen.go
index f7cab1b14..46c9446d2 100644
--- a/internal/mocks/gen.go
+++ b/internal/mocks/gen.go
@@ -10,7 +10,9 @@ package mocks
//go:generate mockgen -package mocks -destination duo_api.go -mock_names API=MockAPI github.com/authelia/authelia/v4/internal/duo API
//go:generate mockgen -package mocks -destination random.go -mock_names Provider=MockRandom github.com/authelia/authelia/v4/internal/random Provider
-// Fosite Mocks.
+// External Mocks.
+
+// Mocks for authelia.com/provider/oauth2.
//go:generate mockgen -package mocks -destination oauth2_client_credentials_grant_storage.go -mock_names Provider=MockClientCredentialsGrantStorage authelia.com/provider/oauth2/handler/oauth2 ClientCredentialsGrantStorage
//go:generate mockgen -package mocks -destination oauth2_token_revocation_storage.go -mock_names Provider=MockTokenRevocationStorage authelia.com/provider/oauth2/handler/oauth2 TokenRevocationStorage
//go:generate mockgen -package mocks -destination oauth2_access_token_strategy.go -mock_names Provider=MockAccessTokenStrategy authelia.com/provider/oauth2/handler/oauth2 AccessTokenStrategy
diff --git a/internal/mocks/user_provider.go b/internal/mocks/user_provider.go
index 81fa53483..b235d80b7 100644
--- a/internal/mocks/user_provider.go
+++ b/internal/mocks/user_provider.go
@@ -85,6 +85,20 @@ func (mr *MockUserProviderMockRecorder) GetDetailsExtended(username any) *gomock
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDetailsExtended", reflect.TypeOf((*MockUserProvider)(nil).GetDetailsExtended), username)
}
+// Shutdown mocks base method.
+func (m *MockUserProvider) Shutdown() error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "Shutdown")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// Shutdown indicates an expected call of Shutdown.
+func (mr *MockUserProviderMockRecorder) Shutdown() *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Shutdown", reflect.TypeOf((*MockUserProvider)(nil).Shutdown))
+}
+
// StartupCheck mocks base method.
func (m *MockUserProvider) StartupCheck() error {
m.ctrl.T.Helper()
diff --git a/internal/suites/ActiveDirectory/configuration.yml b/internal/suites/ActiveDirectory/configuration.yml
index eb5ae0359..657bacc2c 100644
--- a/internal/suites/ActiveDirectory/configuration.yml
+++ b/internal/suites/ActiveDirectory/configuration.yml
@@ -43,6 +43,11 @@ session:
authentication_backend:
ldap:
address: 'ldap://sambaldap'
+ pooling:
+ enable: true
+ count: 4
+ retries: 3
+ timeout: 10s
implementation: 'activedirectory'
tls:
skip_verify: true
diff --git a/internal/suites/LDAP/configuration.yml b/internal/suites/LDAP/configuration.yml
index a96976996..72876c0b5 100644
--- a/internal/suites/LDAP/configuration.yml
+++ b/internal/suites/LDAP/configuration.yml
@@ -43,6 +43,11 @@ session:
authentication_backend:
ldap:
address: 'ldaps://openldap'
+ pooling:
+ enable: true
+ count: 4
+ retries: 3
+ timeout: 10s
tls:
skip_verify: true
base_dn: 'dc=example,dc=com'
diff --git a/internal/utils/crypto.go b/internal/utils/crypto.go
index 884aac5a2..9493ade5b 100644
--- a/internal/utils/crypto.go
+++ b/internal/utils/crypto.go
@@ -314,6 +314,10 @@ func IsX509PrivateKey(i any) bool {
// NewTLSConfig generates a tls.Config from a schema.TLS and a x509.CertPool.
func NewTLSConfig(config *schema.TLS, rootCAs *x509.CertPool) (tlsConfig *tls.Config) {
+ if config == nil {
+ return nil
+ }
+
var certificates []tls.Certificate
if config.PrivateKey != nil && config.CertificateChain.HasCertificates() {