Plugins: Modify interface for plugin validations to allow taking PDC into account (#96089)

* Request interceptor: Do not block PDC

* Apply change after feedback received

* Add test

* Check if secure socks proxy configured for the instance

* Apply suggestions from code review

* Add dedicated service for datasource request URL validation (#99179)

---------

Co-authored-by: Will Browne <wbrowne@users.noreply.github.com>
pull/99517/head
Sofia Papagiannaki 6 months ago committed by GitHub
parent 33a53d170b
commit d192a44469
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 7
      pkg/api/datasources.go
  2. 10
      pkg/api/ds_query_test.go
  3. 6
      pkg/api/http_server.go
  4. 7
      pkg/api/plugin_resource.go
  5. 4
      pkg/infra/httpclient/httpclientprovider/host_redirect_validation_middleware.go
  6. 2
      pkg/infra/httpclient/httpclientprovider/http_client_provider.go
  7. 6
      pkg/infra/httpclient/httpclientprovider/http_client_provider_test.go
  8. 4
      pkg/server/wireexts_oss.go
  9. 8
      pkg/services/datasourceproxy/datasourceproxy.go
  10. 6
      pkg/services/datasourceproxy/datasourceproxy_test.go
  11. 10
      pkg/services/datasources/models.go
  12. 55
      pkg/services/datasources/models_test.go
  13. 2
      pkg/services/datasources/service/datasource.go
  14. 6
      pkg/services/publicdashboards/api/common_test.go
  15. 8
      pkg/services/query/query.go
  16. 8
      pkg/services/query/query_test.go
  17. 20
      pkg/services/validations/oss.go
  18. 11
      pkg/services/validations/service.go

@ -841,12 +841,7 @@ func (hs *HTTPServer) checkDatasourceHealth(c *contextmodel.ReqContext, ds *data
Headers: map[string]string{}, Headers: map[string]string{},
} }
var dsURL string err = hs.DataSourceRequestValidator.Validate(ds, c.Req)
if req.PluginContext.DataSourceInstanceSettings != nil {
dsURL = req.PluginContext.DataSourceInstanceSettings.URL
}
err = hs.PluginRequestValidator.Validate(dsURL, c.Req)
if err != nil { if err != nil {
return response.Error(http.StatusForbidden, "Access denied", err) return response.Error(http.StatusForbidden, "Access denied", err)
} }

@ -36,7 +36,7 @@ import (
"github.com/grafana/grafana/pkg/web/webtest" "github.com/grafana/grafana/pkg/web/webtest"
) )
type fakePluginRequestValidator struct { type fakeDataSourceRequestValidator struct {
err error err error
} }
@ -45,7 +45,7 @@ type secretsErrorResponseBody struct {
Message string `json:"message"` Message string `json:"message"`
} }
func (rv *fakePluginRequestValidator) Validate(dsURL string, req *http.Request) error { func (rv *fakeDataSourceRequestValidator) Validate(ds *datasources.DataSource, req *http.Request) error {
return rv.err return rv.err
} }
@ -56,7 +56,7 @@ func TestAPIEndpoint_Metrics_QueryMetricsV2(t *testing.T) {
cfg, cfg,
nil, nil,
nil, nil,
&fakePluginRequestValidator{}, &fakeDataSourceRequestValidator{},
&fakePluginClient{ &fakePluginClient{
QueryDataHandlerFunc: func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { QueryDataHandlerFunc: func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
resp := backend.Responses{ resp := backend.Responses{
@ -114,7 +114,7 @@ func TestAPIEndpoint_Metrics_PluginDecryptionFailure(t *testing.T) {
cfg, cfg,
nil, nil,
nil, nil,
&fakePluginRequestValidator{}, &fakeDataSourceRequestValidator{},
&fakePluginClient{ &fakePluginClient{
QueryDataHandlerFunc: func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { QueryDataHandlerFunc: func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
resp := backend.Responses{ resp := backend.Responses{
@ -309,7 +309,7 @@ func TestDataSourceQueryError(t *testing.T) {
cfg, cfg,
&fakeDatasources.FakeCacheService{}, &fakeDatasources.FakeCacheService{},
nil, nil,
&fakePluginRequestValidator{}, &fakeDataSourceRequestValidator{},
pluginClient.ProvideService(r), pluginClient.ProvideService(r),
plugincontext.ProvideService(cfg, localcache.ProvideService(), &pluginstore.FakePluginStore{ plugincontext.ProvideService(cfg, localcache.ProvideService(), &pluginstore.FakePluginStore{
PluginList: []pluginstore.Plugin{pluginstore.ToGrafanaDTO(p)}, PluginList: []pluginstore.Plugin{pluginstore.ToGrafanaDTO(p)},

@ -140,7 +140,7 @@ type HTTPServer struct {
License licensing.Licensing License licensing.Licensing
AccessControl accesscontrol.AccessControl AccessControl accesscontrol.AccessControl
DataProxy *datasourceproxy.DataSourceProxyService DataProxy *datasourceproxy.DataSourceProxyService
PluginRequestValidator validations.PluginRequestValidator DataSourceRequestValidator validations.DataSourceRequestValidator
pluginClient plugins.Client pluginClient plugins.Client
pluginStore pluginstore.Store pluginStore pluginstore.Store
pluginInstaller plugins.Installer pluginInstaller plugins.Installer
@ -237,7 +237,7 @@ type ServerOptions struct {
func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routing.RouteRegister, bus bus.Bus, func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routing.RouteRegister, bus bus.Bus,
renderService rendering.Service, licensing licensing.Licensing, hooksService *hooks.HooksService, renderService rendering.Service, licensing licensing.Licensing, hooksService *hooks.HooksService,
cacheService *localcache.CacheService, sqlStore db.DB, cacheService *localcache.CacheService, sqlStore db.DB,
pluginRequestValidator validations.PluginRequestValidator, pluginStaticRouteResolver plugins.StaticRouteResolver, dataSourceRequestValidator validations.DataSourceRequestValidator, pluginStaticRouteResolver plugins.StaticRouteResolver,
pluginDashboardService plugindashboards.Service, pluginStore pluginstore.Store, pluginClient plugins.Client, pluginDashboardService plugindashboards.Service, pluginStore pluginstore.Store, pluginClient plugins.Client,
pluginErrorResolver plugins.ErrorResolver, pluginInstaller plugins.Installer, settingsProvider setting.Provider, pluginErrorResolver plugins.ErrorResolver, pluginInstaller plugins.Installer, settingsProvider setting.Provider,
dataSourceCache datasources.CacheService, userTokenService auth.UserTokenService, dataSourceCache datasources.CacheService, userTokenService auth.UserTokenService,
@ -284,7 +284,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
HooksService: hooksService, HooksService: hooksService,
CacheService: cacheService, CacheService: cacheService,
SQLStore: sqlStore, SQLStore: sqlStore,
PluginRequestValidator: pluginRequestValidator, DataSourceRequestValidator: dataSourceRequestValidator,
pluginInstaller: pluginInstaller, pluginInstaller: pluginInstaller,
pluginClient: pluginClient, pluginClient: pluginClient,
pluginStore: pluginStore, pluginStore: pluginStore,

@ -62,12 +62,7 @@ func (hs *HTTPServer) callPluginResourceWithDataSource(c *contextmodel.ReqContex
return return
} }
var dsURL string err = hs.DataSourceRequestValidator.Validate(ds, c.Req)
if pCtx.DataSourceInstanceSettings != nil {
dsURL = pCtx.DataSourceInstanceSettings.URL
}
err = hs.PluginRequestValidator.Validate(dsURL, c.Req)
if err != nil { if err != nil {
c.JsonApiErr(http.StatusForbidden, "Access denied", err) c.JsonApiErr(http.StatusForbidden, "Access denied", err)
return return

@ -11,7 +11,7 @@ import (
const HostRedirectValidationMiddlewareName = "host-redirect-validation" const HostRedirectValidationMiddlewareName = "host-redirect-validation"
func RedirectLimitMiddleware(reqValidator validations.PluginRequestValidator) sdkhttpclient.Middleware { func RedirectLimitMiddleware(reqValidator validations.DataSourceRequestURLValidator) sdkhttpclient.Middleware {
return sdkhttpclient.NamedMiddlewareFunc(HostRedirectValidationMiddlewareName, func(opts sdkhttpclient.Options, next http.RoundTripper) http.RoundTripper { return sdkhttpclient.NamedMiddlewareFunc(HostRedirectValidationMiddlewareName, func(opts sdkhttpclient.Options, next http.RoundTripper) http.RoundTripper {
return sdkhttpclient.RoundTripperFunc(func(req *http.Request) (*http.Response, error) { return sdkhttpclient.RoundTripperFunc(func(req *http.Request) (*http.Response, error) {
res, err := next.RoundTrip(req) res, err := next.RoundTrip(req)
@ -27,7 +27,7 @@ func RedirectLimitMiddleware(reqValidator validations.PluginRequestValidator) sd
return nil, locationErr return nil, locationErr
} }
if validationErr := reqValidator.Validate(location.String(), nil); validationErr != nil { if validationErr := reqValidator.Validate(location.String()); validationErr != nil {
return nil, validationErr return nil, validationErr
} }
} }

@ -20,7 +20,7 @@ import (
var newProviderFunc = sdkhttpclient.NewProvider var newProviderFunc = sdkhttpclient.NewProvider
// New creates a new HTTP client provider with pre-configured middlewares. // New creates a new HTTP client provider with pre-configured middlewares.
func New(cfg *setting.Cfg, validator validations.PluginRequestValidator, tracer tracing.Tracer) *sdkhttpclient.Provider { func New(cfg *setting.Cfg, validator validations.DataSourceRequestURLValidator, tracer tracing.Tracer) *sdkhttpclient.Provider {
logger := log.New("httpclient") logger := log.New("httpclient")
middlewares := []sdkhttpclient.Middleware{ middlewares := []sdkhttpclient.Middleware{

@ -24,7 +24,7 @@ func TestHTTPClientProvider(t *testing.T) {
newProviderFunc = origNewProviderFunc newProviderFunc = origNewProviderFunc
}) })
tracer := tracing.InitializeTracerForTest() tracer := tracing.InitializeTracerForTest()
_ = New(&setting.Cfg{SigV4AuthEnabled: false}, &validations.OSSPluginRequestValidator{}, tracer) _ = New(&setting.Cfg{SigV4AuthEnabled: false}, &validations.OSSDataSourceRequestURLValidator{}, tracer)
require.Len(t, providerOpts, 1) require.Len(t, providerOpts, 1)
o := providerOpts[0] o := providerOpts[0]
require.Len(t, o.Middlewares, 9) require.Len(t, o.Middlewares, 9)
@ -50,7 +50,7 @@ func TestHTTPClientProvider(t *testing.T) {
newProviderFunc = origNewProviderFunc newProviderFunc = origNewProviderFunc
}) })
tracer := tracing.InitializeTracerForTest() tracer := tracing.InitializeTracerForTest()
_ = New(&setting.Cfg{SigV4AuthEnabled: true}, &validations.OSSPluginRequestValidator{}, tracer) _ = New(&setting.Cfg{SigV4AuthEnabled: true}, &validations.OSSDataSourceRequestURLValidator{}, tracer)
require.Len(t, providerOpts, 1) require.Len(t, providerOpts, 1)
o := providerOpts[0] o := providerOpts[0]
require.Len(t, o.Middlewares, 10) require.Len(t, o.Middlewares, 10)
@ -77,7 +77,7 @@ func TestHTTPClientProvider(t *testing.T) {
newProviderFunc = origNewProviderFunc newProviderFunc = origNewProviderFunc
}) })
tracer := tracing.InitializeTracerForTest() tracer := tracing.InitializeTracerForTest()
_ = New(&setting.Cfg{PluginSettings: setting.PluginSettings{"example": {"har_log_enabled": "true"}}}, &validations.OSSPluginRequestValidator{}, tracer) _ = New(&setting.Cfg{PluginSettings: setting.PluginSettings{"example": {"har_log_enabled": "true"}}}, &validations.OSSDataSourceRequestURLValidator{}, tracer)
require.Len(t, providerOpts, 1) require.Len(t, providerOpts, 1)
o := providerOpts[0] o := providerOpts[0]
require.Len(t, o.Middlewares, 10) require.Len(t, o.Middlewares, 10)

@ -70,7 +70,9 @@ var wireExtsBasicSet = wire.NewSet(
wire.Bind(new(pluginaccesscontrol.RoleRegistry), new(*acimpl.Service)), wire.Bind(new(pluginaccesscontrol.RoleRegistry), new(*acimpl.Service)),
wire.Bind(new(accesscontrol.Service), new(*acimpl.Service)), wire.Bind(new(accesscontrol.Service), new(*acimpl.Service)),
validations.ProvideValidator, validations.ProvideValidator,
wire.Bind(new(validations.PluginRequestValidator), new(*validations.OSSPluginRequestValidator)), wire.Bind(new(validations.DataSourceRequestValidator), new(*validations.OSSDataSourceRequestValidator)),
validations.ProvideURLValidator,
wire.Bind(new(validations.DataSourceRequestURLValidator), new(*validations.OSSDataSourceRequestURLValidator)),
provisioning.ProvideService, provisioning.ProvideService,
wire.Bind(new(provisioning.ProvisioningService), new(*provisioning.ProvisioningServiceImpl)), wire.Bind(new(provisioning.ProvisioningService), new(*provisioning.ProvisioningServiceImpl)),
backgroundsvcs.ProvideBackgroundServiceRegistry, backgroundsvcs.ProvideBackgroundServiceRegistry,

@ -24,13 +24,13 @@ import (
"github.com/grafana/grafana/pkg/web" "github.com/grafana/grafana/pkg/web"
) )
func ProvideService(dataSourceCache datasources.CacheService, plugReqValidator validations.PluginRequestValidator, func ProvideService(dataSourceCache datasources.CacheService, datasourceReqValidator validations.DataSourceRequestValidator,
pluginStore pluginstore.Store, cfg *setting.Cfg, httpClientProvider httpclient.Provider, pluginStore pluginstore.Store, cfg *setting.Cfg, httpClientProvider httpclient.Provider,
oauthTokenService *oauthtoken.Service, dsService datasources.DataSourceService, oauthTokenService *oauthtoken.Service, dsService datasources.DataSourceService,
tracer tracing.Tracer, secretsService secrets.Service, features featuremgmt.FeatureToggles) *DataSourceProxyService { tracer tracing.Tracer, secretsService secrets.Service, features featuremgmt.FeatureToggles) *DataSourceProxyService {
return &DataSourceProxyService{ return &DataSourceProxyService{
DataSourceCache: dataSourceCache, DataSourceCache: dataSourceCache,
PluginRequestValidator: plugReqValidator, DataSourceRequestValidator: datasourceReqValidator,
pluginStore: pluginStore, pluginStore: pluginStore,
Cfg: cfg, Cfg: cfg,
HTTPClientProvider: httpClientProvider, HTTPClientProvider: httpClientProvider,
@ -44,7 +44,7 @@ func ProvideService(dataSourceCache datasources.CacheService, plugReqValidator v
type DataSourceProxyService struct { type DataSourceProxyService struct {
DataSourceCache datasources.CacheService DataSourceCache datasources.CacheService
PluginRequestValidator validations.PluginRequestValidator DataSourceRequestValidator validations.DataSourceRequestValidator
pluginStore pluginstore.Store pluginStore pluginstore.Store
Cfg *setting.Cfg Cfg *setting.Cfg
HTTPClientProvider httpclient.Provider HTTPClientProvider httpclient.Provider
@ -108,7 +108,7 @@ func toAPIError(c *contextmodel.ReqContext, err error) {
} }
func (p *DataSourceProxyService) proxyDatasourceRequest(c *contextmodel.ReqContext, ds *datasources.DataSource) { func (p *DataSourceProxyService) proxyDatasourceRequest(c *contextmodel.ReqContext, ds *datasources.DataSource) {
err := p.PluginRequestValidator.Validate(ds.URL, c.Req) err := p.DataSourceRequestValidator.Validate(ds, c.Req)
if err != nil { if err != nil {
c.JsonApiErr(http.StatusForbidden, "Access denied", err) c.JsonApiErr(http.StatusForbidden, "Access denied", err)
return return

@ -94,7 +94,7 @@ func TestDatasourceProxy_proxyDatasourceRequest(t *testing.T) {
}} }}
p := DataSourceProxyService{ p := DataSourceProxyService{
PluginRequestValidator: &fakePluginRequestValidator{}, DataSourceRequestValidator: &fakeDataSourceRequestValidator{},
pluginStore: pluginStore, pluginStore: pluginStore,
} }
@ -129,8 +129,8 @@ func TestDatasourceProxy_proxyDatasourceRequest(t *testing.T) {
} }
} }
type fakePluginRequestValidator struct{} type fakeDataSourceRequestValidator struct{}
func (rv *fakePluginRequestValidator) Validate(_ string, _ *http.Request) error { func (rv *fakeDataSourceRequestValidator) Validate(_ *datasources.DataSource, _ *http.Request) error {
return nil return nil
} }

@ -70,6 +70,16 @@ type DataSource struct {
Created time.Time `json:"created,omitempty"` Created time.Time `json:"created,omitempty"`
Updated time.Time `json:"updated,omitempty"` Updated time.Time `json:"updated,omitempty"`
isSecureSocksDSProxyEnabled *bool `xorm:"-"`
}
func (ds *DataSource) IsSecureSocksDSProxyEnabled() bool {
if ds.isSecureSocksDSProxyEnabled == nil {
enabled := ds.JsonData != nil && ds.JsonData.Get("enableSecureSocksProxy").MustBool(false)
ds.isSecureSocksDSProxyEnabled = &enabled
}
return *ds.isSecureSocksDSProxyEnabled
} }
type TeamHTTPHeadersJSONData struct { type TeamHTTPHeadersJSONData struct {

@ -102,3 +102,58 @@ func TestTeamHTTPHeaders(t *testing.T) {
}) })
} }
} }
func TestIsSecureSocksDSProxyEnabled(t *testing.T) {
testCases := []struct {
desc string
ds *DataSource
want bool
}{
{
desc: "Empty json",
ds: &DataSource{
JsonData: simplejson.New(),
},
want: false,
},
{
desc: "Json with enableSecureSocksProxy",
ds: &DataSource{
JsonData: simplejson.NewFromAny(map[string]interface{}{
"enableSecureSocksProxy": true,
}),
},
want: true,
},
{
desc: "Json with string enableSecureSocksProxy",
ds: &DataSource{
JsonData: simplejson.NewFromAny(map[string]interface{}{
"enableSecureSocksProxy": "true",
}),
},
want: false,
},
{
desc: "Json with enableSecureSocksProxy false",
ds: &DataSource{
JsonData: simplejson.NewFromAny(map[string]interface{}{
"enableSecureSocksProxy": false,
}),
},
want: false,
},
{
desc: "Json with no json data",
ds: &DataSource{},
want: false,
},
}
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
actual := tc.ds.IsSecureSocksDSProxyEnabled()
assert.Equal(t, tc.want, actual)
})
}
}

@ -745,7 +745,7 @@ func (s *Service) httpClientOptions(ctx context.Context, ds *datasources.DataSou
} }
} }
if ds.JsonData != nil && ds.JsonData.Get("enableSecureSocksProxy").MustBool(false) { if ds.IsSecureSocksDSProxyEnabled() {
proxyOpts := &sdkproxy.Options{ proxyOpts := &sdkproxy.Options{
Enabled: true, Enabled: true,
Auth: &sdkproxy.AuthOptions{ Auth: &sdkproxy.AuthOptions{

@ -152,18 +152,18 @@ func buildQueryDataService(t *testing.T, cs datasources.CacheService, fpc *fakeP
setting.NewCfg(), setting.NewCfg(),
cs, cs,
nil, nil,
&fakePluginRequestValidator{}, &fakeDataSourceRequestValidator{},
fpc, fpc,
pCtxProvider, pCtxProvider,
) )
} }
// copied from pkg/api/metrics_test.go // copied from pkg/api/metrics_test.go
type fakePluginRequestValidator struct { type fakeDataSourceRequestValidator struct {
err error err error
} }
func (rv *fakePluginRequestValidator) Validate(dsURL string, req *http.Request) error { func (rv *fakeDataSourceRequestValidator) Validate(ds *datasources.DataSource, req *http.Request) error {
return rv.err return rv.err
} }

@ -42,7 +42,7 @@ func ProvideService(
cfg *setting.Cfg, cfg *setting.Cfg,
dataSourceCache datasources.CacheService, dataSourceCache datasources.CacheService,
expressionService *expr.Service, expressionService *expr.Service,
pluginRequestValidator validations.PluginRequestValidator, dataSourceRequestValidator validations.DataSourceRequestValidator,
pluginClient plugins.Client, pluginClient plugins.Client,
pCtxProvider *plugincontext.Provider, pCtxProvider *plugincontext.Provider,
) *ServiceImpl { ) *ServiceImpl {
@ -50,7 +50,7 @@ func ProvideService(
cfg: cfg, cfg: cfg,
dataSourceCache: dataSourceCache, dataSourceCache: dataSourceCache,
expressionService: expressionService, expressionService: expressionService,
pluginRequestValidator: pluginRequestValidator, dataSourceRequestValidator: dataSourceRequestValidator,
pluginClient: pluginClient, pluginClient: pluginClient,
pCtxProvider: pCtxProvider, pCtxProvider: pCtxProvider,
log: log.New("query_data"), log: log.New("query_data"),
@ -73,7 +73,7 @@ type ServiceImpl struct {
cfg *setting.Cfg cfg *setting.Cfg
dataSourceCache datasources.CacheService dataSourceCache datasources.CacheService
expressionService *expr.Service expressionService *expr.Service
pluginRequestValidator validations.PluginRequestValidator dataSourceRequestValidator validations.DataSourceRequestValidator
pluginClient plugins.Client pluginClient plugins.Client
pCtxProvider *plugincontext.Provider pCtxProvider *plugincontext.Provider
log log.Logger log log.Logger
@ -244,7 +244,7 @@ func (s *ServiceImpl) handleExpressions(ctx context.Context, user identity.Reque
func (s *ServiceImpl) handleQuerySingleDatasource(ctx context.Context, user identity.Requester, parsedReq *parsedRequest) (*backend.QueryDataResponse, error) { func (s *ServiceImpl) handleQuerySingleDatasource(ctx context.Context, user identity.Requester, parsedReq *parsedRequest) (*backend.QueryDataResponse, error) {
queries := parsedReq.getFlattenedQueries() queries := parsedReq.getFlattenedQueries()
ds := queries[0].datasource ds := queries[0].datasource
if err := s.pluginRequestValidator.Validate(ds.URL, nil); err != nil { if err := s.dataSourceRequestValidator.Validate(ds, nil); err != nil {
return nil, datasources.ErrDataSourceAccessDenied return nil, datasources.ErrDataSourceAccessDenied
} }

@ -462,7 +462,7 @@ func setup(t *testing.T) *testContext {
t.Helper() t.Helper()
pc := &fakePluginClient{} pc := &fakePluginClient{}
dc := &fakeDataSourceCache{cache: dss} dc := &fakeDataSourceCache{cache: dss}
rv := &fakePluginRequestValidator{} rv := &fakeDataSourceRequestValidator{}
sqlStore, cfg := db.InitTestDBWithCfg(t) sqlStore, cfg := db.InitTestDBWithCfg(t)
secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore()) secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore())
@ -497,7 +497,7 @@ func setup(t *testing.T) *testContext {
type testContext struct { type testContext struct {
pluginContext *fakePluginClient pluginContext *fakePluginClient
secretStore secretskvs.SecretsKVStore secretStore secretskvs.SecretsKVStore
pluginRequestValidator *fakePluginRequestValidator pluginRequestValidator *fakeDataSourceRequestValidator
queryService *ServiceImpl // implementation belonging to this package queryService *ServiceImpl // implementation belonging to this package
signedInUser *user.SignedInUser signedInUser *user.SignedInUser
} }
@ -518,11 +518,11 @@ func metricRequestWithQueries(t *testing.T, rawQueries ...string) dtos.MetricReq
} }
} }
type fakePluginRequestValidator struct { type fakeDataSourceRequestValidator struct {
err error err error
} }
func (rv *fakePluginRequestValidator) Validate(dsURL string, req *http.Request) error { func (rv *fakeDataSourceRequestValidator) Validate(ds *datasources.DataSource, req *http.Request) error {
return rv.err return rv.err
} }

@ -2,14 +2,26 @@ package validations
import ( import (
"net/http" "net/http"
"github.com/grafana/grafana/pkg/services/datasources"
) )
type OSSPluginRequestValidator struct{} type OSSDataSourceRequestValidator struct{}
func (*OSSDataSourceRequestValidator) Validate(*datasources.DataSource, *http.Request) error {
return nil
}
func ProvideValidator() *OSSDataSourceRequestValidator {
return &OSSDataSourceRequestValidator{}
}
type OSSDataSourceRequestURLValidator struct{}
func (*OSSPluginRequestValidator) Validate(string, *http.Request) error { func (*OSSDataSourceRequestURLValidator) Validate(string) error {
return nil return nil
} }
func ProvideValidator() *OSSPluginRequestValidator { func ProvideURLValidator() *OSSDataSourceRequestURLValidator {
return &OSSPluginRequestValidator{} return &OSSDataSourceRequestURLValidator{}
} }

@ -2,11 +2,18 @@ package validations
import ( import (
"net/http" "net/http"
"github.com/grafana/grafana/pkg/services/datasources"
) )
type PluginRequestValidator interface { type DataSourceRequestValidator interface {
// Validate performs a request validation based // Validate performs a request validation based
// on the data source URL and some of the request // on the data source URL and some of the request
// attributes (headers, cookies, etc). // attributes (headers, cookies, etc).
Validate(dsURL string, req *http.Request) error Validate(ds *datasources.DataSource, req *http.Request) error
}
type DataSourceRequestURLValidator interface {
// Validate performs a request validation based on the data source URL
Validate(dsURL string) error
} }

Loading…
Cancel
Save