mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge branch 'ldap-grafana-admin'
This commit is contained in:
commit
3fa2ec0762
@ -72,6 +72,8 @@ email = "email"
|
|||||||
[[servers.group_mappings]]
|
[[servers.group_mappings]]
|
||||||
group_dn = "cn=admins,dc=grafana,dc=org"
|
group_dn = "cn=admins,dc=grafana,dc=org"
|
||||||
org_role = "Admin"
|
org_role = "Admin"
|
||||||
|
# To make user a instance admin (Grafana Admin) uncomment line below
|
||||||
|
# grafana_admin = true
|
||||||
# The Grafana organization database id, optional, if left out the default org (id 1) will be used
|
# The Grafana organization database id, optional, if left out the default org (id 1) will be used
|
||||||
# org_id = 1
|
# org_id = 1
|
||||||
|
|
||||||
|
@ -23,8 +23,9 @@ specific configuration file (default: `/etc/grafana/ldap.toml`).
|
|||||||
### Example config
|
### Example config
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
# Set to true to log user information returned from LDAP
|
# To troubleshoot and get more log info enable ldap debug logging in grafana.ini
|
||||||
verbose_logging = false
|
# [log]
|
||||||
|
# filters = ldap:debug
|
||||||
|
|
||||||
[[servers]]
|
[[servers]]
|
||||||
# Ldap server host (specify multiple hosts space separated)
|
# Ldap server host (specify multiple hosts space separated)
|
||||||
@ -73,6 +74,8 @@ email = "email"
|
|||||||
[[servers.group_mappings]]
|
[[servers.group_mappings]]
|
||||||
group_dn = "cn=admins,dc=grafana,dc=org"
|
group_dn = "cn=admins,dc=grafana,dc=org"
|
||||||
org_role = "Admin"
|
org_role = "Admin"
|
||||||
|
# To make user a instance admin (Grafana Admin) uncomment line below
|
||||||
|
# grafana_admin = true
|
||||||
# The Grafana organization database id, optional, if left out the default org (id 1) will be used. Setting this allows for multiple group_dn's to be assigned to the same org_role provided the org_id differs
|
# The Grafana organization database id, optional, if left out the default org (id 1) will be used. Setting this allows for multiple group_dn's to be assigned to the same org_role provided the org_id differs
|
||||||
# org_id = 1
|
# org_id = 1
|
||||||
|
|
||||||
@ -132,6 +135,10 @@ Users page, this change will be reset the next time the user logs in. If you
|
|||||||
change the LDAP groups of a user, the change will take effect the next
|
change the LDAP groups of a user, the change will take effect the next
|
||||||
time the user logs in.
|
time the user logs in.
|
||||||
|
|
||||||
|
### Grafana Admin
|
||||||
|
with a servers.group_mappings section you can set grafana_admin = true or false to sync Grafana Admin permission. A Grafana server admin has admin access over all orgs &
|
||||||
|
users.
|
||||||
|
|
||||||
### Priority
|
### Priority
|
||||||
The first group mapping that an LDAP user is matched to will be used for the sync. If you have LDAP users that fit multiple mappings, the topmost mapping in the TOML config will be used.
|
The first group mapping that an LDAP user is matched to will be used for the sync. If you have LDAP users that fit multiple mappings, the topmost mapping in the TOML config will be used.
|
||||||
|
|
||||||
|
@ -72,6 +72,13 @@ func UpsertUser(cmd *m.UpsertUserCommand) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sync isGrafanaAdmin permission
|
||||||
|
if extUser.IsGrafanaAdmin != nil && *extUser.IsGrafanaAdmin != cmd.Result.IsAdmin {
|
||||||
|
if err := bus.Dispatch(&m.UpdateUserPermissionsCommand{UserId: cmd.Result.Id, IsGrafanaAdmin: *extUser.IsGrafanaAdmin}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err = bus.Dispatch(&m.SyncTeamsCommand{
|
err = bus.Dispatch(&m.SyncTeamsCommand{
|
||||||
User: cmd.Result,
|
User: cmd.Result,
|
||||||
ExternalUser: extUser,
|
ExternalUser: extUser,
|
||||||
|
@ -175,6 +175,7 @@ func (a *ldapAuther) GetGrafanaUserFor(ctx *m.ReqContext, ldapUser *LdapUserInfo
|
|||||||
|
|
||||||
if ldapUser.isMemberOf(group.GroupDN) {
|
if ldapUser.isMemberOf(group.GroupDN) {
|
||||||
extUser.OrgRoles[group.OrgId] = group.OrgRole
|
extUser.OrgRoles[group.OrgId] = group.OrgRole
|
||||||
|
extUser.IsGrafanaAdmin = group.IsGrafanaAdmin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,18 +191,18 @@ func (a *ldapAuther) GetGrafanaUserFor(ctx *m.ReqContext, ldapUser *LdapUserInfo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add/update user in grafana
|
// add/update user in grafana
|
||||||
userQuery := &m.UpsertUserCommand{
|
upsertUserCmd := &m.UpsertUserCommand{
|
||||||
ReqContext: ctx,
|
ReqContext: ctx,
|
||||||
ExternalUser: extUser,
|
ExternalUser: extUser,
|
||||||
SignupAllowed: setting.LdapAllowSignup,
|
SignupAllowed: setting.LdapAllowSignup,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := bus.Dispatch(userQuery)
|
err := bus.Dispatch(upsertUserCmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return userQuery.Result, nil
|
return upsertUserCmd.Result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ldapAuther) serverBind() error {
|
func (a *ldapAuther) serverBind() error {
|
||||||
|
@ -44,9 +44,10 @@ type LdapAttributeMap struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type LdapGroupToOrgRole struct {
|
type LdapGroupToOrgRole struct {
|
||||||
GroupDN string `toml:"group_dn"`
|
GroupDN string `toml:"group_dn"`
|
||||||
OrgId int64 `toml:"org_id"`
|
OrgId int64 `toml:"org_id"`
|
||||||
OrgRole m.RoleType `toml:"org_role"`
|
IsGrafanaAdmin *bool `toml:"grafana_admin"` // This is a pointer to know if it was set or not (for backwards compatability)
|
||||||
|
OrgRole m.RoleType `toml:"org_role"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var LdapCfg LdapConfig
|
var LdapCfg LdapConfig
|
||||||
|
@ -98,6 +98,10 @@ func TestLdapAuther(t *testing.T) {
|
|||||||
So(result.Login, ShouldEqual, "torkelo")
|
So(result.Login, ShouldEqual, "torkelo")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Convey("Should set isGrafanaAdmin to false by default", func() {
|
||||||
|
So(result.IsAdmin, ShouldBeFalse)
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
@ -223,8 +227,32 @@ func TestLdapAuther(t *testing.T) {
|
|||||||
So(sc.addOrgUserCmd.Role, ShouldEqual, m.ROLE_ADMIN)
|
So(sc.addOrgUserCmd.Role, ShouldEqual, m.ROLE_ADMIN)
|
||||||
So(sc.setUsingOrgCmd.OrgId, ShouldEqual, 1)
|
So(sc.setUsingOrgCmd.OrgId, ShouldEqual, 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Convey("Should not update permissions unless specified", func() {
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(sc.updateUserPermissionsCmd, ShouldBeNil)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ldapAutherScenario("given ldap groups with grafana_admin=true", func(sc *scenarioContext) {
|
||||||
|
trueVal := true
|
||||||
|
|
||||||
|
ldapAuther := NewLdapAuthenticator(&LdapServerConf{
|
||||||
|
LdapGroups: []*LdapGroupToOrgRole{
|
||||||
|
{GroupDN: "cn=admins", OrgId: 1, OrgRole: "Admin", IsGrafanaAdmin: &trueVal},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
sc.userOrgsQueryReturns([]*m.UserOrgDTO{})
|
||||||
|
_, err := ldapAuther.GetGrafanaUserFor(nil, &LdapUserInfo{
|
||||||
|
MemberOf: []string{"cn=admins"},
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("Should create user with admin set to true", func() {
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(sc.updateUserPermissionsCmd.IsGrafanaAdmin, ShouldBeTrue)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("When calling SyncUser", t, func() {
|
Convey("When calling SyncUser", t, func() {
|
||||||
@ -332,6 +360,11 @@ func ldapAutherScenario(desc string, fn scenarioFunc) {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
bus.AddHandlerCtx("test", func(ctx context.Context, cmd *m.UpdateUserPermissionsCommand) error {
|
||||||
|
sc.updateUserPermissionsCmd = cmd
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
bus.AddHandler("test", func(cmd *m.GetUserByAuthInfoQuery) error {
|
bus.AddHandler("test", func(cmd *m.GetUserByAuthInfoQuery) error {
|
||||||
sc.getUserByAuthInfoQuery = cmd
|
sc.getUserByAuthInfoQuery = cmd
|
||||||
sc.getUserByAuthInfoQuery.Result = &m.User{Login: cmd.Login}
|
sc.getUserByAuthInfoQuery.Result = &m.User{Login: cmd.Login}
|
||||||
@ -379,14 +412,15 @@ func ldapAutherScenario(desc string, fn scenarioFunc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type scenarioContext struct {
|
type scenarioContext struct {
|
||||||
getUserByAuthInfoQuery *m.GetUserByAuthInfoQuery
|
getUserByAuthInfoQuery *m.GetUserByAuthInfoQuery
|
||||||
getUserOrgListQuery *m.GetUserOrgListQuery
|
getUserOrgListQuery *m.GetUserOrgListQuery
|
||||||
createUserCmd *m.CreateUserCommand
|
createUserCmd *m.CreateUserCommand
|
||||||
addOrgUserCmd *m.AddOrgUserCommand
|
addOrgUserCmd *m.AddOrgUserCommand
|
||||||
updateOrgUserCmd *m.UpdateOrgUserCommand
|
updateOrgUserCmd *m.UpdateOrgUserCommand
|
||||||
removeOrgUserCmd *m.RemoveOrgUserCommand
|
removeOrgUserCmd *m.RemoveOrgUserCommand
|
||||||
updateUserCmd *m.UpdateUserCommand
|
updateUserCmd *m.UpdateUserCommand
|
||||||
setUsingOrgCmd *m.SetUsingOrgCommand
|
setUsingOrgCmd *m.SetUsingOrgCommand
|
||||||
|
updateUserPermissionsCmd *m.UpdateUserPermissionsCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *scenarioContext) userQueryReturns(user *m.User) {
|
func (sc *scenarioContext) userQueryReturns(user *m.User) {
|
||||||
|
@ -13,14 +13,15 @@ type UserAuth struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ExternalUserInfo struct {
|
type ExternalUserInfo struct {
|
||||||
AuthModule string
|
AuthModule string
|
||||||
AuthId string
|
AuthId string
|
||||||
UserId int64
|
UserId int64
|
||||||
Email string
|
Email string
|
||||||
Login string
|
Login string
|
||||||
Name string
|
Name string
|
||||||
Groups []string
|
Groups []string
|
||||||
OrgRoles map[int64]RoleType
|
OrgRoles map[int64]RoleType
|
||||||
|
IsGrafanaAdmin *bool // This is a pointer to know if we should sync this or not (nil = ignore sync)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------
|
// ---------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user