mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
RBAC: cascaded nested folder permissions for search v2 (#62608)
* fetch inherited folder scopes for search v2 * fix error and don't fetch parents for the general folder * remove feature toggle check and lower log level
This commit is contained in:
parent
161ff6d310
commit
49ccae7489
@ -104,7 +104,7 @@ func TestIntegrationPluginManager(t *testing.T) {
|
||||
pg := postgres.ProvideService(cfg)
|
||||
my := mysql.ProvideService(cfg, hcp)
|
||||
ms := mssql.ProvideService(cfg)
|
||||
sv2 := searchV2.ProvideService(cfg, db.InitTestDB(t), nil, nil, tracer, features, nil, nil, nil)
|
||||
sv2 := searchV2.ProvideService(cfg, db.InitTestDB(t), nil, nil, tracer, features, nil, nil, nil, nil)
|
||||
graf := grafanads.ProvideService(sv2, nil)
|
||||
phlare := phlare.ProvideService(hcp)
|
||||
parca := parca.ProvideService(hcp)
|
||||
|
@ -86,7 +86,7 @@ var (
|
||||
func service(t *testing.T) *StandardSearchService {
|
||||
service, ok := ProvideService(&setting.Cfg{Search: setting.SearchSettings{}},
|
||||
nil, nil, accesscontrolmock.New(), tracing.InitializeTracerForTest(), featuremgmt.WithFeatures(),
|
||||
nil, nil, nil).(*StandardSearchService)
|
||||
nil, nil, nil, nil).(*StandardSearchService)
|
||||
require.True(t, ok)
|
||||
return service
|
||||
}
|
||||
|
@ -4,8 +4,10 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/permissions"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
)
|
||||
@ -15,28 +17,41 @@ type ResourceFilter func(kind entityKind, uid, parentUID string) bool
|
||||
|
||||
// FutureAuthService eventually implemented by the security service
|
||||
type FutureAuthService interface {
|
||||
GetDashboardReadFilter(user *user.SignedInUser) (ResourceFilter, error)
|
||||
GetDashboardReadFilter(ctx context.Context, orgID int64, user *user.SignedInUser) (ResourceFilter, error)
|
||||
}
|
||||
|
||||
var _ FutureAuthService = (*simpleAuthService)(nil)
|
||||
|
||||
type simpleAuthService struct {
|
||||
sql db.DB
|
||||
ac accesscontrol.Service
|
||||
sql db.DB
|
||||
ac accesscontrol.Service
|
||||
folderService folder.Service
|
||||
logger log.Logger
|
||||
}
|
||||
|
||||
type dashIdQueryResult struct {
|
||||
UID string `xorm:"uid"`
|
||||
}
|
||||
|
||||
func (a *simpleAuthService) GetDashboardReadFilter(user *user.SignedInUser) (ResourceFilter, error) {
|
||||
func (a *simpleAuthService) GetDashboardReadFilter(ctx context.Context, orgID int64, user *user.SignedInUser) (ResourceFilter, error) {
|
||||
if !a.ac.IsDisabled() {
|
||||
canReadDashboard, canReadFolder := accesscontrol.Checker(user, dashboards.ActionDashboardsRead), accesscontrol.Checker(user, dashboards.ActionFoldersRead)
|
||||
return func(kind entityKind, uid, parent string) bool {
|
||||
if kind == entityKindFolder {
|
||||
return canReadFolder(dashboards.ScopeFoldersProvider.GetResourceScopeUID(uid))
|
||||
scopes, err := dashboards.GetInheritedScopes(ctx, orgID, uid, a.folderService)
|
||||
if err != nil {
|
||||
a.logger.Debug("could not retrieve inherited folder scopes:", "err", err)
|
||||
}
|
||||
scopes = append(scopes, dashboards.ScopeFoldersProvider.GetResourceScopeUID(uid))
|
||||
return canReadFolder(scopes...)
|
||||
} else if kind == entityKindDashboard {
|
||||
return canReadDashboard(dashboards.ScopeDashboardsProvider.GetResourceScopeUID(uid), dashboards.ScopeFoldersProvider.GetResourceScopeUID(parent))
|
||||
scopes, err := dashboards.GetInheritedScopes(ctx, orgID, parent, a.folderService)
|
||||
if err != nil {
|
||||
a.logger.Debug("could not retrieve inherited folder scopes:", "err", err)
|
||||
}
|
||||
scopes = append(scopes, dashboards.ScopeDashboardsProvider.GetResourceScopeUID(uid))
|
||||
scopes = append(scopes, dashboards.ScopeFoldersProvider.GetResourceScopeUID(parent))
|
||||
return canReadDashboard(scopes...)
|
||||
}
|
||||
return false
|
||||
}, nil
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/querylibrary"
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
@ -84,15 +85,18 @@ func (s *StandardSearchService) IsReady(ctx context.Context, orgId int64) IsSear
|
||||
|
||||
func ProvideService(cfg *setting.Cfg, sql db.DB, entityEventStore store.EntityEventsService,
|
||||
ac accesscontrol.Service, tracer tracing.Tracer, features featuremgmt.FeatureToggles, orgService org.Service,
|
||||
userService user.Service, queries querylibrary.Service) SearchService {
|
||||
userService user.Service, queries querylibrary.Service, folderService folder.Service) SearchService {
|
||||
extender := &NoopExtender{}
|
||||
logger := log.New("searchV2")
|
||||
s := &StandardSearchService{
|
||||
cfg: cfg,
|
||||
sql: sql,
|
||||
ac: ac,
|
||||
auth: &simpleAuthService{
|
||||
sql: sql,
|
||||
ac: ac,
|
||||
sql: sql,
|
||||
ac: ac,
|
||||
folderService: folderService,
|
||||
logger: logger,
|
||||
},
|
||||
dashboardIndex: newSearchIndex(
|
||||
newSQLDashboardLoader(sql, tracer, cfg.Search),
|
||||
@ -103,7 +107,7 @@ func ProvideService(cfg *setting.Cfg, sql db.DB, entityEventStore store.EntityEv
|
||||
features,
|
||||
cfg.Search,
|
||||
),
|
||||
logger: log.New("searchV2"),
|
||||
logger: logger,
|
||||
extender: extender,
|
||||
reIndexCh: make(chan struct{}, 1),
|
||||
orgService: orgService,
|
||||
@ -244,7 +248,7 @@ func (s *StandardSearchService) doDashboardQuery(ctx context.Context, signedInUs
|
||||
|
||||
rsp := &backend.DataResponse{}
|
||||
|
||||
filter, err := s.auth.GetDashboardReadFilter(signedInUser)
|
||||
filter, err := s.auth.GetDashboardReadFilter(ctx, orgID, signedInUser)
|
||||
if err != nil {
|
||||
dashboardSearchFailureRequestsCounter.With(prometheus.Labels{
|
||||
"reason": "get_dashboard_filter_error",
|
||||
|
@ -39,7 +39,7 @@ func setupBenchEnv(b *testing.B, folderCount, dashboardsPerFolder int) (*Standar
|
||||
}
|
||||
querySvc := querylibraryimpl.ProvideService(cfg, features)
|
||||
searchService, ok := ProvideService(cfg, sqlStore, store.NewDummyEntityEventsService(), actest.FakeService{},
|
||||
tracing.InitializeTracerForTest(), features, orgSvc, nil, querySvc).(*StandardSearchService)
|
||||
tracing.InitializeTracerForTest(), features, orgSvc, nil, querySvc, nil).(*StandardSearchService)
|
||||
require.True(b, ok)
|
||||
|
||||
err = runSearchService(searchService)
|
||||
|
Loading…
Reference in New Issue
Block a user