mirror of
https://github.com/grafana/grafana.git
synced 2024-11-25 10:20:29 -06:00
Merge branch 'ldap-grafana-admin'
This commit is contained in:
commit
3fa2ec0762
@ -72,6 +72,8 @@ email = "email"
|
||||
[[servers.group_mappings]]
|
||||
group_dn = "cn=admins,dc=grafana,dc=org"
|
||||
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
|
||||
# org_id = 1
|
||||
|
||||
|
@ -23,8 +23,9 @@ specific configuration file (default: `/etc/grafana/ldap.toml`).
|
||||
### Example config
|
||||
|
||||
```toml
|
||||
# Set to true to log user information returned from LDAP
|
||||
verbose_logging = false
|
||||
# To troubleshoot and get more log info enable ldap debug logging in grafana.ini
|
||||
# [log]
|
||||
# filters = ldap:debug
|
||||
|
||||
[[servers]]
|
||||
# Ldap server host (specify multiple hosts space separated)
|
||||
@ -73,6 +74,8 @@ email = "email"
|
||||
[[servers.group_mappings]]
|
||||
group_dn = "cn=admins,dc=grafana,dc=org"
|
||||
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
|
||||
# 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
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
// 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{
|
||||
User: cmd.Result,
|
||||
ExternalUser: extUser,
|
||||
|
@ -175,6 +175,7 @@ func (a *ldapAuther) GetGrafanaUserFor(ctx *m.ReqContext, ldapUser *LdapUserInfo
|
||||
|
||||
if ldapUser.isMemberOf(group.GroupDN) {
|
||||
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
|
||||
userQuery := &m.UpsertUserCommand{
|
||||
upsertUserCmd := &m.UpsertUserCommand{
|
||||
ReqContext: ctx,
|
||||
ExternalUser: extUser,
|
||||
SignupAllowed: setting.LdapAllowSignup,
|
||||
}
|
||||
|
||||
err := bus.Dispatch(userQuery)
|
||||
err := bus.Dispatch(upsertUserCmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return userQuery.Result, nil
|
||||
return upsertUserCmd.Result, nil
|
||||
}
|
||||
|
||||
func (a *ldapAuther) serverBind() error {
|
||||
|
@ -44,9 +44,10 @@ type LdapAttributeMap struct {
|
||||
}
|
||||
|
||||
type LdapGroupToOrgRole struct {
|
||||
GroupDN string `toml:"group_dn"`
|
||||
OrgId int64 `toml:"org_id"`
|
||||
OrgRole m.RoleType `toml:"org_role"`
|
||||
GroupDN string `toml:"group_dn"`
|
||||
OrgId int64 `toml:"org_id"`
|
||||
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
|
||||
|
@ -98,6 +98,10 @@ func TestLdapAuther(t *testing.T) {
|
||||
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.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() {
|
||||
@ -332,6 +360,11 @@ func ldapAutherScenario(desc string, fn scenarioFunc) {
|
||||
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 {
|
||||
sc.getUserByAuthInfoQuery = cmd
|
||||
sc.getUserByAuthInfoQuery.Result = &m.User{Login: cmd.Login}
|
||||
@ -379,14 +412,15 @@ func ldapAutherScenario(desc string, fn scenarioFunc) {
|
||||
}
|
||||
|
||||
type scenarioContext struct {
|
||||
getUserByAuthInfoQuery *m.GetUserByAuthInfoQuery
|
||||
getUserOrgListQuery *m.GetUserOrgListQuery
|
||||
createUserCmd *m.CreateUserCommand
|
||||
addOrgUserCmd *m.AddOrgUserCommand
|
||||
updateOrgUserCmd *m.UpdateOrgUserCommand
|
||||
removeOrgUserCmd *m.RemoveOrgUserCommand
|
||||
updateUserCmd *m.UpdateUserCommand
|
||||
setUsingOrgCmd *m.SetUsingOrgCommand
|
||||
getUserByAuthInfoQuery *m.GetUserByAuthInfoQuery
|
||||
getUserOrgListQuery *m.GetUserOrgListQuery
|
||||
createUserCmd *m.CreateUserCommand
|
||||
addOrgUserCmd *m.AddOrgUserCommand
|
||||
updateOrgUserCmd *m.UpdateOrgUserCommand
|
||||
removeOrgUserCmd *m.RemoveOrgUserCommand
|
||||
updateUserCmd *m.UpdateUserCommand
|
||||
setUsingOrgCmd *m.SetUsingOrgCommand
|
||||
updateUserPermissionsCmd *m.UpdateUserPermissionsCommand
|
||||
}
|
||||
|
||||
func (sc *scenarioContext) userQueryReturns(user *m.User) {
|
||||
|
@ -13,14 +13,15 @@ type UserAuth struct {
|
||||
}
|
||||
|
||||
type ExternalUserInfo struct {
|
||||
AuthModule string
|
||||
AuthId string
|
||||
UserId int64
|
||||
Email string
|
||||
Login string
|
||||
Name string
|
||||
Groups []string
|
||||
OrgRoles map[int64]RoleType
|
||||
AuthModule string
|
||||
AuthId string
|
||||
UserId int64
|
||||
Email string
|
||||
Login string
|
||||
Name string
|
||||
Groups []string
|
||||
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