mirror of
https://github.com/grafana/grafana.git
synced 2025-02-20 11:48:34 -06:00
LDAP: Adds bind before searching LDAP for non-login cases. (#18023)
This commit is contained in:
parent
5f0a7f43c3
commit
5d3a60d46e
@ -31,7 +31,8 @@ type IConnection interface {
|
||||
type IServer interface {
|
||||
Login(*models.LoginUserQuery) (*models.ExternalUserInfo, error)
|
||||
Users([]string) ([]*models.ExternalUserInfo, error)
|
||||
Auth(string, string) error
|
||||
Bind() error
|
||||
UserBind(string, string) error
|
||||
Dial() error
|
||||
Close()
|
||||
}
|
||||
@ -43,6 +44,23 @@ type Server struct {
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
// Bind authenticates the connection with the LDAP server
|
||||
// - with the username and password setup in the config
|
||||
// - or, anonymously
|
||||
func (server *Server) Bind() error {
|
||||
if server.shouldAuthAdmin() {
|
||||
if err := server.AuthAdmin(); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err := server.Connection.UnauthenticatedBind(server.Config.BindDN)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UsersMaxRequest is a max amount of users we can request via Users().
|
||||
// Since many LDAP servers has limitations
|
||||
// on how much items can we return in one request
|
||||
@ -149,7 +167,7 @@ func (server *Server) Login(query *models.LoginUserQuery) (
|
||||
}
|
||||
} else if server.shouldSingleBind() {
|
||||
authAndBind = true
|
||||
err = server.Auth(server.singleBindDN(query.Username), query.Password)
|
||||
err = server.UserBind(server.singleBindDN(query.Username), query.Password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -179,7 +197,7 @@ func (server *Server) Login(query *models.LoginUserQuery) (
|
||||
|
||||
if !authAndBind {
|
||||
// Authenticate user
|
||||
err = server.Auth(user.AuthId, query.Password)
|
||||
err = server.UserBind(user.AuthId, query.Password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -380,9 +398,9 @@ func (server *Server) shouldAuthAdmin() bool {
|
||||
return server.Config.BindPassword != ""
|
||||
}
|
||||
|
||||
// Auth authentificates user in LDAP
|
||||
func (server *Server) Auth(username, password string) error {
|
||||
err := server.auth(username, password)
|
||||
// UserBind authenticates the connection with the LDAP server
|
||||
func (server *Server) UserBind(username, password string) error {
|
||||
err := server.userBind(username, password)
|
||||
if err != nil {
|
||||
server.log.Error(
|
||||
fmt.Sprintf("Cannot authentificate user %s in LDAP", username),
|
||||
@ -397,7 +415,7 @@ func (server *Server) Auth(username, password string) error {
|
||||
|
||||
// AuthAdmin authentificates LDAP admin user
|
||||
func (server *Server) AuthAdmin() error {
|
||||
err := server.auth(server.Config.BindDN, server.Config.BindPassword)
|
||||
err := server.userBind(server.Config.BindDN, server.Config.BindPassword)
|
||||
if err != nil {
|
||||
server.log.Error(
|
||||
"Cannot authentificate admin user in LDAP",
|
||||
@ -410,8 +428,8 @@ func (server *Server) AuthAdmin() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// auth is helper for several types of LDAP authentification
|
||||
func (server *Server) auth(path, password string) error {
|
||||
// userBind authenticates the connection with the LDAP server
|
||||
func (server *Server) userBind(path, password string) error {
|
||||
err := server.Connection.Bind(path, password)
|
||||
if err != nil {
|
||||
if ldapErr, ok := err.(*ldap.Error); ok {
|
||||
|
@ -19,7 +19,7 @@ func TestLDAPLogin(t *testing.T) {
|
||||
}
|
||||
|
||||
Convey("Login()", t, func() {
|
||||
Convey("Should get invalid credentials when auth fails", func() {
|
||||
Convey("Should get invalid credentials when userBind fails", func() {
|
||||
connection := &MockConnection{}
|
||||
entry := ldap.Entry{}
|
||||
result := ldap.SearchResult{Entries: []*ldap.Entry{&entry}}
|
||||
|
@ -145,7 +145,7 @@ func TestLDAPPrivateMethods(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("shouldAuthAdmin()", t, func() {
|
||||
Convey("it should require admin auth", func() {
|
||||
Convey("it should require admin userBind", func() {
|
||||
server := &Server{
|
||||
Config: &ServerConfig{
|
||||
BindPassword: "test",
|
||||
@ -156,7 +156,7 @@ func TestLDAPPrivateMethods(t *testing.T) {
|
||||
So(result, ShouldBeTrue)
|
||||
})
|
||||
|
||||
Convey("it should not require admin auth", func() {
|
||||
Convey("it should not require admin userBind", func() {
|
||||
server := &Server{
|
||||
Config: &ServerConfig{
|
||||
BindPassword: "",
|
||||
|
@ -102,7 +102,7 @@ func TestPublicAPI(t *testing.T) {
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Auth()", t, func() {
|
||||
Convey("UserBind()", t, func() {
|
||||
Convey("Should use provided DN and password", func() {
|
||||
connection := &MockConnection{}
|
||||
var actualUsername, actualPassword string
|
||||
@ -119,7 +119,7 @@ func TestPublicAPI(t *testing.T) {
|
||||
}
|
||||
|
||||
dn := "cn=user,ou=users,dc=grafana,dc=org"
|
||||
err := server.Auth(dn, "pwd")
|
||||
err := server.UserBind(dn, "pwd")
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(actualUsername, ShouldEqual, dn)
|
||||
@ -141,7 +141,7 @@ func TestPublicAPI(t *testing.T) {
|
||||
},
|
||||
log: log.New("test-logger"),
|
||||
}
|
||||
err := server.Auth("user", "pwd")
|
||||
err := server.UserBind("user", "pwd")
|
||||
So(err, ShouldEqual, expected)
|
||||
})
|
||||
})
|
||||
|
@ -109,6 +109,10 @@ func (multiples *MultiLDAP) User(login string) (
|
||||
|
||||
defer server.Close()
|
||||
|
||||
if err := server.Bind(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
users, err := server.Users(search)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -142,6 +146,10 @@ func (multiples *MultiLDAP) Users(logins []string) (
|
||||
|
||||
defer server.Close()
|
||||
|
||||
if err := server.Bind(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
users, err := server.Users(logins)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -11,12 +11,15 @@ type MockLDAP struct {
|
||||
loginCalledTimes int
|
||||
closeCalledTimes int
|
||||
usersCalledTimes int
|
||||
bindCalledTimes int
|
||||
|
||||
dialErrReturn error
|
||||
|
||||
loginErrReturn error
|
||||
loginReturn *models.ExternalUserInfo
|
||||
|
||||
bindErrReturn error
|
||||
|
||||
usersErrReturn error
|
||||
usersFirstReturn []*models.ExternalUserInfo
|
||||
usersRestReturn []*models.ExternalUserInfo
|
||||
@ -40,8 +43,8 @@ func (mock *MockLDAP) Users([]string) ([]*models.ExternalUserInfo, error) {
|
||||
return mock.usersRestReturn, mock.usersErrReturn
|
||||
}
|
||||
|
||||
// Auth test fn
|
||||
func (mock *MockLDAP) Auth(string, string) error {
|
||||
// UserBind test fn
|
||||
func (mock *MockLDAP) UserBind(string, string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -56,6 +59,11 @@ func (mock *MockLDAP) Close() {
|
||||
mock.closeCalledTimes = mock.closeCalledTimes + 1
|
||||
}
|
||||
|
||||
func (mock *MockLDAP) Bind() error {
|
||||
mock.bindCalledTimes++
|
||||
return mock.bindErrReturn
|
||||
}
|
||||
|
||||
// MockMultiLDAP represents testing struct for multildap testing
|
||||
type MockMultiLDAP struct {
|
||||
LoginCalledTimes int
|
||||
|
Loading…
Reference in New Issue
Block a user