RBAC: Check plugins:install globally (#78438)

* RBAC: Check plugins:install globally

* Add disclamer to the RBACSingleOrganization config option
This commit is contained in:
Gabriel MABILLE
2023-11-21 15:09:43 +01:00
committed by GitHub
parent 9e11779921
commit b6b86bb0b3
6 changed files with 38 additions and 13 deletions
+21 -9
View File
@@ -28,6 +28,7 @@ import (
"github.com/grafana/grafana/pkg/plugins/manager/registry"
"github.com/grafana/grafana/pkg/plugins/pluginscdn"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgtest"
@@ -43,23 +44,31 @@ func Test_PluginsInstallAndUninstall(t *testing.T) {
canInstall := []ac.Permission{{Action: pluginaccesscontrol.ActionInstall}}
cannotInstall := []ac.Permission{{Action: "plugins:cannotinstall"}}
localOrg := int64(1)
globalOrg := int64(ac.GlobalOrgID)
type testCase struct {
expectedCode int
permissionOrg int64
permissions []ac.Permission
pluginAdminEnabled bool
pluginAdminExternalManageEnabled bool
singleOrganization bool
}
tcs := []testCase{
{expectedCode: http.StatusNotFound, permissions: canInstall, pluginAdminEnabled: true, pluginAdminExternalManageEnabled: true},
{expectedCode: http.StatusNotFound, permissions: canInstall, pluginAdminEnabled: false, pluginAdminExternalManageEnabled: true},
{expectedCode: http.StatusNotFound, permissions: canInstall, pluginAdminEnabled: false, pluginAdminExternalManageEnabled: false},
{expectedCode: http.StatusForbidden, permissions: cannotInstall, pluginAdminEnabled: true, pluginAdminExternalManageEnabled: false},
{expectedCode: http.StatusOK, permissions: canInstall, pluginAdminEnabled: true, pluginAdminExternalManageEnabled: false},
{expectedCode: http.StatusNotFound, permissionOrg: globalOrg, permissions: canInstall, pluginAdminEnabled: true, pluginAdminExternalManageEnabled: true},
{expectedCode: http.StatusNotFound, permissionOrg: globalOrg, permissions: canInstall, pluginAdminEnabled: false, pluginAdminExternalManageEnabled: true},
{expectedCode: http.StatusNotFound, permissionOrg: globalOrg, permissions: canInstall, pluginAdminEnabled: false, pluginAdminExternalManageEnabled: false},
{expectedCode: http.StatusForbidden, permissionOrg: globalOrg, permissions: cannotInstall, pluginAdminEnabled: true, pluginAdminExternalManageEnabled: false},
{expectedCode: http.StatusOK, permissionOrg: globalOrg, permissions: canInstall, pluginAdminEnabled: true, pluginAdminExternalManageEnabled: false},
{expectedCode: http.StatusForbidden, permissionOrg: localOrg, permissions: canInstall, pluginAdminEnabled: true, pluginAdminExternalManageEnabled: false},
{expectedCode: http.StatusForbidden, permissionOrg: localOrg, permissions: cannotInstall, pluginAdminEnabled: true, pluginAdminExternalManageEnabled: false, singleOrganization: true},
{expectedCode: http.StatusOK, permissionOrg: localOrg, permissions: canInstall, pluginAdminEnabled: true, pluginAdminExternalManageEnabled: false, singleOrganization: true},
}
testName := func(action string, tc testCase) string {
return fmt.Sprintf("%s request returns %d when adminEnabled: %t, externalEnabled: %t, permissions: %q",
action, tc.expectedCode, tc.pluginAdminEnabled, tc.pluginAdminExternalManageEnabled, tc.permissions)
return fmt.Sprintf("%s request returns %d when adminEnabled: %t, externalEnabled: %t, permissions: %d: %s, single_org: %t",
action, tc.expectedCode, tc.pluginAdminEnabled, tc.pluginAdminExternalManageEnabled, tc.permissionOrg, tc.permissions[0].Action, tc.singleOrganization)
}
for _, tc := range tcs {
@@ -67,15 +76,18 @@ func Test_PluginsInstallAndUninstall(t *testing.T) {
hs.Cfg = setting.NewCfg()
hs.Cfg.PluginAdminEnabled = tc.pluginAdminEnabled
hs.Cfg.PluginAdminExternalManageEnabled = tc.pluginAdminExternalManageEnabled
hs.Cfg.RBACSingleOrganization = tc.singleOrganization
hs.orgService = &orgtest.FakeOrgService{ExpectedOrg: &org.Org{}}
hs.accesscontrolService = &actest.FakeService{}
hs.pluginInstaller = NewFakePluginInstaller()
hs.pluginFileStore = &fakes.FakePluginFileStore{}
})
t.Run(testName("Install", tc), func(t *testing.T) {
input := strings.NewReader(`{"version": "1.0.2"}`)
req := webtest.RequestWithSignedInUser(server.NewPostRequest("/api/plugins/test/install", input), userWithPermissions(1, tc.permissions))
req := webtest.RequestWithSignedInUser(server.NewPostRequest("/api/plugins/test/install", input), userWithPermissions(tc.permissionOrg, tc.permissions))
res, err := server.SendJSON(req)
require.NoError(t, err)
require.Equal(t, tc.expectedCode, res.StatusCode)
@@ -84,7 +96,7 @@ func Test_PluginsInstallAndUninstall(t *testing.T) {
t.Run(testName("Uninstall", tc), func(t *testing.T) {
input := strings.NewReader("{ }")
req := webtest.RequestWithSignedInUser(server.NewPostRequest("/api/plugins/test/uninstall", input), userWithPermissions(1, tc.permissions))
req := webtest.RequestWithSignedInUser(server.NewPostRequest("/api/plugins/test/uninstall", input), userWithPermissions(tc.permissionOrg, tc.permissions))
res, err := server.SendJSON(req)
require.NoError(t, err)
require.Equal(t, tc.expectedCode, res.StatusCode)