Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I-70 allow to skip users and groups deletion #1

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 28 additions & 20 deletions cmd/idpscim/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ func init() {

rootCmd.PersistentFlags().StringVarP(&cfg.SyncMethod, "sync-method", "m", config.DefaultSyncMethod, "Sync method to use [groups]")
rootCmd.PersistentFlags().BoolVarP(&cfg.UseSecretsManager, "use-secrets-manager", "g", config.DefaultUseSecretsManager, "use AWS Secrets Manager content or not (default false)")
rootCmd.PersistentFlags().BoolVar(&cfg.PreventGroupDeletion, "prevent-group-deletion", config.DefaultPreventGroupDeletion, "determines are we delete groups from AWS Identity Store or not")
rootCmd.PersistentFlags().BoolVar(&cfg.PreventUserDeletion, "prevent-user-deletion", config.DefaultPreventUserDeletion, "determines are we delete users from AWS Identity Store or not")
}

// initConfig reads in config file and ENV variables if set.
Expand All @@ -126,6 +128,8 @@ func initConfig() {
"aws_scim_endpoint",
"aws_scim_endpoint_secret_name",
"use_secrets_manager",
"prevent_group_deletion",
"prevent_user_deletion",
}
for _, e := range envVars {
if err := viper.BindEnv(e); err != nil {
Expand Down Expand Up @@ -211,18 +215,8 @@ func getSecrets() {
log.Fatalf(errors.Wrap(err, "cannot create aws secrets manager service").Error())
}

log.WithField("name", cfg.GWSUserEmailSecretName).Debug("reading secret")
unwrap, err := secrets.GetSecretValue(context.Background(), cfg.GWSUserEmailSecretName)
if err != nil {
log.Fatalf(errors.Wrap(err, "cannot get secretmanager value").Error())
}
cfg.GWSUserEmail = unwrap
log.WithFields(
log.Fields{"secretARN": cfg.GWSUserEmailSecretName},
).Debug("read secret")

log.WithField("name", cfg.GWSServiceAccountFileSecretName).Debug("reading secret")
unwrap, err = secrets.GetSecretValue(context.Background(), cfg.GWSServiceAccountFileSecretName)
unwrap, err := secrets.GetSecretValue(context.Background(), cfg.GWSServiceAccountFileSecretName)
if err != nil {
log.Fatalf(errors.Wrap(err, "cannot get secretmanager value").Error())
}
Expand All @@ -231,6 +225,18 @@ func getSecrets() {
log.Fields{"secretARN": cfg.GWSServiceAccountFileSecretName},
).Debug("read secret")

if cfg.GWSUserEmailSecretName != "" {
log.WithField("name", cfg.GWSUserEmailSecretName).Debug("reading secret")
unwrap, err = secrets.GetSecretValue(context.Background(), cfg.GWSUserEmailSecretName)
if err != nil {
log.Fatalf(errors.Wrap(err, "cannot get secretmanager value").Error())
}
cfg.GWSUserEmail = unwrap
log.WithFields(
log.Fields{"secretARN": cfg.GWSUserEmailSecretName},
).Debug("read secret")
}

log.WithField("name", cfg.AWSSCIMAccessTokenSecretName).Debug("reading secret")
unwrap, err = secrets.GetSecretValue(context.Background(), cfg.AWSSCIMAccessTokenSecretName)
if err != nil {
Expand All @@ -241,15 +247,17 @@ func getSecrets() {
log.Fields{"secretARN": cfg.AWSSCIMAccessTokenSecretName},
).Debug("read secret")

log.WithField("name", cfg.AWSSCIMEndpointSecretName).Debug("reading secret")
unwrap, err = secrets.GetSecretValue(context.Background(), cfg.AWSSCIMEndpointSecretName)
if err != nil {
log.Fatalf(errors.Wrap(err, "cannot get secretmanager value").Error())
if cfg.AWSSCIMEndpointSecretName != "" {
log.WithField("name", cfg.AWSSCIMEndpointSecretName).Debug("reading secret")
unwrap, err = secrets.GetSecretValue(context.Background(), cfg.AWSSCIMEndpointSecretName)
if err != nil {
log.Fatalf(errors.Wrap(err, "cannot get secretmanager value").Error())
}
cfg.AWSSCIMEndpoint = unwrap
log.WithFields(
log.Fields{"secretARN": cfg.AWSSCIMEndpointSecretName},
).Debug("read secret")
}
cfg.AWSSCIMEndpoint = unwrap
log.WithFields(
log.Fields{"secretARN": cfg.AWSSCIMEndpointSecretName},
).Debug("read secret")
}

func sync() error {
Expand Down Expand Up @@ -340,7 +348,7 @@ func syncGroups() error {
log.Fatalf(errors.Wrap(err, "cannot create s3 repository").Error())
}

ss, err := core.NewSyncService(idpService, scimService, repo, core.WithIdentityProviderGroupsFilter(cfg.GWSGroupsFilter))
ss, err := core.NewSyncService(idpService, scimService, repo, core.WithIdentityProviderGroupsFilter(cfg.GWSGroupsFilter), core.WithSCIMGroupDeleteionPrevention(cfg.PreventGroupDeletion), core.WithSCIMUserDeleteionPrevention(cfg.PreventUserDeletion))
if err != nil {
return errors.Wrap(err, "cannot create sync service")
}
Expand Down
1 change: 1 addition & 0 deletions cmd/idpscimcli/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ func initConfig() {
"gws_users_filter",
"aws_scim_access_token",
"aws_scim_endpoint",
"prevent_group_deletion",
}
for _, e := range envVars {
if err := viper.BindEnv(e); err != nil {
Expand Down
18 changes: 16 additions & 2 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,22 @@ const (
DefaultGWSServiceAccountFileSecretName = "IDPSCIM_GWSServiceAccountFile"

// DefaultGWSUserEmailSecretName is the name of the secret containing the user email.
DefaultGWSUserEmailSecretName = "IDPSCIM_GWSUserEmail"
DefaultGWSUserEmailSecretName = ""

// DefaultAWSSCIMEndpointSecretName is the name of the secret containing the SCIM endpoint.
DefaultAWSSCIMEndpointSecretName = "IDPSCIM_SCIMEndpoint"
DefaultAWSSCIMEndpointSecretName = ""

// DefaultAWSSCIMAccessTokenSecretName is the name of the secret containing the SCIM access token.
DefaultAWSSCIMAccessTokenSecretName = "IDPSCIM_SCIMAccessToken"

// DefaultUseSecretsManager determines if we will use the AWS Secrets Manager secrets or program parameter values
DefaultUseSecretsManager = false

// DefaultPreventGroupDeletion determines are we delete groups from AWS Identity Store or not
DefaultPreventGroupDeletion = false

// DefaultPreventUserDeletion determines are we delete users from AWS Identity Store or not
DefaultPreventUserDeletion = false
)

// Config represents the configuration of the application.
Expand Down Expand Up @@ -72,6 +78,12 @@ type Config struct {

// UseSecretsManager determines if we will use the AWS Secrets Manager secrets or program parameter values
UseSecretsManager bool `mapstructure:"use_secrets_manager" json:"use_secrets_manager" yaml:"use_secrets_manager"`

// PreventGroupDeletion determines are we delete groups from AWS Identity Store or not
PreventGroupDeletion bool `mapstructure:"prevent_group_deletion" json:"prevent_group_deletion", yaml:"prevent_group_deletion"`

// PreventGroupDeletion determines are we delete users from AWS Identity Store or not
PreventUserDeletion bool `mapstructure:"prevent_user_deletion" json:"prevent_user_deletion", yaml:"prevent_user_deletion"`
}

// New returns a new Config
Expand All @@ -90,5 +102,7 @@ func New() Config {
AWSSCIMEndpointSecretName: DefaultAWSSCIMEndpointSecretName,
AWSSCIMAccessTokenSecretName: DefaultAWSSCIMAccessTokenSecretName,
UseSecretsManager: DefaultUseSecretsManager,
PreventGroupDeletion: DefaultPreventGroupDeletion,
PreventUserDeletion: DefaultPreventUserDeletion,
}
}
1 change: 1 addition & 0 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ func TestNew(t *testing.T) {
assert.Equal(cfg.AWSSCIMEndpointSecretName, DefaultAWSSCIMEndpointSecretName)
assert.Equal(cfg.AWSSCIMAccessTokenSecretName, DefaultAWSSCIMAccessTokenSecretName)
assert.Equal(cfg.UseSecretsManager, DefaultUseSecretsManager)
assert.Equal(cfg.PreventGroupDeletion, DefaultUseSecretsManager)
}
20 changes: 20 additions & 0 deletions internal/core/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ func scimSync(
idpGroupsResult *model.GroupsResult,
idpUsersResult *model.UsersResult,
idpGroupsMembersResult *model.GroupsMembersResult,
preventUserDeletion bool,
preventGroupDeletion bool,
) (*model.GroupsResult, *model.UsersResult, *model.GroupsMembersResult, error) {
log.Warn("reconciling the SCIM data with the Identity Provider data")

Expand All @@ -39,6 +41,10 @@ func scimSync(
return nil, nil, nil, fmt.Errorf("error reconciling groups: %w", err)
}

if preventGroupDeletion {
groupsDelete = &model.GroupsResult{}
}

groupsCreated, groupsUpdated, err := reconcilingGroups(ctx, scim, groupsCreate, groupsUpdate, groupsDelete)
if err != nil {
return nil, nil, nil, fmt.Errorf("error reconciling groups: %w", err)
Expand All @@ -62,6 +68,10 @@ func scimSync(
return nil, nil, nil, fmt.Errorf("error operating with users: %w", err)
}

if preventUserDeletion {
usersDelete = &model.UsersResult{}
}

usersCreated, usersUpdated, err := reconcilingUsers(ctx, scim, usersCreate, usersUpdate, usersDelete)
if err != nil {
return nil, nil, nil, fmt.Errorf("error reconciling users: %w", err)
Expand Down Expand Up @@ -108,6 +118,8 @@ func stateSync(
idpGroupsResult *model.GroupsResult,
idpUsersResult *model.UsersResult,
idpGroupsMembersResult *model.GroupsMembersResult,
preventUserDeletion bool,
preventGroupDeletion bool,
) (*model.GroupsResult, *model.UsersResult, *model.GroupsMembersResult, error) {
var totalGroupsResult *model.GroupsResult
var totalUsersResult *model.UsersResult
Expand Down Expand Up @@ -143,6 +155,10 @@ func stateSync(
return nil, nil, nil, fmt.Errorf("error reconciling groups: %w", err)
}

if preventGroupDeletion {
groupsDelete = &model.GroupsResult{}
}

groupsCreated, groupsUpdated, err := reconcilingGroups(ctx, scim, groupsCreate, groupsUpdate, groupsDelete)
if err != nil {
return nil, nil, nil, fmt.Errorf("error reconciling groups: %w", err)
Expand All @@ -168,6 +184,10 @@ func stateSync(
return nil, nil, nil, fmt.Errorf("error operating with users: %w", err)
}

if preventUserDeletion {
usersDelete = &model.UsersResult{}
}

usersCreated, usersUpdated, err := reconcilingUsers(ctx, scim, usersCreate, usersUpdate, usersDelete)
if err != nil {
return nil, nil, nil, fmt.Errorf("error reconciling users: %w", err)
Expand Down
12 changes: 12 additions & 0 deletions internal/core/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,15 @@ func WithIdentityProviderUsersFilter(filter []string) SyncServiceOption {
ss.provUsersFilter = filter
}
}

func WithSCIMGroupDeleteionPrevention(preventGroupDeletion bool) SyncServiceOption {
return func(ss *SyncService) {
ss.scimPreventGroupDeletion = preventGroupDeletion
}
}

func WithSCIMUserDeleteionPrevention(preventUserDeletion bool) SyncServiceOption {
return func(ss *SyncService) {
ss.scimPreventUserDeletion = preventUserDeletion
}
}
28 changes: 18 additions & 10 deletions internal/core/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ var (

// SyncService represent the sync service and the core of the sync process
type SyncService struct {
provGroupsFilter []string
provUsersFilter []string
prov IdentityProviderService
scim SCIMService
repo StateRepository
provGroupsFilter []string
provUsersFilter []string
scimPreventGroupDeletion bool
scimPreventUserDeletion bool
prov IdentityProviderService
scim SCIMService
repo StateRepository
}

// NewSyncService creates a new sync service.
Expand All @@ -46,11 +48,13 @@ func NewSyncService(prov IdentityProviderService, scim SCIMService, repo StateRe
}

ss := &SyncService{
prov: prov,
provGroupsFilter: []string{}, // fill in with the opts
provUsersFilter: []string{}, // fill in with the opts
scim: scim,
repo: repo,
prov: prov,
provGroupsFilter: []string{}, // fill in with the opts
provUsersFilter: []string{}, // fill in with the opts
scimPreventUserDeletion: false,
scimPreventGroupDeletion: false,
scim: scim,
repo: repo,
}

for _, opt := range opts {
Expand Down Expand Up @@ -139,6 +143,8 @@ func (ss *SyncService) SyncGroupsAndTheirMembers(ctx context.Context) error {
idpGroupsResult,
idpUsersResult,
idpGroupsMembersResult,
ss.scimPreventUserDeletion,
ss.scimPreventGroupDeletion,
)
if err != nil {
return fmt.Errorf("error doing the first sync: %w", err)
Expand All @@ -152,6 +158,8 @@ func (ss *SyncService) SyncGroupsAndTheirMembers(ctx context.Context) error {
idpGroupsResult,
idpUsersResult,
idpGroupsMembersResult,
ss.scimPreventUserDeletion,
ss.scimPreventGroupDeletion,
)
if err != nil {
return fmt.Errorf("error syncing state: %w", err)
Expand Down
Loading