Skip to content

SAML Group Sync - Add/Remove Groups

Problem to solve

Once SAML groups have been mapped, we should check the groups section in a SAML assertion. If the SAML group is found then we should add the user to that GitLab group. If the SAML group isn't found then we should remove the user from that GitLab group.

Intended users

User experience goal

Proposal

  • Sync process on user sign-in
    1. User signs in via Group SAML
    2. Sign-in kicks off a SamlGroupSync worker from Gitlab::Auth::GroupSaml::User#find_and_update!. Parameters likely need to consist of at least:
      • User ID
      • Top-level group ID
      • Array of Group Names from IdP
    3. Worker will query for group links where:
      • group_id is in the list of IDs contained within the top-level group. This can be obtained via Group#self_and_descendents.
      • group_name is in the array of group names from the IdP
    4. Worker adds the user as a member of the groups at the respective access level.

NOTE: The last MR (if there are multiple MRs in this issue) should default enable the :saml_group_links feature flag introduced in !45080 (merged). We can keep the feature flag around for a while in case we need to disable the feature for any reason.

During implementation we should consider how to make the worker and/or service classes reusable for other sync-on-sign-in solutions, such as for OAuth.

Everything built here can also be used for instance-level sync. The only difference needed, as an example, is to pass a nil value for top-level group ID for the worker. In this case the worker can query for any group in the whole instance by name and add members accordingly. And instead of the worker being kicked off from Gitlab::Auth::GroupSaml::User it is called from Gitlab::Auth::Saml::User. We should keep this in mind during implementation, especially during the worker creation phase so the parameters and usage feels natural for either case.

The supported way to pass groups via SAML will be the same as is currently supported for self-managed admin and external groups: https://docs.gitlab.com/ee/integration/saml.html#requirements

    <saml2:AttributeStatement>
      <saml2:Attribute Name="Groups" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Everyone</saml2:AttributeValue>
        <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">DBlessing Test Group</saml2:AttributeValue>
      </saml2:Attribute>
    </saml2:AttributeStatement>

In the initial implementation we should only support attribute statements with the name 'Groups'. Later we can make this configurable like it is for self-managed. For self-managed, the 'Groups' are obtained from the auth_hash (see Gitlab::Auth::Saml::AuthHash).

Further details

This is an Ultimate level feature.

Permissions and Security

Documentation

Availability & Testing

A new end-to-end test would be need to cover this feature. Testcase issue: gitlab-org/quality/testcases#1072 (moved)

What does success look like, and how can we measure that?

What is the type of buyer?

Is this a cross-stage feature?

Links / references

Edited by Melissa Ushakov