Plugins App: Add access control (#114869)

This commit is contained in:
Todd Treece
2025-12-05 12:56:01 -05:00
committed by GitHub
parent 74c7b5a292
commit 5b89d3b807
4 changed files with 145 additions and 9 deletions
+127
View File
@@ -0,0 +1,127 @@
package plugins
import (
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/org"
)
const (
// Plugins
ActionPluginsPluginsCreate = "plugins.plugins:create" // CREATE.
ActionPluginsPluginsWrite = "plugins.plugins:write" // UPDATE.
ActionPluginsPluginsRead = "plugins.plugins:read" // GET + LIST.
ActionPluginsPluginsDelete = "plugins.plugins:delete" // DELETE.
// PluginMetas
ActionPluginsPluginsMetaCreate = "plugins.pluginsmeta:create" // CREATE.
ActionPluginsPluginsMetaWrite = "plugins.pluginsmeta:write" // UPDATE.
ActionPluginsPluginsMetaRead = "plugins.pluginsmeta:read" // GET + LIST.
ActionPluginsPluginsMetaDelete = "plugins.pluginsmeta:delete" // DELETE.
)
var (
ScopeProviderPluginsPlugins = accesscontrol.NewScopeProvider("plugins.plugins")
ScopeProviderPluginsPluginsMeta = accesscontrol.NewScopeProvider("plugins.pluginsmeta")
ScopeAllPluginsPlugins = ScopeProviderPluginsPlugins.GetResourceAllScope()
ScopeAllPluginsPluginsMeta = ScopeProviderPluginsPluginsMeta.GetResourceAllScope()
)
func registerAccessControlRoles(service accesscontrol.Service) error {
// Plugins
pluginsReader := accesscontrol.RoleRegistration{
Role: accesscontrol.RoleDTO{
Name: "fixed:plugins.plugins:reader",
DisplayName: "Plugins Reader",
Description: "Read and list plugins.",
Group: "Plugins",
Permissions: []accesscontrol.Permission{
{
Action: ActionPluginsPluginsRead,
Scope: ScopeAllPluginsPlugins,
},
},
},
Grants: []string{string(org.RoleViewer), string(org.RoleEditor), string(org.RoleAdmin)},
}
pluginsWriter := accesscontrol.RoleRegistration{
Role: accesscontrol.RoleDTO{
Name: "fixed:plugins.plugins:writer",
DisplayName: "Plugins Writer",
Description: "Create, update and delete plugins.",
Group: "Plugins",
Permissions: []accesscontrol.Permission{
{
Action: ActionPluginsPluginsCreate,
Scope: ScopeAllPluginsPlugins,
},
{
Action: ActionPluginsPluginsRead,
Scope: ScopeAllPluginsPlugins,
},
{
Action: ActionPluginsPluginsWrite,
Scope: ScopeAllPluginsPlugins,
},
{
Action: ActionPluginsPluginsDelete,
Scope: ScopeAllPluginsPlugins,
},
},
},
Grants: []string{string(org.RoleAdmin)},
}
// PluginMetas
pluginsMetaReader := accesscontrol.RoleRegistration{
Role: accesscontrol.RoleDTO{
Name: "fixed:plugins.pluginsmeta:reader",
DisplayName: "Plugin Metas Reader",
Description: "Read and list plugin metadata.",
Group: "Plugins",
Permissions: []accesscontrol.Permission{
{
Action: ActionPluginsPluginsMetaRead,
Scope: ScopeAllPluginsPluginsMeta,
},
},
},
Grants: []string{string(org.RoleViewer), string(org.RoleEditor), string(org.RoleAdmin)},
}
pluginsMetaWriter := accesscontrol.RoleRegistration{
Role: accesscontrol.RoleDTO{
Name: "fixed:plugins.pluginsmeta:writer",
DisplayName: "Plugin Metas Writer",
Description: "Create, update and delete plugin metadata.",
Group: "Plugins",
Permissions: []accesscontrol.Permission{
{
Action: ActionPluginsPluginsMetaCreate,
Scope: ScopeAllPluginsPluginsMeta,
},
{
Action: ActionPluginsPluginsMetaRead,
Scope: ScopeAllPluginsPluginsMeta,
},
{
Action: ActionPluginsPluginsMetaWrite,
Scope: ScopeAllPluginsPluginsMeta,
},
{
Action: ActionPluginsPluginsMetaDelete,
Scope: ScopeAllPluginsPluginsMeta,
},
},
},
Grants: []string{string(org.RoleAdmin)},
}
return service.DeclareFixedRoles(
pluginsReader,
pluginsWriter,
pluginsMetaReader,
pluginsMetaWriter,
)
}
+14 -7
View File
@@ -1,14 +1,16 @@
package plugins
import (
"fmt"
"os"
"k8s.io/apiserver/pkg/authorization/authorizer"
authlib "github.com/grafana/authlib/types"
appsdkapiserver "github.com/grafana/grafana-app-sdk/k8s/apiserver"
"k8s.io/apiserver/pkg/authorization/authorizer"
pluginsapp "github.com/grafana/grafana/apps/plugins/pkg/app"
"github.com/grafana/grafana/apps/plugins/pkg/app/meta"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/apiserver/appinstaller"
)
@@ -18,10 +20,14 @@ var (
)
type AppInstaller struct {
appsdkapiserver.AppInstaller
*pluginsapp.PluginAppInstaller
}
func ProvideAppInstaller() (*AppInstaller, error) {
func ProvideAppInstaller(accessControlService accesscontrol.Service, accessClient authlib.AccessClient) (*AppInstaller, error) {
if err := registerAccessControlRoles(accessControlService); err != nil {
return nil, fmt.Errorf("registering access control roles: %w", err)
}
grafanaComAPIURL := os.Getenv("GRAFANA_COM_API_URL")
if grafanaComAPIURL == "" {
grafanaComAPIURL = "https://grafana.com/api/plugins"
@@ -36,12 +42,13 @@ func ProvideAppInstaller() (*AppInstaller, error) {
return nil, err
}
i.WithAccessChecker(accessClient)
return &AppInstaller{
AppInstaller: i,
PluginAppInstaller: i,
}, nil
}
// GetAuthorizer returns the authorizer for the plugins app.
func (p *AppInstaller) GetAuthorizer() authorizer.Authorizer {
func (a *AppInstaller) GetAuthorizer() authorizer.Authorizer {
return pluginsapp.GetAuthorizer()
}
+2 -2
View File
@@ -783,7 +783,7 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api
if err != nil {
return nil, err
}
appInstaller, err := plugins.ProvideAppInstaller()
appInstaller, err := plugins.ProvideAppInstaller(acimplService, accessClient)
if err != nil {
return nil, err
}
@@ -1436,7 +1436,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac
if err != nil {
return nil, err
}
appInstaller, err := plugins.ProvideAppInstaller()
appInstaller, err := plugins.ProvideAppInstaller(acimplService, accessClient)
if err != nil {
return nil, err
}
@@ -84,6 +84,8 @@ func newPermissionRegistry() *permissionRegistry {
"annotations": "annotations:type:",
"orgs": "orgs:id:",
"plugins": "plugins:id:",
"plugins.plugins": "plugins.plugins:uid:",
"plugins.pluginsmeta": "plugins.pluginsmeta:uid:",
"provisioners": "provisioners:",
"reports": "reports:id:",
"permissions": "permissions:type:",