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:
Joan López de la Franca Beltran
2021-02-03 20:47:45 +01:00
committed by GitHub
co-authored by Leonard Gram
parent 4a324e3d74
commit 6415d2802e
26 changed files with 224 additions and 102 deletions
+32 -7
View File
@@ -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 != "" {