Skip to content

Resolve "Plug-In logic to auto assign duo-seats when LDAP group sync occurs behind the feature flag"

What does this MR do and why?

This MR adds logic to read the LDAP config for duo_add_on_group and assign or remove Duo Add-on seat of a LDAP enabled user when they log-in via LDAP.

References

Please include cross links to any resources that are relevant to this MR. This will give reviewers and future readers helpful context to give an efficient review of the changes introduced.

Summary:

  1. When the duo_add_on_group is set, it will be "Single Source of Truth" for "All LDAP enabled user".
  2. Whenever a user signs in via LDAP, we check if the user is a member of the duo_add_on_group in LDAP server
    1. If the user, is member of the duo_add_on_group , we assign user a Duo Seat, if not already assigned.
    2. If user is not member of any duo_add_on_group server, we remove the Duo Seat of the user, if any.
  3. This approach will not consider any user that is not LDAP enabled or does not use LDAP sign in.

MR acceptance checklist

Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Screenshots or screen recordings

Screenshots are required for UI changes, and strongly recommended for all other merge requests.

How to set up and validate locally

  1. This MR works on self-managed instance with LDAP enabled. Please follow this documentation on setting up LDAP in gdk

    1. https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/ldap.md#ldap
  2. Start the gdk on self-managed mode: GITLAB_SIMULATE_SAAS=0 gdk restart

  3. Log in using LDAP with user generated from above setup:

    1. username: john, password: password
    2. username: mary, password: password
  4. This should create new User record and LDAP Identity for these users after login

  5. Open the console and create an add-on purchase: gdk rails c

    Gitlab.com?
    => false
    # If the License doesn't already have Duo add-on create one
    add_on = GitlabSubscriptions::AddOn.find_or_create_by!(name: "duo_enterprise") {|e| e.description = "Test"}
    add_on_purchase = GitlabSubscriptions::AddOnPurchase.create!(
      add_on: add_on, expires_on: 1.year.from_now, quantity: 5, purchase_xid: 'A-S0001',
      started_at: 1.day.ago, organization: Organizations::Organization.first
    )
  6. The list of LDAP groups and membership created during setup can be found in the doc:

    1. https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/ldap.md#ldap-groups

    2. Update the config/gitlab.yml file to set the duo_add_on_groups with group2 --> only john is memberOf

        ldap:
          enabled: true
          servers:
            main: # 'main' is the GitLab 'provider ID' of this LDAP server
              base: 'dc=example,dc=com'
              group_base: 'ou=groups,dc=example,dc=com'
              duo_add_on_groups: ['group2']
    3. Restart: gdk restart

  7. Check that duo_add_on_groups has been set correctly

     Gitlab.config.ldap.servers.values.first['duo_add_on_groups']
    => ["group2"]
  8. Sign out and login to ldapmain as john

  9. The seat assignments should have been created. It may take some time for the LdapAddOnSeatSyncWorker to be processed in queue.

    1. Try gdk restart redis rails-background-jobs if the job doesn't get processed

      add_on_purchase = GitlabSubscriptions::AddOnPurchase.where(namespace_id: nil).last
      add_on_purchase.assigned_users # user john should have record
  10. Sign out and login as mary, no seat assignment will be created.

    add_on_purchase.assigned_users # no change
  11. Alternatively, you can run the worker directly

    add_on_purchase = GitlabSubscriptions::AddOnPurchase.where(namespace_id: nil).last
    add_on_purchase.assigned_users.destroy_all # destroy all records
    
    user_john = User.find_by_username("john") # find the LDAP user john
    
    GitlabSubscriptions::AddOnPurchases::LdapAddOnSeatSyncWorker.new.perform({'user_id' => user_john.id}) # Run the worker
    # Seat for john has been created
    add_on_purchase.reload.assigned_users.map(&:user) # john should have seat => [#<User id:110 @john>]
    
    # create a seat for mary, by hand, to test seat removal
    user_mary = User.find_by_username("mary")
    add_on_purchase.assigned_users.create!(user: user_mary)
    add_on_purchase.reload.assigned_users.map(&:user) # => [#<User id:110 @john>, #<User id:111 @Mary>]
    
    # Now, run the worker for Mary
    GitlabSubscriptions::AddOnPurchases::LdapAddOnSeatSyncWorker.new.perform({'user_id' => user_mary.id})
    
    # Mary seat has been removed
    add_on_purchase.reload.assigned_users.map(&:user) # => [#<User id:110 @john>]

Related to #506884

Edited by Bishwa Hang Rai

Merge request reports

Loading