Plugins: Requests validator (#30445)
* Introduce PluginRequestValidator abstraction with a NoOp implementation * Update PluginRequestValidator abstraction to use the dsURL instead * Inject PluginRequestValidator into the HTTPServer and validate requests going through data source proxy * Inject PluginRequestValidator into the BackendPluginManager and validate requests going through it * Validate requests going through QueryMetrics & QueryMetricsV2 * Validate BackendPluginManager health requests * Fix backend plugins manager tests * Validate requests going through alerting service * Fix tests * fix tests * goimports Co-authored-by: Leonard Gram <leo@xlson.com>
This commit is contained in:
co-authored by
Leonard Gram
parent
4a324e3d74
commit
6415d2802e
@@ -51,12 +51,13 @@ type Manager interface {
|
||||
}
|
||||
|
||||
type manager struct {
|
||||
Cfg *setting.Cfg `inject:""`
|
||||
License models.Licensing `inject:""`
|
||||
pluginsMu sync.RWMutex
|
||||
plugins map[string]Plugin
|
||||
logger log.Logger
|
||||
pluginSettings map[string]pluginSettings
|
||||
Cfg *setting.Cfg `inject:""`
|
||||
License models.Licensing `inject:""`
|
||||
PluginRequestValidator models.PluginRequestValidator `inject:""`
|
||||
pluginsMu sync.RWMutex
|
||||
plugins map[string]Plugin
|
||||
logger log.Logger
|
||||
pluginSettings map[string]pluginSettings
|
||||
}
|
||||
|
||||
func (m *manager) Init() error {
|
||||
@@ -195,6 +196,19 @@ func (m *manager) CollectMetrics(ctx context.Context, pluginID string) (*backend
|
||||
|
||||
// CheckHealth checks the health of a registered backend plugin.
|
||||
func (m *manager) CheckHealth(ctx context.Context, pluginContext backend.PluginContext) (*backend.CheckHealthResult, error) {
|
||||
var dsURL string
|
||||
if pluginContext.DataSourceInstanceSettings != nil {
|
||||
dsURL = pluginContext.DataSourceInstanceSettings.URL
|
||||
}
|
||||
|
||||
err := m.PluginRequestValidator.Validate(dsURL, nil)
|
||||
if err != nil {
|
||||
return &backend.CheckHealthResult{
|
||||
Status: http.StatusForbidden,
|
||||
Message: "Access denied",
|
||||
}, nil
|
||||
}
|
||||
|
||||
m.pluginsMu.RLock()
|
||||
p, registered := m.plugins[pluginContext.PluginID]
|
||||
m.pluginsMu.RUnlock()
|
||||
@@ -204,7 +218,7 @@ func (m *manager) CheckHealth(ctx context.Context, pluginContext backend.PluginC
|
||||
}
|
||||
|
||||
var resp *backend.CheckHealthResult
|
||||
err := instrumentCheckHealthRequest(p.PluginID(), func() (innerErr error) {
|
||||
err = instrumentCheckHealthRequest(p.PluginID(), func() (innerErr error) {
|
||||
resp, innerErr = p.CheckHealth(ctx, &backend.CheckHealthRequest{PluginContext: pluginContext})
|
||||
return
|
||||
})
|
||||
@@ -289,6 +303,17 @@ func (m *manager) callResourceInternal(w http.ResponseWriter, req *http.Request,
|
||||
|
||||
// CallResource calls a plugin resource.
|
||||
func (m *manager) CallResource(pCtx backend.PluginContext, reqCtx *models.ReqContext, path string) {
|
||||
var dsURL string
|
||||
if pCtx.DataSourceInstanceSettings != nil {
|
||||
dsURL = pCtx.DataSourceInstanceSettings.URL
|
||||
}
|
||||
|
||||
err := m.PluginRequestValidator.Validate(dsURL, reqCtx.Req.Request)
|
||||
if err != nil {
|
||||
reqCtx.JsonApiErr(http.StatusForbidden, "Access denied", err)
|
||||
return
|
||||
}
|
||||
|
||||
clonedReq := reqCtx.Req.Clone(reqCtx.Req.Context())
|
||||
rawURL := path
|
||||
if clonedReq.URL.RawQuery != "" {
|
||||
|
||||
@@ -279,12 +279,14 @@ func newManagerScenario(t *testing.T, managed bool, fn func(t *testing.T, ctx *m
|
||||
t.Helper()
|
||||
cfg := setting.NewCfg()
|
||||
license := &testLicensingService{}
|
||||
validator := &testPluginRequestValidator{}
|
||||
ctx := &managerScenarioCtx{
|
||||
cfg: cfg,
|
||||
license: license,
|
||||
manager: &manager{
|
||||
Cfg: cfg,
|
||||
License: license,
|
||||
Cfg: cfg,
|
||||
License: license,
|
||||
PluginRequestValidator: validator,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -418,3 +420,9 @@ func (t *testLicensingService) HasValidLicense() bool {
|
||||
func (t *testLicensingService) Environment() map[string]string {
|
||||
return map[string]string{"GF_ENTERPRISE_LICENSE_TEXT": t.tokenRaw}
|
||||
}
|
||||
|
||||
type testPluginRequestValidator struct{}
|
||||
|
||||
func (t *testPluginRequestValidator) Validate(string, *http.Request) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -6,11 +6,12 @@ package pluginextensionv2
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
math "math"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
||||
Reference in New Issue
Block a user