Plugins: Unexport PluginDir field from PluginDTO (#59190)

* unexport pluginDir from dto

* more err checks

* tidy

* fix tests

* fix dboard file tests

* fix import

* fix tests

* apply PR feedback

* combine interfaces

* fix logs and clean up test

* filepath clean

* use fs.File

* rm explicit type
This commit is contained in:
Will Browne
2022-12-02 13:46:55 +01:00
committed by GitHub
parent 6d1bcd9f40
commit 76233f9997
15 changed files with 223 additions and 286 deletions
+3 -8
View File
@@ -4,8 +4,6 @@ import (
"context"
"fmt"
"io/fs"
"os"
"path/filepath"
"strings"
"github.com/grafana/grafana/pkg/plugins"
@@ -24,10 +22,8 @@ func ProvideFileStoreManager(pluginStore plugins.Store) *FileStoreManager {
}
}
var openDashboardFile = func(name string) (fs.File, error) {
// Wrapping in filepath.Clean to properly handle
// gosec G304 Potential file inclusion via variable rule.
return os.Open(filepath.Clean(name))
var openDashboardFile = func(p plugins.PluginDTO, name string) (fs.File, error) {
return p.File(name)
}
func (m *FileStoreManager) ListPluginDashboardFiles(ctx context.Context, args *ListPluginDashboardFilesArgs) (*ListPluginDashboardFilesResult, error) {
@@ -90,8 +86,7 @@ func (m *FileStoreManager) GetPluginDashboardFileContents(ctx context.Context, a
return nil, err
}
dashboardFilePath := filepath.Join(plugin.PluginDir, cleanPath)
file, err := openDashboardFile(dashboardFilePath)
file, err := openDashboardFile(plugin, cleanPath)
if err != nil {
return nil, err
}
@@ -3,6 +3,7 @@ package dashboards
import (
"context"
"io"
"io/fs"
"testing"
"testing/fstest"
@@ -117,20 +118,24 @@ func TestDashboardFileStore(t *testing.T) {
t.Run("With filesystem", func(t *testing.T) {
origOpenDashboardFile := openDashboardFile
mapFs := fstest.MapFS{
"plugins/plugin-id/dashboards/dash1.json": {
"dashboards/dash1.json": {
Data: []byte("dash1"),
},
"plugins/plugin-id/dashboards/dash2.json": {
"dashboards/dash2.json": {
Data: []byte("dash2"),
},
"plugins/plugin-id/dashboards/dash3.json": {
"dashboards/dash3.json": {
Data: []byte("dash3"),
},
"plugins/plugin-id/dash2.json": {
"dash2.json": {
Data: []byte("dash2"),
},
}
openDashboardFile = mapFs.Open
openDashboardFile = func(p plugins.PluginDTO, name string) (fs.File, error) {
f, err := mapFs.Open(name)
require.NoError(t, err)
return f, nil
}
t.Cleanup(func() {
openDashboardFile = origOpenDashboardFile
})
@@ -156,7 +161,6 @@ func TestDashboardFileStore(t *testing.T) {
b, err := io.ReadAll(res.Content)
require.NoError(t, err)
require.Equal(t, "dash1", string(b))
require.NoError(t, res.Content.Close())
})
t.Run("Should return file content for dashboards/dash2.json", func(t *testing.T) {
@@ -170,7 +174,6 @@ func TestDashboardFileStore(t *testing.T) {
b, err := io.ReadAll(res.Content)
require.NoError(t, err)
require.Equal(t, "dash2", string(b))
require.NoError(t, res.Content.Close())
})
t.Run("Should return error when trying to read relative file", func(t *testing.T) {
@@ -189,39 +192,39 @@ func TestDashboardFileStore(t *testing.T) {
func setupPluginDashboardsForTest(t *testing.T) *FileStoreManager {
t.Helper()
return &FileStoreManager{
pluginStore: &plugins.FakePluginStore{
PluginList: []plugins.PluginDTO{
p1 := &plugins.Plugin{
JSONData: plugins.JSONData{
ID: "pluginWithoutDashboards",
Includes: []*plugins.Includes{
{
JSONData: plugins.JSONData{
ID: "pluginWithoutDashboards",
Includes: []*plugins.Includes{
{
Type: "page",
},
},
},
},
{
PluginDir: "plugins/plugin-id",
JSONData: plugins.JSONData{
ID: "pluginWithDashboards",
Includes: []*plugins.Includes{
{
Type: "page",
},
{
Type: "dashboard",
Path: "dashboards/dash1.json",
},
{
Type: "dashboard",
Path: "dashboards/dash2.json",
},
},
},
Type: "page",
},
},
},
}
p2 := &plugins.Plugin{
JSONData: plugins.JSONData{
ID: "pluginWithDashboards",
Includes: []*plugins.Includes{
{
Type: "page",
},
{
Type: "dashboard",
Path: "dashboards/dash1.json",
},
{
Type: "dashboard",
Path: "dashboards/dash2.json",
},
},
},
}
return &FileStoreManager{
pluginStore: &plugins.FakePluginStore{
PluginList: []plugins.PluginDTO{p1.ToDTO(), p2.ToDTO()},
},
}
}
+2 -4
View File
@@ -51,8 +51,7 @@ func (m *PluginInstaller) Add(ctx context.Context, pluginID, version string, opt
if plugin.Info.Version == version {
return plugins.DuplicateError{
PluginID: plugin.ID,
ExistingPluginDir: plugin.PluginDir,
PluginID: plugin.ID,
}
}
@@ -65,8 +64,7 @@ func (m *PluginInstaller) Add(ctx context.Context, pluginID, version string, opt
// if existing plugin version is the same as the target update version
if dlOpts.Version == plugin.Info.Version {
return plugins.DuplicateError{
PluginID: plugin.ID,
ExistingPluginDir: plugin.PluginDir,
PluginID: plugin.ID,
}
}
+1 -2
View File
@@ -81,8 +81,7 @@ func TestPluginManager_Add_Remove(t *testing.T) {
err = inst.Add(context.Background(), pluginID, v1, plugins.CompatOpts{})
require.Equal(t, plugins.DuplicateError{
PluginID: pluginV1.ID,
ExistingPluginDir: pluginV1.PluginDir,
PluginID: pluginV1.ID,
}, err)
})
-1
View File
@@ -127,7 +127,6 @@ func (l *Loader) loadPlugins(ctx context.Context, class plugins.Class, pluginJSO
plugin.Signature = sig.Status
plugin.SignatureType = sig.Type
plugin.SignatureOrg = sig.SigningOrg
plugin.SignedFiles = sig.Files
loadedPlugins[plugin.PluginDir] = plugin
}
@@ -116,8 +116,8 @@ func TestIntegrationPluginManager(t *testing.T) {
ctx := context.Background()
verifyCorePluginCatalogue(t, ctx, ps)
verifyBundledPlugins(t, ctx, ps)
verifyPluginStaticRoutes(t, ctx, ps)
verifyBundledPlugins(t, ctx, ps, reg)
verifyPluginStaticRoutes(t, ctx, ps, reg)
verifyBackendProcesses(t, reg.Plugins(ctx))
verifyPluginQuery(t, ctx, client.ProvideService(reg, pCfg))
}
@@ -245,7 +245,7 @@ func verifyCorePluginCatalogue(t *testing.T, ctx context.Context, ps *store.Serv
require.Equal(t, len(expPanels)+len(expDataSources)+len(expApps), len(ps.Plugins(ctx)))
}
func verifyBundledPlugins(t *testing.T, ctx context.Context, ps *store.Service) {
func verifyBundledPlugins(t *testing.T, ctx context.Context, ps *store.Service, reg registry.Service) {
t.Helper()
dsPlugins := make(map[string]struct{})
@@ -258,6 +258,9 @@ func verifyBundledPlugins(t *testing.T, ctx context.Context, ps *store.Service)
require.NotEqual(t, plugins.PluginDTO{}, inputPlugin)
require.NotNil(t, dsPlugins["input"])
intInputPlugin, exists := reg.Plugin(ctx, "input")
require.True(t, exists)
pluginRoutes := make(map[string]*plugins.StaticRoute)
for _, r := range ps.Routes() {
pluginRoutes[r.PluginID] = r
@@ -265,23 +268,23 @@ func verifyBundledPlugins(t *testing.T, ctx context.Context, ps *store.Service)
for _, pluginID := range []string{"input"} {
require.Contains(t, pluginRoutes, pluginID)
require.True(t, strings.HasPrefix(pluginRoutes[pluginID].Directory, inputPlugin.PluginDir))
require.True(t, strings.HasPrefix(pluginRoutes[pluginID].Directory, intInputPlugin.PluginDir))
}
}
func verifyPluginStaticRoutes(t *testing.T, ctx context.Context, ps *store.Service) {
func verifyPluginStaticRoutes(t *testing.T, ctx context.Context, rr plugins.StaticRouteResolver, reg registry.Service) {
routes := make(map[string]*plugins.StaticRoute)
for _, route := range ps.Routes() {
for _, route := range rr.Routes() {
routes[route.PluginID] = route
}
require.Len(t, routes, 2)
inputPlugin, _ := ps.Plugin(ctx, "input")
inputPlugin, _ := reg.Plugin(ctx, "input")
require.NotNil(t, routes["input"])
require.Equal(t, routes["input"].Directory, inputPlugin.PluginDir)
testAppPlugin, _ := ps.Plugin(ctx, "test-app")
testAppPlugin, _ := reg.Plugin(ctx, "test-app")
require.Contains(t, routes, "test-app")
require.Equal(t, routes["test-app"].Directory, testAppPlugin.PluginDir)
}
+1 -6
View File
@@ -111,12 +111,7 @@ func Calculate(mlog log.Logger, plugin *plugins.Plugin) (plugins.Signature, erro
}, err
}
manifestPath := filepath.Join(plugin.PluginDir, "MANIFEST.txt")
// nolint:gosec
// We can ignore the gosec G304 warning on this one because `manifestPath` is based
// on plugin the folder structure on disk and not user input.
byteValue, err := os.ReadFile(manifestPath)
byteValue := plugin.Manifest()
if err != nil || len(byteValue) < 10 {
mlog.Debug("Plugin is unsigned", "id", plugin.ID)
return plugins.Signature{
+1 -1
View File
@@ -54,7 +54,7 @@ func (s *Validator) Validate(plugin *plugins.Plugin) *plugins.SignatureError {
SignatureStatus: plugins.SignatureUnsigned,
}
}
s.log.Warn("Permitting unsigned plugin. This is not recommended", "pluginID", plugin.ID, "pluginDir", plugin.PluginDir)
s.log.Warn("Permitting unsigned plugin. This is not recommended", "pluginID", plugin.ID)
return nil
case plugins.SignatureInvalid:
s.log.Debug("Plugin has an invalid signature", "pluginID", plugin.ID)