From e9ec97b34c1f0a66acf6154e44ab17f55d04e019 Mon Sep 17 00:00:00 2001 From: Gabriel MABILLE Date: Thu, 9 Jun 2022 14:25:04 +0200 Subject: [PATCH] RBAC: Include alert.rules action when setting folder permissions (#49946) (#50510) * Generate additional actions when setting folder permissions in acl list * Add migration for managed folder permissions to include alert rule actions (cherry picked from commit bdff63d4a8c25b6e2e400d278b11eb510db030e7) Co-authored-by: Karl Persson --- .../ossaccesscontrol/permissions_services.go | 11 +- pkg/services/dashboards/accesscontrol.go | 1 + .../accesscontrol/dashboard_permissions.go | 124 ++++++++++++++++++ .../sqlstore/migrations/migrations.go | 1 + 4 files changed, 135 insertions(+), 2 deletions(-) diff --git a/pkg/services/accesscontrol/ossaccesscontrol/permissions_services.go b/pkg/services/accesscontrol/ossaccesscontrol/permissions_services.go index 217812cea9f..98a71016e28 100644 --- a/pkg/services/accesscontrol/ossaccesscontrol/permissions_services.go +++ b/pkg/services/accesscontrol/ossaccesscontrol/permissions_services.go @@ -202,8 +202,15 @@ func ProvideDashboardPermissions( return resourcepermissions.New(options, cfg, router, ac, store, sql) } -var FolderViewActions = []string{dashboards.ActionFoldersRead} -var FolderEditActions = append(FolderViewActions, []string{dashboards.ActionFoldersWrite, dashboards.ActionFoldersDelete, accesscontrol.ActionDashboardsCreate}...) +var FolderViewActions = []string{dashboards.ActionFoldersRead, accesscontrol.ActionAlertingRuleRead} +var FolderEditActions = append(FolderViewActions, []string{ + dashboards.ActionFoldersWrite, + dashboards.ActionFoldersDelete, + dashboards.ActionDashboardsCreate, + accesscontrol.ActionAlertingRuleCreate, + accesscontrol.ActionAlertingRuleUpdate, + accesscontrol.ActionAlertingRuleDelete, +}...) var FolderAdminActions = append(FolderEditActions, []string{dashboards.ActionFoldersPermissionsRead, dashboards.ActionFoldersPermissionsWrite}...) func ProvideFolderPermissions( diff --git a/pkg/services/dashboards/accesscontrol.go b/pkg/services/dashboards/accesscontrol.go index d362fc270f9..e6cf25461e9 100644 --- a/pkg/services/dashboards/accesscontrol.go +++ b/pkg/services/dashboards/accesscontrol.go @@ -12,6 +12,7 @@ const ( ScopeFoldersRoot = "folders" ScopeFoldersPrefix = "folders:uid:" + ActionDashboardsCreate = "dashboards:create" ActionFoldersCreate = "folders:create" ActionFoldersRead = "folders:read" ActionFoldersWrite = "folders:write" diff --git a/pkg/services/sqlstore/migrations/accesscontrol/dashboard_permissions.go b/pkg/services/sqlstore/migrations/accesscontrol/dashboard_permissions.go index 5811a290cdd..7ff19d4e614 100644 --- a/pkg/services/sqlstore/migrations/accesscontrol/dashboard_permissions.go +++ b/pkg/services/sqlstore/migrations/accesscontrol/dashboard_permissions.go @@ -294,3 +294,127 @@ func (m *managedFolderCreateAction) Exec(sess *xorm.Session, migrator *migrator. } return nil } + +const managedFolderAlertActionsMigratorID = "managed folder permissions alert actions migration" + +func AddManagedFolderAlertActionsMigration(mg *migrator.Migrator) { + mg.AddMigration(managedFolderAlertActionsMigratorID, &managedFolderAlertActionsMigrator{}) +} + +type managedFolderAlertActionsMigrator struct { + migrator.MigrationBase +} + +func (m *managedFolderAlertActionsMigrator) SQL(dialect migrator.Dialect) string { + return CodeMigrationSQL +} + +func (m *managedFolderAlertActionsMigrator) Exec(sess *xorm.Session, mg *migrator.Migrator) error { + var ids []interface{} + if err := sess.SQL("SELECT id FROM role WHERE name LIKE 'managed:%'").Find(&ids); err != nil { + return err + } + + if len(ids) == 0 { + return nil + } + + var permissions []ac.Permission + if err := sess.SQL("SELECT role_id, action, scope FROM permission WHERE role_id IN(?"+strings.Repeat(" ,?", len(ids)-1)+") AND scope LIKE 'folders:%'", ids...).Find(&permissions); err != nil { + return err + } + + mapped := make(map[int64]map[string][]ac.Permission, len(ids)-1) + for _, p := range permissions { + if mapped[p.RoleID] == nil { + mapped[p.RoleID] = make(map[string][]ac.Permission) + } + mapped[p.RoleID][p.Scope] = append(mapped[p.RoleID][p.Scope], p) + } + + var toAdd []ac.Permission + now := time.Now() + + for id, a := range mapped { + for scope, p := range a { + if hasFolderView(p) { + toAdd = append(toAdd, ac.Permission{ + RoleID: id, + Updated: now, + Created: now, + Scope: scope, + Action: ac.ActionAlertingRuleRead, + }) + } + + if hasFolderAdmin(p) || hasFolderEdit(p) { + toAdd = append( + toAdd, + ac.Permission{ + RoleID: id, + Updated: now, + Created: now, + Scope: scope, + Action: ac.ActionAlertingRuleCreate, + }, + ac.Permission{ + RoleID: id, + Updated: now, + Created: now, + Scope: scope, + Action: ac.ActionAlertingRuleDelete, + }, + ac.Permission{ + RoleID: id, + Updated: now, + Created: now, + Scope: scope, + Action: ac.ActionAlertingRuleUpdate, + }, + ) + } + } + } + + if len(toAdd) == 0 { + return nil + } + + err := batch(len(toAdd), batchSize, func(start, end int) error { + if _, err := sess.InsertMulti(toAdd[start:end]); err != nil { + return err + } + return nil + }) + + if err != nil { + return err + } + + return nil +} + +func hasFolderAdmin(permissions []ac.Permission) bool { + return hasActions(folderPermissionTranslation[models.PERMISSION_ADMIN], permissions) +} + +func hasFolderEdit(permissions []ac.Permission) bool { + return hasActions(folderPermissionTranslation[models.PERMISSION_EDIT], permissions) +} + +func hasFolderView(permissions []ac.Permission) bool { + return hasActions(folderPermissionTranslation[models.PERMISSION_VIEW], permissions) +} + +func hasActions(actions []string, permissions []ac.Permission) bool { + var contains int + for _, action := range actions { + for _, p := range permissions { + if action == p.Action { + contains++ + break + } + } + } + return contains >= len(actions) +} diff --git a/pkg/services/sqlstore/migrations/migrations.go b/pkg/services/sqlstore/migrations/migrations.go index 0912a5add95..0c43889d878 100644 --- a/pkg/services/sqlstore/migrations/migrations.go +++ b/pkg/services/sqlstore/migrations/migrations.go @@ -91,6 +91,7 @@ func (*OSSMigrations) AddMigration(mg *Migrator) { addCommentMigrations(mg) } } + accesscontrol.AddManagedFolderAlertActionsMigration(mg) } func addMigrationLogMigrations(mg *Migrator) {