mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
parent
b17967e001
commit
2316414786
@ -22,6 +22,9 @@ var ErrNoLDAPServers = errors.New("No LDAP servers are configured")
|
||||
// ErrDidNotFindUser if request for user is unsuccessful
|
||||
var ErrDidNotFindUser = errors.New("Did not find a user")
|
||||
|
||||
// newLDAP return instance of the single LDAP server
|
||||
var newLDAP = ldap.New
|
||||
|
||||
// IMultiLDAP is interface for MultiLDAP
|
||||
type IMultiLDAP interface {
|
||||
Login(query *models.LoginUserQuery) (
|
||||
@ -53,12 +56,13 @@ func New(configs []*ldap.ServerConfig) IMultiLDAP {
|
||||
func (multiples *MultiLDAP) Login(query *models.LoginUserQuery) (
|
||||
*models.ExternalUserInfo, error,
|
||||
) {
|
||||
|
||||
if len(multiples.configs) == 0 {
|
||||
return nil, ErrNoLDAPServers
|
||||
}
|
||||
|
||||
for _, config := range multiples.configs {
|
||||
server := ldap.New(config)
|
||||
server := newLDAP(config)
|
||||
|
||||
if err := server.Dial(); err != nil {
|
||||
return nil, err
|
||||
@ -67,7 +71,6 @@ func (multiples *MultiLDAP) Login(query *models.LoginUserQuery) (
|
||||
defer server.Close()
|
||||
|
||||
user, err := server.Login(query)
|
||||
|
||||
if user != nil {
|
||||
return user, nil
|
||||
}
|
||||
@ -80,8 +83,6 @@ func (multiples *MultiLDAP) Login(query *models.LoginUserQuery) (
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// Return invalid credentials if we couldn't find the user anywhere
|
||||
@ -100,7 +101,7 @@ func (multiples *MultiLDAP) User(login string) (
|
||||
|
||||
search := []string{login}
|
||||
for _, config := range multiples.configs {
|
||||
server := ldap.New(config)
|
||||
server := newLDAP(config)
|
||||
|
||||
if err := server.Dial(); err != nil {
|
||||
return nil, err
|
||||
@ -133,7 +134,7 @@ func (multiples *MultiLDAP) Users(logins []string) (
|
||||
}
|
||||
|
||||
for _, config := range multiples.configs {
|
||||
server := ldap.New(config)
|
||||
server := newLDAP(config)
|
||||
|
||||
if err := server.Dial(); err != nil {
|
||||
return nil, err
|
||||
|
327
pkg/services/multildap/multildap_test.go
Normal file
327
pkg/services/multildap/multildap_test.go
Normal file
@ -0,0 +1,327 @@
|
||||
package multildap
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/ldap"
|
||||
)
|
||||
|
||||
func TestMultiLDAP(t *testing.T) {
|
||||
Convey("Multildap", t, func() {
|
||||
Convey("Login()", func() {
|
||||
Convey("Should return error for absent config list", func() {
|
||||
setup()
|
||||
|
||||
multi := New([]*ldap.ServerConfig{})
|
||||
_, err := multi.Login(&models.LoginUserQuery{})
|
||||
|
||||
So(err, ShouldBeError)
|
||||
So(err, ShouldEqual, ErrNoLDAPServers)
|
||||
|
||||
teardown()
|
||||
})
|
||||
|
||||
Convey("Should return a dial error", func() {
|
||||
mock := setup()
|
||||
|
||||
expected := errors.New("Dial error")
|
||||
mock.dialErrReturn = expected
|
||||
|
||||
multi := New([]*ldap.ServerConfig{
|
||||
{}, {},
|
||||
})
|
||||
|
||||
_, err := multi.Login(&models.LoginUserQuery{})
|
||||
|
||||
So(err, ShouldBeError)
|
||||
So(err, ShouldEqual, expected)
|
||||
|
||||
teardown()
|
||||
})
|
||||
|
||||
Convey("Should call underlying LDAP methods", func() {
|
||||
mock := setup()
|
||||
|
||||
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 get login result", func() {
|
||||
mock := setup()
|
||||
|
||||
mock.loginReturn = &models.ExternalUserInfo{
|
||||
Login: "killa",
|
||||
}
|
||||
|
||||
multi := New([]*ldap.ServerConfig{
|
||||
{}, {},
|
||||
})
|
||||
result, err := multi.Login(&models.LoginUserQuery{})
|
||||
|
||||
So(mock.dialCalledTimes, ShouldEqual, 1)
|
||||
So(mock.loginCalledTimes, ShouldEqual, 1)
|
||||
So(mock.closeCalledTimes, ShouldEqual, 1)
|
||||
|
||||
So(result.Login, ShouldEqual, "killa")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
teardown()
|
||||
})
|
||||
|
||||
Convey("Should still call a second error for invalid cred error", 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()
|
||||
|
||||
expected := errors.New("Something unknown")
|
||||
mock.loginErrReturn = expected
|
||||
|
||||
multi := New([]*ldap.ServerConfig{
|
||||
{}, {},
|
||||
})
|
||||
_, err := multi.Login(&models.LoginUserQuery{})
|
||||
|
||||
So(mock.dialCalledTimes, ShouldEqual, 1)
|
||||
So(mock.loginCalledTimes, ShouldEqual, 1)
|
||||
So(mock.closeCalledTimes, ShouldEqual, 1)
|
||||
|
||||
So(err, ShouldEqual, expected)
|
||||
|
||||
teardown()
|
||||
})
|
||||
})
|
||||
|
||||
Convey("User()", func() {
|
||||
Convey("Should return error for absent config list", func() {
|
||||
setup()
|
||||
|
||||
multi := New([]*ldap.ServerConfig{})
|
||||
_, err := multi.User("test")
|
||||
|
||||
So(err, ShouldBeError)
|
||||
So(err, ShouldEqual, ErrNoLDAPServers)
|
||||
|
||||
teardown()
|
||||
})
|
||||
|
||||
Convey("Should return a dial error", func() {
|
||||
mock := setup()
|
||||
|
||||
expected := errors.New("Dial error")
|
||||
mock.dialErrReturn = expected
|
||||
|
||||
multi := New([]*ldap.ServerConfig{
|
||||
{}, {},
|
||||
})
|
||||
|
||||
_, err := multi.User("test")
|
||||
|
||||
So(err, ShouldBeError)
|
||||
So(err, ShouldEqual, expected)
|
||||
|
||||
teardown()
|
||||
})
|
||||
|
||||
Convey("Should call underlying LDAP methods", func() {
|
||||
mock := setup()
|
||||
|
||||
multi := New([]*ldap.ServerConfig{
|
||||
{}, {},
|
||||
})
|
||||
_, err := multi.User("test")
|
||||
|
||||
So(mock.dialCalledTimes, ShouldEqual, 2)
|
||||
So(mock.usersCalledTimes, ShouldEqual, 2)
|
||||
So(mock.closeCalledTimes, ShouldEqual, 2)
|
||||
|
||||
So(err, ShouldEqual, ErrDidNotFindUser)
|
||||
|
||||
teardown()
|
||||
})
|
||||
|
||||
Convey("Should return some error", func() {
|
||||
mock := setup()
|
||||
|
||||
expected := errors.New("Killa Gorilla")
|
||||
mock.usersErrReturn = expected
|
||||
|
||||
multi := New([]*ldap.ServerConfig{
|
||||
{}, {},
|
||||
})
|
||||
_, err := multi.User("test")
|
||||
|
||||
So(mock.dialCalledTimes, ShouldEqual, 1)
|
||||
So(mock.usersCalledTimes, ShouldEqual, 1)
|
||||
So(mock.closeCalledTimes, ShouldEqual, 1)
|
||||
|
||||
So(err, ShouldEqual, expected)
|
||||
|
||||
teardown()
|
||||
})
|
||||
|
||||
Convey("Should get only one user", func() {
|
||||
mock := setup()
|
||||
|
||||
mock.usersFirstReturn = []*models.ExternalUserInfo{
|
||||
{
|
||||
Login: "one",
|
||||
},
|
||||
|
||||
{
|
||||
Login: "two",
|
||||
},
|
||||
}
|
||||
|
||||
multi := New([]*ldap.ServerConfig{
|
||||
{}, {},
|
||||
})
|
||||
user, err := multi.User("test")
|
||||
|
||||
So(mock.dialCalledTimes, ShouldEqual, 1)
|
||||
So(mock.usersCalledTimes, ShouldEqual, 1)
|
||||
So(mock.closeCalledTimes, ShouldEqual, 1)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(user.Login, ShouldEqual, "one")
|
||||
|
||||
teardown()
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Users()", func() {
|
||||
Convey("Should return error for absent config list", func() {
|
||||
setup()
|
||||
|
||||
multi := New([]*ldap.ServerConfig{})
|
||||
_, err := multi.Users([]string{"test"})
|
||||
|
||||
So(err, ShouldBeError)
|
||||
So(err, ShouldEqual, ErrNoLDAPServers)
|
||||
|
||||
teardown()
|
||||
})
|
||||
|
||||
Convey("Should return a dial error", func() {
|
||||
mock := setup()
|
||||
|
||||
expected := errors.New("Dial error")
|
||||
mock.dialErrReturn = expected
|
||||
|
||||
multi := New([]*ldap.ServerConfig{
|
||||
{}, {},
|
||||
})
|
||||
|
||||
_, err := multi.Users([]string{"test"})
|
||||
|
||||
So(err, ShouldBeError)
|
||||
So(err, ShouldEqual, expected)
|
||||
|
||||
teardown()
|
||||
})
|
||||
|
||||
Convey("Should call underlying LDAP methods", func() {
|
||||
mock := setup()
|
||||
|
||||
multi := New([]*ldap.ServerConfig{
|
||||
{}, {},
|
||||
})
|
||||
_, err := multi.Users([]string{"test"})
|
||||
|
||||
So(mock.dialCalledTimes, ShouldEqual, 2)
|
||||
So(mock.usersCalledTimes, ShouldEqual, 2)
|
||||
So(mock.closeCalledTimes, ShouldEqual, 2)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
teardown()
|
||||
})
|
||||
|
||||
Convey("Should return some error", func() {
|
||||
mock := setup()
|
||||
|
||||
expected := errors.New("Killa Gorilla")
|
||||
mock.usersErrReturn = expected
|
||||
|
||||
multi := New([]*ldap.ServerConfig{
|
||||
{}, {},
|
||||
})
|
||||
_, err := multi.Users([]string{"test"})
|
||||
|
||||
So(mock.dialCalledTimes, ShouldEqual, 1)
|
||||
So(mock.usersCalledTimes, ShouldEqual, 1)
|
||||
So(mock.closeCalledTimes, ShouldEqual, 1)
|
||||
|
||||
So(err, ShouldEqual, expected)
|
||||
|
||||
teardown()
|
||||
})
|
||||
|
||||
Convey("Should get users", func() {
|
||||
mock := setup()
|
||||
|
||||
mock.usersFirstReturn = []*models.ExternalUserInfo{
|
||||
{
|
||||
Login: "one",
|
||||
},
|
||||
|
||||
{
|
||||
Login: "two",
|
||||
},
|
||||
}
|
||||
|
||||
mock.usersRestReturn = []*models.ExternalUserInfo{
|
||||
{
|
||||
Login: "three",
|
||||
},
|
||||
}
|
||||
|
||||
multi := New([]*ldap.ServerConfig{
|
||||
{}, {},
|
||||
})
|
||||
users, err := multi.Users([]string{"test"})
|
||||
|
||||
So(mock.dialCalledTimes, ShouldEqual, 2)
|
||||
So(mock.usersCalledTimes, ShouldEqual, 2)
|
||||
So(mock.closeCalledTimes, ShouldEqual, 2)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(users[0].Login, ShouldEqual, "one")
|
||||
So(users[1].Login, ShouldEqual, "two")
|
||||
So(users[2].Login, ShouldEqual, "three")
|
||||
|
||||
teardown()
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
61
pkg/services/multildap/test.go
Normal file
61
pkg/services/multildap/test.go
Normal file
@ -0,0 +1,61 @@
|
||||
package multildap
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/ldap"
|
||||
)
|
||||
|
||||
type mockLDAP struct {
|
||||
dialCalledTimes int
|
||||
loginCalledTimes int
|
||||
closeCalledTimes int
|
||||
usersCalledTimes int
|
||||
|
||||
dialErrReturn error
|
||||
|
||||
loginErrReturn error
|
||||
loginReturn *models.ExternalUserInfo
|
||||
|
||||
usersErrReturn error
|
||||
usersFirstReturn []*models.ExternalUserInfo
|
||||
usersRestReturn []*models.ExternalUserInfo
|
||||
}
|
||||
|
||||
func (mock *mockLDAP) Login(*models.LoginUserQuery) (*models.ExternalUserInfo, error) {
|
||||
|
||||
mock.loginCalledTimes = mock.loginCalledTimes + 1
|
||||
return mock.loginReturn, mock.loginErrReturn
|
||||
}
|
||||
func (mock *mockLDAP) Users([]string) ([]*models.ExternalUserInfo, error) {
|
||||
mock.usersCalledTimes = mock.usersCalledTimes + 1
|
||||
|
||||
if mock.usersCalledTimes == 1 {
|
||||
return mock.usersFirstReturn, mock.usersErrReturn
|
||||
}
|
||||
|
||||
return mock.usersRestReturn, mock.usersErrReturn
|
||||
}
|
||||
func (mock *mockLDAP) InitialBind(string, string) error {
|
||||
return nil
|
||||
}
|
||||
func (mock *mockLDAP) Dial() error {
|
||||
mock.dialCalledTimes = mock.dialCalledTimes + 1
|
||||
return mock.dialErrReturn
|
||||
}
|
||||
func (mock *mockLDAP) Close() {
|
||||
mock.closeCalledTimes = mock.closeCalledTimes + 1
|
||||
}
|
||||
|
||||
func setup() *mockLDAP {
|
||||
mock := &mockLDAP{}
|
||||
|
||||
newLDAP = func(config *ldap.ServerConfig) ldap.IServer {
|
||||
return mock
|
||||
}
|
||||
|
||||
return mock
|
||||
}
|
||||
|
||||
func teardown() {
|
||||
newLDAP = ldap.New
|
||||
}
|
Loading…
Reference in New Issue
Block a user