From f0ff7d57b4bbad8907edcffc213dcb5a44119f68 Mon Sep 17 00:00:00 2001 From: Gabriel MABILLE Date: Fri, 21 Jun 2024 11:08:30 +0200 Subject: [PATCH] RBAC: Allow folders actions in plugins roles (#89523) * Allow some additional core actions for plugins * typo * Test nit. --- .../accesscontrol/pluginutils/utils.go | 30 ++++++++++++++----- .../accesscontrol/pluginutils/utils_test.go | 23 ++++++++++++++ 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/pkg/services/accesscontrol/pluginutils/utils.go b/pkg/services/accesscontrol/pluginutils/utils.go index ffbde39295f..7db8cf635a0 100644 --- a/pkg/services/accesscontrol/pluginutils/utils.go +++ b/pkg/services/accesscontrol/pluginutils/utils.go @@ -9,20 +9,36 @@ import ( "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginaccesscontrol" ) +var ( + allowedCoreActions = map[string]string{ + "plugins.app:access": "plugins:id:", + "folders:create": "folders:uid:", + "folders:read": "folders:uid:", + "folders:write": "folders:uid:", + "folders:delete": "folders:uid:", + "folders.permissions:read": "folders:uid:", + "folders.permissions:write": "folders:uid:", + } +) + // ValidatePluginPermissions errors when a permission does not match expected pattern for plugins func ValidatePluginPermissions(pluginID string, permissions []ac.Permission) error { for i := range permissions { - if permissions[i].Action != pluginaccesscontrol.ActionAppAccess && - !strings.HasPrefix(permissions[i].Action, pluginID+":") && + scopePrefix, isCore := allowedCoreActions[permissions[i].Action] + if isCore { + if permissions[i].Scope != scopePrefix+pluginID { + return &ac.ErrorScopeTarget{Action: permissions[i].Action, Scope: permissions[i].Scope, + ExpectedScope: scopePrefix + pluginID} + } + // Prevent any unlikely injection + permissions[i].Scope = scopePrefix + pluginID + continue + } + if !strings.HasPrefix(permissions[i].Action, pluginID+":") && !strings.HasPrefix(permissions[i].Action, pluginID+".") { return &ac.ErrorActionPrefixMissing{Action: permissions[i].Action, Prefixes: []string{pluginaccesscontrol.ActionAppAccess, pluginID + ":", pluginID + "."}} } - if strings.HasPrefix(permissions[i].Action, pluginaccesscontrol.ActionAppAccess) && - permissions[i].Scope != pluginaccesscontrol.ScopeProvider.GetResourceScope(pluginID) { - return &ac.ErrorScopeTarget{Action: permissions[i].Action, Scope: permissions[i].Scope, - ExpectedScope: pluginaccesscontrol.ScopeProvider.GetResourceScope(pluginID)} - } } return nil diff --git a/pkg/services/accesscontrol/pluginutils/utils_test.go b/pkg/services/accesscontrol/pluginutils/utils_test.go index 38ae6f4765c..80289ec77e7 100644 --- a/pkg/services/accesscontrol/pluginutils/utils_test.go +++ b/pkg/services/accesscontrol/pluginutils/utils_test.go @@ -149,6 +149,29 @@ func TestValidatePluginRole(t *testing.T) { }, wantErr: &ac.ErrorInvalidRole{}, }, + { + name: "valid core permission targets plugin", + pluginID: "test-app", + role: ac.RoleDTO{ + Name: "plugins:test-app:reader", + DisplayName: "Plugin Folder Reader", + Permissions: []ac.Permission{ + {Action: "folders:read", Scope: "folders:uid:test-app"}, + }, + }, + }, + { + name: "invalid core permission targets other plugin", + pluginID: "test-app", + role: ac.RoleDTO{ + Name: "plugins:test-app:reader", + DisplayName: "Plugin Folder Reader", + Permissions: []ac.Permission{ + {Action: "folders:read", Scope: "folders:uid:other-app"}, + }, + }, + wantErr: &ac.ErrorInvalidRole{}, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {