Plugins: Check installer's permissions include plugins' permissions (#78211)

* Check installer perm

* Failed eval better output

* Switch fetching json data in the repo

* Comment

* Account for feedback

* Mv single_organization config option

* Inline error check

* Starting to replace errors not to have to do the management in two places

* Continue error translation

* Cover ErrChecksumMismatch

* Refactor a bit

* Lint. Tab

* log instead of erroring out

* Nit.

* Revert change on kinds

* revert file again

* Fix tests

* Match core plugin error status code

* Skip permission check for Grafana Admin

* Use errutil templates

* Use errutil templating

* Inline

* Test templating

* revert error changes

* Remove isGrafanaAdmin skip

* Feature toggle check

* Small refactor on hasPluginRequestedPermissions

* Add test

* Imports

* Post install check

* change log messages so that they make sense

* Cover no scope case

* Inline

* Nit.

* Fix test
This commit is contained in:
Gabriel MABILLE
2023-11-24 16:02:44 +01:00
committed by GitHub
parent ab982e7bd3
commit 24a6ee4a91
2 changed files with 149 additions and 0 deletions
+99
View File
@@ -20,14 +20,17 @@ import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/log/logtest"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/config"
"github.com/grafana/grafana/pkg/plugins/manager/fakes"
"github.com/grafana/grafana/pkg/plugins/manager/filestore"
"github.com/grafana/grafana/pkg/plugins/manager/registry"
"github.com/grafana/grafana/pkg/plugins/plugindef"
"github.com/grafana/grafana/pkg/plugins/pluginscdn"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/org"
@@ -36,7 +39,9 @@ import (
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
"github.com/grafana/grafana/pkg/services/updatechecker"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web"
"github.com/grafana/grafana/pkg/web/webtest"
)
@@ -637,3 +642,97 @@ func createPlugin(jd plugins.JSONData, class plugins.Class, files plugins.FS) *p
FS: files,
}
}
func TestHTTPServer_hasPluginRequestedPermissions(t *testing.T) {
newStr := func(s string) *string {
return &s
}
pluginReg := pluginstore.Plugin{
JSONData: plugins.JSONData{
ID: "grafana-test-app",
ExternalServiceRegistration: &plugindef.ExternalServiceRegistration{
Permissions: []plugindef.Permission{{Action: ac.ActionUsersRead, Scope: newStr(ac.ScopeUsersAll)}, {Action: ac.ActionUsersCreate}},
},
},
}
tests := []struct {
name string
plugin pluginstore.Plugin
orgID int64
singleOrg bool
permissions map[int64]map[string][]string
warnCount int
}{
{
name: "no warn if plugin has no registration",
plugin: pluginstore.Plugin{
JSONData: plugins.JSONData{
ID: "grafana-test-app",
},
},
warnCount: 0,
},
{
name: "warn if user does not have plugin permissions globally",
plugin: pluginReg,
orgID: 1,
permissions: map[int64]map[string][]string{
1: {ac.ActionUsersRead: {ac.ScopeUsersAll}, ac.ActionUsersCreate: {}},
},
warnCount: 1,
},
{
name: "no warn if user has plugin permissions globally",
plugin: pluginReg,
orgID: 0,
permissions: map[int64]map[string][]string{
0: {ac.ActionUsersRead: {ac.ScopeUsersAll}, ac.ActionUsersCreate: {}},
},
warnCount: 0,
},
{
name: "no warn if user has plugin permissions in single organization",
plugin: pluginReg,
singleOrg: true,
orgID: 1,
permissions: map[int64]map[string][]string{
1: {ac.ActionUsersRead: {ac.ScopeUsersAll}, ac.ActionUsersCreate: {}},
},
warnCount: 0,
},
{
name: "warn if user does not have all plugin permissions",
plugin: pluginReg,
singleOrg: true,
orgID: 1,
permissions: map[int64]map[string][]string{1: {ac.ActionUsersCreate: {}}},
warnCount: 1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
logger := &logtest.Fake{}
hs := &HTTPServer{}
httpReq, err := http.NewRequest(http.MethodGet, "", nil)
require.NoError(t, err)
hs.Cfg = setting.NewCfg()
hs.Cfg.RBACSingleOrganization = tt.singleOrg
hs.pluginStore = &pluginstore.FakePluginStore{
PluginList: []pluginstore.Plugin{tt.plugin},
}
hs.log = logger
hs.accesscontrolService = actest.FakeService{}
hs.AccessControl = acimpl.ProvideAccessControl(hs.Cfg)
c := &contextmodel.ReqContext{
Context: &web.Context{Req: httpReq},
SignedInUser: &user.SignedInUser{OrgID: tt.orgID, Permissions: tt.permissions},
}
hs.hasPluginRequestedPermissions(c, "grafana-test-app")
assert.Equal(t, tt.warnCount, logger.WarnLogs.Calls)
})
}
}