mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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>
This commit is contained in:
parent
33a53d170b
commit
d192a44469
@ -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,35 +24,35 @@ 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,
|
||||||
OAuthTokenService: oauthTokenService,
|
OAuthTokenService: oauthTokenService,
|
||||||
DataSourcesService: dsService,
|
DataSourcesService: dsService,
|
||||||
tracer: tracer,
|
tracer: tracer,
|
||||||
secretsService: secretsService,
|
secretsService: secretsService,
|
||||||
features: features,
|
features: features,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
OAuthTokenService *oauthtoken.Service
|
OAuthTokenService *oauthtoken.Service
|
||||||
DataSourcesService datasources.DataSourceService
|
DataSourcesService datasources.DataSourceService
|
||||||
tracer tracing.Tracer
|
tracer tracing.Tracer
|
||||||
secretsService secrets.Service
|
secretsService secrets.Service
|
||||||
features featuremgmt.FeatureToggles
|
features featuremgmt.FeatureToggles
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *DataSourceProxyService) ProxyDataSourceRequest(c *contextmodel.ReqContext) {
|
func (p *DataSourceProxyService) ProxyDataSourceRequest(c *contextmodel.ReqContext) {
|
||||||
@ -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,8 +94,8 @@ func TestDatasourceProxy_proxyDatasourceRequest(t *testing.T) {
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
p := DataSourceProxyService{
|
p := DataSourceProxyService{
|
||||||
PluginRequestValidator: &fakePluginRequestValidator{},
|
DataSourceRequestValidator: &fakeDataSourceRequestValidator{},
|
||||||
pluginStore: pluginStore,
|
pluginStore: pluginStore,
|
||||||
}
|
}
|
||||||
|
|
||||||
responseRecorder := httptest.NewRecorder()
|
responseRecorder := httptest.NewRecorder()
|
||||||
@ -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,19 +42,19 @@ 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 {
|
||||||
g := &ServiceImpl{
|
g := &ServiceImpl{
|
||||||
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"),
|
||||||
concurrentQueryLimit: cfg.SectionWithEnvOverrides("query").Key("concurrent_query_limit").MustInt(runtime.NumCPU()),
|
concurrentQueryLimit: cfg.SectionWithEnvOverrides("query").Key("concurrent_query_limit").MustInt(runtime.NumCPU()),
|
||||||
}
|
}
|
||||||
g.log.Info("Query Service initialization")
|
g.log.Info("Query Service initialization")
|
||||||
return g
|
return g
|
||||||
@ -70,14 +70,14 @@ type Service interface {
|
|||||||
var _ Service = (*ServiceImpl)(nil)
|
var _ Service = (*ServiceImpl)(nil)
|
||||||
|
|
||||||
type ServiceImpl struct {
|
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
|
||||||
concurrentQueryLimit int
|
concurrentQueryLimit int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run ServiceImpl.
|
// Run ServiceImpl.
|
||||||
@ -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 (*OSSPluginRequestValidator) Validate(string, *http.Request) error {
|
func (*OSSDataSourceRequestValidator) Validate(*datasources.DataSource, *http.Request) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProvideValidator() *OSSPluginRequestValidator {
|
func ProvideValidator() *OSSDataSourceRequestValidator {
|
||||||
return &OSSPluginRequestValidator{}
|
return &OSSDataSourceRequestValidator{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type OSSDataSourceRequestURLValidator struct{}
|
||||||
|
|
||||||
|
func (*OSSDataSourceRequestURLValidator) Validate(string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ProvideURLValidator() *OSSDataSourceRequestURLValidator {
|
||||||
|
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…
Reference in New Issue
Block a user