mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Plugin: Enable service account based on plugin settings on init (#77193)
* Disable plugin service account
* Revert extsvc injection
* handle plugin state changes
* Use isProxyEnabled
* Remove plugininteg changes
* Change update function to also work for mysql 😩
* Plugin: enable service account based on plugin settings on
initialization
* Remove misleading comment
* Fix tests
* test message
* Clean up tests
* Simplify tests
* Re-order imports
* Remove unecessary comment
* Enable datasource plugins by default
Co-authored-by: Andres Martinez Gotor <andres.martinez@grafana.com>
---------
Co-authored-by: Andres Martinez Gotor <andres.martinez@grafana.com>
This commit is contained in:
parent
2727f41474
commit
25b30aeb6d
@ -13,5 +13,5 @@ type ExternalService struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ExternalServiceRegistry interface {
|
type ExternalServiceRegistry interface {
|
||||||
RegisterExternalService(ctx context.Context, name string, svc *plugindef.ExternalServiceRegistration) (*ExternalService, error)
|
RegisterExternalService(ctx context.Context, name string, pType plugindef.Type, svc *plugindef.ExternalServiceRegistration) (*ExternalService, error)
|
||||||
}
|
}
|
||||||
|
@ -437,7 +437,7 @@ type FakeAuthService struct {
|
|||||||
Result *auth.ExternalService
|
Result *auth.ExternalService
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FakeAuthService) RegisterExternalService(ctx context.Context, name string, svc *plugindef.ExternalServiceRegistration) (*auth.ExternalService, error) {
|
func (f *FakeAuthService) RegisterExternalService(ctx context.Context, name string, pType plugindef.Type, svc *plugindef.ExternalServiceRegistration) (*auth.ExternalService, error) {
|
||||||
return f.Result, nil
|
return f.Result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/plugins/manager/pipeline/initialization"
|
"github.com/grafana/grafana/pkg/plugins/manager/pipeline/initialization"
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/pipeline/validation"
|
"github.com/grafana/grafana/pkg/plugins/manager/pipeline/validation"
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/signature"
|
"github.com/grafana/grafana/pkg/plugins/manager/signature"
|
||||||
|
"github.com/grafana/grafana/pkg/plugins/plugindef"
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs"
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs"
|
||||||
)
|
)
|
||||||
@ -40,7 +41,7 @@ func newExternalServiceRegistration(cfg *config.Cfg, serviceRegistry auth.Extern
|
|||||||
func (r *ExternalServiceRegistration) Register(ctx context.Context, p *plugins.Plugin) (*plugins.Plugin, error) {
|
func (r *ExternalServiceRegistration) Register(ctx context.Context, p *plugins.Plugin) (*plugins.Plugin, error) {
|
||||||
if p.ExternalServiceRegistration != nil &&
|
if p.ExternalServiceRegistration != nil &&
|
||||||
(r.cfg.Features.IsEnabled(featuremgmt.FlagExternalServiceAuth) || r.cfg.Features.IsEnabled(featuremgmt.FlagExternalServiceAccounts)) {
|
(r.cfg.Features.IsEnabled(featuremgmt.FlagExternalServiceAuth) || r.cfg.Features.IsEnabled(featuremgmt.FlagExternalServiceAccounts)) {
|
||||||
s, err := r.externalServiceRegistry.RegisterExternalService(ctx, p.ID, p.ExternalServiceRegistration)
|
s, err := r.externalServiceRegistry.RegisterExternalService(ctx, p.ID, plugindef.Type(p.Type), p.ExternalServiceRegistration)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.log.Error("Could not register an external service. Initialization skipped", "pluginId", p.ID, "error", err)
|
r.log.Error("Could not register an external service. Initialization skipped", "pluginId", p.ID, "error", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -2,26 +2,42 @@ package serviceregistration
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins/auth"
|
"github.com/grafana/grafana/pkg/plugins/auth"
|
||||||
"github.com/grafana/grafana/pkg/plugins/plugindef"
|
"github.com/grafana/grafana/pkg/plugins/plugindef"
|
||||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||||
"github.com/grafana/grafana/pkg/services/extsvcauth"
|
"github.com/grafana/grafana/pkg/services/extsvcauth"
|
||||||
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
os extsvcauth.ExternalServiceRegistry
|
reg extsvcauth.ExternalServiceRegistry
|
||||||
|
settingsSvc pluginsettings.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProvideService(os extsvcauth.ExternalServiceRegistry) *Service {
|
func ProvideService(reg extsvcauth.ExternalServiceRegistry, settingsSvc pluginsettings.Service) *Service {
|
||||||
s := &Service{
|
s := &Service{
|
||||||
os: os,
|
reg: reg,
|
||||||
|
settingsSvc: settingsSvc,
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterExternalService is a simplified wrapper around SaveExternalService for the plugin use case.
|
// RegisterExternalService is a simplified wrapper around SaveExternalService for the plugin use case.
|
||||||
func (s *Service) RegisterExternalService(ctx context.Context, svcName string, svc *plugindef.ExternalServiceRegistration) (*auth.ExternalService, error) {
|
func (s *Service) RegisterExternalService(ctx context.Context, svcName string, pType plugindef.Type, svc *plugindef.ExternalServiceRegistration) (*auth.ExternalService, error) {
|
||||||
|
// Datasource plugins can only be enabled
|
||||||
|
enabled := true
|
||||||
|
// App plugins can be disabled
|
||||||
|
if pType == plugindef.TypeApp {
|
||||||
|
settings, err := s.settingsSvc.GetPluginSettingByPluginID(ctx, &pluginsettings.GetByPluginIDArgs{PluginID: svcName})
|
||||||
|
if err != nil && !errors.Is(err, pluginsettings.ErrPluginSettingNotFound) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
enabled = (settings != nil) && settings.Enabled
|
||||||
|
}
|
||||||
|
|
||||||
impersonation := extsvcauth.ImpersonationCfg{}
|
impersonation := extsvcauth.ImpersonationCfg{}
|
||||||
if svc.Impersonation != nil {
|
if svc.Impersonation != nil {
|
||||||
impersonation.Permissions = toAccessControlPermissions(svc.Impersonation.Permissions)
|
impersonation.Permissions = toAccessControlPermissions(svc.Impersonation.Permissions)
|
||||||
@ -38,9 +54,9 @@ func (s *Service) RegisterExternalService(ctx context.Context, svcName string, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
self := extsvcauth.SelfCfg{}
|
self := extsvcauth.SelfCfg{}
|
||||||
|
self.Enabled = enabled
|
||||||
if len(svc.Permissions) > 0 {
|
if len(svc.Permissions) > 0 {
|
||||||
self.Permissions = toAccessControlPermissions(svc.Permissions)
|
self.Permissions = toAccessControlPermissions(svc.Permissions)
|
||||||
self.Enabled = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
registration := &extsvcauth.ExternalServiceRegistration{
|
registration := &extsvcauth.ExternalServiceRegistration{
|
||||||
@ -56,7 +72,7 @@ func (s *Service) RegisterExternalService(ctx context.Context, svcName string, s
|
|||||||
registration.OAuthProviderCfg = &extsvcauth.OAuthProviderCfg{Key: &extsvcauth.KeyOption{Generate: true}}
|
registration.OAuthProviderCfg = &extsvcauth.OAuthProviderCfg{Key: &extsvcauth.KeyOption{Generate: true}}
|
||||||
}
|
}
|
||||||
|
|
||||||
extSvc, err := s.os.SaveExternalService(ctx, registration)
|
extSvc, err := s.reg.SaveExternalService(ctx, registration)
|
||||||
if err != nil || extSvc == nil {
|
if err != nil || extSvc == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ type SaveCredentialsCmd struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type saveCmd struct {
|
type saveCmd struct {
|
||||||
|
Enabled bool
|
||||||
ExtSvcSlug string
|
ExtSvcSlug string
|
||||||
OrgID int64
|
OrgID int64
|
||||||
Permissions []ac.Permission
|
Permissions []ac.Permission
|
||||||
|
@ -144,7 +144,7 @@ func (esa *ExtSvcAccountsService) ManageExtSvcAccount(ctx context.Context, cmd *
|
|||||||
return 0, errRetrieve
|
return 0, errRetrieve
|
||||||
}
|
}
|
||||||
|
|
||||||
if !cmd.Enabled || len(cmd.Permissions) == 0 {
|
if len(cmd.Permissions) == 0 {
|
||||||
if saID > 0 {
|
if saID > 0 {
|
||||||
if err := esa.deleteExtSvcAccount(ctx, cmd.OrgID, cmd.ExtSvcSlug, saID); err != nil {
|
if err := esa.deleteExtSvcAccount(ctx, cmd.OrgID, cmd.ExtSvcSlug, saID); err != nil {
|
||||||
esa.logger.Error("Error occurred while deleting service account",
|
esa.logger.Error("Error occurred while deleting service account",
|
||||||
@ -155,15 +155,15 @@ func (esa *ExtSvcAccountsService) ManageExtSvcAccount(ctx context.Context, cmd *
|
|||||||
}
|
}
|
||||||
esa.metrics.deletedCount.Inc()
|
esa.metrics.deletedCount.Inc()
|
||||||
}
|
}
|
||||||
esa.logger.Info("Skipping service account creation",
|
esa.logger.Info("Skipping service account creation, no permission",
|
||||||
"service", cmd.ExtSvcSlug,
|
"service", cmd.ExtSvcSlug,
|
||||||
"enabled", cmd.Enabled,
|
|
||||||
"permission count", len(cmd.Permissions),
|
"permission count", len(cmd.Permissions),
|
||||||
"saID", saID)
|
"saID", saID)
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
saID, errSave := esa.saveExtSvcAccount(ctx, &saveCmd{
|
saID, errSave := esa.saveExtSvcAccount(ctx, &saveCmd{
|
||||||
|
Enabled: cmd.Enabled,
|
||||||
ExtSvcSlug: cmd.ExtSvcSlug,
|
ExtSvcSlug: cmd.ExtSvcSlug,
|
||||||
OrgID: cmd.OrgID,
|
OrgID: cmd.OrgID,
|
||||||
Permissions: cmd.Permissions,
|
Permissions: cmd.Permissions,
|
||||||
@ -194,6 +194,12 @@ func (esa *ExtSvcAccountsService) saveExtSvcAccount(ctx context.Context, cmd *sa
|
|||||||
cmd.SaID = sa.Id
|
cmd.SaID = sa.Id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable or disable the service account
|
||||||
|
esa.logger.Debug("Set service account state", "service", cmd.ExtSvcSlug, "saID", cmd.SaID, "enabled", cmd.Enabled)
|
||||||
|
if err := esa.saSvc.EnableServiceAccount(ctx, cmd.OrgID, cmd.SaID, cmd.Enabled); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
// update the service account's permissions
|
// update the service account's permissions
|
||||||
esa.logger.Debug("Update role permissions", "service", cmd.ExtSvcSlug, "saID", cmd.SaID)
|
esa.logger.Debug("Update role permissions", "service", cmd.ExtSvcSlug, "saID", cmd.SaID)
|
||||||
if err := esa.acSvc.SaveExternalServiceRole(ctx, ac.SaveExternalServiceRoleCommand{
|
if err := esa.acSvc.SaveExternalServiceRole(ctx, ac.SaveExternalServiceRoleCommand{
|
||||||
|
@ -70,17 +70,23 @@ func TestExtSvcAccountsService_ManageExtSvcAccount(t *testing.T) {
|
|||||||
name string
|
name string
|
||||||
init func(env *TestEnv)
|
init func(env *TestEnv)
|
||||||
cmd sa.ManageExtSvcAccountCmd
|
cmd sa.ManageExtSvcAccountCmd
|
||||||
checks func(t *testing.T, env *TestEnv)
|
|
||||||
want int64
|
want int64
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "should remove service account when disabled",
|
name: "should disable service account",
|
||||||
init: func(env *TestEnv) {
|
init: func(env *TestEnv) {
|
||||||
// A previous service account was attached to this slug
|
// A previous service account was attached to this slug
|
||||||
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, mock.Anything, mock.Anything).Return(extSvcAccID, nil)
|
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, extSvcOrgID, sa.ExtSvcPrefix+extSvcSlug).Return(extSvcAccID, nil)
|
||||||
env.SaSvc.On("DeleteServiceAccount", mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
env.SaSvc.On("EnableServiceAccount", mock.Anything, extSvcOrgID, extSvcAccID, false).Return(nil)
|
||||||
env.AcStore.On("DeleteExternalServiceRole", mock.Anything, mock.Anything).Return(nil)
|
env.AcStore.On("SaveExternalServiceRole",
|
||||||
|
mock.Anything,
|
||||||
|
mock.MatchedBy(func(cmd ac.SaveExternalServiceRoleCommand) bool {
|
||||||
|
return cmd.ServiceAccountID == extSvcAccID && cmd.ExternalServiceID == extSvcSlug &&
|
||||||
|
cmd.OrgID == int64(ac.GlobalOrgID) && len(cmd.Permissions) == 1 &&
|
||||||
|
cmd.Permissions[0] == extSvcPerms[0]
|
||||||
|
})).
|
||||||
|
Return(nil)
|
||||||
},
|
},
|
||||||
cmd: sa.ManageExtSvcAccountCmd{
|
cmd: sa.ManageExtSvcAccountCmd{
|
||||||
ExtSvcSlug: extSvcSlug,
|
ExtSvcSlug: extSvcSlug,
|
||||||
@ -88,26 +94,16 @@ func TestExtSvcAccountsService_ManageExtSvcAccount(t *testing.T) {
|
|||||||
OrgID: extSvcOrgID,
|
OrgID: extSvcOrgID,
|
||||||
Permissions: extSvcPerms,
|
Permissions: extSvcPerms,
|
||||||
},
|
},
|
||||||
checks: func(t *testing.T, env *TestEnv) {
|
want: extSvcAccID,
|
||||||
env.SaSvc.AssertCalled(t, "RetrieveServiceAccountIdByName", mock.Anything,
|
|
||||||
mock.MatchedBy(func(orgID int64) bool { return orgID == extSvcOrgID }),
|
|
||||||
mock.MatchedBy(func(slug string) bool { return slug == sa.ExtSvcPrefix+extSvcSlug }))
|
|
||||||
env.SaSvc.AssertCalled(t, "DeleteServiceAccount", mock.Anything,
|
|
||||||
mock.MatchedBy(func(orgID int64) bool { return orgID == extSvcOrgID }),
|
|
||||||
mock.MatchedBy(func(saID int64) bool { return saID == extSvcAccID }))
|
|
||||||
env.AcStore.AssertCalled(t, "DeleteExternalServiceRole", mock.Anything,
|
|
||||||
mock.MatchedBy(func(slug string) bool { return slug == extSvcSlug }))
|
|
||||||
},
|
|
||||||
want: 0,
|
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "should remove service account when no permission",
|
name: "should remove service account when no permission",
|
||||||
init: func(env *TestEnv) {
|
init: func(env *TestEnv) {
|
||||||
// A previous service account was attached to this slug
|
// A previous service account was attached to this slug
|
||||||
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, mock.Anything, mock.Anything).Return(extSvcAccID, nil)
|
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, extSvcOrgID, sa.ExtSvcPrefix+extSvcSlug).Return(extSvcAccID, nil)
|
||||||
env.SaSvc.On("DeleteServiceAccount", mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
env.SaSvc.On("DeleteServiceAccount", mock.Anything, extSvcOrgID, extSvcAccID).Return(nil)
|
||||||
env.AcStore.On("DeleteExternalServiceRole", mock.Anything, mock.Anything).Return(nil)
|
env.AcStore.On("DeleteExternalServiceRole", mock.Anything, extSvcSlug).Return(nil)
|
||||||
},
|
},
|
||||||
cmd: sa.ManageExtSvcAccountCmd{
|
cmd: sa.ManageExtSvcAccountCmd{
|
||||||
ExtSvcSlug: extSvcSlug,
|
ExtSvcSlug: extSvcSlug,
|
||||||
@ -115,16 +111,6 @@ func TestExtSvcAccountsService_ManageExtSvcAccount(t *testing.T) {
|
|||||||
OrgID: extSvcOrgID,
|
OrgID: extSvcOrgID,
|
||||||
Permissions: []ac.Permission{},
|
Permissions: []ac.Permission{},
|
||||||
},
|
},
|
||||||
checks: func(t *testing.T, env *TestEnv) {
|
|
||||||
env.SaSvc.AssertCalled(t, "RetrieveServiceAccountIdByName", mock.Anything,
|
|
||||||
mock.MatchedBy(func(orgID int64) bool { return orgID == extSvcOrgID }),
|
|
||||||
mock.MatchedBy(func(slug string) bool { return slug == sa.ExtSvcPrefix+extSvcSlug }))
|
|
||||||
env.SaSvc.AssertCalled(t, "DeleteServiceAccount", mock.Anything,
|
|
||||||
mock.MatchedBy(func(orgID int64) bool { return orgID == extSvcOrgID }),
|
|
||||||
mock.MatchedBy(func(saID int64) bool { return saID == extSvcAccID }))
|
|
||||||
env.AcStore.AssertCalled(t, "DeleteExternalServiceRole", mock.Anything,
|
|
||||||
mock.MatchedBy(func(slug string) bool { return slug == extSvcSlug }))
|
|
||||||
},
|
|
||||||
want: 0,
|
want: 0,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
@ -132,11 +118,24 @@ func TestExtSvcAccountsService_ManageExtSvcAccount(t *testing.T) {
|
|||||||
name: "should create new service account",
|
name: "should create new service account",
|
||||||
init: func(env *TestEnv) {
|
init: func(env *TestEnv) {
|
||||||
// No previous service account was attached to this slug
|
// No previous service account was attached to this slug
|
||||||
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, mock.Anything, mock.Anything).
|
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, extSvcOrgID, sa.ExtSvcPrefix+extSvcSlug).
|
||||||
Return(int64(0), sa.ErrServiceAccountNotFound.Errorf("mock"))
|
Return(int64(0), sa.ErrServiceAccountNotFound.Errorf("mock"))
|
||||||
env.SaSvc.On("CreateServiceAccount", mock.Anything, mock.Anything, mock.Anything).
|
env.SaSvc.On("CreateServiceAccount",
|
||||||
|
mock.Anything,
|
||||||
|
extSvcOrgID,
|
||||||
|
mock.MatchedBy(func(cmd *sa.CreateServiceAccountForm) bool {
|
||||||
|
return cmd.Name == sa.ExtSvcPrefix+extSvcSlug && *cmd.Role == roletype.RoleNone
|
||||||
|
})).
|
||||||
Return(extSvcAccount, nil)
|
Return(extSvcAccount, nil)
|
||||||
env.AcStore.On("SaveExternalServiceRole", mock.Anything, mock.Anything).Return(nil)
|
env.SaSvc.On("EnableServiceAccount", mock.Anything, extSvcOrgID, extSvcAccount.Id, true).Return(nil)
|
||||||
|
env.AcStore.On("SaveExternalServiceRole",
|
||||||
|
mock.Anything,
|
||||||
|
mock.MatchedBy(func(cmd ac.SaveExternalServiceRoleCommand) bool {
|
||||||
|
return cmd.ServiceAccountID == extSvcAccount.Id && cmd.ExternalServiceID == extSvcSlug &&
|
||||||
|
cmd.OrgID == int64(ac.GlobalOrgID) && len(cmd.Permissions) == 1 &&
|
||||||
|
cmd.Permissions[0] == extSvcPerms[0]
|
||||||
|
})).
|
||||||
|
Return(nil)
|
||||||
},
|
},
|
||||||
cmd: sa.ManageExtSvcAccountCmd{
|
cmd: sa.ManageExtSvcAccountCmd{
|
||||||
ExtSvcSlug: extSvcSlug,
|
ExtSvcSlug: extSvcSlug,
|
||||||
@ -144,23 +143,6 @@ func TestExtSvcAccountsService_ManageExtSvcAccount(t *testing.T) {
|
|||||||
OrgID: extSvcOrgID,
|
OrgID: extSvcOrgID,
|
||||||
Permissions: extSvcPerms,
|
Permissions: extSvcPerms,
|
||||||
},
|
},
|
||||||
checks: func(t *testing.T, env *TestEnv) {
|
|
||||||
env.SaSvc.AssertCalled(t, "RetrieveServiceAccountIdByName", mock.Anything,
|
|
||||||
mock.MatchedBy(func(orgID int64) bool { return orgID == extSvcOrgID }),
|
|
||||||
mock.MatchedBy(func(slug string) bool { return slug == sa.ExtSvcPrefix+extSvcSlug }))
|
|
||||||
env.SaSvc.AssertCalled(t, "CreateServiceAccount", mock.Anything,
|
|
||||||
mock.MatchedBy(func(orgID int64) bool { return orgID == extSvcOrgID }),
|
|
||||||
mock.MatchedBy(func(cmd *sa.CreateServiceAccountForm) bool {
|
|
||||||
return cmd.Name == sa.ExtSvcPrefix+extSvcSlug && *cmd.Role == roletype.RoleNone
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
env.AcStore.AssertCalled(t, "SaveExternalServiceRole", mock.Anything,
|
|
||||||
mock.MatchedBy(func(cmd ac.SaveExternalServiceRoleCommand) bool {
|
|
||||||
return cmd.ServiceAccountID == extSvcAccount.Id && cmd.ExternalServiceID == extSvcSlug &&
|
|
||||||
cmd.OrgID == int64(ac.GlobalOrgID) && len(cmd.Permissions) == 1 &&
|
|
||||||
cmd.Permissions[0] == extSvcPerms[0]
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
want: extSvcAccID,
|
want: extSvcAccID,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
@ -168,9 +150,17 @@ func TestExtSvcAccountsService_ManageExtSvcAccount(t *testing.T) {
|
|||||||
name: "should update service account",
|
name: "should update service account",
|
||||||
init: func(env *TestEnv) {
|
init: func(env *TestEnv) {
|
||||||
// A previous service account was attached to this slug
|
// A previous service account was attached to this slug
|
||||||
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, mock.Anything, mock.Anything).
|
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, extSvcOrgID, sa.ExtSvcPrefix+extSvcSlug).
|
||||||
Return(int64(11), nil)
|
Return(int64(11), nil)
|
||||||
env.AcStore.On("SaveExternalServiceRole", mock.Anything, mock.Anything).Return(nil)
|
env.SaSvc.On("EnableServiceAccount", mock.Anything, extSvcOrgID, int64(11), true).Return(nil)
|
||||||
|
env.AcStore.On("SaveExternalServiceRole",
|
||||||
|
mock.Anything,
|
||||||
|
mock.MatchedBy(func(cmd ac.SaveExternalServiceRoleCommand) bool {
|
||||||
|
return cmd.ServiceAccountID == int64(11) && cmd.ExternalServiceID == extSvcSlug &&
|
||||||
|
cmd.OrgID == int64(ac.GlobalOrgID) && len(cmd.Permissions) == 1 &&
|
||||||
|
cmd.Permissions[0] == extSvcPerms[0]
|
||||||
|
})).
|
||||||
|
Return(nil)
|
||||||
},
|
},
|
||||||
cmd: sa.ManageExtSvcAccountCmd{
|
cmd: sa.ManageExtSvcAccountCmd{
|
||||||
ExtSvcSlug: extSvcSlug,
|
ExtSvcSlug: extSvcSlug,
|
||||||
@ -178,17 +168,6 @@ func TestExtSvcAccountsService_ManageExtSvcAccount(t *testing.T) {
|
|||||||
OrgID: extSvcOrgID,
|
OrgID: extSvcOrgID,
|
||||||
Permissions: extSvcPerms,
|
Permissions: extSvcPerms,
|
||||||
},
|
},
|
||||||
checks: func(t *testing.T, env *TestEnv) {
|
|
||||||
env.SaSvc.AssertCalled(t, "RetrieveServiceAccountIdByName", mock.Anything,
|
|
||||||
mock.MatchedBy(func(orgID int64) bool { return orgID == extSvcOrgID }),
|
|
||||||
mock.MatchedBy(func(slug string) bool { return slug == sa.ExtSvcPrefix+extSvcSlug }))
|
|
||||||
env.AcStore.AssertCalled(t, "SaveExternalServiceRole", mock.Anything,
|
|
||||||
mock.MatchedBy(func(cmd ac.SaveExternalServiceRoleCommand) bool {
|
|
||||||
return cmd.ServiceAccountID == int64(11) && cmd.ExternalServiceID == extSvcSlug &&
|
|
||||||
cmd.OrgID == int64(ac.GlobalOrgID) && len(cmd.Permissions) == 1 &&
|
|
||||||
cmd.Permissions[0] == extSvcPerms[0]
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
want: 11,
|
want: 11,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
@ -210,10 +189,6 @@ func TestExtSvcAccountsService_ManageExtSvcAccount(t *testing.T) {
|
|||||||
}
|
}
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
if tt.checks != nil {
|
|
||||||
tt.checks(t, env)
|
|
||||||
}
|
|
||||||
|
|
||||||
require.Equal(t, tt.want, got)
|
require.Equal(t, tt.want, got)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -242,12 +217,20 @@ func TestExtSvcAccountsService_SaveExternalService(t *testing.T) {
|
|||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "should remove service account when disabled",
|
name: "should disable service account",
|
||||||
init: func(env *TestEnv) {
|
init: func(env *TestEnv) {
|
||||||
// A previous service account was attached to this slug
|
// A previous service account was attached to this slug
|
||||||
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, mock.Anything, mock.Anything).Return(extSvcAccID, nil)
|
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, tmpOrgID, sa.ExtSvcPrefix+extSvcSlug).
|
||||||
env.SaSvc.On("DeleteServiceAccount", mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
Return(extSvcAccID, nil)
|
||||||
env.AcStore.On("DeleteExternalServiceRole", mock.Anything, mock.Anything).Return(nil)
|
env.SaSvc.On("EnableServiceAccount", mock.Anything, tmpOrgID, extSvcAccID, false).Return(nil)
|
||||||
|
env.AcStore.On("SaveExternalServiceRole",
|
||||||
|
mock.Anything,
|
||||||
|
mock.MatchedBy(func(cmd ac.SaveExternalServiceRoleCommand) bool {
|
||||||
|
return cmd.ServiceAccountID == extSvcAccID && cmd.ExternalServiceID == extSvcSlug &&
|
||||||
|
cmd.OrgID == int64(ac.GlobalOrgID) && len(cmd.Permissions) == 1 &&
|
||||||
|
cmd.Permissions[0] == extSvcPerms[0]
|
||||||
|
})).
|
||||||
|
Return(nil)
|
||||||
// A token was previously stored in the secret store
|
// A token was previously stored in the secret store
|
||||||
_ = env.SkvStore.Set(context.Background(), tmpOrgID, extSvcSlug, kvStoreType, "ExtSvcSecretToken")
|
_ = env.SkvStore.Set(context.Background(), tmpOrgID, extSvcSlug, kvStoreType, "ExtSvcSecretToken")
|
||||||
},
|
},
|
||||||
@ -259,27 +242,26 @@ func TestExtSvcAccountsService_SaveExternalService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
checks: func(t *testing.T, env *TestEnv) {
|
checks: func(t *testing.T, env *TestEnv) {
|
||||||
env.SaSvc.AssertCalled(t, "RetrieveServiceAccountIdByName", mock.Anything,
|
|
||||||
mock.MatchedBy(func(orgID int64) bool { return orgID == tmpOrgID }),
|
|
||||||
mock.MatchedBy(func(slug string) bool { return slug == sa.ExtSvcPrefix+extSvcSlug }))
|
|
||||||
env.SaSvc.AssertCalled(t, "DeleteServiceAccount", mock.Anything,
|
|
||||||
mock.MatchedBy(func(orgID int64) bool { return orgID == tmpOrgID }),
|
|
||||||
mock.MatchedBy(func(saID int64) bool { return saID == extSvcAccID }))
|
|
||||||
env.AcStore.AssertCalled(t, "DeleteExternalServiceRole", mock.Anything,
|
|
||||||
mock.MatchedBy(func(slug string) bool { return slug == extSvcSlug }))
|
|
||||||
_, ok, _ := env.SkvStore.Get(context.Background(), tmpOrgID, extSvcSlug, kvStoreType)
|
_, ok, _ := env.SkvStore.Get(context.Background(), tmpOrgID, extSvcSlug, kvStoreType)
|
||||||
require.False(t, ok, "secret should have been removed from store")
|
require.True(t, ok, "secret should have been kept in store")
|
||||||
|
},
|
||||||
|
want: &extsvcauth.ExternalService{
|
||||||
|
Name: extSvcSlug,
|
||||||
|
ID: extSvcSlug,
|
||||||
|
Secret: "not empty",
|
||||||
},
|
},
|
||||||
want: nil,
|
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "should remove service account when no permission",
|
name: "should remove service account when no permission",
|
||||||
init: func(env *TestEnv) {
|
init: func(env *TestEnv) {
|
||||||
// A previous service account was attached to this slug
|
// A previous service account was attached to this slug
|
||||||
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, mock.Anything, mock.Anything).Return(extSvcAccID, nil)
|
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, tmpOrgID, sa.ExtSvcPrefix+extSvcSlug).
|
||||||
env.SaSvc.On("DeleteServiceAccount", mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
Return(extSvcAccID, nil)
|
||||||
env.AcStore.On("DeleteExternalServiceRole", mock.Anything, mock.Anything).Return(nil)
|
env.SaSvc.On("DeleteServiceAccount", mock.Anything, tmpOrgID, extSvcAccID).Return(nil)
|
||||||
|
env.AcStore.On("DeleteExternalServiceRole", mock.Anything, extSvcSlug).Return(nil)
|
||||||
|
// A token was previously stored in the secret store
|
||||||
|
_ = env.SkvStore.Set(context.Background(), tmpOrgID, extSvcSlug, kvStoreType, "ExtSvcSecretToken")
|
||||||
},
|
},
|
||||||
cmd: extsvcauth.ExternalServiceRegistration{
|
cmd: extsvcauth.ExternalServiceRegistration{
|
||||||
Name: extSvcSlug,
|
Name: extSvcSlug,
|
||||||
@ -289,14 +271,8 @@ func TestExtSvcAccountsService_SaveExternalService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
checks: func(t *testing.T, env *TestEnv) {
|
checks: func(t *testing.T, env *TestEnv) {
|
||||||
env.SaSvc.AssertCalled(t, "RetrieveServiceAccountIdByName", mock.Anything,
|
_, ok, _ := env.SkvStore.Get(context.Background(), tmpOrgID, extSvcSlug, kvStoreType)
|
||||||
mock.MatchedBy(func(orgID int64) bool { return orgID == tmpOrgID }),
|
require.False(t, ok, "secret should have been removed from store")
|
||||||
mock.MatchedBy(func(slug string) bool { return slug == sa.ExtSvcPrefix+extSvcSlug }))
|
|
||||||
env.SaSvc.AssertCalled(t, "DeleteServiceAccount", mock.Anything,
|
|
||||||
mock.MatchedBy(func(orgID int64) bool { return orgID == tmpOrgID }),
|
|
||||||
mock.MatchedBy(func(saID int64) bool { return saID == extSvcAccID }))
|
|
||||||
env.AcStore.AssertCalled(t, "DeleteExternalServiceRole", mock.Anything,
|
|
||||||
mock.MatchedBy(func(slug string) bool { return slug == extSvcSlug }))
|
|
||||||
},
|
},
|
||||||
want: nil,
|
want: nil,
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
@ -305,13 +281,26 @@ func TestExtSvcAccountsService_SaveExternalService(t *testing.T) {
|
|||||||
name: "should create new service account",
|
name: "should create new service account",
|
||||||
init: func(env *TestEnv) {
|
init: func(env *TestEnv) {
|
||||||
// No previous service account was attached to this slug
|
// No previous service account was attached to this slug
|
||||||
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, mock.Anything, mock.Anything).
|
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, tmpOrgID, sa.ExtSvcPrefix+extSvcSlug).
|
||||||
Return(int64(0), sa.ErrServiceAccountNotFound.Errorf("mock"))
|
Return(int64(0), sa.ErrServiceAccountNotFound.Errorf("mock"))
|
||||||
env.SaSvc.On("CreateServiceAccount", mock.Anything, mock.Anything, mock.Anything).
|
env.SaSvc.On("CreateServiceAccount",
|
||||||
|
mock.Anything,
|
||||||
|
tmpOrgID,
|
||||||
|
mock.MatchedBy(func(cmd *sa.CreateServiceAccountForm) bool {
|
||||||
|
return cmd.Name == sa.ExtSvcPrefix+extSvcSlug && *cmd.Role == roletype.RoleNone
|
||||||
|
})).
|
||||||
Return(extSvcAccount, nil)
|
Return(extSvcAccount, nil)
|
||||||
|
env.SaSvc.On("EnableServiceAccount", mock.Anything, extsvcauth.TmpOrgID, extSvcAccID, true).Return(nil)
|
||||||
// Api Key was added without problem
|
// Api Key was added without problem
|
||||||
env.SaSvc.On("AddServiceAccountToken", mock.Anything, mock.Anything, mock.Anything).Return(&apikey.APIKey{}, nil)
|
env.SaSvc.On("AddServiceAccountToken", mock.Anything, mock.Anything, mock.Anything).Return(&apikey.APIKey{}, nil)
|
||||||
env.AcStore.On("SaveExternalServiceRole", mock.Anything, mock.Anything).Return(nil)
|
env.AcStore.On("SaveExternalServiceRole",
|
||||||
|
mock.Anything,
|
||||||
|
mock.MatchedBy(func(cmd ac.SaveExternalServiceRoleCommand) bool {
|
||||||
|
return cmd.ServiceAccountID == extSvcAccount.Id && cmd.ExternalServiceID == extSvcSlug &&
|
||||||
|
cmd.OrgID == int64(ac.GlobalOrgID) && len(cmd.Permissions) == 1 &&
|
||||||
|
cmd.Permissions[0] == extSvcPerms[0]
|
||||||
|
})).
|
||||||
|
Return(nil)
|
||||||
},
|
},
|
||||||
cmd: extsvcauth.ExternalServiceRegistration{
|
cmd: extsvcauth.ExternalServiceRegistration{
|
||||||
Name: extSvcSlug,
|
Name: extSvcSlug,
|
||||||
@ -320,23 +309,6 @@ func TestExtSvcAccountsService_SaveExternalService(t *testing.T) {
|
|||||||
Permissions: extSvcPerms,
|
Permissions: extSvcPerms,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
checks: func(t *testing.T, env *TestEnv) {
|
|
||||||
env.SaSvc.AssertCalled(t, "RetrieveServiceAccountIdByName", mock.Anything,
|
|
||||||
mock.MatchedBy(func(orgID int64) bool { return orgID == tmpOrgID }),
|
|
||||||
mock.MatchedBy(func(slug string) bool { return slug == sa.ExtSvcPrefix+extSvcSlug }))
|
|
||||||
env.SaSvc.AssertCalled(t, "CreateServiceAccount", mock.Anything,
|
|
||||||
mock.MatchedBy(func(orgID int64) bool { return orgID == tmpOrgID }),
|
|
||||||
mock.MatchedBy(func(cmd *sa.CreateServiceAccountForm) bool {
|
|
||||||
return cmd.Name == sa.ExtSvcPrefix+extSvcSlug && *cmd.Role == roletype.RoleNone
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
env.AcStore.AssertCalled(t, "SaveExternalServiceRole", mock.Anything,
|
|
||||||
mock.MatchedBy(func(cmd ac.SaveExternalServiceRoleCommand) bool {
|
|
||||||
return cmd.ServiceAccountID == extSvcAccount.Id && cmd.ExternalServiceID == extSvcSlug &&
|
|
||||||
cmd.OrgID == int64(ac.GlobalOrgID) && len(cmd.Permissions) == 1 &&
|
|
||||||
cmd.Permissions[0] == extSvcPerms[0]
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
want: &extsvcauth.ExternalService{
|
want: &extsvcauth.ExternalService{
|
||||||
Name: extSvcSlug,
|
Name: extSvcSlug,
|
||||||
ID: extSvcSlug,
|
ID: extSvcSlug,
|
||||||
@ -348,9 +320,17 @@ func TestExtSvcAccountsService_SaveExternalService(t *testing.T) {
|
|||||||
name: "should update service account",
|
name: "should update service account",
|
||||||
init: func(env *TestEnv) {
|
init: func(env *TestEnv) {
|
||||||
// A previous service account was attached to this slug
|
// A previous service account was attached to this slug
|
||||||
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, mock.Anything, mock.Anything).
|
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, tmpOrgID, sa.ExtSvcPrefix+extSvcSlug).
|
||||||
Return(int64(11), nil)
|
Return(int64(11), nil)
|
||||||
env.AcStore.On("SaveExternalServiceRole", mock.Anything, mock.Anything).Return(nil)
|
env.AcStore.On("SaveExternalServiceRole",
|
||||||
|
mock.Anything,
|
||||||
|
mock.MatchedBy(func(cmd ac.SaveExternalServiceRoleCommand) bool {
|
||||||
|
return cmd.ServiceAccountID == int64(11) && cmd.ExternalServiceID == extSvcSlug &&
|
||||||
|
cmd.OrgID == int64(ac.GlobalOrgID) && len(cmd.Permissions) == 1 &&
|
||||||
|
cmd.Permissions[0] == extSvcPerms[0]
|
||||||
|
})).
|
||||||
|
Return(nil)
|
||||||
|
env.SaSvc.On("EnableServiceAccount", mock.Anything, extsvcauth.TmpOrgID, int64(11), true).Return(nil)
|
||||||
// This time we don't add a token but rely on the secret store
|
// This time we don't add a token but rely on the secret store
|
||||||
_ = env.SkvStore.Set(context.Background(), tmpOrgID, extSvcSlug, kvStoreType, "ExtSvcSecretToken")
|
_ = env.SkvStore.Set(context.Background(), tmpOrgID, extSvcSlug, kvStoreType, "ExtSvcSecretToken")
|
||||||
},
|
},
|
||||||
@ -361,17 +341,6 @@ func TestExtSvcAccountsService_SaveExternalService(t *testing.T) {
|
|||||||
Permissions: extSvcPerms,
|
Permissions: extSvcPerms,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
checks: func(t *testing.T, env *TestEnv) {
|
|
||||||
env.SaSvc.AssertCalled(t, "RetrieveServiceAccountIdByName", mock.Anything,
|
|
||||||
mock.MatchedBy(func(orgID int64) bool { return orgID == tmpOrgID }),
|
|
||||||
mock.MatchedBy(func(slug string) bool { return slug == sa.ExtSvcPrefix+extSvcSlug }))
|
|
||||||
env.AcStore.AssertCalled(t, "SaveExternalServiceRole", mock.Anything,
|
|
||||||
mock.MatchedBy(func(cmd ac.SaveExternalServiceRoleCommand) bool {
|
|
||||||
return cmd.ServiceAccountID == int64(11) && cmd.ExternalServiceID == extSvcSlug &&
|
|
||||||
cmd.OrgID == int64(ac.GlobalOrgID) && len(cmd.Permissions) == 1 &&
|
|
||||||
cmd.Permissions[0] == extSvcPerms[0]
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
want: &extsvcauth.ExternalService{
|
want: &extsvcauth.ExternalService{
|
||||||
Name: extSvcSlug,
|
Name: extSvcSlug,
|
||||||
ID: extSvcSlug,
|
ID: extSvcSlug,
|
||||||
|
@ -191,7 +191,7 @@ type ExtSvcAccount struct {
|
|||||||
|
|
||||||
type ManageExtSvcAccountCmd struct {
|
type ManageExtSvcAccountCmd struct {
|
||||||
ExtSvcSlug string
|
ExtSvcSlug string
|
||||||
Enabled bool // disabled: the service account and its permissions will be deleted
|
Enabled bool
|
||||||
OrgID int64
|
OrgID int64
|
||||||
Permissions []accesscontrol.Permission
|
Permissions []accesscontrol.Permission
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user