Commit cce55571 by Jon Gyllenswärd Committed by GitHub

LDAP: All LDAP servers should be tried even if one of them returns a connection error (#20077)

All ldap servers are now being tried and the first one that gives back an answer is used if a previous one is failing. Applies to login and syncing
parent 5210a8f2
...@@ -109,11 +109,17 @@ func (multiples *MultiLDAP) Login(query *models.LoginUserQuery) ( ...@@ -109,11 +109,17 @@ func (multiples *MultiLDAP) Login(query *models.LoginUserQuery) (
return nil, ErrNoLDAPServers return nil, ErrNoLDAPServers
} }
for _, config := range multiples.configs { for index, config := range multiples.configs {
server := newLDAP(config) server := newLDAP(config)
if err := server.Dial(); err != nil { if err := server.Dial(); err != nil {
return nil, err logDialFailure(err, config)
// Only return an error if it is the last server so we can try next server
if index == len(multiples.configs)-1 {
return nil, err
}
continue
} }
defer server.Close() defer server.Close()
...@@ -155,11 +161,17 @@ func (multiples *MultiLDAP) User(login string) ( ...@@ -155,11 +161,17 @@ func (multiples *MultiLDAP) User(login string) (
} }
search := []string{login} search := []string{login}
for _, config := range multiples.configs { for index, config := range multiples.configs {
server := newLDAP(config) server := newLDAP(config)
if err := server.Dial(); err != nil { if err := server.Dial(); err != nil {
return nil, *config, err logDialFailure(err, config)
// Only return an error if it is the last server so we can try next server
if index == len(multiples.configs)-1 {
return nil, *config, err
}
continue
} }
defer server.Close() defer server.Close()
...@@ -192,11 +204,17 @@ func (multiples *MultiLDAP) Users(logins []string) ( ...@@ -192,11 +204,17 @@ func (multiples *MultiLDAP) Users(logins []string) (
return nil, ErrNoLDAPServers return nil, ErrNoLDAPServers
} }
for _, config := range multiples.configs { for index, config := range multiples.configs {
server := newLDAP(config) server := newLDAP(config)
if err := server.Dial(); err != nil { if err := server.Dial(); err != nil {
return nil, err logDialFailure(err, config)
// Only return an error if it is the last server so we can try next server
if index == len(multiples.configs)-1 {
return nil, err
}
continue
} }
defer server.Close() defer server.Close()
...@@ -228,3 +246,12 @@ func isSilentError(err error) bool { ...@@ -228,3 +246,12 @@ func isSilentError(err error) bool {
return false return false
} }
func logDialFailure(err error, config *ldap.ServerConfig) {
logger.Debug(
"unable to dial LDAP server",
"host", config.Host,
"port", config.Port,
"error", err,
)
}
...@@ -171,6 +171,24 @@ func TestMultiLDAP(t *testing.T) { ...@@ -171,6 +171,24 @@ func TestMultiLDAP(t *testing.T) {
teardown() teardown()
}) })
Convey("Should still try to auth with the second server after receiving a dial error from the first", func() {
mock := setup()
expectedError := errors.New("Dial error")
mock.dialErrReturn = expectedError
multi := New([]*ldap.ServerConfig{
{}, {},
})
_, err := multi.Login(&models.LoginUserQuery{})
So(mock.dialCalledTimes, ShouldEqual, 2)
So(err, ShouldEqual, expectedError)
teardown()
})
Convey("Should return unknown error", func() { Convey("Should return unknown error", func() {
mock := setup() mock := setup()
...@@ -287,9 +305,42 @@ func TestMultiLDAP(t *testing.T) { ...@@ -287,9 +305,42 @@ func TestMultiLDAP(t *testing.T) {
teardown() teardown()
}) })
Convey("Should still try to auth with the second server after receiving a dial error from the first", func() {
mock := setup()
expectedError := errors.New("Dial error")
mock.dialErrReturn = expectedError
multi := New([]*ldap.ServerConfig{
{}, {},
})
_, _, err := multi.User("test")
So(mock.dialCalledTimes, ShouldEqual, 2)
So(err, ShouldEqual, expectedError)
teardown()
})
}) })
Convey("Users()", func() { Convey("Users()", func() {
Convey("Should still try to auth with the second server after receiving a dial error from the first", func() {
mock := setup()
expectedError := errors.New("Dial error")
mock.dialErrReturn = expectedError
multi := New([]*ldap.ServerConfig{
{}, {},
})
_, err := multi.Users([]string{"test"})
So(mock.dialCalledTimes, ShouldEqual, 2)
So(err, ShouldEqual, expectedError)
teardown()
})
Convey("Should return error for absent config list", func() { Convey("Should return error for absent config list", func() {
setup() setup()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment