ManagedServiceAccounts: Add a config option to disable the feature on-prem (#93571)

* ManagedServiceAccounts: Add a config option to disabled by default

* Update log in pkg/services/extsvcauth/registry/service.go

Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>
pull/93783/head^2
Gabriel MABILLE 9 months ago committed by GitHub
parent 2cfba519f1
commit 7928245eb6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 3
      conf/defaults.ini
  2. 3
      conf/sample.ini
  3. 4
      pkg/api/plugins.go
  4. 4
      pkg/services/accesscontrol/acimpl/service.go
  5. 2
      pkg/services/accesscontrol/acimpl/service_test.go
  6. 30
      pkg/services/extsvcauth/registry/service.go
  7. 3
      pkg/services/extsvcauth/registry/service_test.go
  8. 6
      pkg/services/pluginsintegration/serviceregistration/serviceregistration.go
  9. 3
      pkg/services/serviceaccounts/api/api.go
  10. 12
      pkg/services/serviceaccounts/extsvcaccounts/service.go
  11. 3
      pkg/services/serviceaccounts/extsvcaccounts/service_test.go
  12. 2
      pkg/services/serviceaccounts/proxy/service.go
  13. 5
      pkg/setting/setting.go

@ -615,6 +615,9 @@ id_response_header_prefix = X-Grafana
# The header value will encode the namespace ("user:<id>", "api-key:<id>", "service-account:<id>")
id_response_header_namespaces = user api-key service-account
# Enables the use of managed service accounts for plugin authentication
managed_service_accounts_enabled = false
#################################### SSO Settings ###########################
[sso_settings]
# interval for reloading the SSO Settings from the database

@ -619,6 +619,9 @@
# The header value will encode the namespace ("user:<id>", "api-key:<id>", "service-account:<id>")
;id_response_header_namespaces = user api-key service-account
# Enables the use of managed service accounts for plugin authentication
; managed_service_accounts_enabled = false
#################################### Anonymous Auth ######################
[auth.anonymous]
# enable anonymous access

@ -144,7 +144,7 @@ func (hs *HTTPServer) GetPluginList(c *contextmodel.ReqContext) response.Respons
AngularDetected: pluginDef.Angular.Detected,
}
if hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagExternalServiceAccounts) {
if hs.Cfg.ManagedServiceAccountsEnabled && hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagExternalServiceAccounts) {
listItem.IAM = pluginDef.IAM
}
@ -484,7 +484,7 @@ func (hs *HTTPServer) InstallPlugin(c *contextmodel.ReqContext) response.Respons
return response.ErrOrFallback(http.StatusInternalServerError, "Failed to install plugin", err)
}
if hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagExternalServiceAccounts) {
if hs.Cfg.ManagedServiceAccountsEnabled && hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagExternalServiceAccounts) {
// This is a non-blocking function that verifies that the installer has
// the permissions that the plugin requests to have on Grafana.
// If we want to make this blocking, the check will have to happen before or during the installation.

@ -735,7 +735,7 @@ func (s *Service) SaveExternalServiceRole(ctx context.Context, cmd accesscontrol
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.SaveExternalServiceRole")
defer span.End()
if !s.features.IsEnabled(ctx, featuremgmt.FlagExternalServiceAccounts) {
if !s.cfg.ManagedServiceAccountsEnabled || !s.features.IsEnabled(ctx, featuremgmt.FlagExternalServiceAccounts) {
s.log.Debug("Registering an external service role is behind a feature flag, enable it to use this feature.")
return nil
}
@ -751,7 +751,7 @@ func (s *Service) DeleteExternalServiceRole(ctx context.Context, externalService
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.DeleteExternalServiceRole")
defer span.End()
if !s.features.IsEnabled(ctx, featuremgmt.FlagExternalServiceAccounts) {
if !s.cfg.ManagedServiceAccountsEnabled || !s.features.IsEnabled(ctx, featuremgmt.FlagExternalServiceAccounts) {
s.log.Debug("Deleting an external service role is behind a feature flag, enable it to use this feature.")
return nil
}

@ -900,6 +900,7 @@ func TestService_SaveExternalServiceRole(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
ac := setupTestEnv(t)
ac.cfg.ManagedServiceAccountsEnabled = true
ac.features = featuremgmt.WithFeatures(featuremgmt.FlagExternalServiceAccounts)
for _, r := range tt.runs {
err := ac.SaveExternalServiceRole(ctx, r.cmd)
@ -946,6 +947,7 @@ func TestService_DeleteExternalServiceRole(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
ac := setupTestEnv(t)
ac.cfg.ManagedServiceAccountsEnabled = true
ac.features = featuremgmt.WithFeatures(featuremgmt.FlagExternalServiceAccounts)
if tt.initCmd != nil {

@ -13,6 +13,7 @@ import (
"github.com/grafana/grafana/pkg/services/extsvcauth"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/serviceaccounts/extsvcaccounts"
"github.com/grafana/grafana/pkg/setting"
)
var _ extsvcauth.ExternalServiceRegistry = &Registry{}
@ -28,9 +29,9 @@ type serverLocker interface {
}
type Registry struct {
features featuremgmt.FeatureToggles
logger log.Logger
saReg extsvcauth.ExternalServiceRegistry
enabled bool
logger log.Logger
saReg extsvcauth.ExternalServiceRegistry
// FIXME (gamab): we can remove this field and use the saReg.GetExternalServiceNames directly
extSvcProviders map[string]extsvcauth.AuthProvider
@ -38,10 +39,11 @@ type Registry struct {
serverLock serverLocker
}
func ProvideExtSvcRegistry(saSvc *extsvcaccounts.ExtSvcAccountsService, serverLock *serverlock.ServerLockService, features featuremgmt.FeatureToggles) *Registry {
func ProvideExtSvcRegistry(cfg *setting.Cfg, saSvc *extsvcaccounts.ExtSvcAccountsService, serverLock *serverlock.ServerLockService, features featuremgmt.FeatureToggles) *Registry {
enabled := features.IsEnabledGlobally(featuremgmt.FlagExternalServiceAccounts) && cfg.ManagedServiceAccountsEnabled
return &Registry{
extSvcProviders: map[string]extsvcauth.AuthProvider{},
features: features,
enabled: enabled,
lock: sync.Mutex{},
logger: log.New("extsvcauth.registry"),
saReg: saSvc,
@ -110,8 +112,12 @@ func (r *Registry) RemoveExternalService(ctx context.Context, name string) error
switch provider {
case extsvcauth.ServiceAccounts:
if !r.features.IsEnabled(ctx, featuremgmt.FlagExternalServiceAccounts) {
r.logger.Debug("Skipping External Service removal, flag disabled", "service", name, "flag", featuremgmt.FlagExternalServiceAccounts)
if !r.enabled {
r.logger.Warn("Skipping External Service authentication, flag or configuration option is disabled",
"service", name,
"flag", featuremgmt.FlagExternalServiceAccounts,
"option", "ManagedServiceAccountsEnabled",
)
return nil
}
r.logger.Debug("Routing External Service removal to the External Service Account service", "service", name)
@ -140,8 +146,12 @@ func (r *Registry) SaveExternalService(ctx context.Context, cmd *extsvcauth.Exte
switch cmd.AuthProvider {
case extsvcauth.ServiceAccounts:
if !r.features.IsEnabled(ctx, featuremgmt.FlagExternalServiceAccounts) {
ctxLogger.Warn("Skipping External Service authentication, flag disabled", "service", cmd.Name, "flag", featuremgmt.FlagExternalServiceAccounts)
if !r.enabled {
ctxLogger.Warn("Skipping External Service authentication, flag or configuration option disabled",
"service", cmd.Name,
"flag", featuremgmt.FlagExternalServiceAccounts,
"option", "ManagedServiceAccountsEnabled",
)
return
}
ctxLogger.Debug("Routing the External Service registration to the External Service Account service", "service", cmd.Name)
@ -160,7 +170,7 @@ func (r *Registry) SaveExternalService(ctx context.Context, cmd *extsvcauth.Exte
// retrieveExtSvcProviders fetches external services from store and map their associated provider
func (r *Registry) retrieveExtSvcProviders(ctx context.Context) (map[string]extsvcauth.AuthProvider, error) {
extsvcs := map[string]extsvcauth.AuthProvider{}
if r.features.IsEnabled(ctx, featuremgmt.FlagExternalServiceAccounts) {
if r.enabled {
names, err := r.saReg.GetExternalServiceNames(ctx)
if err != nil {
return nil, err

@ -8,7 +8,6 @@ import (
"github.com/grafana/grafana/pkg/infra/serverlock"
"github.com/grafana/grafana/pkg/services/extsvcauth"
"github.com/grafana/grafana/pkg/services/extsvcauth/tests"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
@ -30,7 +29,7 @@ func setupTestEnv(t *testing.T) *TestEnv {
env := TestEnv{}
env.saReg = tests.NewExternalServiceRegistryMock(t)
env.r = &Registry{
features: featuremgmt.WithFeatures(featuremgmt.FlagExternalServiceAccounts),
enabled: true,
logger: log.New("extsvcauth.registry.test"),
saReg: env.saReg,
extSvcProviders: map[string]extsvcauth.AuthProvider{},

@ -11,6 +11,7 @@ import (
"github.com/grafana/grafana/pkg/services/extsvcauth"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
"github.com/grafana/grafana/pkg/setting"
)
type Service struct {
@ -20,9 +21,10 @@ type Service struct {
settingsSvc pluginsettings.Service
}
func ProvideService(features featuremgmt.FeatureToggles, reg extsvcauth.ExternalServiceRegistry, settingsSvc pluginsettings.Service) *Service {
func ProvideService(cfg *setting.Cfg, features featuremgmt.FeatureToggles, reg extsvcauth.ExternalServiceRegistry, settingsSvc pluginsettings.Service) *Service {
enabled := features.IsEnabledGlobally(featuremgmt.FlagExternalServiceAccounts) && cfg.ManagedServiceAccountsEnabled
s := &Service{
featureEnabled: features.IsEnabledGlobally(featuremgmt.FlagExternalServiceAccounts),
featureEnabled: enabled,
log: log.New("plugins.external.registration"),
reg: reg,
settingsSvc: settingsSvc,

@ -40,6 +40,7 @@ func NewServiceAccountsAPI(
permissionService accesscontrol.ServiceAccountPermissionsService,
features featuremgmt.FeatureToggles,
) *ServiceAccountsAPI {
enabled := features.IsEnabledGlobally(featuremgmt.FlagExternalServiceAccounts) && cfg.ManagedServiceAccountsEnabled
return &ServiceAccountsAPI{
cfg: cfg,
service: service,
@ -48,7 +49,7 @@ func NewServiceAccountsAPI(
RouterRegister: routerRegister,
log: log.New("serviceaccounts.api"),
permissionService: permissionService,
isExternalSAEnabled: features.IsEnabledGlobally(featuremgmt.FlagExternalServiceAccounts),
isExternalSAEnabled: enabled,
}
}

@ -28,12 +28,12 @@ import (
type ExtSvcAccountsService struct {
acSvc ac.Service
defaultOrgID int64
features featuremgmt.FeatureToggles
logger log.Logger
metrics *metrics
saSvc sa.Service
skvStore kvstore.SecretsKVStore
tracer tracing.Tracer
enabled bool
}
func ProvideExtSvcAccountsService(acSvc ac.Service, cfg *setting.Cfg, bus bus.Bus, db db.DB, features featuremgmt.FeatureToggles, reg prometheus.Registerer, saSvc *manager.ServiceAccountsService, secretsSvc secrets.Service, tracer tracing.Tracer) *ExtSvcAccountsService {
@ -43,12 +43,12 @@ func ProvideExtSvcAccountsService(acSvc ac.Service, cfg *setting.Cfg, bus bus.Bu
defaultOrgID: cfg.DefaultOrgID(),
logger: logger,
saSvc: saSvc,
features: features,
skvStore: kvstore.NewSQLSecretsKVStore(db, secretsSvc, logger), // Using SQL store to avoid a cyclic dependency
tracer: tracer,
enabled: cfg.ManagedServiceAccountsEnabled && features.IsEnabledGlobally(featuremgmt.FlagExternalServiceAccounts),
}
if features.IsEnabledGlobally(featuremgmt.FlagExternalServiceAccounts) {
if esa.enabled {
// Register the metrics
esa.metrics = newMetrics(reg, esa.defaultOrgID, saSvc, logger)
@ -138,7 +138,7 @@ func (esa *ExtSvcAccountsService) GetExternalServiceNames(ctx context.Context) (
// SaveExternalService creates, updates or delete a service account (and its token) with the requested permissions.
func (esa *ExtSvcAccountsService) SaveExternalService(ctx context.Context, cmd *extsvcauth.ExternalServiceRegistration) (*extsvcauth.ExternalService, error) {
// This is double proofing, we should never reach here anyway the flags have already been checked.
if !esa.features.IsEnabled(ctx, featuremgmt.FlagExternalServiceAccounts) {
if !esa.enabled {
esa.logger.FromContext(ctx).Warn("This feature is behind a feature flag, please set it if you want to save external services")
return nil, nil
}
@ -184,7 +184,7 @@ func (esa *ExtSvcAccountsService) SaveExternalService(ctx context.Context, cmd *
func (esa *ExtSvcAccountsService) RemoveExternalService(ctx context.Context, name string) error {
// This is double proofing, we should never reach here anyway the flags have already been checked.
if !esa.features.IsEnabled(ctx, featuremgmt.FlagExternalServiceAccounts) {
if !esa.enabled {
esa.logger.Warn("This feature is behind a feature flag, please set it if you want to save external services")
return nil
}
@ -225,7 +225,7 @@ func (esa *ExtSvcAccountsService) RemoveExtSvcAccount(ctx context.Context, orgID
// ManageExtSvcAccount creates, updates or deletes the service account associated with an external service
func (esa *ExtSvcAccountsService) ManageExtSvcAccount(ctx context.Context, cmd *sa.ManageExtSvcAccountCmd) (int64, error) {
// This is double proofing, we should never reach here anyway the flags have already been checked.
if !esa.features.IsEnabled(ctx, featuremgmt.FlagExternalServiceAccounts) {
if !esa.enabled {
esa.logger.FromContext(ctx).Warn("This feature is behind a feature flag, please set it if you want to save external services")
return 0, nil
}

@ -41,6 +41,7 @@ func setupTestEnv(t *testing.T) *TestEnv {
t.Helper()
cfg := setting.NewCfg()
cfg.ManagedServiceAccountsEnabled = true
fmgt := featuremgmt.WithFeatures(featuremgmt.FlagExternalServiceAccounts)
env := &TestEnv{
@ -50,13 +51,13 @@ func setupTestEnv(t *testing.T) *TestEnv {
}
logger := log.New("extsvcaccounts.test")
env.S = &ExtSvcAccountsService{
enabled: true,
acSvc: acimpl.ProvideOSSService(
cfg, env.AcStore, &resourcepermissions.FakeActionSetSvc{},
localcache.New(0, 0), fmgt, tracing.InitializeTracerForTest(), nil, nil,
permreg.ProvidePermissionRegistry(),
),
defaultOrgID: autoAssignOrgID,
features: fmgt,
logger: logger,
metrics: newMetrics(nil, autoAssignOrgID, env.SaSvc, logger),
saSvc: env.SaSvc,

@ -38,7 +38,7 @@ func ProvideServiceAccountsProxy(
s := &ServiceAccountsProxy{
log: log.New("serviceaccounts.proxy"),
proxiedService: proxiedService,
isProxyEnabled: features.IsEnabledGlobally(featuremgmt.FlagExternalServiceAccounts),
isProxyEnabled: cfg.ManagedServiceAccountsEnabled && features.IsEnabledGlobally(featuremgmt.FlagExternalServiceAccounts),
}
serviceaccountsAPI := api.NewServiceAccountsAPI(cfg, s, ac, accesscontrolService, routeRegister, permissionService, features)

@ -245,6 +245,7 @@ type Cfg struct {
IDResponseHeaderEnabled bool
IDResponseHeaderPrefix string
IDResponseHeaderNamespaces map[string]struct{}
ManagedServiceAccountsEnabled bool
// AWS Plugin Auth
AWSAllowedAuthProviders []string
@ -1668,6 +1669,10 @@ func readAuthSettings(iniFile *ini.File, cfg *Cfg) (err error) {
for _, provider := range util.SplitString(providers) {
cfg.SSOSettingsConfigurableProviders[provider] = true
}
// Managed Service Accounts
cfg.ManagedServiceAccountsEnabled = auth.Key("managed_service_accounts_enabled").MustBool(false)
return nil
}

Loading…
Cancel
Save