Skip to content

Commit

Permalink
Adds a new flag to let us disable syncing secondary emails (#62)
Browse files Browse the repository at this point in the history
* Adds a new flag to let us disable syncing secondary emails

* invert flag

---------

Co-authored-by: michael burton <[email protected]>
  • Loading branch information
mstanbCO and michael burton authored Dec 12, 2024
1 parent 82191fe commit 698ac2d
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 71 deletions.
2 changes: 2 additions & 0 deletions cmd/baton-okta/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ var (
cacheTTI = field.IntField("cache-tti", field.WithDescription("Response cache cleanup interval in seconds"), field.WithDefaultValue(60))
cacheTTL = field.IntField("cache-ttl", field.WithDescription("Response cache time to live in seconds"), field.WithDefaultValue(300))
syncCustomRoles = field.BoolField("sync-custom-roles", field.WithDescription("Enable syncing custom roles"), field.WithDefaultValue(false))
skipSecondaryEmails = field.BoolField("skip-secondary-emails", field.WithDescription("Skip syncing secondary emails"), field.WithDefaultValue(false))
awsIdentityCenterMode = field.BoolField("aws-identity-center-mode",
field.WithDescription("Whether to run in AWS Identity center mode or not. In AWS mode, only samlRoles for groups and the users assigned to groups are synced"))
awsOktaAppId = field.StringField("aws-okta-app-id", field.WithDescription("The Okta app id for the AWS application"))
Expand Down Expand Up @@ -47,6 +48,7 @@ var configuration = field.NewConfiguration([]field.SchemaField{
cacheTTI,
cacheTTL,
syncCustomRoles,
skipSecondaryEmails,
awsIdentityCenterMode,
awsOktaAppId,
}, relationships...)
31 changes: 16 additions & 15 deletions cmd/baton-okta/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,22 @@ func main() {
func getConnector(ctx context.Context, v *viper.Viper) (types.ConnectorServer, error) {
l := ctxzap.Extract(ctx)
ccfg := &connector.Config{
Domain: v.GetString("domain"),
ApiToken: v.GetString("api-token"),
OktaClientId: v.GetString("okta-client-id"),
OktaPrivateKey: v.GetString("okta-private-key"),
OktaPrivateKeyId: v.GetString("okta-private-key-id"),
SyncInactiveApps: v.GetBool("sync-inactive-apps"),
OktaProvisioning: v.GetBool("okta-provisioning"),
Ciam: v.GetBool("ciam"),
CiamEmailDomains: v.GetStringSlice("ciam-email-domains"),
Cache: v.GetBool("cache"),
CacheTTI: v.GetInt32("cache-tti"),
CacheTTL: v.GetInt32("cache-ttl"),
SyncCustomRoles: v.GetBool("sync-custom-roles"),
AWSMode: v.GetBool("aws-identity-center-mode"),
AWSOktaAppId: v.GetString("aws-okta-app-id"),
Domain: v.GetString("domain"),
ApiToken: v.GetString("api-token"),
OktaClientId: v.GetString("okta-client-id"),
OktaPrivateKey: v.GetString("okta-private-key"),
OktaPrivateKeyId: v.GetString("okta-private-key-id"),
SyncInactiveApps: v.GetBool("sync-inactive-apps"),
OktaProvisioning: v.GetBool("okta-provisioning"),
Ciam: v.GetBool("ciam"),
CiamEmailDomains: v.GetStringSlice("ciam-email-domains"),
Cache: v.GetBool("cache"),
CacheTTI: v.GetInt32("cache-tti"),
CacheTTL: v.GetInt32("cache-ttl"),
SyncCustomRoles: v.GetBool("sync-custom-roles"),
SkipSecondaryEmails: v.GetBool("skip-secondary-emails"),
AWSMode: v.GetBool("aws-identity-center-mode"),
AWSOktaAppId: v.GetString("aws-okta-app-id"),
}

cb, err := connector.New(ctx, ccfg)
Expand Down
10 changes: 6 additions & 4 deletions pkg/connector/ciam.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import (
)

type ciamResourceBuilder struct {
client *okta.Client
client *okta.Client
skipSecondaryEmails bool
}

func (o *ciamResourceBuilder) List(ctx context.Context, parentResourceID *v2.ResourceId, pToken *pagination.Token) ([]*v2.Resource, string, annotations.Annotations, error) {
Expand Down Expand Up @@ -53,7 +54,7 @@ func (o *ciamResourceBuilder) List(ctx context.Context, parentResourceID *v2.Res
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to parse response: %w", err)
}

resource, err := userResource(ctx, oktaUser)
resource, err := userResource(ctx, oktaUser, o.skipSecondaryEmails)
if err != nil {
return nil, "", nil, fmt.Errorf("okta-connectorv2: failed to create user resource: %w", err)
}
Expand Down Expand Up @@ -346,8 +347,9 @@ func (o *ciamResourceBuilder) ResourceType(ctx context.Context) *v2.ResourceType
return resourceTypeRole
}

func ciamBuilder(client *okta.Client) *ciamResourceBuilder {
func ciamBuilder(client *okta.Client, skipSecondaryEmails bool) *ciamResourceBuilder {
return &ciamResourceBuilder{
client: client,
client: client,
skipSecondaryEmails: skipSecondaryEmails,
}
}
65 changes: 34 additions & 31 deletions pkg/connector/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@ const ExpectedIdentityProviderArnRegexCaptureGroups = 2
const ExpectedGroupNameCaptureGroupsWithGroupFilterForMultipleAWSInstances = 3

type Okta struct {
client *okta.Client
domain string
apiToken string
syncInactiveApps bool
ciamConfig *ciamConfig
syncCustomRoles bool
awsConfig *awsConfig
client *okta.Client
domain string
apiToken string
syncInactiveApps bool
ciamConfig *ciamConfig
syncCustomRoles bool
skipSecondaryEmails bool
awsConfig *awsConfig
}

type ciamConfig struct {
Expand Down Expand Up @@ -77,21 +78,22 @@ type oktaAWSAppSettings struct {
}

type Config struct {
Domain string
ApiToken string
OktaClientId string
OktaPrivateKey string
OktaPrivateKeyId string
SyncInactiveApps bool
OktaProvisioning bool
Ciam bool
CiamEmailDomains []string
Cache bool
CacheTTI int32
CacheTTL int32
SyncCustomRoles bool
AWSMode bool
AWSOktaAppId string
Domain string
ApiToken string
OktaClientId string
OktaPrivateKey string
OktaPrivateKeyId string
SyncInactiveApps bool
OktaProvisioning bool
Ciam bool
CiamEmailDomains []string
Cache bool
CacheTTI int32
CacheTTL int32
SyncCustomRoles bool
SkipSecondaryEmails bool
AWSMode bool
AWSOktaAppId string
}

func v1AnnotationsForResourceType(resourceTypeID string, skipEntitlementsAndGrants bool) annotations.Annotations {
Expand Down Expand Up @@ -171,22 +173,22 @@ var (
func (o *Okta) ResourceSyncers(ctx context.Context) []connectorbuilder.ResourceSyncer {
if o.ciamConfig.Enabled {
return []connectorbuilder.ResourceSyncer{
ciamUserBuilder(o.domain, o.apiToken, o.client, o.ciamConfig.EmailDomains),
ciamBuilder(o.client),
ciamUserBuilder(o.domain, o.apiToken, o.client, o.ciamConfig.EmailDomains, o.skipSecondaryEmails),
ciamBuilder(o.client, o.skipSecondaryEmails),
}
}

if o.awsConfig.Enabled {
return []connectorbuilder.ResourceSyncer{
userBuilder(o.domain, o.apiToken, o.client),
userBuilder(o.domain, o.apiToken, o.client, o.skipSecondaryEmails),
groupBuilder(o),
accountBuilder(o),
}
}

resourceSyncer := []connectorbuilder.ResourceSyncer{
roleBuilder(o.client, o),
userBuilder(o.domain, o.apiToken, o.client),
userBuilder(o.domain, o.apiToken, o.client, o.skipSecondaryEmails),
groupBuilder(o),
appBuilder(o.domain, o.apiToken, o.syncInactiveApps, o.client),
}
Expand Down Expand Up @@ -326,11 +328,12 @@ func New(ctx context.Context, cfg *Config) (*Okta, error) {
}

return &Okta{
client: oktaClient,
domain: cfg.Domain,
apiToken: cfg.ApiToken,
syncInactiveApps: cfg.SyncInactiveApps,
syncCustomRoles: cfg.SyncCustomRoles,
client: oktaClient,
domain: cfg.Domain,
apiToken: cfg.ApiToken,
syncInactiveApps: cfg.SyncInactiveApps,
syncCustomRoles: cfg.SyncCustomRoles,
skipSecondaryEmails: cfg.SkipSecondaryEmails,
ciamConfig: &ciamConfig{
Enabled: cfg.Ciam,
EmailDomains: cfg.CiamEmailDomains,
Expand Down
49 changes: 28 additions & 21 deletions pkg/connector/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ const (
)

type userResourceType struct {
resourceType *v2.ResourceType
domain string
apiToken string
client *okta.Client
ciamMode bool
emailFilters []string
resourceType *v2.ResourceType
domain string
apiToken string
client *okta.Client
ciamMode bool
emailFilters []string
skipSecondaryEmails bool
}

func (o *userResourceType) ResourceType(_ context.Context) *v2.ResourceType {
Expand Down Expand Up @@ -74,7 +75,7 @@ func (o *userResourceType) List(
if o.ciamMode && !shouldIncludeOktaUser(user, o.emailFilters) {
continue
}
resource, err := userResource(ctx, user)
resource, err := userResource(ctx, user, o.skipSecondaryEmails)
if err != nil {
return nil, "", nil, err
}
Expand Down Expand Up @@ -170,32 +171,34 @@ func listUsers(ctx context.Context, client *okta.Client, token *pagination.Token
return oktaUsers, respCtx, nil
}

func ciamUserBuilder(domain string, apiToken string, client *okta.Client, emailFilters []string) *userResourceType {
func ciamUserBuilder(domain string, apiToken string, client *okta.Client, emailFilters []string, skipSecondaryEmails bool) *userResourceType {
var loweredFilters []string
for _, ef := range emailFilters {
loweredFilters = append(loweredFilters, strings.ToLower(ef))
}
return &userResourceType{
resourceType: resourceTypeUser,
domain: domain,
apiToken: apiToken,
client: client,
ciamMode: true,
emailFilters: loweredFilters,
resourceType: resourceTypeUser,
domain: domain,
apiToken: apiToken,
client: client,
ciamMode: true,
emailFilters: loweredFilters,
skipSecondaryEmails: skipSecondaryEmails,
}
}

func userBuilder(domain string, apiToken string, client *okta.Client) *userResourceType {
func userBuilder(domain string, apiToken string, client *okta.Client, skipSecondaryEmails bool) *userResourceType {
return &userResourceType{
resourceType: resourceTypeUser,
domain: domain,
apiToken: apiToken,
client: client,
resourceType: resourceTypeUser,
domain: domain,
apiToken: apiToken,
client: client,
skipSecondaryEmails: skipSecondaryEmails,
}
}

// Create a new connector resource for a okta user.
func userResource(ctx context.Context, user *okta.User) (*v2.Resource, error) {
func userResource(ctx context.Context, user *okta.User, skipSecondaryEmails bool) (*v2.Resource, error) {
firstName, lastName := userName(user)

oktaProfile := *user.Profile
Expand Down Expand Up @@ -223,10 +226,14 @@ func userResource(ctx context.Context, user *okta.User) (*v2.Resource, error) {
if email, ok := oktaProfile["email"].(string); ok && email != "" {
options = append(options, resource.WithEmail(email, true))
}
if secondEmail, ok := oktaProfile["secondEmail"].(string); ok && secondEmail != "" {
if secondEmail, ok := oktaProfile["secondEmail"].(string); ok && secondEmail != "" && !skipSecondaryEmails {
options = append(options, resource.WithEmail(secondEmail, false))
}

if skipSecondaryEmails {
oktaProfile["secondEmail"] = nil
}

if login, ok := oktaProfile["login"].(string); ok {
// If possible, calculate shortname alias from login
splitLogin := strings.Split(login, "@")
Expand Down

0 comments on commit 698ac2d

Please sign in to comment.