mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(ldap): more unit tests for ldap to grafana user sync
This commit is contained in:
parent
2fa9311eee
commit
a7b1df34c5
@ -30,7 +30,7 @@ func AuthenticateUser(query *AuthenticateUserQuery) error {
|
||||
}
|
||||
|
||||
if setting.LdapEnabled {
|
||||
for _, server := range setting.LdapServers {
|
||||
for _, server := range ldapServers {
|
||||
auther := NewLdapAuthenticator(server)
|
||||
err = auther.login(query)
|
||||
if err == nil || err != ErrInvalidCredentials {
|
||||
|
@ -8,12 +8,13 @@ import (
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/log"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
var ldapServers []*LdapServerConf
|
||||
|
||||
func init() {
|
||||
setting.LdapServers = []*setting.LdapServerConf{
|
||||
&setting.LdapServerConf{
|
||||
ldapServers = []*LdapServerConf{
|
||||
{
|
||||
UseSSL: false,
|
||||
Host: "127.0.0.1",
|
||||
Port: "389",
|
||||
@ -25,45 +26,20 @@ func init() {
|
||||
AttrEmail: "email",
|
||||
SearchFilter: "(cn=%s)",
|
||||
SearchBaseDNs: []string{"dc=grafana,dc=org"},
|
||||
LdapGroups: []*LdapGroupToOrgRole{
|
||||
{GroupDN: "cn=users,dc=grafana,dc=org", OrgName: "Main Org.", OrgRole: "Editor"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type ldapAuther struct {
|
||||
server *setting.LdapServerConf
|
||||
server *LdapServerConf
|
||||
conn *ldap.Conn
|
||||
}
|
||||
|
||||
type ldapUserInfo struct {
|
||||
FirstName string
|
||||
LastName string
|
||||
Username string
|
||||
Email string
|
||||
MemberOf []string
|
||||
}
|
||||
|
||||
func (u *ldapUserInfo) isMemberOfAny(groups []string) bool {
|
||||
for _, group := range groups {
|
||||
if u.isMemberOf(group) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (u *ldapUserInfo) isMemberOf(group string) bool {
|
||||
for _, member := range u.MemberOf {
|
||||
if member == group {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func NewLdapAuthenticator(server *setting.LdapServerConf) *ldapAuther {
|
||||
return &ldapAuther{
|
||||
server: server,
|
||||
}
|
||||
func NewLdapAuthenticator(server *LdapServerConf) *ldapAuther {
|
||||
return &ldapAuther{server: server}
|
||||
}
|
||||
|
||||
func (a *ldapAuther) Dial() error {
|
||||
@ -108,11 +84,26 @@ func (a *ldapAuther) login(query *AuthenticateUserQuery) error {
|
||||
}
|
||||
|
||||
func (a *ldapAuther) getGrafanaUserFor(ldapUser *ldapUserInfo) (*m.User, error) {
|
||||
// validate that the user has access
|
||||
access := false
|
||||
for _, ldapGroup := range a.server.LdapGroups {
|
||||
if ldapUser.isMemberOf(ldapGroup.GroupDN) {
|
||||
access = true
|
||||
}
|
||||
}
|
||||
|
||||
if !access {
|
||||
log.Info("Ldap Auth: user %s does not belong in any of the specified ldap groups", ldapUser.Username)
|
||||
return nil, ErrInvalidCredentials
|
||||
}
|
||||
|
||||
// get user from grafana db
|
||||
userQuery := m.GetUserByLoginQuery{LoginOrEmail: ldapUser.Username}
|
||||
if err := bus.Dispatch(&userQuery); err != nil {
|
||||
if err == m.ErrUserNotFound {
|
||||
return a.createGrafanaUser(ldapUser)
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,5 +212,4 @@ func getLdapAttrArray(name string, result *ldap.SearchResult) []string {
|
||||
|
||||
func createUserFromLdapInfo() error {
|
||||
return nil
|
||||
|
||||
}
|
||||
|
113
pkg/auth/ldap_test.go
Normal file
113
pkg/auth/ldap_test.go
Normal file
@ -0,0 +1,113 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestLdapAuther(t *testing.T) {
|
||||
|
||||
Convey("When translating ldap user to grafana user", t, func() {
|
||||
|
||||
Convey("Given no ldap group map match", func() {
|
||||
ldapAuther := NewLdapAuthenticator(&LdapServerConf{})
|
||||
_, err := ldapAuther.getGrafanaUserFor(&ldapUserInfo{})
|
||||
|
||||
So(err, ShouldEqual, ErrInvalidCredentials)
|
||||
})
|
||||
|
||||
var user1 = &m.User{}
|
||||
|
||||
ldapAutherScenario("Given wildcard group match", func(sc *scenarioContext) {
|
||||
ldapAuther := NewLdapAuthenticator(&LdapServerConf{
|
||||
LdapGroups: []*LdapGroupToOrgRole{
|
||||
{GroupDN: "*", OrgRole: "Admin", OrgName: "Main"},
|
||||
},
|
||||
})
|
||||
|
||||
sc.userQueryReturns(user1)
|
||||
|
||||
result, err := ldapAuther.getGrafanaUserFor(&ldapUserInfo{})
|
||||
So(err, ShouldBeNil)
|
||||
So(result, ShouldEqual, user1)
|
||||
})
|
||||
|
||||
ldapAutherScenario("Given exact group match", func(sc *scenarioContext) {
|
||||
ldapAuther := NewLdapAuthenticator(&LdapServerConf{
|
||||
LdapGroups: []*LdapGroupToOrgRole{
|
||||
{GroupDN: "cn=users", OrgRole: "Admin", OrgName: "Main"},
|
||||
},
|
||||
})
|
||||
|
||||
sc.userQueryReturns(user1)
|
||||
|
||||
result, err := ldapAuther.getGrafanaUserFor(&ldapUserInfo{MemberOf: []string{"cn=users"}})
|
||||
So(err, ShouldBeNil)
|
||||
So(result, ShouldEqual, user1)
|
||||
})
|
||||
|
||||
ldapAutherScenario("Given no existing grafana user", func(sc *scenarioContext) {
|
||||
ldapAuther := NewLdapAuthenticator(&LdapServerConf{
|
||||
LdapGroups: []*LdapGroupToOrgRole{
|
||||
{GroupDN: "cn=users", OrgRole: "Admin", OrgName: "Main"},
|
||||
},
|
||||
})
|
||||
|
||||
sc.userQueryReturns(nil)
|
||||
|
||||
result, err := ldapAuther.getGrafanaUserFor(&ldapUserInfo{
|
||||
Username: "torkelo",
|
||||
Email: "my@email.com",
|
||||
MemberOf: []string{"cn=users"},
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
Convey("Should create new user", func() {
|
||||
So(sc.createUserCmd.Login, ShouldEqual, "torkelo")
|
||||
So(sc.createUserCmd.Email, ShouldEqual, "my@email.com")
|
||||
})
|
||||
|
||||
Convey("Should return new user", func() {
|
||||
So(result.Login, ShouldEqual, "torkelo")
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func ldapAutherScenario(desc string, fn scenarioFunc) {
|
||||
Convey(desc, func() {
|
||||
defer bus.ClearBusHandlers()
|
||||
|
||||
sc := &scenarioContext{}
|
||||
bus.AddHandler("test", func(cmd *m.CreateUserCommand) error {
|
||||
sc.createUserCmd = cmd
|
||||
sc.createUserCmd.Result = m.User{Login: cmd.Login}
|
||||
return nil
|
||||
})
|
||||
|
||||
fn(sc)
|
||||
})
|
||||
}
|
||||
|
||||
type scenarioContext struct {
|
||||
createUserCmd *m.CreateUserCommand
|
||||
}
|
||||
|
||||
func (sc *scenarioContext) userQueryReturns(user *m.User) {
|
||||
bus.AddHandler("test", func(query *m.GetUserByLoginQuery) error {
|
||||
if user == nil {
|
||||
return m.ErrUserNotFound
|
||||
} else {
|
||||
query.Result = user
|
||||
return nil
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
type scenarioFunc func(c *scenarioContext)
|
22
pkg/auth/ldap_user.go
Normal file
22
pkg/auth/ldap_user.go
Normal file
@ -0,0 +1,22 @@
|
||||
package auth
|
||||
|
||||
type ldapUserInfo struct {
|
||||
FirstName string
|
||||
LastName string
|
||||
Username string
|
||||
Email string
|
||||
MemberOf []string
|
||||
}
|
||||
|
||||
func (u *ldapUserInfo) isMemberOf(group string) bool {
|
||||
if group == "*" {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, member := range u.MemberOf {
|
||||
if member == group {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
package setting
|
||||
package auth
|
||||
|
||||
type LdapGroupToOrgRole struct {
|
||||
LdapGroupPath string
|
||||
OrgId int
|
||||
OrgRole string
|
||||
GroupDN string
|
||||
OrgId int
|
||||
OrgName string
|
||||
OrgRole string
|
||||
}
|
||||
|
||||
type LdapServerConf struct {
|
||||
@ -21,5 +22,5 @@ type LdapServerConf struct {
|
||||
SearchFilter string
|
||||
SearchBaseDNs []string
|
||||
|
||||
LdapGroups []LdapGroupToOrgRole
|
||||
LdapGroups []*LdapGroupToOrgRole
|
||||
}
|
@ -119,7 +119,6 @@ var (
|
||||
|
||||
// LDAP
|
||||
LdapEnabled bool
|
||||
LdapServers []*LdapServerConf
|
||||
|
||||
// SMTP email settings
|
||||
Smtp SmtpSettings
|
||||
|
Loading…
Reference in New Issue
Block a user