Pyroscope: Add authentication when calling backendType resource API (#67667)

pull/68319/head
Andrej Ocenas 2 years ago committed by GitHub
parent c9ce1a28c3
commit 8da90f624d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      pkg/plugins/manager/manager_integration_test.go
  2. 39
      pkg/tsdb/phlare/instance.go
  3. 9
      pkg/tsdb/phlare/service.go

@ -10,6 +10,7 @@ import (
"github.com/grafana/grafana-azure-sdk-go/azsettings"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
"github.com/stretchr/testify/require"
"gopkg.in/ini.v1"
@ -107,7 +108,7 @@ func TestIntegrationPluginManager(t *testing.T) {
ms := mssql.ProvideService(cfg)
sv2 := searchV2.ProvideService(cfg, db.InitTestDB(t), nil, nil, tracer, features, nil, nil, nil)
graf := grafanads.ProvideService(sv2, nil)
phlare := phlare.ProvideService(hcp)
phlare := phlare.ProvideService(hcp, acimpl.ProvideAccessControl(cfg))
parca := parca.ProvideService(hcp)
coreRegistry := coreplugin.ProvideCoreRegistry(am, cw, cm, es, grap, idb, lk, otsdb, pr, tmpo, td, pg, my, ms, graf, phlare, parca)

@ -13,6 +13,9 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/contexthandler"
"github.com/grafana/grafana/pkg/services/datasources"
)
var (
@ -27,6 +30,7 @@ type PhlareDatasource struct {
httpClient *http.Client
client ProfilingClient
settings backend.DataSourceInstanceSettings
ac accesscontrol.AccessControl
}
type JsonData struct {
@ -34,7 +38,7 @@ type JsonData struct {
}
// NewPhlareDatasource creates a new datasource instance.
func NewPhlareDatasource(httpClientProvider httpclient.Provider, settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
func NewPhlareDatasource(httpClientProvider httpclient.Provider, settings backend.DataSourceInstanceSettings, ac accesscontrol.AccessControl) (instancemgmt.Instance, error) {
opt, err := settings.HTTPClientOptions()
if err != nil {
return nil, err
@ -54,6 +58,7 @@ func NewPhlareDatasource(httpClientProvider httpclient.Provider, settings backen
httpClient: httpClient,
client: getClient(jsonData.BackendType, httpClient, settings.URL),
settings: settings,
ac: ac,
}, nil
}
@ -165,6 +170,17 @@ type BackendTypeRespBody struct {
// backendType is a simplistic test to figure out if we are speaking to phlare or pyroscope backend
func (d *PhlareDatasource) backendType(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
// To prevent any user sending arbitrary URL for us to test with we allow this only for users who can edit the datasource
// as config page is where this is meant to be used.
ok, err := d.isUserAllowedToEditDatasource(ctx)
if err != nil {
return err
}
if !ok {
return sender.Send(&backend.CallResourceResponse{Headers: req.Headers, Status: 401})
}
u, err := url.Parse(req.URL)
if err != nil {
return err
@ -194,11 +210,26 @@ func (d *PhlareDatasource) backendType(ctx context.Context, req *backend.CallRes
return err
}
err = sender.Send(&backend.CallResourceResponse{Body: data, Headers: req.Headers, Status: 200})
return sender.Send(&backend.CallResourceResponse{Body: data, Headers: req.Headers, Status: 200})
}
func (d *PhlareDatasource) isUserAllowedToEditDatasource(ctx context.Context) (bool, error) {
reqCtx := contexthandler.FromContext(ctx)
uidScope := datasources.ScopeProvider.GetResourceScopeUID(accesscontrol.Parameter(":uid"))
if reqCtx == nil || reqCtx.SignedInUser == nil {
return false, nil
}
ok, err := d.ac.Evaluate(ctx, reqCtx.SignedInUser, accesscontrol.EvalPermission(datasources.ActionWrite, uidScope))
if err != nil {
return err
return false, err
}
return nil
if !ok {
return false, nil
}
return true, nil
}
// QueryData handles multiple queries and returns multiple responses.

@ -8,6 +8,7 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/accesscontrol"
)
// Make sure PhlareDatasource implements required interfaces. This is important to do
@ -41,15 +42,15 @@ func (s *Service) getInstance(pluginCtx backend.PluginContext) (*PhlareDatasourc
return in, nil
}
func ProvideService(httpClientProvider httpclient.Provider) *Service {
func ProvideService(httpClientProvider httpclient.Provider, ac accesscontrol.AccessControl) *Service {
return &Service{
im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider)),
im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider, ac)),
}
}
func newInstanceSettings(httpClientProvider httpclient.Provider) datasource.InstanceFactoryFunc {
func newInstanceSettings(httpClientProvider httpclient.Provider, ac accesscontrol.AccessControl) datasource.InstanceFactoryFunc {
return func(settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return NewPhlareDatasource(httpClientProvider, settings)
return NewPhlareDatasource(httpClientProvider, settings, ac)
}
}

Loading…
Cancel
Save