Skip to content

chore: support multi-org group sync with runtime configuration #14578

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

Merged
merged 38 commits into from
Sep 11, 2024

Conversation

Emyrk
Copy link
Member

@Emyrk Emyrk commented Sep 5, 2024

Closes #14202

What is this

Group sync implemented to support multi-organization runtime configuration (CRUD does not yet exist).

All previous logic existed in oidcGroups and oauthLogin. I disliked this approach, as the components were completely untestable. So tests had to be integration tests.

The goal of this package is to completely test the sync logic independent of the oidc or broader coderd code.

What is does

Enables group sync to work in multiple organizations, not just the default. There is no way to configure other organizations in this PR, the API and CRUD is not done yet.

Unit tests show how these values can be set.

Testing notes

This is a large refactor to a section of code that had very little testing of it's parts. It did however have good integration style tests for group sync in the default org. In the package tests, multi-org sync is tested, but only with dbmem as it inserts a lot of data. When CRUD api is added, more tests can be added similar to those below for multi-org.

@Emyrk Emyrk force-pushed the stevenmasley/org_group_sync branch from 07fa2b1 to c343f86 Compare September 5, 2024 19:26
Base automatically changed from stevenmasley/runtime_refactor to dk/runtime-configs September 5, 2024 21:12
@Emyrk Emyrk changed the title chore: organization group sync feature with runtime configuration chore: sync groups with runtime configuration, supports multi-org Sep 5, 2024
@Emyrk Emyrk force-pushed the stevenmasley/org_group_sync branch from de150b1 to 2163eb7 Compare September 6, 2024 14:44
@Emyrk Emyrk changed the title chore: sync groups with runtime configuration, supports multi-org chore: support multi-org group sync with runtime configuration Sep 6, 2024
@Emyrk Emyrk force-pushed the dk/runtime-configs branch from 0f7deba to 9f546d0 Compare September 6, 2024 15:19
@Emyrk Emyrk force-pushed the stevenmasley/org_group_sync branch 2 times, most recently from b22d62d to ae5315f Compare September 6, 2024 15:42
@Emyrk Emyrk marked this pull request as ready for review September 6, 2024 18:31
}, nil
}

func (s AGPLIDPSync) SyncGroups(ctx context.Context, db database.Store, user database.User, params GroupParams) error {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enterprise license code just handles the ParseGroupClaims. So AGPL will always be disabled.

I put the actual SyncGroups code in AGPL so that I can unit test and maintain the sync code all in 1 package. It is a convenience, while still making sure AGPL code cannot leverage this feature.

Comment on lines +47 to +60
// Only care about the default org for deployment settings if the
// legacy deployment settings exist.
defaultOrgID := uuid.Nil
// Default organization is configured via legacy deployment values
if s.DeploymentSyncSettings.Legacy.GroupField != "" {
defaultOrganization, err := db.GetDefaultOrganization(ctx)
if err != nil {
return xerrors.Errorf("get default organization: %w", err)
}
defaultOrgID = defaultOrganization.ID
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Startup group sync config has to be pulled for the default org 😢. Backwards compatibility.

Comment on lines +81 to +85
orgResolver := s.Manager.OrganizationResolver(tx, orgID)
settings, err := s.SyncSettings.Group.Resolve(ctx, orgResolver)
Copy link
Member Author

@Emyrk Emyrk Sep 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently this is a DB call.

#14586 will make it a cache lookup

So 100 org deployments would be a bit slow to login until we handle caching. Problem for another day

Comment on lines +68 to +75
GroupField string
// GroupAllowList (if set) will restrict authentication to only users who
// have at least one group in this list.
// A map representation is used for easier lookup.
GroupAllowList map[string]struct{}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At some point we should disconnect these from the default org. Might need to move the existing config env and flags, and deprecate the old.

@Emyrk Emyrk force-pushed the stevenmasley/org_group_sync branch 3 times, most recently from a5b64dd to 3263d99 Compare September 9, 2024 15:58
@Emyrk Emyrk requested review from f0ssel and coadler September 9, 2024 18:38
@Emyrk Emyrk force-pushed the stevenmasley/org_group_sync branch from 1995c13 to 0df7f28 Compare September 9, 2024 21:33
Copy link
Contributor

@f0ssel f0ssel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good, glad the runtime config only impacts this feature. Unfortunate about the sql tests being disabled, maybe we can add some sort of simple cache or debounce for just tests? Could be a followup.

Also it seems like all the frontend changes should be in a separate PR? Or maybe the branch just needs rebasing?

@Emyrk Emyrk changed the base branch from dk/runtime-configs to main September 10, 2024 19:42
@Emyrk
Copy link
Member Author

Emyrk commented Sep 10, 2024

@f0ssel yea, I rebased it correctly, but forgot to change the base branch to main 🤦. Should be correct now 👍

Copy link
Contributor

@coadler coadler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still trying to catch up to speed but all lgtm!

Comment on lines 55 to 58
AND CASE WHEN array_length(@group_names :: text[], 1) > 0 THEN
groups.name = ANY(@group_names)
ELSE true
END
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
AND CASE WHEN array_length(@group_names :: text[], 1) > 0 THEN
groups.name = ANY(@group_names)
ELSE true
END
AND CASE WHEN array_length(@group_names :: text[], 1) > 0 THEN
groups.name = ANY(@group_names)
ELSE true
END

nit; indentation is a little weird

Comment on lines 685 to 694
func (q *FakeQuerier) getGroupByNameNoLock(arg database.NameOrganizationPair) (database.Group, error) {
for _, group := range q.groups {
if group.OrganizationID == arg.OrganizationID &&
group.Name == arg.Name {
return group, nil
}
}

return database.Group{}, sql.ErrNoRows
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm very curious what this is necessary for

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I originally was using it in another query. Wanted to reuse the same code. Now it's not necessary to extract to it's own function 🤷‍♂️. I'll put it back.

@Emyrk Emyrk merged commit 6a846cd into main Sep 11, 2024
26 checks passed
@Emyrk Emyrk deleted the stevenmasley/org_group_sync branch September 11, 2024 18:43
@github-actions github-actions bot locked and limited conversation to collaborators Sep 11, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Multi-Organization Group Sync compatibility upgrade
4 participants