Access Control: Add fixed role loader service (#112747)
This commit is contained in:
@@ -1228,7 +1228,7 @@ export interface FeatureToggles {
|
||||
*/
|
||||
preventPanelChromeOverflow?: boolean;
|
||||
/**
|
||||
* Load plugins during store service startup instead of wire provider
|
||||
* Load plugins on store service startup instead of wire provider, and call RegisterFixedRoles after all plugins are loaded
|
||||
* @default false
|
||||
*/
|
||||
pluginStoreServiceLoading?: boolean;
|
||||
|
||||
@@ -3,6 +3,7 @@ package adapter
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/modules"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/plugininstaller"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/provisioning"
|
||||
@@ -31,6 +32,9 @@ const (
|
||||
// Core is the module name for the core module.
|
||||
// This module is an alias for a set of service dependencies that must be running before most other services can start.
|
||||
Core = "core"
|
||||
|
||||
// FixedRolesLoader is the module name for the fixed roles loader service.
|
||||
FixedRolesLoader = accesscontrol.FixedRolesLoaderServiceName
|
||||
)
|
||||
|
||||
// dependencyMap returns the module dependency relationships for the background service system.
|
||||
@@ -43,8 +47,9 @@ func dependencyMap() map[string][]string {
|
||||
GrafanaAPIServer: {Tracing},
|
||||
PluginStore: {GrafanaAPIServer},
|
||||
PluginInstaller: {PluginStore},
|
||||
Provisioning: {PluginStore, PluginInstaller},
|
||||
Core: {GrafanaAPIServer, PluginStore, PluginInstaller, Provisioning},
|
||||
FixedRolesLoader: {PluginInstaller},
|
||||
Provisioning: {PluginStore, PluginInstaller, FixedRolesLoader},
|
||||
Core: {GrafanaAPIServer, PluginStore, PluginInstaller, FixedRolesLoader, Provisioning},
|
||||
BackgroundServices: {Core},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
apiregistry "github.com/grafana/grafana/pkg/registry/apis"
|
||||
secretsgarbagecollectionworker "github.com/grafana/grafana/pkg/registry/apis/secret/garbagecollectionworker"
|
||||
appregistry "github.com/grafana/grafana/pkg/registry/apps"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/dualwrite"
|
||||
"github.com/grafana/grafana/pkg/services/anonymous/anonimpl"
|
||||
grafanaapiserver "github.com/grafana/grafana/pkg/services/apiserver"
|
||||
@@ -71,6 +72,7 @@ func ProvideBackgroundServiceRegistry(
|
||||
pluginDashboardUpdater *plugindashboardsservice.DashboardUpdater,
|
||||
dashboardServiceImpl *service.DashboardServiceImpl,
|
||||
secretsGarbageCollectionWorker *secretsgarbagecollectionworker.Worker,
|
||||
fixedRolesLoader *accesscontrol.FixedRolesLoader,
|
||||
// Need to make sure these are initialized, is there a better place to put them?
|
||||
_ dashboardsnapshots.Service,
|
||||
_ serviceaccounts.Service,
|
||||
@@ -118,6 +120,7 @@ func ProvideBackgroundServiceRegistry(
|
||||
pluginDashboardUpdater,
|
||||
dashboardServiceImpl,
|
||||
secretsGarbageCollectionWorker,
|
||||
fixedRolesLoader,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+10
-5
@@ -20,6 +20,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
"github.com/grafana/grafana/pkg/registry/backgroundsvcs/adapter"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/provisioning"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
@@ -38,11 +39,11 @@ type Options struct {
|
||||
func New(opts Options, cfg *setting.Cfg, httpServer *api.HTTPServer, roleRegistry accesscontrol.RoleRegistry,
|
||||
provisioningService provisioning.ProvisioningService, backgroundServiceProvider registry.BackgroundServiceRegistry,
|
||||
usageStatsProvidersRegistry registry.UsageStatsProvidersRegistry, statsCollectorService *statscollector.Service,
|
||||
tracerProvider *tracing.TracingService,
|
||||
tracerProvider *tracing.TracingService, features featuremgmt.FeatureToggles,
|
||||
promReg prometheus.Registerer,
|
||||
) (*Server, error) {
|
||||
statsCollectorService.RegisterProviders(usageStatsProvidersRegistry.GetServices())
|
||||
s, err := newServer(opts, cfg, httpServer, roleRegistry, provisioningService, backgroundServiceProvider, tracerProvider, promReg)
|
||||
s, err := newServer(opts, cfg, httpServer, roleRegistry, provisioningService, backgroundServiceProvider, tracerProvider, features, promReg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -56,7 +57,7 @@ func New(opts Options, cfg *setting.Cfg, httpServer *api.HTTPServer, roleRegistr
|
||||
|
||||
func newServer(opts Options, cfg *setting.Cfg, httpServer *api.HTTPServer, roleRegistry accesscontrol.RoleRegistry,
|
||||
provisioningService provisioning.ProvisioningService, backgroundServiceProvider registry.BackgroundServiceRegistry,
|
||||
tracerProvider *tracing.TracingService,
|
||||
tracerProvider *tracing.TracingService, features featuremgmt.FeatureToggles,
|
||||
promReg prometheus.Registerer,
|
||||
) (*Server, error) {
|
||||
rootCtx := context.Background()
|
||||
@@ -75,6 +76,7 @@ func newServer(opts Options, cfg *setting.Cfg, httpServer *api.HTTPServer, roleR
|
||||
buildBranch: opts.BuildBranch,
|
||||
backgroundServiceRegistry: backgroundServiceProvider,
|
||||
tracerProvider: tracerProvider,
|
||||
features: features,
|
||||
managerAdapter: adapter.NewManagerAdapter(backgroundServiceProvider),
|
||||
}
|
||||
|
||||
@@ -99,6 +101,7 @@ type Server struct {
|
||||
|
||||
backgroundServiceRegistry registry.BackgroundServiceRegistry
|
||||
tracerProvider *tracing.TracingService
|
||||
features featuremgmt.FeatureToggles
|
||||
|
||||
HTTPServer *api.HTTPServer
|
||||
roleRegistry accesscontrol.RoleRegistry
|
||||
@@ -125,8 +128,10 @@ func (s *Server) Init() error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.roleRegistry.RegisterFixedRoles(s.context); err != nil {
|
||||
return err
|
||||
if !s.features.IsEnabledGlobally(featuremgmt.FlagPluginStoreServiceLoading) {
|
||||
if err := s.roleRegistry.RegisterFixedRoles(s.context); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return s.provisioningService.RunInitProvisioners(s.context)
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/registry/backgroundsvcs"
|
||||
"github.com/grafana/grafana/pkg/registry/backgroundsvcs/adapter"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@@ -51,7 +52,7 @@ func (s *testService) IsDisabled() bool {
|
||||
|
||||
func testServer(t *testing.T, services ...registry.BackgroundService) *Server {
|
||||
t.Helper()
|
||||
s, err := newServer(Options{}, setting.NewCfg(), nil, &acimpl.Service{}, nil, backgroundsvcs.NewBackgroundServiceRegistry(services...), tracing.NewNoopTracerService(), prometheus.NewRegistry())
|
||||
s, err := newServer(Options{}, setting.NewCfg(), nil, &acimpl.Service{}, nil, backgroundsvcs.NewBackgroundServiceRegistry(services...), tracing.NewNoopTracerService(), featuremgmt.WithFeatures(), prometheus.NewRegistry())
|
||||
require.NoError(t, err)
|
||||
s.managerAdapter.WithDependencies(map[string][]string{
|
||||
adapter.Core: {},
|
||||
|
||||
@@ -401,6 +401,7 @@ var wireBasicSet = wire.NewSet(
|
||||
wire.Bind(new(pluginaccesscontrol.ActionSetRegistry), new(resourcepermissions.ActionSetService)),
|
||||
permreg.ProvidePermissionRegistry,
|
||||
acimpl.ProvideAccessControl,
|
||||
accesscontrol.ProvideFixedRolesLoader,
|
||||
dualwrite.ProvideZanzanaReconciler,
|
||||
navtreeimpl.ProvideService,
|
||||
wire.Bind(new(accesscontrol.AccessControl), new(*acimpl.AccessControl)),
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,57 @@
|
||||
package accesscontrol
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/dskit/services"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
)
|
||||
|
||||
const FixedRolesLoaderServiceName = "accesscontrol.fixedrolesloader"
|
||||
|
||||
type FixedRolesLoader struct {
|
||||
services.NamedService
|
||||
|
||||
roleRegistry RoleRegistry
|
||||
features featuremgmt.FeatureToggles
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
func ProvideFixedRolesLoader(roleRegistry RoleRegistry, features featuremgmt.FeatureToggles) *FixedRolesLoader {
|
||||
loader := &FixedRolesLoader{
|
||||
roleRegistry: roleRegistry,
|
||||
features: features,
|
||||
log: log.New(FixedRolesLoaderServiceName),
|
||||
}
|
||||
|
||||
loader.NamedService = services.NewBasicService(loader.starting, loader.running, nil).WithName(FixedRolesLoaderServiceName)
|
||||
return loader
|
||||
}
|
||||
|
||||
func (l *FixedRolesLoader) starting(ctx context.Context) error {
|
||||
ctxLogger := l.log.FromContext(ctx)
|
||||
|
||||
ctxLogger.Debug("Registering fixed roles")
|
||||
if err := l.roleRegistry.RegisterFixedRoles(ctx); err != nil {
|
||||
ctxLogger.Error("Failed to register fixed roles", "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *FixedRolesLoader) running(ctx context.Context) error {
|
||||
<-ctx.Done()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *FixedRolesLoader) IsDisabled() bool {
|
||||
return !l.features.IsEnabledGlobally(featuremgmt.FlagPluginStoreServiceLoading)
|
||||
}
|
||||
|
||||
func (l *FixedRolesLoader) Run(ctx context.Context) error {
|
||||
<-ctx.Done()
|
||||
return nil
|
||||
}
|
||||
@@ -2128,7 +2128,7 @@ var (
|
||||
},
|
||||
{
|
||||
Name: "pluginStoreServiceLoading",
|
||||
Description: "Load plugins during store service startup instead of wire provider",
|
||||
Description: "Load plugins on store service startup instead of wire provider, and call RegisterFixedRoles after all plugins are loaded",
|
||||
Stage: FeatureStageExperimental,
|
||||
FrontendOnly: false,
|
||||
Owner: grafanaPluginsPlatformSquad,
|
||||
|
||||
@@ -1103,7 +1103,7 @@ const (
|
||||
FlagPreventPanelChromeOverflow = "preventPanelChromeOverflow"
|
||||
|
||||
// FlagPluginStoreServiceLoading
|
||||
// Load plugins during store service startup instead of wire provider
|
||||
// Load plugins on store service startup instead of wire provider, and call RegisterFixedRoles after all plugins are loaded
|
||||
FlagPluginStoreServiceLoading = "pluginStoreServiceLoading"
|
||||
|
||||
// FlagOnlyStoreActionSets
|
||||
|
||||
@@ -2997,11 +2997,14 @@
|
||||
{
|
||||
"metadata": {
|
||||
"name": "pluginStoreServiceLoading",
|
||||
"resourceVersion": "1760712768362",
|
||||
"creationTimestamp": "2025-10-17T14:52:48Z"
|
||||
"resourceVersion": "1761144346944",
|
||||
"creationTimestamp": "2025-10-17T14:52:48Z",
|
||||
"annotations": {
|
||||
"grafana.app/updatedTimestamp": "2025-10-22 14:45:46.944669 +0000 UTC"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"description": "Load plugins during store service startup instead of wire provider",
|
||||
"description": "Load plugins on store service startup instead of wire provider, and call RegisterFixedRoles after all plugins are loaded",
|
||||
"stage": "experimental",
|
||||
"codeowner": "@grafana/plugins-platform-backend",
|
||||
"expression": "false"
|
||||
|
||||
Reference in New Issue
Block a user