mirror of
https://github.com/grafana/grafana.git
synced 2025-02-10 23:55:47 -06:00
RBAC: Feature to override default assignments (#66561)
* RBAC: Feature to override default assignments Co-authored-by: Kalle Persson <kalle.persson@grafana.com> * Add test and trim spaces * Pass linting * Apply the rbac overrides to fixed_authentication.config_writer * Removing from the default ini file for now * Add grants overrides section to cfg * slimmer handleGrantOverrides function --------- Co-authored-by: Kalle Persson <kalle.persson@grafana.com>
This commit is contained in:
parent
02951e8a26
commit
3b63844390
@ -166,7 +166,12 @@ func (s *Service) DeclareFixedRoles(registrations ...accesscontrol.RoleRegistrat
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, r := range registrations {
|
for i := range registrations {
|
||||||
|
r := registrations[i]
|
||||||
|
if r.AllowGrantsOverride {
|
||||||
|
s.handleGrantOverrides(&r)
|
||||||
|
}
|
||||||
|
|
||||||
err := accesscontrol.ValidateFixedRole(r.Role)
|
err := accesscontrol.ValidateFixedRole(r.Role)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -183,6 +188,15 @@ func (s *Service) DeclareFixedRoles(registrations ...accesscontrol.RoleRegistrat
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) handleGrantOverrides(r *accesscontrol.RoleRegistration) {
|
||||||
|
// Replace ":" and "." with "_" to match the key in the config
|
||||||
|
key := strings.ReplaceAll(strings.ReplaceAll(r.Role.Name, ":", "_"), ".", "_")
|
||||||
|
if overrides, ok := s.cfg.RBACGrantOverrides[key]; ok {
|
||||||
|
r.Grants = overrides
|
||||||
|
s.log.Info("Overriding grants for role", "role", r.Role.Name, "overrides", overrides)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterFixedRoles registers all declared roles in RAM
|
// RegisterFixedRoles registers all declared roles in RAM
|
||||||
func (s *Service) RegisterFixedRoles(ctx context.Context) error {
|
func (s *Service) RegisterFixedRoles(ctx context.Context) error {
|
||||||
// If accesscontrol is disabled no need to register roles
|
// If accesscontrol is disabled no need to register roles
|
||||||
|
@ -161,6 +161,77 @@ func TestService_DeclareFixedRoles(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestService_DeclareFixedRoles_Overrides(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
registration accesscontrol.RoleRegistration
|
||||||
|
overrides map[string][]string
|
||||||
|
wantGrants []string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "no grant override",
|
||||||
|
registration: accesscontrol.RoleRegistration{
|
||||||
|
Role: accesscontrol.RoleDTO{Name: "fixed:test:test"},
|
||||||
|
Grants: []string{"Admin"},
|
||||||
|
AllowGrantsOverride: true,
|
||||||
|
},
|
||||||
|
wantGrants: []string{"Admin"},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should account for grant overrides",
|
||||||
|
registration: accesscontrol.RoleRegistration{
|
||||||
|
Role: accesscontrol.RoleDTO{Name: "fixed:test:test"},
|
||||||
|
Grants: []string{"Admin"},
|
||||||
|
AllowGrantsOverride: true,
|
||||||
|
},
|
||||||
|
overrides: map[string][]string{"fixed_test_test": {"Viewer", "Grafana Admin"}},
|
||||||
|
wantGrants: []string{"Viewer", "Grafana Admin"},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should not account for grant overrides",
|
||||||
|
registration: accesscontrol.RoleRegistration{
|
||||||
|
Role: accesscontrol.RoleDTO{Name: "fixed:test:test"},
|
||||||
|
Grants: []string{"Admin"},
|
||||||
|
AllowGrantsOverride: false,
|
||||||
|
},
|
||||||
|
overrides: map[string][]string{"fixed_test_test": {"Viewer", "Grafana Admin"}},
|
||||||
|
wantGrants: []string{"Admin"},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
ac := setupTestEnv(t)
|
||||||
|
|
||||||
|
// Reset the registations
|
||||||
|
ac.registrations = accesscontrol.RegistrationList{}
|
||||||
|
ac.cfg.RBACGrantOverrides = tt.overrides
|
||||||
|
|
||||||
|
// Test
|
||||||
|
err := ac.DeclareFixedRoles(tt.registration)
|
||||||
|
if tt.wantErr {
|
||||||
|
require.Error(t, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
registrationCnt := 0
|
||||||
|
grants := []string{}
|
||||||
|
ac.registrations.Range(func(registration accesscontrol.RoleRegistration) bool {
|
||||||
|
registrationCnt++
|
||||||
|
grants = registration.Grants
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
require.Equal(t, 1, registrationCnt,
|
||||||
|
"expected service registration list to contain the registration")
|
||||||
|
require.ElementsMatch(t, tt.wantGrants, grants)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestService_DeclarePluginRoles(t *testing.T) {
|
func TestService_DeclarePluginRoles(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -16,8 +16,9 @@ var ErrInternal = errutil.NewBase(errutil.StatusInternal, "accesscontrol.interna
|
|||||||
// RoleRegistration stores a role and its assignments to built-in roles
|
// RoleRegistration stores a role and its assignments to built-in roles
|
||||||
// (Viewer, Editor, Admin, Grafana Admin)
|
// (Viewer, Editor, Admin, Grafana Admin)
|
||||||
type RoleRegistration struct {
|
type RoleRegistration struct {
|
||||||
Role RoleDTO
|
Role RoleDTO
|
||||||
Grants []string
|
Grants []string
|
||||||
|
AllowGrantsOverride bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Role is the model for Role in RBAC.
|
// Role is the model for Role in RBAC.
|
||||||
|
@ -233,8 +233,9 @@ func DeclareFixedRoles(service Service) error {
|
|||||||
Grants: []string{RoleGrafanaAdmin},
|
Grants: []string{RoleGrafanaAdmin},
|
||||||
}
|
}
|
||||||
authenticationConfigWriter := RoleRegistration{
|
authenticationConfigWriter := RoleRegistration{
|
||||||
Role: authenticationConfigWriterRole,
|
Role: authenticationConfigWriterRole,
|
||||||
Grants: []string{RoleGrafanaAdmin},
|
Grants: []string{RoleGrafanaAdmin},
|
||||||
|
AllowGrantsOverride: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
return service.DeclareFixedRoles(ldapReader, ldapWriter, orgUsersReader, orgUsersWriter,
|
return service.DeclareFixedRoles(ldapReader, ldapWriter, orgUsersReader, orgUsersWriter,
|
||||||
|
@ -505,6 +505,9 @@ type Cfg struct {
|
|||||||
RBACPermissionValidationEnabled bool
|
RBACPermissionValidationEnabled bool
|
||||||
// Reset basic roles permissions on start-up
|
// Reset basic roles permissions on start-up
|
||||||
RBACResetBasicRoles bool
|
RBACResetBasicRoles bool
|
||||||
|
// Override default fixed role assignments
|
||||||
|
RBACGrantOverrides map[string][]string
|
||||||
|
|
||||||
// GRPC Server.
|
// GRPC Server.
|
||||||
GRPCServerNetwork string
|
GRPCServerNetwork string
|
||||||
GRPCServerAddress string
|
GRPCServerAddress string
|
||||||
@ -1559,6 +1562,17 @@ func readAccessControlSettings(iniFile *ini.File, cfg *Cfg) {
|
|||||||
cfg.RBACPermissionCache = rbac.Key("permission_cache").MustBool(true)
|
cfg.RBACPermissionCache = rbac.Key("permission_cache").MustBool(true)
|
||||||
cfg.RBACPermissionValidationEnabled = rbac.Key("permission_validation_enabled").MustBool(false)
|
cfg.RBACPermissionValidationEnabled = rbac.Key("permission_validation_enabled").MustBool(false)
|
||||||
cfg.RBACResetBasicRoles = rbac.Key("reset_basic_roles").MustBool(false)
|
cfg.RBACResetBasicRoles = rbac.Key("reset_basic_roles").MustBool(false)
|
||||||
|
|
||||||
|
rbacOverrides := iniFile.Section("rbac.overrides")
|
||||||
|
cfg.RBACGrantOverrides = map[string][]string{}
|
||||||
|
for _, key := range rbacOverrides.Keys() {
|
||||||
|
value := key.MustString("")
|
||||||
|
grants := strings.Split(value, ",")
|
||||||
|
for i, grant := range grants {
|
||||||
|
grants[i] = strings.TrimSpace(grant)
|
||||||
|
}
|
||||||
|
cfg.RBACGrantOverrides[key.Name()] = grants
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func readUserSettings(iniFile *ini.File, cfg *Cfg) error {
|
func readUserSettings(iniFile *ini.File, cfg *Cfg) error {
|
||||||
|
Loading…
Reference in New Issue
Block a user