2019-05-17 06:57:26 -05:00
|
|
|
package multildap
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
|
|
|
|
"github.com/grafana/grafana/pkg/models"
|
|
|
|
"github.com/grafana/grafana/pkg/services/ldap"
|
|
|
|
)
|
|
|
|
|
|
|
|
// GetConfig gets LDAP config
|
|
|
|
var GetConfig = ldap.GetConfig
|
|
|
|
|
|
|
|
// IsEnabled checks if LDAP is enabled
|
|
|
|
var IsEnabled = ldap.IsEnabled
|
|
|
|
|
|
|
|
// ErrInvalidCredentials is returned if username and password do not match
|
|
|
|
var ErrInvalidCredentials = ldap.ErrInvalidCredentials
|
|
|
|
|
|
|
|
// ErrNoLDAPServers is returned when there is no LDAP servers specified
|
|
|
|
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")
|
|
|
|
|
2019-06-07 07:16:00 -05:00
|
|
|
// newLDAP return instance of the single LDAP server
|
|
|
|
var newLDAP = ldap.New
|
|
|
|
|
2019-05-17 06:57:26 -05:00
|
|
|
// IMultiLDAP is interface for MultiLDAP
|
|
|
|
type IMultiLDAP interface {
|
|
|
|
Login(query *models.LoginUserQuery) (
|
|
|
|
*models.ExternalUserInfo, error,
|
|
|
|
)
|
|
|
|
|
|
|
|
Users(logins []string) (
|
|
|
|
[]*models.ExternalUserInfo, error,
|
|
|
|
)
|
|
|
|
|
|
|
|
User(login string) (
|
|
|
|
*models.ExternalUserInfo, error,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// MultiLDAP is basic struct of LDAP authorization
|
|
|
|
type MultiLDAP struct {
|
|
|
|
configs []*ldap.ServerConfig
|
|
|
|
}
|
|
|
|
|
|
|
|
// New creates the new LDAP auth
|
|
|
|
func New(configs []*ldap.ServerConfig) IMultiLDAP {
|
|
|
|
return &MultiLDAP{
|
|
|
|
configs: configs,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Login tries to log in the user in multiples LDAP
|
|
|
|
func (multiples *MultiLDAP) Login(query *models.LoginUserQuery) (
|
|
|
|
*models.ExternalUserInfo, error,
|
|
|
|
) {
|
2019-06-07 07:16:00 -05:00
|
|
|
|
2019-05-17 06:57:26 -05:00
|
|
|
if len(multiples.configs) == 0 {
|
|
|
|
return nil, ErrNoLDAPServers
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, config := range multiples.configs {
|
2019-06-07 07:16:00 -05:00
|
|
|
server := newLDAP(config)
|
2019-05-17 06:57:26 -05:00
|
|
|
|
|
|
|
if err := server.Dial(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
defer server.Close()
|
|
|
|
|
|
|
|
user, err := server.Login(query)
|
|
|
|
if user != nil {
|
|
|
|
return user, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Continue if we couldn't find the user
|
|
|
|
if err == ErrInvalidCredentials {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return invalid credentials if we couldn't find the user anywhere
|
|
|
|
return nil, ErrInvalidCredentials
|
|
|
|
}
|
|
|
|
|
|
|
|
// User gets a user by login
|
|
|
|
func (multiples *MultiLDAP) User(login string) (
|
|
|
|
*models.ExternalUserInfo,
|
|
|
|
error,
|
|
|
|
) {
|
|
|
|
|
|
|
|
if len(multiples.configs) == 0 {
|
|
|
|
return nil, ErrNoLDAPServers
|
|
|
|
}
|
|
|
|
|
|
|
|
search := []string{login}
|
|
|
|
for _, config := range multiples.configs {
|
2019-06-07 07:16:00 -05:00
|
|
|
server := newLDAP(config)
|
2019-05-17 06:57:26 -05:00
|
|
|
|
|
|
|
if err := server.Dial(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
defer server.Close()
|
|
|
|
|
|
|
|
users, err := server.Users(search)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(users) != 0 {
|
|
|
|
return users[0], nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, ErrDidNotFindUser
|
|
|
|
}
|
|
|
|
|
|
|
|
// Users gets users from multiple LDAP servers
|
|
|
|
func (multiples *MultiLDAP) Users(logins []string) (
|
|
|
|
[]*models.ExternalUserInfo,
|
|
|
|
error,
|
|
|
|
) {
|
|
|
|
var result []*models.ExternalUserInfo
|
|
|
|
|
|
|
|
if len(multiples.configs) == 0 {
|
|
|
|
return nil, ErrNoLDAPServers
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, config := range multiples.configs {
|
2019-06-07 07:16:00 -05:00
|
|
|
server := newLDAP(config)
|
2019-05-17 06:57:26 -05:00
|
|
|
|
|
|
|
if err := server.Dial(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
defer server.Close()
|
|
|
|
|
|
|
|
users, err := server.Users(logins)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
result = append(result, users...)
|
|
|
|
}
|
|
|
|
|
|
|
|
return result, nil
|
|
|
|
}
|