RBAC: Allow folders actions in plugins roles (#89523)

* Allow some additional core actions for plugins

* typo

* Test nit.
This commit is contained in:
Gabriel MABILLE 2024-06-21 11:08:30 +02:00 committed by GitHub
parent be65aaf5dc
commit f0ff7d57b4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 46 additions and 7 deletions

View File

@ -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

View File

@ -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) {