mirror of https://github.com/grafana/grafana
RBAC: Allow omitting default permissions when a new resource is created (#90720)
* Cfg: Move rbac settings to own struct * Cfg: Add setting to control if resource should generate managed permissions when created * Dashboards: Check if we should generate default permissions when dashboard is created * Folders: Check if we should generate default permissions when folder is created * Datasource: Check if we should generate default permissions when datasource is created * ServiceAccount: Check if we should generate default permissions when service account is created * Cfg: Add option to specify resources for wich we should default seed * ManagedPermissions: Move providers to their own files * Dashboards: Default seed all possible managed permissions if configured * Folders: Default seed all possible managed permissions if configured * Cfg: Remove service account from list * RBAC: Move utility function * remove managed permission settings from the config file examples, change the setting names * remove ini file changes from the PR * fix setting reading * fix linting errors * fix tests * fix wildcard role seeding --------- Co-authored-by: Karl Persson <kalle.persson@grafana.com> Co-authored-by: jguer <me@jguer.space>pull/90939/head
parent
82236976ae
commit
9bb2cf4968
@ -0,0 +1,177 @@ |
||||
package ossaccesscontrol |
||||
|
||||
import ( |
||||
"context" |
||||
"errors" |
||||
|
||||
"github.com/grafana/grafana/pkg/api/routing" |
||||
"github.com/grafana/grafana/pkg/infra/db" |
||||
"github.com/grafana/grafana/pkg/infra/metrics" |
||||
"github.com/grafana/grafana/pkg/services/accesscontrol" |
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions" |
||||
"github.com/grafana/grafana/pkg/services/dashboards" |
||||
"github.com/grafana/grafana/pkg/services/featuremgmt" |
||||
"github.com/grafana/grafana/pkg/services/folder" |
||||
"github.com/grafana/grafana/pkg/services/licensing" |
||||
"github.com/grafana/grafana/pkg/services/team" |
||||
"github.com/grafana/grafana/pkg/services/user" |
||||
"github.com/grafana/grafana/pkg/setting" |
||||
) |
||||
|
||||
type DashboardPermissionsService struct { |
||||
*resourcepermissions.Service |
||||
} |
||||
|
||||
var DashboardViewActions = []string{dashboards.ActionDashboardsRead} |
||||
var DashboardEditActions = append(DashboardViewActions, []string{dashboards.ActionDashboardsWrite, dashboards.ActionDashboardsDelete}...) |
||||
var DashboardAdminActions = append(DashboardEditActions, []string{dashboards.ActionDashboardsPermissionsRead, dashboards.ActionDashboardsPermissionsWrite}...) |
||||
|
||||
func getDashboardViewActions(features featuremgmt.FeatureToggles) []string { |
||||
if features.IsEnabled(context.Background(), featuremgmt.FlagAnnotationPermissionUpdate) { |
||||
return append(DashboardViewActions, accesscontrol.ActionAnnotationsRead) |
||||
} |
||||
return DashboardViewActions |
||||
} |
||||
|
||||
func getDashboardEditActions(features featuremgmt.FeatureToggles) []string { |
||||
if features.IsEnabled(context.Background(), featuremgmt.FlagAnnotationPermissionUpdate) { |
||||
return append(DashboardEditActions, []string{accesscontrol.ActionAnnotationsRead, accesscontrol.ActionAnnotationsWrite, accesscontrol.ActionAnnotationsDelete, accesscontrol.ActionAnnotationsCreate}...) |
||||
} |
||||
return DashboardEditActions |
||||
} |
||||
|
||||
func getDashboardAdminActions(features featuremgmt.FeatureToggles) []string { |
||||
if features.IsEnabled(context.Background(), featuremgmt.FlagAnnotationPermissionUpdate) { |
||||
return append(DashboardAdminActions, []string{accesscontrol.ActionAnnotationsRead, accesscontrol.ActionAnnotationsWrite, accesscontrol.ActionAnnotationsDelete, accesscontrol.ActionAnnotationsCreate}...) |
||||
} |
||||
return DashboardAdminActions |
||||
} |
||||
|
||||
func registerDashboardRoles(cfg *setting.Cfg, features featuremgmt.FeatureToggles, service accesscontrol.Service) error { |
||||
if !cfg.RBAC.PermissionsWildcardSeed("dashboard") { |
||||
return nil |
||||
} |
||||
|
||||
viewer := accesscontrol.RoleRegistration{ |
||||
Role: accesscontrol.RoleDTO{ |
||||
Name: "fixed:dashboards:viewer", |
||||
DisplayName: "Viewer", |
||||
Description: "View all dashboards", |
||||
Group: "Dashboards", |
||||
Permissions: accesscontrol.PermissionsForActions(getDashboardViewActions(features), dashboards.ScopeDashboardsAll), |
||||
Hidden: true, |
||||
}, |
||||
Grants: []string{"Viewer"}, |
||||
} |
||||
|
||||
editor := accesscontrol.RoleRegistration{ |
||||
Role: accesscontrol.RoleDTO{ |
||||
Name: "fixed:dashboards:editor", |
||||
DisplayName: "Editor", |
||||
Description: "Edit all dashboards.", |
||||
Group: "Dashboards", |
||||
Permissions: accesscontrol.PermissionsForActions(getDashboardEditActions(features), dashboards.ScopeDashboardsAll), |
||||
Hidden: true, |
||||
}, |
||||
Grants: []string{"Editor"}, |
||||
} |
||||
|
||||
admin := accesscontrol.RoleRegistration{ |
||||
Role: accesscontrol.RoleDTO{ |
||||
Name: "fixed:dashboards:admin", |
||||
DisplayName: "Admin", |
||||
Description: "Administer all dashboards.", |
||||
Group: "Dashboards", |
||||
Permissions: accesscontrol.PermissionsForActions(getDashboardAdminActions(features), dashboards.ScopeDashboardsAll), |
||||
Hidden: true, |
||||
}, |
||||
Grants: []string{"Admin"}, |
||||
} |
||||
|
||||
return service.DeclareFixedRoles(viewer, editor, admin) |
||||
} |
||||
|
||||
func ProvideDashboardPermissions( |
||||
cfg *setting.Cfg, features featuremgmt.FeatureToggles, router routing.RouteRegister, sql db.DB, ac accesscontrol.AccessControl, |
||||
license licensing.Licensing, dashboardStore dashboards.Store, folderService folder.Service, service accesscontrol.Service, |
||||
teamService team.Service, userService user.Service, actionSetService resourcepermissions.ActionSetService, |
||||
) (*DashboardPermissionsService, error) { |
||||
getDashboard := func(ctx context.Context, orgID int64, resourceID string) (*dashboards.Dashboard, error) { |
||||
query := &dashboards.GetDashboardQuery{UID: resourceID, OrgID: orgID} |
||||
queryResult, err := dashboardStore.GetDashboard(ctx, query) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return queryResult, nil |
||||
} |
||||
|
||||
if err := registerDashboardRoles(cfg, features, service); err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
options := resourcepermissions.Options{ |
||||
Resource: "dashboards", |
||||
ResourceAttribute: "uid", |
||||
ResourceValidator: func(ctx context.Context, orgID int64, resourceID string) error { |
||||
dashboard, err := getDashboard(ctx, orgID, resourceID) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
if dashboard.IsFolder { |
||||
return errors.New("not found") |
||||
} |
||||
|
||||
return nil |
||||
}, |
||||
InheritedScopesSolver: func(ctx context.Context, orgID int64, resourceID string) ([]string, error) { |
||||
wildcards := accesscontrol.WildcardsFromPrefix(dashboards.ScopeFoldersPrefix) |
||||
scopes := []string(wildcards) |
||||
|
||||
dashboard, err := getDashboard(ctx, orgID, resourceID) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.AccessControl).Inc() |
||||
// nolint:staticcheck
|
||||
if dashboard.FolderUID != "" { |
||||
query := &dashboards.GetDashboardQuery{UID: dashboard.FolderUID, OrgID: orgID} |
||||
queryResult, err := dashboardStore.GetDashboard(ctx, query) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
parentScope := dashboards.ScopeFoldersProvider.GetResourceScopeUID(queryResult.UID) |
||||
|
||||
nestedScopes, err := dashboards.GetInheritedScopes(ctx, orgID, queryResult.UID, folderService) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
scopes = append(scopes, parentScope) |
||||
scopes = append(scopes, nestedScopes...) |
||||
return scopes, nil |
||||
} |
||||
return append(scopes, dashboards.ScopeFoldersProvider.GetResourceScopeUID(folder.GeneralFolderUID)), nil |
||||
}, |
||||
Assignments: resourcepermissions.Assignments{ |
||||
Users: true, |
||||
Teams: true, |
||||
BuiltInRoles: true, |
||||
ServiceAccounts: true, |
||||
}, |
||||
PermissionsToActions: map[string][]string{ |
||||
"View": getDashboardViewActions(features), |
||||
"Edit": getDashboardEditActions(features), |
||||
"Admin": getDashboardAdminActions(features), |
||||
}, |
||||
ReaderRoleName: "Dashboard permission reader", |
||||
WriterRoleName: "Dashboard permission writer", |
||||
RoleGroup: "Dashboards", |
||||
} |
||||
|
||||
srv, err := resourcepermissions.New(cfg, options, features, router, license, ac, service, sql, teamService, userService, actionSetService) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &DashboardPermissionsService{srv}, nil |
||||
} |
||||
@ -0,0 +1,87 @@ |
||||
package ossaccesscontrol |
||||
|
||||
import ( |
||||
"context" |
||||
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity" |
||||
"github.com/grafana/grafana/pkg/infra/db" |
||||
"github.com/grafana/grafana/pkg/services/accesscontrol" |
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions" |
||||
"github.com/grafana/grafana/pkg/services/datasources" |
||||
"github.com/grafana/grafana/pkg/services/featuremgmt" |
||||
"github.com/grafana/grafana/pkg/setting" |
||||
) |
||||
|
||||
// DatasourceQueryActions contains permissions to read information
|
||||
// about a data source and submit arbitrary queries to it.
|
||||
var DatasourceQueryActions = []string{ |
||||
datasources.ActionRead, |
||||
datasources.ActionQuery, |
||||
} |
||||
|
||||
func ProvideDatasourcePermissionsService(cfg *setting.Cfg, features featuremgmt.FeatureToggles, db db.DB) *DatasourcePermissionsService { |
||||
return &DatasourcePermissionsService{ |
||||
store: resourcepermissions.NewStore(cfg, db, features), |
||||
} |
||||
} |
||||
|
||||
var _ accesscontrol.DatasourcePermissionsService = new(DatasourcePermissionsService) |
||||
|
||||
type DatasourcePermissionsService struct { |
||||
store resourcepermissions.Store |
||||
} |
||||
|
||||
func (e DatasourcePermissionsService) GetPermissions(ctx context.Context, user identity.Requester, resourceID string) ([]accesscontrol.ResourcePermission, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (e DatasourcePermissionsService) SetUserPermission(ctx context.Context, orgID int64, user accesscontrol.User, resourceID, permission string) (*accesscontrol.ResourcePermission, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (e DatasourcePermissionsService) SetTeamPermission(ctx context.Context, orgID, teamID int64, resourceID, permission string) (*accesscontrol.ResourcePermission, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (e DatasourcePermissionsService) SetBuiltInRolePermission(ctx context.Context, orgID int64, builtInRole string, resourceID string, permission string) (*accesscontrol.ResourcePermission, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
// SetPermissions sets managed permissions for a datasource in OSS. This ensures that Viewers and Editors maintain query access to a data source
|
||||
// if an OSS/unlicensed instance is upgraded to Enterprise/licensed.
|
||||
// https://github.com/grafana/identity-access-team/issues/672
|
||||
func (e DatasourcePermissionsService) SetPermissions(ctx context.Context, orgID int64, resourceID string, commands ...accesscontrol.SetResourcePermissionCommand) ([]accesscontrol.ResourcePermission, error) { |
||||
dbCommands := make([]resourcepermissions.SetResourcePermissionsCommand, 0, len(commands)) |
||||
for _, cmd := range commands { |
||||
// Only set query permissions for built-in roles; do not set permissions for data sources with * as UID, as this would grant wildcard permissions
|
||||
if cmd.Permission != "Query" || cmd.BuiltinRole == "" || resourceID == "*" { |
||||
continue |
||||
} |
||||
actions := DatasourceQueryActions |
||||
|
||||
dbCommands = append(dbCommands, resourcepermissions.SetResourcePermissionsCommand{ |
||||
BuiltinRole: cmd.BuiltinRole, |
||||
SetResourcePermissionCommand: resourcepermissions.SetResourcePermissionCommand{ |
||||
Actions: actions, |
||||
Resource: datasources.ScopeRoot, |
||||
ResourceID: resourceID, |
||||
ResourceAttribute: "uid", |
||||
Permission: cmd.Permission, |
||||
}, |
||||
}) |
||||
} |
||||
|
||||
return e.store.SetResourcePermissions(ctx, orgID, dbCommands, resourcepermissions.ResourceHooks{}) |
||||
} |
||||
|
||||
func (e DatasourcePermissionsService) DeleteResourcePermissions(ctx context.Context, orgID int64, resourceID string) error { |
||||
return e.store.DeleteResourcePermissions(ctx, orgID, &resourcepermissions.DeleteResourcePermissionsCmd{ |
||||
Resource: datasources.ScopeRoot, |
||||
ResourceAttribute: "uid", |
||||
ResourceID: resourceID, |
||||
}) |
||||
} |
||||
|
||||
func (e DatasourcePermissionsService) MapActions(permission accesscontrol.ResourcePermission) string { |
||||
return "" |
||||
} |
||||
@ -0,0 +1,133 @@ |
||||
package ossaccesscontrol |
||||
|
||||
import ( |
||||
"context" |
||||
"errors" |
||||
|
||||
"github.com/grafana/grafana/pkg/api/routing" |
||||
"github.com/grafana/grafana/pkg/infra/db" |
||||
"github.com/grafana/grafana/pkg/services/accesscontrol" |
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions" |
||||
"github.com/grafana/grafana/pkg/services/dashboards" |
||||
"github.com/grafana/grafana/pkg/services/featuremgmt" |
||||
"github.com/grafana/grafana/pkg/services/folder" |
||||
"github.com/grafana/grafana/pkg/services/libraryelements" |
||||
"github.com/grafana/grafana/pkg/services/licensing" |
||||
"github.com/grafana/grafana/pkg/services/team" |
||||
"github.com/grafana/grafana/pkg/services/user" |
||||
"github.com/grafana/grafana/pkg/setting" |
||||
) |
||||
|
||||
type FolderPermissionsService struct { |
||||
*resourcepermissions.Service |
||||
} |
||||
|
||||
var FolderViewActions = []string{dashboards.ActionFoldersRead, accesscontrol.ActionAlertingRuleRead, libraryelements.ActionLibraryPanelsRead, accesscontrol.ActionAlertingSilencesRead} |
||||
var FolderEditActions = append(FolderViewActions, []string{ |
||||
dashboards.ActionFoldersWrite, |
||||
dashboards.ActionFoldersDelete, |
||||
dashboards.ActionDashboardsCreate, |
||||
accesscontrol.ActionAlertingRuleCreate, |
||||
accesscontrol.ActionAlertingRuleUpdate, |
||||
accesscontrol.ActionAlertingRuleDelete, |
||||
accesscontrol.ActionAlertingSilencesCreate, |
||||
accesscontrol.ActionAlertingSilencesWrite, |
||||
libraryelements.ActionLibraryPanelsCreate, |
||||
libraryelements.ActionLibraryPanelsWrite, |
||||
libraryelements.ActionLibraryPanelsDelete, |
||||
}...) |
||||
var FolderAdminActions = append(FolderEditActions, []string{dashboards.ActionFoldersPermissionsRead, dashboards.ActionFoldersPermissionsWrite}...) |
||||
|
||||
func registerFolderRoles(cfg *setting.Cfg, features featuremgmt.FeatureToggles, service accesscontrol.Service) error { |
||||
if !cfg.RBAC.PermissionsWildcardSeed("folder") { |
||||
return nil |
||||
} |
||||
|
||||
viewer := accesscontrol.RoleRegistration{ |
||||
Role: accesscontrol.RoleDTO{ |
||||
Name: "fixed:folders:viewer", |
||||
DisplayName: "Viewer", |
||||
Description: "View all folders and dashboards.", |
||||
Group: "Folders", |
||||
Permissions: accesscontrol.PermissionsForActions(append(getDashboardViewActions(features), FolderViewActions...), dashboards.ScopeFoldersAll), |
||||
Hidden: true, |
||||
}, |
||||
Grants: []string{"Viewer"}, |
||||
} |
||||
|
||||
editor := accesscontrol.RoleRegistration{ |
||||
Role: accesscontrol.RoleDTO{ |
||||
Name: "fixed:folders:editor", |
||||
DisplayName: "Editor", |
||||
Description: "Edit all folders and dashboards.", |
||||
Group: "Folders", |
||||
Permissions: accesscontrol.PermissionsForActions(append(getDashboardEditActions(features), FolderEditActions...), dashboards.ScopeFoldersAll), |
||||
Hidden: true, |
||||
}, |
||||
Grants: []string{"Editor"}, |
||||
} |
||||
|
||||
admin := accesscontrol.RoleRegistration{ |
||||
Role: accesscontrol.RoleDTO{ |
||||
Name: "fixed:folders:admin", |
||||
DisplayName: "Admin", |
||||
Description: "Administer all folders and dashboards", |
||||
Group: "folders", |
||||
Permissions: accesscontrol.PermissionsForActions(append(getDashboardAdminActions(features), FolderAdminActions...), dashboards.ScopeFoldersAll), |
||||
Hidden: true, |
||||
}, |
||||
Grants: []string{"Admin"}, |
||||
} |
||||
|
||||
return service.DeclareFixedRoles(viewer, editor, admin) |
||||
} |
||||
|
||||
func ProvideFolderPermissions( |
||||
cfg *setting.Cfg, features featuremgmt.FeatureToggles, router routing.RouteRegister, sql db.DB, accesscontrol accesscontrol.AccessControl, |
||||
license licensing.Licensing, dashboardStore dashboards.Store, folderService folder.Service, service accesscontrol.Service, |
||||
teamService team.Service, userService user.Service, actionSetService resourcepermissions.ActionSetService, |
||||
) (*FolderPermissionsService, error) { |
||||
if err := registerFolderRoles(cfg, features, service); err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
options := resourcepermissions.Options{ |
||||
Resource: "folders", |
||||
ResourceAttribute: "uid", |
||||
ResourceValidator: func(ctx context.Context, orgID int64, resourceID string) error { |
||||
query := &dashboards.GetDashboardQuery{UID: resourceID, OrgID: orgID} |
||||
queryResult, err := dashboardStore.GetDashboard(ctx, query) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
if !queryResult.IsFolder { |
||||
return errors.New("not found") |
||||
} |
||||
|
||||
return nil |
||||
}, |
||||
InheritedScopesSolver: func(ctx context.Context, orgID int64, resourceID string) ([]string, error) { |
||||
return dashboards.GetInheritedScopes(ctx, orgID, resourceID, folderService) |
||||
}, |
||||
Assignments: resourcepermissions.Assignments{ |
||||
Users: true, |
||||
Teams: true, |
||||
BuiltInRoles: true, |
||||
ServiceAccounts: true, |
||||
}, |
||||
PermissionsToActions: map[string][]string{ |
||||
"View": append(getDashboardViewActions(features), FolderViewActions...), |
||||
"Edit": append(getDashboardEditActions(features), FolderEditActions...), |
||||
"Admin": append(getDashboardAdminActions(features), FolderAdminActions...), |
||||
}, |
||||
ReaderRoleName: "Folder permission reader", |
||||
WriterRoleName: "Folder permission writer", |
||||
RoleGroup: "Folders", |
||||
} |
||||
srv, err := resourcepermissions.New(cfg, options, features, router, license, accesscontrol, service, sql, teamService, userService, actionSetService) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &FolderPermissionsService{srv}, nil |
||||
} |
||||
@ -1,417 +0,0 @@ |
||||
package ossaccesscontrol |
||||
|
||||
import ( |
||||
"context" |
||||
"errors" |
||||
"fmt" |
||||
"strconv" |
||||
|
||||
"github.com/grafana/grafana/pkg/api/routing" |
||||
"github.com/grafana/grafana/pkg/apimachinery/identity" |
||||
"github.com/grafana/grafana/pkg/infra/db" |
||||
"github.com/grafana/grafana/pkg/infra/metrics" |
||||
"github.com/grafana/grafana/pkg/services/accesscontrol" |
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions" |
||||
"github.com/grafana/grafana/pkg/services/dashboards" |
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess" |
||||
"github.com/grafana/grafana/pkg/services/datasources" |
||||
"github.com/grafana/grafana/pkg/services/featuremgmt" |
||||
"github.com/grafana/grafana/pkg/services/folder" |
||||
"github.com/grafana/grafana/pkg/services/libraryelements" |
||||
"github.com/grafana/grafana/pkg/services/licensing" |
||||
"github.com/grafana/grafana/pkg/services/serviceaccounts" |
||||
"github.com/grafana/grafana/pkg/services/serviceaccounts/retriever" |
||||
"github.com/grafana/grafana/pkg/services/team" |
||||
"github.com/grafana/grafana/pkg/services/team/teamimpl" |
||||
"github.com/grafana/grafana/pkg/services/user" |
||||
"github.com/grafana/grafana/pkg/setting" |
||||
) |
||||
|
||||
type TeamPermissionsService struct { |
||||
*resourcepermissions.Service |
||||
} |
||||
|
||||
var ( |
||||
TeamMemberActions = []string{ |
||||
accesscontrol.ActionTeamsRead, |
||||
} |
||||
|
||||
TeamAdminActions = []string{ |
||||
accesscontrol.ActionTeamsRead, |
||||
accesscontrol.ActionTeamsDelete, |
||||
accesscontrol.ActionTeamsWrite, |
||||
accesscontrol.ActionTeamsPermissionsRead, |
||||
accesscontrol.ActionTeamsPermissionsWrite, |
||||
} |
||||
) |
||||
|
||||
func ProvideTeamPermissions( |
||||
cfg *setting.Cfg, features featuremgmt.FeatureToggles, router routing.RouteRegister, sql db.DB, |
||||
ac accesscontrol.AccessControl, license licensing.Licensing, service accesscontrol.Service, |
||||
teamService team.Service, userService user.Service, actionSetService resourcepermissions.ActionSetService, |
||||
) (*TeamPermissionsService, error) { |
||||
options := resourcepermissions.Options{ |
||||
Resource: "teams", |
||||
ResourceAttribute: "id", |
||||
OnlyManaged: true, |
||||
ResourceValidator: func(ctx context.Context, orgID int64, resourceID string) error { |
||||
id, err := strconv.ParseInt(resourceID, 10, 64) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
_, err = teamService.GetTeamByID(context.Background(), &team.GetTeamByIDQuery{ |
||||
OrgID: orgID, |
||||
ID: id, |
||||
}) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
return nil |
||||
}, |
||||
Assignments: resourcepermissions.Assignments{ |
||||
Users: true, |
||||
Teams: false, |
||||
BuiltInRoles: false, |
||||
}, |
||||
PermissionsToActions: map[string][]string{ |
||||
"Member": TeamMemberActions, |
||||
"Admin": TeamAdminActions, |
||||
}, |
||||
ReaderRoleName: "Team permission reader", |
||||
WriterRoleName: "Team permission writer", |
||||
RoleGroup: "Teams", |
||||
OnSetUser: func(session *db.Session, orgID int64, user accesscontrol.User, resourceID, permission string) error { |
||||
teamId, err := strconv.ParseInt(resourceID, 10, 64) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
switch permission { |
||||
case "Member": |
||||
return teamimpl.AddOrUpdateTeamMemberHook(session, user.ID, orgID, teamId, user.IsExternal, 0) |
||||
case "Admin": |
||||
return teamimpl.AddOrUpdateTeamMemberHook(session, user.ID, orgID, teamId, user.IsExternal, dashboardaccess.PERMISSION_ADMIN) |
||||
case "": |
||||
return teamimpl.RemoveTeamMemberHook(session, &team.RemoveTeamMemberCommand{ |
||||
OrgID: orgID, |
||||
UserID: user.ID, |
||||
TeamID: teamId, |
||||
}) |
||||
default: |
||||
return fmt.Errorf("invalid team permission type %s", permission) |
||||
} |
||||
}, |
||||
} |
||||
|
||||
srv, err := resourcepermissions.New(cfg, options, features, router, license, ac, service, sql, teamService, userService, actionSetService) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &TeamPermissionsService{srv}, nil |
||||
} |
||||
|
||||
type DashboardPermissionsService struct { |
||||
*resourcepermissions.Service |
||||
} |
||||
|
||||
var DashboardViewActions = []string{dashboards.ActionDashboardsRead} |
||||
var DashboardEditActions = append(DashboardViewActions, []string{dashboards.ActionDashboardsWrite, dashboards.ActionDashboardsDelete}...) |
||||
var DashboardAdminActions = append(DashboardEditActions, []string{dashboards.ActionDashboardsPermissionsRead, dashboards.ActionDashboardsPermissionsWrite}...) |
||||
|
||||
func getDashboardViewActions(features featuremgmt.FeatureToggles) []string { |
||||
if features.IsEnabled(context.Background(), featuremgmt.FlagAnnotationPermissionUpdate) { |
||||
return append(DashboardViewActions, accesscontrol.ActionAnnotationsRead) |
||||
} |
||||
return DashboardViewActions |
||||
} |
||||
|
||||
func getDashboardEditActions(features featuremgmt.FeatureToggles) []string { |
||||
if features.IsEnabled(context.Background(), featuremgmt.FlagAnnotationPermissionUpdate) { |
||||
return append(DashboardEditActions, []string{accesscontrol.ActionAnnotationsRead, accesscontrol.ActionAnnotationsWrite, accesscontrol.ActionAnnotationsDelete, accesscontrol.ActionAnnotationsCreate}...) |
||||
} |
||||
return DashboardEditActions |
||||
} |
||||
|
||||
func getDashboardAdminActions(features featuremgmt.FeatureToggles) []string { |
||||
if features.IsEnabled(context.Background(), featuremgmt.FlagAnnotationPermissionUpdate) { |
||||
return append(DashboardAdminActions, []string{accesscontrol.ActionAnnotationsRead, accesscontrol.ActionAnnotationsWrite, accesscontrol.ActionAnnotationsDelete, accesscontrol.ActionAnnotationsCreate}...) |
||||
} |
||||
return DashboardAdminActions |
||||
} |
||||
|
||||
func ProvideDashboardPermissions( |
||||
cfg *setting.Cfg, features featuremgmt.FeatureToggles, router routing.RouteRegister, sql db.DB, ac accesscontrol.AccessControl, |
||||
license licensing.Licensing, dashboardStore dashboards.Store, folderService folder.Service, service accesscontrol.Service, |
||||
teamService team.Service, userService user.Service, actionSetService resourcepermissions.ActionSetService, |
||||
) (*DashboardPermissionsService, error) { |
||||
getDashboard := func(ctx context.Context, orgID int64, resourceID string) (*dashboards.Dashboard, error) { |
||||
query := &dashboards.GetDashboardQuery{UID: resourceID, OrgID: orgID} |
||||
queryResult, err := dashboardStore.GetDashboard(ctx, query) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return queryResult, nil |
||||
} |
||||
|
||||
options := resourcepermissions.Options{ |
||||
Resource: "dashboards", |
||||
ResourceAttribute: "uid", |
||||
ResourceValidator: func(ctx context.Context, orgID int64, resourceID string) error { |
||||
dashboard, err := getDashboard(ctx, orgID, resourceID) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
if dashboard.IsFolder { |
||||
return errors.New("not found") |
||||
} |
||||
|
||||
return nil |
||||
}, |
||||
InheritedScopesSolver: func(ctx context.Context, orgID int64, resourceID string) ([]string, error) { |
||||
wildcards := accesscontrol.WildcardsFromPrefix(dashboards.ScopeFoldersPrefix) |
||||
scopes := []string(wildcards) |
||||
|
||||
dashboard, err := getDashboard(ctx, orgID, resourceID) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.AccessControl).Inc() |
||||
// nolint:staticcheck
|
||||
if dashboard.FolderUID != "" { |
||||
query := &dashboards.GetDashboardQuery{UID: dashboard.FolderUID, OrgID: orgID} |
||||
queryResult, err := dashboardStore.GetDashboard(ctx, query) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
parentScope := dashboards.ScopeFoldersProvider.GetResourceScopeUID(queryResult.UID) |
||||
|
||||
nestedScopes, err := dashboards.GetInheritedScopes(ctx, orgID, queryResult.UID, folderService) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
scopes = append(scopes, parentScope) |
||||
scopes = append(scopes, nestedScopes...) |
||||
return scopes, nil |
||||
} |
||||
return append(scopes, dashboards.ScopeFoldersProvider.GetResourceScopeUID(folder.GeneralFolderUID)), nil |
||||
}, |
||||
Assignments: resourcepermissions.Assignments{ |
||||
Users: true, |
||||
Teams: true, |
||||
BuiltInRoles: true, |
||||
ServiceAccounts: true, |
||||
}, |
||||
PermissionsToActions: map[string][]string{ |
||||
"View": getDashboardViewActions(features), |
||||
"Edit": getDashboardEditActions(features), |
||||
"Admin": getDashboardAdminActions(features), |
||||
}, |
||||
ReaderRoleName: "Dashboard permission reader", |
||||
WriterRoleName: "Dashboard permission writer", |
||||
RoleGroup: "Dashboards", |
||||
} |
||||
|
||||
srv, err := resourcepermissions.New(cfg, options, features, router, license, ac, service, sql, teamService, userService, actionSetService) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &DashboardPermissionsService{srv}, nil |
||||
} |
||||
|
||||
type FolderPermissionsService struct { |
||||
*resourcepermissions.Service |
||||
} |
||||
|
||||
var FolderViewActions = []string{dashboards.ActionFoldersRead, accesscontrol.ActionAlertingRuleRead, libraryelements.ActionLibraryPanelsRead, accesscontrol.ActionAlertingSilencesRead} |
||||
var FolderEditActions = append(FolderViewActions, []string{ |
||||
dashboards.ActionFoldersWrite, |
||||
dashboards.ActionFoldersDelete, |
||||
dashboards.ActionDashboardsCreate, |
||||
accesscontrol.ActionAlertingRuleCreate, |
||||
accesscontrol.ActionAlertingRuleUpdate, |
||||
accesscontrol.ActionAlertingRuleDelete, |
||||
accesscontrol.ActionAlertingSilencesCreate, |
||||
accesscontrol.ActionAlertingSilencesWrite, |
||||
libraryelements.ActionLibraryPanelsCreate, |
||||
libraryelements.ActionLibraryPanelsWrite, |
||||
libraryelements.ActionLibraryPanelsDelete, |
||||
}...) |
||||
var FolderAdminActions = append(FolderEditActions, []string{dashboards.ActionFoldersPermissionsRead, dashboards.ActionFoldersPermissionsWrite}...) |
||||
|
||||
func ProvideFolderPermissions( |
||||
cfg *setting.Cfg, features featuremgmt.FeatureToggles, router routing.RouteRegister, sql db.DB, accesscontrol accesscontrol.AccessControl, |
||||
license licensing.Licensing, dashboardStore dashboards.Store, folderService folder.Service, service accesscontrol.Service, |
||||
teamService team.Service, userService user.Service, actionSetService resourcepermissions.ActionSetService, |
||||
) (*FolderPermissionsService, error) { |
||||
options := resourcepermissions.Options{ |
||||
Resource: "folders", |
||||
ResourceAttribute: "uid", |
||||
ResourceValidator: func(ctx context.Context, orgID int64, resourceID string) error { |
||||
query := &dashboards.GetDashboardQuery{UID: resourceID, OrgID: orgID} |
||||
queryResult, err := dashboardStore.GetDashboard(ctx, query) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
if !queryResult.IsFolder { |
||||
return errors.New("not found") |
||||
} |
||||
|
||||
return nil |
||||
}, |
||||
InheritedScopesSolver: func(ctx context.Context, orgID int64, resourceID string) ([]string, error) { |
||||
return dashboards.GetInheritedScopes(ctx, orgID, resourceID, folderService) |
||||
}, |
||||
Assignments: resourcepermissions.Assignments{ |
||||
Users: true, |
||||
Teams: true, |
||||
BuiltInRoles: true, |
||||
ServiceAccounts: true, |
||||
}, |
||||
PermissionsToActions: map[string][]string{ |
||||
"View": append(getDashboardViewActions(features), FolderViewActions...), |
||||
"Edit": append(getDashboardEditActions(features), FolderEditActions...), |
||||
"Admin": append(getDashboardAdminActions(features), FolderAdminActions...), |
||||
}, |
||||
ReaderRoleName: "Folder permission reader", |
||||
WriterRoleName: "Folder permission writer", |
||||
RoleGroup: "Folders", |
||||
} |
||||
srv, err := resourcepermissions.New(cfg, options, features, router, license, accesscontrol, service, sql, teamService, userService, actionSetService) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &FolderPermissionsService{srv}, nil |
||||
} |
||||
|
||||
// DatasourceQueryActions contains permissions to read information
|
||||
// about a data source and submit arbitrary queries to it.
|
||||
var DatasourceQueryActions = []string{ |
||||
datasources.ActionRead, |
||||
datasources.ActionQuery, |
||||
} |
||||
|
||||
func ProvideDatasourcePermissionsService(cfg *setting.Cfg, features featuremgmt.FeatureToggles, db db.DB) *DatasourcePermissionsService { |
||||
return &DatasourcePermissionsService{ |
||||
store: resourcepermissions.NewStore(cfg, db, features), |
||||
} |
||||
} |
||||
|
||||
var _ accesscontrol.DatasourcePermissionsService = new(DatasourcePermissionsService) |
||||
|
||||
type DatasourcePermissionsService struct { |
||||
store resourcepermissions.Store |
||||
} |
||||
|
||||
func (e DatasourcePermissionsService) GetPermissions(ctx context.Context, user identity.Requester, resourceID string) ([]accesscontrol.ResourcePermission, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (e DatasourcePermissionsService) SetUserPermission(ctx context.Context, orgID int64, user accesscontrol.User, resourceID, permission string) (*accesscontrol.ResourcePermission, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (e DatasourcePermissionsService) SetTeamPermission(ctx context.Context, orgID, teamID int64, resourceID, permission string) (*accesscontrol.ResourcePermission, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (e DatasourcePermissionsService) SetBuiltInRolePermission(ctx context.Context, orgID int64, builtInRole string, resourceID string, permission string) (*accesscontrol.ResourcePermission, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
// SetPermissions sets managed permissions for a datasource in OSS. This ensures that Viewers and Editors maintain query access to a data source
|
||||
// if an OSS/unlicensed instance is upgraded to Enterprise/licensed.
|
||||
// https://github.com/grafana/identity-access-team/issues/672
|
||||
func (e DatasourcePermissionsService) SetPermissions(ctx context.Context, orgID int64, resourceID string, commands ...accesscontrol.SetResourcePermissionCommand) ([]accesscontrol.ResourcePermission, error) { |
||||
dbCommands := make([]resourcepermissions.SetResourcePermissionsCommand, 0, len(commands)) |
||||
for _, cmd := range commands { |
||||
// Only set query permissions for built-in roles; do not set permissions for data sources with * as UID, as this would grant wildcard permissions
|
||||
if cmd.Permission != "Query" || cmd.BuiltinRole == "" || resourceID == "*" { |
||||
continue |
||||
} |
||||
actions := DatasourceQueryActions |
||||
|
||||
dbCommands = append(dbCommands, resourcepermissions.SetResourcePermissionsCommand{ |
||||
BuiltinRole: cmd.BuiltinRole, |
||||
SetResourcePermissionCommand: resourcepermissions.SetResourcePermissionCommand{ |
||||
Actions: actions, |
||||
Resource: datasources.ScopeRoot, |
||||
ResourceID: resourceID, |
||||
ResourceAttribute: "uid", |
||||
Permission: cmd.Permission, |
||||
}, |
||||
}) |
||||
} |
||||
|
||||
return e.store.SetResourcePermissions(ctx, orgID, dbCommands, resourcepermissions.ResourceHooks{}) |
||||
} |
||||
|
||||
func (e DatasourcePermissionsService) DeleteResourcePermissions(ctx context.Context, orgID int64, resourceID string) error { |
||||
return e.store.DeleteResourcePermissions(ctx, orgID, &resourcepermissions.DeleteResourcePermissionsCmd{ |
||||
Resource: datasources.ScopeRoot, |
||||
ResourceAttribute: "uid", |
||||
ResourceID: resourceID, |
||||
}) |
||||
} |
||||
|
||||
func (e DatasourcePermissionsService) MapActions(permission accesscontrol.ResourcePermission) string { |
||||
return "" |
||||
} |
||||
|
||||
var ( |
||||
ServiceAccountEditActions = []string{ |
||||
serviceaccounts.ActionRead, |
||||
serviceaccounts.ActionWrite, |
||||
} |
||||
ServiceAccountAdminActions = []string{ |
||||
serviceaccounts.ActionRead, |
||||
serviceaccounts.ActionWrite, |
||||
serviceaccounts.ActionDelete, |
||||
serviceaccounts.ActionPermissionsRead, |
||||
serviceaccounts.ActionPermissionsWrite, |
||||
} |
||||
) |
||||
|
||||
type ServiceAccountPermissionsService struct { |
||||
*resourcepermissions.Service |
||||
} |
||||
|
||||
func ProvideServiceAccountPermissions( |
||||
cfg *setting.Cfg, features featuremgmt.FeatureToggles, router routing.RouteRegister, sql db.DB, ac accesscontrol.AccessControl, |
||||
license licensing.Licensing, serviceAccountRetrieverService *retriever.Service, service accesscontrol.Service, |
||||
teamService team.Service, userService user.Service, actionSetService resourcepermissions.ActionSetService, |
||||
) (*ServiceAccountPermissionsService, error) { |
||||
options := resourcepermissions.Options{ |
||||
Resource: "serviceaccounts", |
||||
ResourceAttribute: "id", |
||||
ResourceValidator: func(ctx context.Context, orgID int64, resourceID string) error { |
||||
id, err := strconv.ParseInt(resourceID, 10, 64) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
_, err = serviceAccountRetrieverService.RetrieveServiceAccount(ctx, orgID, id) |
||||
return err |
||||
}, |
||||
Assignments: resourcepermissions.Assignments{ |
||||
Users: true, |
||||
Teams: true, |
||||
BuiltInRoles: false, |
||||
}, |
||||
PermissionsToActions: map[string][]string{ |
||||
"Edit": ServiceAccountEditActions, |
||||
"Admin": ServiceAccountAdminActions, |
||||
}, |
||||
ReaderRoleName: "Service account permission reader", |
||||
WriterRoleName: "Service account permission writer", |
||||
RoleGroup: "Service accounts", |
||||
} |
||||
|
||||
srv, err := resourcepermissions.New(cfg, options, features, router, license, ac, service, sql, teamService, userService, actionSetService) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &ServiceAccountPermissionsService{srv}, nil |
||||
} |
||||
@ -0,0 +1,73 @@ |
||||
package ossaccesscontrol |
||||
|
||||
import ( |
||||
"context" |
||||
"strconv" |
||||
|
||||
"github.com/grafana/grafana/pkg/api/routing" |
||||
"github.com/grafana/grafana/pkg/infra/db" |
||||
"github.com/grafana/grafana/pkg/services/accesscontrol" |
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions" |
||||
"github.com/grafana/grafana/pkg/services/featuremgmt" |
||||
"github.com/grafana/grafana/pkg/services/licensing" |
||||
"github.com/grafana/grafana/pkg/services/serviceaccounts" |
||||
"github.com/grafana/grafana/pkg/services/serviceaccounts/retriever" |
||||
"github.com/grafana/grafana/pkg/services/team" |
||||
"github.com/grafana/grafana/pkg/services/user" |
||||
"github.com/grafana/grafana/pkg/setting" |
||||
) |
||||
|
||||
var ( |
||||
ServiceAccountEditActions = []string{ |
||||
serviceaccounts.ActionRead, |
||||
serviceaccounts.ActionWrite, |
||||
} |
||||
ServiceAccountAdminActions = []string{ |
||||
serviceaccounts.ActionRead, |
||||
serviceaccounts.ActionWrite, |
||||
serviceaccounts.ActionDelete, |
||||
serviceaccounts.ActionPermissionsRead, |
||||
serviceaccounts.ActionPermissionsWrite, |
||||
} |
||||
) |
||||
|
||||
type ServiceAccountPermissionsService struct { |
||||
*resourcepermissions.Service |
||||
} |
||||
|
||||
func ProvideServiceAccountPermissions( |
||||
cfg *setting.Cfg, features featuremgmt.FeatureToggles, router routing.RouteRegister, sql db.DB, ac accesscontrol.AccessControl, |
||||
license licensing.Licensing, serviceAccountRetrieverService *retriever.Service, service accesscontrol.Service, |
||||
teamService team.Service, userService user.Service, actionSetService resourcepermissions.ActionSetService, |
||||
) (*ServiceAccountPermissionsService, error) { |
||||
options := resourcepermissions.Options{ |
||||
Resource: "serviceaccounts", |
||||
ResourceAttribute: "id", |
||||
ResourceValidator: func(ctx context.Context, orgID int64, resourceID string) error { |
||||
id, err := strconv.ParseInt(resourceID, 10, 64) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
_, err = serviceAccountRetrieverService.RetrieveServiceAccount(ctx, orgID, id) |
||||
return err |
||||
}, |
||||
Assignments: resourcepermissions.Assignments{ |
||||
Users: true, |
||||
Teams: true, |
||||
BuiltInRoles: false, |
||||
}, |
||||
PermissionsToActions: map[string][]string{ |
||||
"Edit": ServiceAccountEditActions, |
||||
"Admin": ServiceAccountAdminActions, |
||||
}, |
||||
ReaderRoleName: "Service account permission reader", |
||||
WriterRoleName: "Service account permission writer", |
||||
RoleGroup: "Service accounts", |
||||
} |
||||
|
||||
srv, err := resourcepermissions.New(cfg, options, features, router, license, ac, service, sql, teamService, userService, actionSetService) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &ServiceAccountPermissionsService{srv}, nil |
||||
} |
||||
@ -0,0 +1,103 @@ |
||||
package ossaccesscontrol |
||||
|
||||
import ( |
||||
"context" |
||||
"fmt" |
||||
"strconv" |
||||
|
||||
"github.com/grafana/grafana/pkg/api/routing" |
||||
"github.com/grafana/grafana/pkg/infra/db" |
||||
"github.com/grafana/grafana/pkg/services/accesscontrol" |
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions" |
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess" |
||||
"github.com/grafana/grafana/pkg/services/featuremgmt" |
||||
"github.com/grafana/grafana/pkg/services/licensing" |
||||
"github.com/grafana/grafana/pkg/services/team" |
||||
"github.com/grafana/grafana/pkg/services/team/teamimpl" |
||||
"github.com/grafana/grafana/pkg/services/user" |
||||
"github.com/grafana/grafana/pkg/setting" |
||||
) |
||||
|
||||
type TeamPermissionsService struct { |
||||
*resourcepermissions.Service |
||||
} |
||||
|
||||
var ( |
||||
TeamMemberActions = []string{ |
||||
accesscontrol.ActionTeamsRead, |
||||
} |
||||
|
||||
TeamAdminActions = []string{ |
||||
accesscontrol.ActionTeamsRead, |
||||
accesscontrol.ActionTeamsDelete, |
||||
accesscontrol.ActionTeamsWrite, |
||||
accesscontrol.ActionTeamsPermissionsRead, |
||||
accesscontrol.ActionTeamsPermissionsWrite, |
||||
} |
||||
) |
||||
|
||||
func ProvideTeamPermissions( |
||||
cfg *setting.Cfg, features featuremgmt.FeatureToggles, router routing.RouteRegister, sql db.DB, |
||||
ac accesscontrol.AccessControl, license licensing.Licensing, service accesscontrol.Service, |
||||
teamService team.Service, userService user.Service, actionSetService resourcepermissions.ActionSetService, |
||||
) (*TeamPermissionsService, error) { |
||||
options := resourcepermissions.Options{ |
||||
Resource: "teams", |
||||
ResourceAttribute: "id", |
||||
OnlyManaged: true, |
||||
ResourceValidator: func(ctx context.Context, orgID int64, resourceID string) error { |
||||
id, err := strconv.ParseInt(resourceID, 10, 64) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
_, err = teamService.GetTeamByID(context.Background(), &team.GetTeamByIDQuery{ |
||||
OrgID: orgID, |
||||
ID: id, |
||||
}) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
return nil |
||||
}, |
||||
Assignments: resourcepermissions.Assignments{ |
||||
Users: true, |
||||
Teams: false, |
||||
BuiltInRoles: false, |
||||
}, |
||||
PermissionsToActions: map[string][]string{ |
||||
"Member": TeamMemberActions, |
||||
"Admin": TeamAdminActions, |
||||
}, |
||||
ReaderRoleName: "Team permission reader", |
||||
WriterRoleName: "Team permission writer", |
||||
RoleGroup: "Teams", |
||||
OnSetUser: func(session *db.Session, orgID int64, user accesscontrol.User, resourceID, permission string) error { |
||||
teamId, err := strconv.ParseInt(resourceID, 10, 64) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
switch permission { |
||||
case "Member": |
||||
return teamimpl.AddOrUpdateTeamMemberHook(session, user.ID, orgID, teamId, user.IsExternal, 0) |
||||
case "Admin": |
||||
return teamimpl.AddOrUpdateTeamMemberHook(session, user.ID, orgID, teamId, user.IsExternal, dashboardaccess.PERMISSION_ADMIN) |
||||
case "": |
||||
return teamimpl.RemoveTeamMemberHook(session, &team.RemoveTeamMemberCommand{ |
||||
OrgID: orgID, |
||||
UserID: user.ID, |
||||
TeamID: teamId, |
||||
}) |
||||
default: |
||||
return fmt.Errorf("invalid team permission type %s", permission) |
||||
} |
||||
}, |
||||
} |
||||
|
||||
srv, err := resourcepermissions.New(cfg, options, features, router, license, ac, service, sql, teamService, userService, actionSetService) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &TeamPermissionsService{srv}, nil |
||||
} |
||||
@ -0,0 +1,61 @@ |
||||
package setting |
||||
|
||||
import ( |
||||
"github.com/grafana/grafana/pkg/util" |
||||
) |
||||
|
||||
type RBACSettings struct { |
||||
// Enable permission cache
|
||||
PermissionCache bool |
||||
// Enable Permission validation during role creation and provisioning
|
||||
PermissionValidationEnabled bool |
||||
// Reset basic roles permissions on start-up
|
||||
ResetBasicRoles bool |
||||
// RBAC single organization. This configuration option is subject to change.
|
||||
SingleOrganization bool |
||||
|
||||
OnlyStoreAccessActionSets bool |
||||
|
||||
// set of resources that should generate managed permissions when created
|
||||
resourcesWithPermissionsOnCreation map[string]struct{} |
||||
|
||||
// set of resources that should we should seed wildcard scopes for
|
||||
resourcesWithWildcardSeed map[string]struct{} |
||||
} |
||||
|
||||
func (cfg *Cfg) readRBACSettings() { |
||||
s := RBACSettings{} |
||||
|
||||
rbac := cfg.Raw.Section("rbac") |
||||
s.PermissionCache = rbac.Key("permission_cache").MustBool(true) |
||||
s.PermissionValidationEnabled = rbac.Key("permission_validation_enabled").MustBool(false) |
||||
s.ResetBasicRoles = rbac.Key("reset_basic_roles").MustBool(false) |
||||
s.SingleOrganization = rbac.Key("single_organization").MustBool(false) |
||||
s.OnlyStoreAccessActionSets = rbac.Key("only_store_access_action_sets").MustBool(false) |
||||
|
||||
// List of resources to generate managed permissions for upon resource creation (dashboard, folder, service-account, datasource)
|
||||
resources := util.SplitString(rbac.Key("resources_with_managed_permissions_on_creation").MustString("dashboard, folder, service-account, datasource")) |
||||
s.resourcesWithPermissionsOnCreation = map[string]struct{}{} |
||||
for _, resource := range resources { |
||||
s.resourcesWithPermissionsOnCreation[resource] = struct{}{} |
||||
} |
||||
|
||||
// List of resources to seed managed permission wildcards for (dashboard, folder, datasource)
|
||||
resources = util.SplitString(rbac.Key("resources_with_seeded_wildcard_access").MustString("")) |
||||
s.resourcesWithWildcardSeed = map[string]struct{}{} |
||||
for _, resource := range resources { |
||||
s.resourcesWithWildcardSeed[resource] = struct{}{} |
||||
} |
||||
|
||||
cfg.RBAC = s |
||||
} |
||||
|
||||
func (r RBACSettings) PermissionsOnCreation(resource string) bool { |
||||
_, ok := r.resourcesWithPermissionsOnCreation[resource] |
||||
return ok |
||||
} |
||||
|
||||
func (r RBACSettings) PermissionsWildcardSeed(resource string) bool { |
||||
_, ok := r.resourcesWithWildcardSeed[resource] |
||||
return ok |
||||
} |
||||
Loading…
Reference in new issue