Skip to content

Commit

Permalink
Name AWS groups from the email address when using groups sync method
Browse files Browse the repository at this point in the history
We're using the other sync method, "user_groups", but would like to
switch to the "groups" on because it runs a lot more efficiently, just
over 4.5 minutes compared to the "user_groups" one which is timing out
at 15 minutes near the end of the process.

Unfortunately, the "groups" method names AWS group from the email
address in Google i.e. $name@$domain.com. The more efficient method,
"groups", uses the name of the group in Google i.e. $name.

This means if we switch, it'll remove all the old groups and create new
ones, which will then remove everyone's permissions until the account
assignments are added to the new groups. This process is easy in
Terraform, but would create an outage on permissions and has the same
problem when switching back as well.

Instead, let's set the "groups" method to name them after the email as
well.

I've also removed a duplicate loop and ran the LSP formatter on the
code. Most formatting changes are whitespace so easy to ignore.
  • Loading branch information
dancorne committed Oct 30, 2023
1 parent 014accf commit d6bbf43
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 57 deletions.
74 changes: 38 additions & 36 deletions internal/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,14 @@ func New(cfg *config.Config, a aws.Client, g google.Client, ids identitystoreifa
// References:
// * https://developers.google.com/admin-sdk/directory/v1/guides/search-users
// query possible values:
// '' --> empty or not defined
// name:'Jane'
// email:admin*
// isAdmin=true
// manager='janesmith@example.com'
// orgName=Engineering orgTitle:Manager
// EmploymentData.projects:'GeneGnomes'
// "" --> empty or not defined
//
// name:'Jane'
// email:admin*
// isAdmin=true
// manager='janesmith@example.com'
// orgName=Engineering orgTitle:Manager
// EmploymentData.projects:'GeneGnomes'
func (s *syncGSuite) SyncUsers(query string) error {
log.Debug("get deleted users")
deletedUsers, err := s.google.GetDeletedUsers()
Expand Down Expand Up @@ -165,13 +166,14 @@ func (s *syncGSuite) SyncUsers(query string) error {
// References:
// * https://developers.google.com/admin-sdk/directory/v1/guides/search-groups
// query possible values:
// '' --> empty or not defined
// name='contact'
// email:admin*
// memberKey=user@company.com
// name:contact* email:contact*
// name:Admin* email:aws-*
// email:aws-*
// "" --> empty or not defined
//
// name='contact'
// email:admin*
// memberKey=user@company.com
// name:contact* email:contact*
// name:Admin* email:aws-*
// email:aws-*
func (s *syncGSuite) SyncGroups(query string) error {

log.WithField("query", query).Debug("get google groups")
Expand Down Expand Up @@ -271,20 +273,22 @@ func (s *syncGSuite) SyncGroups(query string) error {
// References:
// * https://developers.google.com/admin-sdk/directory/v1/guides/search-groups
// query possible values:
// '' --> empty or not defined
// name='contact'
// email:admin*
// memberKey=user@company.com
// name:contact* email:contact*
// name:Admin* email:aws-*
// email:aws-*
// "" --> empty or not defined
//
// name='contact'
// email:admin*
// memberKey=user@company.com
// name:contact* email:contact*
// name:Admin* email:aws-*
// email:aws-*
//
// process workflow:
// 1) delete users in aws, these were deleted in google
// 2) update users in aws, these were updated in google
// 3) add users in aws, these were added in google
// 4) add groups in aws and add its members, these were added in google
// 5) validate equals aws an google groups members
// 6) delete groups in aws, these were deleted in google
// 1. delete users in aws, these were deleted in google
// 2. update users in aws, these were updated in google
// 3. add users in aws, these were added in google
// 4. add groups in aws and add its members, these were added in google
// 5. validate equals aws an google groups members
// 6. delete groups in aws, these were deleted in google
func (s *syncGSuite) SyncGroupsUsers(query string) error {

log.WithField("query", query).Info("get google groups")
Expand Down Expand Up @@ -601,15 +605,13 @@ func getGroupOperations(awsGroups []*aws.Group, googleGroups []*admin.Group) (ad
}

for _, gGroup := range googleGroups {
googleMap[gGroup.Name] = struct{}{}
}
googleMap[gGroup.Email] = struct{}{}

// AWS Groups found and not found in google
for _, gGroup := range googleGroups {
if _, found := awsMap[gGroup.Name]; found {
equals = append(equals, awsMap[gGroup.Name])
// AWS Groups found and not found in google
if _, found := awsMap[gGroup.Email]; found {
equals = append(equals, awsMap[gGroup.Email])
} else {
add = append(add, aws.NewGroup(gGroup.Name))
add = append(add, aws.NewGroup(gGroup.Email))
}
}

Expand Down Expand Up @@ -867,8 +869,8 @@ func ConvertSdkUserObjToNative(user *identitystore.User) *aws.User {

for _, email := range user.Emails {
if email.Value == nil || email.Type == nil || email.Primary == nil {
// This must be a user created by AWS Control Tower
// Need feature development to make how these users are treated
// This must be a user created by AWS Control Tower
// Need feature development to make how these users are treated
// configurable.
continue
}
Expand Down
42 changes: 21 additions & 21 deletions internal/sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,33 +58,33 @@ func Test_getGroupOperations(t *testing.T) {
name: "equal groups google and aws",
args: args{
awsGroups: []*aws.Group{
aws.NewGroup("Group-1"),
aws.NewGroup("Group-2"),
aws.NewGroup("Group-1@domain.com"),
aws.NewGroup("Group-2@domain.com"),
},
googleGroups: []*admin.Group{
{Name: "Group-1"},
{Name: "Group-2"},
{Email: "Group-1@domain.com"},
{Email: "Group-2@domain.com"},
},
},
wantAdd: nil,
wantDelete: nil,
wantEquals: []*aws.Group{
aws.NewGroup("Group-1"),
aws.NewGroup("Group-2"),
aws.NewGroup("Group-1@domain.com"),
aws.NewGroup("Group-2@domain.com"),
},
},
{
name: "add two new aws groups",
args: args{
awsGroups: nil,
googleGroups: []*admin.Group{
{Name: "Group-1"},
{Name: "Group-2"},
{Email: "Group-1@domain.com"},
{Email: "Group-2@domain.com"},
},
},
wantAdd: []*aws.Group{
aws.NewGroup("Group-1"),
aws.NewGroup("Group-2"),
aws.NewGroup("Group-1@domain.com"),
aws.NewGroup("Group-2@domain.com"),
},
wantDelete: nil,
wantEquals: nil,
Expand All @@ -93,37 +93,37 @@ func Test_getGroupOperations(t *testing.T) {
name: "delete two aws groups",
args: args{
awsGroups: []*aws.Group{
aws.NewGroup("Group-1"),
aws.NewGroup("Group-2"),
aws.NewGroup("Group-1@domain.com"),
aws.NewGroup("Group-2@domain.com"),
}, googleGroups: nil,
},
wantAdd: nil,
wantDelete: []*aws.Group{
aws.NewGroup("Group-1"),
aws.NewGroup("Group-2"),
aws.NewGroup("Group-1@domain.com"),
aws.NewGroup("Group-2@domain.com"),
},
wantEquals: nil,
},
{
name: "add one, delete one and one equal",
args: args{
awsGroups: []*aws.Group{
aws.NewGroup("Group-2"),
aws.NewGroup("Group-3"),
aws.NewGroup("Group-2@domain.com"),
aws.NewGroup("Group-3@domain.com"),
},
googleGroups: []*admin.Group{
{Name: "Group-1"},
{Name: "Group-2"},
{Email: "Group-1@domain.com"},
{Email: "Group-2@domain.com"},
},
},
wantAdd: []*aws.Group{
aws.NewGroup("Group-1"),
aws.NewGroup("Group-1@domain.com"),
},
wantDelete: []*aws.Group{
aws.NewGroup("Group-3"),
aws.NewGroup("Group-3@domain.com"),
},
wantEquals: []*aws.Group{
aws.NewGroup("Group-2"),
aws.NewGroup("Group-2@domain.com"),
},
},
}
Expand Down

0 comments on commit d6bbf43

Please sign in to comment.