grafana/pkg/services/authn/clients/ldap.go
Karl Persson 180a587f70
AuthN: fetch final state of signed in user (#62854)
* AuthN: add a hook we can use to fetch final state of user
2023-02-03 14:14:38 +01:00

116 lines
3.0 KiB
Go

package clients
import (
"context"
"errors"
"github.com/grafana/grafana/pkg/services/authn"
"github.com/grafana/grafana/pkg/services/login"
"github.com/grafana/grafana/pkg/services/multildap"
"github.com/grafana/grafana/pkg/setting"
)
var _ authn.ProxyClient = new(LDAP)
var _ authn.PasswordClient = new(LDAP)
func ProvideLDAP(cfg *setting.Cfg) *LDAP {
return &LDAP{cfg, &ldapServiceImpl{cfg}}
}
type LDAP struct {
cfg *setting.Cfg
service ldapService
}
func (c *LDAP) AuthenticateProxy(ctx context.Context, r *authn.Request, username string, _ map[string]string) (*authn.Identity, error) {
info, err := c.service.User(username)
if errors.Is(err, multildap.ErrDidNotFindUser) {
return nil, errIdentityNotFound.Errorf("no user found: %w", err)
}
if err != nil {
return nil, err
}
return identityFromLDAPInfo(r.OrgID, info, c.cfg.LDAPAllowSignup), nil
}
func (c *LDAP) AuthenticatePassword(ctx context.Context, r *authn.Request, username, password string) (*authn.Identity, error) {
info, err := c.service.Login(&login.LoginUserQuery{
Username: username,
Password: password,
})
if errors.Is(err, multildap.ErrCouldNotFindUser) {
// FIXME: disable user in grafana if not found
return nil, errIdentityNotFound.Errorf("no user found: %w", err)
}
// user was found so set auth module in req metadata
r.SetMeta(authn.MetaKeyAuthModule, "ldap")
if errors.Is(err, multildap.ErrInvalidCredentials) {
return nil, errInvalidPassword.Errorf("invalid password: %w", err)
}
if err != nil {
return nil, err
}
return identityFromLDAPInfo(r.OrgID, info, c.cfg.LDAPAllowSignup), nil
}
type ldapService interface {
Login(query *login.LoginUserQuery) (*login.ExternalUserInfo, error)
User(username string) (*login.ExternalUserInfo, error)
}
// FIXME: remove the implementation if we convert ldap to an actual service
type ldapServiceImpl struct {
cfg *setting.Cfg
}
func (s *ldapServiceImpl) Login(query *login.LoginUserQuery) (*login.ExternalUserInfo, error) {
cfg, err := multildap.GetConfig(s.cfg)
if err != nil {
return nil, err
}
return multildap.New(cfg.Servers).Login(query)
}
func (s *ldapServiceImpl) User(username string) (*login.ExternalUserInfo, error) {
cfg, err := multildap.GetConfig(s.cfg)
if err != nil {
return nil, err
}
user, _, err := multildap.New(cfg.Servers).User(username)
return user, err
}
func identityFromLDAPInfo(orgID int64, info *login.ExternalUserInfo, allowSignup bool) *authn.Identity {
return &authn.Identity{
OrgID: orgID,
OrgRoles: info.OrgRoles,
Login: info.Login,
Name: info.Name,
Email: info.Email,
IsGrafanaAdmin: info.IsGrafanaAdmin,
AuthModule: info.AuthModule,
AuthID: info.AuthId,
Groups: info.Groups,
ClientParams: authn.ClientParams{
SyncUser: true,
SyncTeamMembers: true,
EnableDisabledUsers: true,
FetchSyncedUser: true,
AllowSignUp: allowSignup,
LookUpParams: login.UserLookupParams{
Login: &info.Login,
Email: &info.Email,
},
},
}
}