Plugins: Migrate licensing and access control to pkg/services/pluginsintegration package (#65258)

* migrate licensing + access control

* update package name
This commit is contained in:
Will Browne
2023-03-27 11:15:37 +02:00
committed by GitHub
parent 3b00d2c273
commit 31d6416157
14 changed files with 47 additions and 42 deletions
+2 -2
View File
@@ -3,12 +3,12 @@ package api
import (
"fmt"
"github.com/grafana/grafana/pkg/plugins"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginaccesscontrol"
"github.com/grafana/grafana/pkg/tsdb/grafanads"
)
@@ -32,7 +32,7 @@ var (
// that HTTPServer needs
func (hs *HTTPServer) declareFixedRoles() error {
// Declare plugins roles
if err := plugins.DeclareRBACRoles(hs.accesscontrolService, hs.Cfg); err != nil {
if err := pluginaccesscontrol.DeclareRBACRoles(hs.accesscontrolService, hs.Cfg); err != nil {
return err
}
+12 -12
View File
@@ -33,7 +33,6 @@ import (
"github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/middleware"
"github.com/grafana/grafana/pkg/plugins"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/apikey"
"github.com/grafana/grafana/pkg/services/auth"
@@ -43,6 +42,7 @@ import (
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginaccesscontrol"
publicdashboardsapi "github.com/grafana/grafana/pkg/services/publicdashboards/api"
"github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/user"
@@ -140,9 +140,9 @@ func (hs *HTTPServer) registerRoutes() {
r.Get("/connections/datasources/:id/page/:page", middleware.CanAdminPlugins(hs.Cfg), hs.Index)
// App Root Page
appPluginIDScope := plugins.ScopeProvider.GetResourceScope(ac.Parameter(":id"))
r.Get("/a/:id/*", authorize(reqSignedIn, ac.EvalPermission(plugins.ActionAppAccess, appPluginIDScope)), hs.Index)
r.Get("/a/:id", authorize(reqSignedIn, ac.EvalPermission(plugins.ActionAppAccess, appPluginIDScope)), hs.Index)
appPluginIDScope := pluginaccesscontrol.ScopeProvider.GetResourceScope(ac.Parameter(":id"))
r.Get("/a/:id/*", authorize(reqSignedIn, ac.EvalPermission(pluginaccesscontrol.ActionAppAccess, appPluginIDScope)), hs.Index)
r.Get("/a/:id", authorize(reqSignedIn, ac.EvalPermission(pluginaccesscontrol.ActionAppAccess, appPluginIDScope)), hs.Index)
r.Get("/d/:uid/:slug", reqSignedIn, redirectFromLegacyPanelEditURL, hs.Index)
r.Get("/d/:uid", reqSignedIn, redirectFromLegacyPanelEditURL, hs.Index)
@@ -405,27 +405,27 @@ func (hs *HTTPServer) registerRoutes() {
datasourceRoute.Get("/id/:name", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionIDRead, nameScope)), routing.Wrap(hs.GetDataSourceIdByName))
})
pluginIDScope := plugins.ScopeProvider.GetResourceScope(ac.Parameter(":pluginId"))
pluginIDScope := pluginaccesscontrol.ScopeProvider.GetResourceScope(ac.Parameter(":pluginId"))
apiRoute.Get("/plugins", routing.Wrap(hs.GetPluginList))
apiRoute.Get("/plugins/:pluginId/settings", routing.Wrap(hs.GetPluginSettingByID)) // RBAC check performed in handler for App Plugins
apiRoute.Get("/plugins/:pluginId/markdown/:name", routing.Wrap(hs.GetPluginMarkdown))
apiRoute.Get("/plugins/:pluginId/health", routing.Wrap(hs.CheckHealth))
apiRoute.Any("/plugins/:pluginId/resources", authorize(reqSignedIn, ac.EvalPermission(plugins.ActionAppAccess, pluginIDScope)), hs.CallResource)
apiRoute.Any("/plugins/:pluginId/resources/*", authorize(reqSignedIn, ac.EvalPermission(plugins.ActionAppAccess, pluginIDScope)), hs.CallResource)
apiRoute.Any("/plugins/:pluginId/resources", authorize(reqSignedIn, ac.EvalPermission(pluginaccesscontrol.ActionAppAccess, pluginIDScope)), hs.CallResource)
apiRoute.Any("/plugins/:pluginId/resources/*", authorize(reqSignedIn, ac.EvalPermission(pluginaccesscontrol.ActionAppAccess, pluginIDScope)), hs.CallResource)
apiRoute.Get("/plugins/errors", routing.Wrap(hs.GetPluginErrorsList))
apiRoute.Any("/plugin-proxy/:pluginId/*", authorize(reqSignedIn, ac.EvalPermission(plugins.ActionAppAccess, pluginIDScope)), hs.ProxyPluginRequest)
apiRoute.Any("/plugin-proxy/:pluginId", authorize(reqSignedIn, ac.EvalPermission(plugins.ActionAppAccess, pluginIDScope)), hs.ProxyPluginRequest)
apiRoute.Any("/plugin-proxy/:pluginId/*", authorize(reqSignedIn, ac.EvalPermission(pluginaccesscontrol.ActionAppAccess, pluginIDScope)), hs.ProxyPluginRequest)
apiRoute.Any("/plugin-proxy/:pluginId", authorize(reqSignedIn, ac.EvalPermission(pluginaccesscontrol.ActionAppAccess, pluginIDScope)), hs.ProxyPluginRequest)
if hs.Cfg.PluginAdminEnabled && !hs.Cfg.PluginAdminExternalManageEnabled {
apiRoute.Group("/plugins", func(pluginRoute routing.RouteRegister) {
pluginRoute.Post("/:pluginId/install", authorize(reqGrafanaAdmin, ac.EvalPermission(plugins.ActionInstall)), routing.Wrap(hs.InstallPlugin))
pluginRoute.Post("/:pluginId/uninstall", authorize(reqGrafanaAdmin, ac.EvalPermission(plugins.ActionInstall)), routing.Wrap(hs.UninstallPlugin))
pluginRoute.Post("/:pluginId/install", authorize(reqGrafanaAdmin, ac.EvalPermission(pluginaccesscontrol.ActionInstall)), routing.Wrap(hs.InstallPlugin))
pluginRoute.Post("/:pluginId/uninstall", authorize(reqGrafanaAdmin, ac.EvalPermission(pluginaccesscontrol.ActionInstall)), routing.Wrap(hs.UninstallPlugin))
})
}
apiRoute.Group("/plugins", func(pluginRoute routing.RouteRegister) {
pluginRoute.Get("/:pluginId/dashboards/", reqOrgAdmin, routing.Wrap(hs.GetPluginDashboards))
pluginRoute.Post("/:pluginId/settings", authorize(reqOrgAdmin, ac.EvalPermission(plugins.ActionWrite, pluginIDScope)), routing.Wrap(hs.UpdatePluginSetting))
pluginRoute.Post("/:pluginId/settings", authorize(reqOrgAdmin, ac.EvalPermission(pluginaccesscontrol.ActionWrite, pluginIDScope)), routing.Wrap(hs.UpdatePluginSetting))
pluginRoute.Get("/:pluginId/metrics", reqOrgAdmin, routing.Wrap(hs.CollectPluginMetrics))
})
+3 -3
View File
@@ -15,7 +15,6 @@ import (
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/localcache"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
"github.com/grafana/grafana/pkg/plugins/backendplugin/provider"
"github.com/grafana/grafana/pkg/plugins/config"
@@ -34,6 +33,7 @@ import (
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/oauthtoken/oauthtokentest"
"github.com/grafana/grafana/pkg/services/pluginsintegration"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginaccesscontrol"
"github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext"
pluginSettings "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings/service"
"github.com/grafana/grafana/pkg/services/quota/quotatest"
@@ -80,7 +80,7 @@ func TestCallResource(t *testing.T) {
req := srv.NewPostRequest("/api/plugins/testdata/resources/test", strings.NewReader("{ \"test\": true }"))
webtest.RequestWithSignedInUser(req, &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{
1: accesscontrol.GroupScopesByAction([]accesscontrol.Permission{
{Action: plugins.ActionAppAccess, Scope: plugins.ScopeProvider.GetResourceAllScope()},
{Action: pluginaccesscontrol.ActionAppAccess, Scope: pluginaccesscontrol.ScopeProvider.GetResourceAllScope()},
}),
}})
resp, err := srv.SendJSON(req)
@@ -118,7 +118,7 @@ func TestCallResource(t *testing.T) {
req := srv.NewGetRequest("/api/plugins/testdata/resources/scenarios")
webtest.RequestWithSignedInUser(req, &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{
1: accesscontrol.GroupScopesByAction([]accesscontrol.Permission{
{Action: plugins.ActionAppAccess, Scope: plugins.ScopeProvider.GetResourceAllScope()},
{Action: pluginaccesscontrol.ActionAppAccess, Scope: pluginaccesscontrol.ScopeProvider.GetResourceAllScope()},
}),
}})
resp, err := srv.SendJSON(req)
+5 -4
View File
@@ -28,6 +28,7 @@ import (
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginaccesscontrol"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
@@ -60,7 +61,7 @@ func (hs *HTTPServer) GetPluginList(c *contextmodel.ReqContext) response.Respons
hasAccess := ac.HasAccess(hs.AccessControl, c)
canListNonCorePlugins := reqOrgAdmin(c) || hasAccess(reqOrgAdmin, ac.EvalAny(
ac.EvalPermission(datasources.ActionCreate),
ac.EvalPermission(plugins.ActionInstall),
ac.EvalPermission(pluginaccesscontrol.ActionInstall),
))
pluginSettingsMap, err := hs.pluginSettings(c.Req.Context(), c.OrgID)
@@ -90,7 +91,7 @@ func (hs *HTTPServer) GetPluginList(c *contextmodel.ReqContext) response.Respons
// Should be able to list this installed plugin:
// * anyone that can edit its settings
if !pluginDef.IsCorePlugin() && !canListNonCorePlugins && !hasAccess(reqOrgAdmin,
ac.EvalPermission(plugins.ActionWrite, plugins.ScopeProvider.GetResourceScope(pluginDef.ID))) {
ac.EvalPermission(pluginaccesscontrol.ActionWrite, pluginaccesscontrol.ScopeProvider.GetResourceScope(pluginDef.ID))) {
continue
}
@@ -121,7 +122,7 @@ func (hs *HTTPServer) GetPluginList(c *contextmodel.ReqContext) response.Respons
// Compute metadata
pluginsMetadata := hs.getMultiAccessControlMetadata(c, c.OrgID,
plugins.ScopeProvider.GetResourceScope(""), filteredPluginIDs)
pluginaccesscontrol.ScopeProvider.GetResourceScope(""), filteredPluginIDs)
// Prepare DTO
result := make(dtos.PluginList, 0)
@@ -176,7 +177,7 @@ func (hs *HTTPServer) GetPluginSettingByID(c *contextmodel.ReqContext) response.
if plugin.IsApp() {
hasAccess := ac.HasAccess(hs.AccessControl, c)
if !hasAccess(ac.ReqSignedIn,
ac.EvalPermission(plugins.ActionAppAccess, plugins.ScopeProvider.GetResourceScope(plugin.ID))) {
ac.EvalPermission(pluginaccesscontrol.ActionAppAccess, pluginaccesscontrol.ScopeProvider.GetResourceScope(plugin.ID))) {
return response.Error(http.StatusForbidden, "Access Denied", nil)
}
}
+3 -2
View File
@@ -27,6 +27,7 @@ import (
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgtest"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginaccesscontrol"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
"github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/updatechecker"
@@ -104,7 +105,7 @@ func Test_PluginsInstallAndUninstall(t *testing.T) {
}
func Test_PluginsInstallAndUninstall_AccessControl(t *testing.T) {
canInstall := []ac.Permission{{Action: plugins.ActionInstall}}
canInstall := []ac.Permission{{Action: pluginaccesscontrol.ActionInstall}}
cannotInstall := []ac.Permission{{Action: "plugins:cannotinstall"}}
type testCase struct {
@@ -568,7 +569,7 @@ func Test_PluginsList_AccessControl(t *testing.T) {
},
{
desc: "should be able to list core plugins and plugins user has permission to",
permissions: []ac.Permission{{Action: plugins.ActionWrite, Scope: "plugins:id:test-app"}},
permissions: []ac.Permission{{Action: pluginaccesscontrol.ActionWrite, Scope: "plugins:id:test-app"}},
expectedCode: http.StatusOK,
expectedPlugins: []string{"mysql", "test-app"},
},