Skip to content

Commit

Permalink
Multi-LDAP: Do not fail-fast on invalid credentials (grafana#19261)
Browse files Browse the repository at this point in the history
* Multi-LDAP: Do not fail-fast on invalid credentials

When configuring LDAP authentication, it is very common to have multiple
servers configured. When using user bind (authenticating with LDAP using
the same credentials as the user authenticating to Grafana) we don't
expect all the users to be on all LDAP servers.

Because of this use-case, we should not fail-fast when authenticating on
multiple LDAP server configurations. Instead, we should continue to try
the credentials with the next LDAP server configured.

Fixes grafana#19066
  • Loading branch information
gotjosh authored Sep 23, 2019
1 parent feb6bc6 commit 279249e
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 5 deletions.
34 changes: 29 additions & 5 deletions pkg/services/multildap/multildap.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ package multildap
import (
"errors"

"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/ldap"
)

// logger to log
var logger = log.New("ldap")

// GetConfig gets LDAP config
var GetConfig = ldap.GetConfig

Expand Down Expand Up @@ -119,12 +123,18 @@ func (multiples *MultiLDAP) Login(query *models.LoginUserQuery) (
return user, nil
}

// Continue if we couldn't find the user
if err == ErrCouldNotFindUser {
continue
}

if err != nil {

if isSilentError(err) {
logger.Debug(
"unable to login with LDAP - skipping server",
"host", config.Host,
"port", config.Port,
"error", err,
)
continue
}

return nil, err
}
}
Expand Down Expand Up @@ -204,3 +214,17 @@ func (multiples *MultiLDAP) Users(logins []string) (

return result, nil
}

// isSilentError evaluates an error and tells whenever we should fail the LDAP request
// immediately or if we should continue into other LDAP servers
func isSilentError(err error) bool {
continueErrs := []error{ErrInvalidCredentials, ErrCouldNotFindUser}

for _, cerr := range continueErrs {
if err == cerr {
return true
}
}

return false
}
19 changes: 19 additions & 0 deletions pkg/services/multildap/multildap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,25 @@ func TestMultiLDAP(t *testing.T) {
teardown()
})

Convey("Should still try to auth with the second server after receiving an invalid credentials error from the first", func() {
mock := setup()

mock.loginErrReturn = ErrInvalidCredentials

multi := New([]*ldap.ServerConfig{
{}, {},
})
_, err := multi.Login(&models.LoginUserQuery{})

So(mock.dialCalledTimes, ShouldEqual, 2)
So(mock.loginCalledTimes, ShouldEqual, 2)
So(mock.closeCalledTimes, ShouldEqual, 2)

So(err, ShouldEqual, ErrInvalidCredentials)

teardown()
})

Convey("Should return unknown error", func() {
mock := setup()

Expand Down

0 comments on commit 279249e

Please sign in to comment.