grafana/pkg/services/ldap/service/ldap.go
Jo d4cfbd9fd3
LDAP: Move LDAP globals to Config (#63255)
* structure dtos and private methods

* add basic LDAP service

* use LDAP service in ldap debug API

* lower non fatal error

* remove unused globals

* wip

* remove final globals

* fix tests to use cfg enabled

* restructure errors

* remove logger from globals

* use ldap service in authn

* use ldap service in context handler

* fix failed tests

* fix ldap middleware provides

* fix provides in auth_test.go
2023-02-10 19:01:55 +01:00

123 lines
2.5 KiB
Go

package service
import (
"errors"
"sync"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/ldap"
"github.com/grafana/grafana/pkg/services/ldap/multildap"
"github.com/grafana/grafana/pkg/services/login"
"github.com/grafana/grafana/pkg/setting"
)
var (
ErrUnableToCreateLDAPClient = errors.New("unable to create LDAP client")
ErrLDAPNotEnabled = errors.New("LDAP not enabled")
)
// LDAP is the interface for the LDAP service.
type LDAP interface {
ReloadConfig() error
Config() *ldap.Config
Client() multildap.IMultiLDAP
// Login authenticates the user against the LDAP server.
Login(query *login.LoginUserQuery) (*login.ExternalUserInfo, error)
// User searches for a user in the LDAP server.
User(username string) (*login.ExternalUserInfo, error)
}
type LDAPImpl struct {
client multildap.IMultiLDAP
cfg *setting.Cfg
ldapCfg *ldap.Config
log log.Logger
// loadingMutex locks the reading of the config so multiple requests for reloading are sequential.
loadingMutex *sync.Mutex
}
func ProvideService(cfg *setting.Cfg) *LDAPImpl {
s := &LDAPImpl{
client: nil,
ldapCfg: nil,
cfg: cfg,
log: log.New("ldap.service"),
loadingMutex: &sync.Mutex{},
}
if !cfg.LDAPEnabled {
return s
}
ldapCfg, err := multildap.GetConfig(s.cfg)
if err != nil {
s.log.Error("Failed to get LDAP config", "error", err)
} else {
s.ldapCfg = ldapCfg
s.client = multildap.New(s.ldapCfg.Servers, s.cfg)
}
return s
}
func (s *LDAPImpl) ReloadConfig() error {
if !s.cfg.LDAPEnabled {
return nil
}
s.loadingMutex.Lock()
defer s.loadingMutex.Unlock()
config, err := readConfig(s.cfg.LDAPConfigFilePath)
if err != nil {
return err
}
client := multildap.New(config.Servers, s.cfg)
if client == nil {
return ErrUnableToCreateLDAPClient
}
s.ldapCfg = config
s.client = client
return nil
}
func (s *LDAPImpl) Client() multildap.IMultiLDAP {
return s.client
}
func (s *LDAPImpl) Config() *ldap.Config {
return s.ldapCfg
}
func (s *LDAPImpl) Login(query *login.LoginUserQuery) (*login.ExternalUserInfo, error) {
if !s.cfg.LDAPEnabled {
return nil, ErrLDAPNotEnabled
}
client := s.Client()
if client == nil {
return nil, ErrUnableToCreateLDAPClient
}
return client.Login(query)
}
func (s *LDAPImpl) User(username string) (*login.ExternalUserInfo, error) {
if !s.cfg.LDAPEnabled {
return nil, ErrLDAPNotEnabled
}
client := s.Client()
if client == nil {
return nil, ErrUnableToCreateLDAPClient
}
user, _, err := client.User(username)
return user, err
}