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.
- Product requirement: #503746 (comment 2237993956)
- Blueprint : Duo Add-on seat assignment via LDAP (#507449 - closed)
- MR issue: https://gitlab.com/gitlab-org/gitlab/-/issues/506884+
Summary:
- When the
duo_add_on_groupis set, it will be "Single Source of Truth" for "All LDAP enabled user". - Whenever a
usersigns in via LDAP, we check if the user is a member of theduo_add_on_groupin LDAP server- If the
user, is member of theduo_add_on_group, we assign user aDuo Seat, if not already assigned. - If
useris not member of anyduo_add_on_groupserver, we remove theDuo Seatof theuser, if any.
- If the
- 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
-
This MR works on self-managed instance with LDAP enabled. Please follow this documentation on setting up LDAP in gdk
-
Start the
gdkon self-managed mode:GITLAB_SIMULATE_SAAS=0 gdk restart -
Log in using
LDAPwithusergenerated from above setup:username: john, password: passwordusername: mary, password: password
-
This should create new User record and LDAP Identity for these users after login
-
Open the console and create an add-on purchase:
gdk rails cGitlab.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 ) -
The list of LDAP groups and membership created during setup can be found in the doc:
-
https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/ldap.md#ldap-groups
-
Update the
config/gitlab.ymlfile to set theduo_add_on_groupswithgroup2--> onlyjohnis memberOfldap: 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'] -
Restart:
gdk restart
-
-
Check that
duo_add_on_groupshas been set correctlyGitlab.config.ldap.servers.values.first['duo_add_on_groups'] => ["group2"] -
Sign out and login to
ldapmainasjohn -
The
seat assignmentsshould have been created. It may take some time for theLdapAddOnSeatSyncWorkerto be processed in queue.-
Try
gdk restart redis rails-background-jobsif the job doesn't get processedadd_on_purchase = GitlabSubscriptions::AddOnPurchase.where(namespace_id: nil).last add_on_purchase.assigned_users # user john should have record
-
-
Sign out and login as
mary, no seat assignment will be created.add_on_purchase.assigned_users # no change -
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