Commit 35f094b0 authored by Robert Speicher's avatar Robert Speicher

Merge branch 'dm-ldap-group-sync-filter-eep' into 'master'

Only enable LDAP group sync filter method on EEP

Closes #3698

See merge request gitlab-org/gitlab-ee!3106
parents 8061d73c 2dae609e
...@@ -2,6 +2,8 @@ document.addEventListener('DOMContentLoaded', () => { ...@@ -2,6 +2,8 @@ document.addEventListener('DOMContentLoaded', () => {
const showGroupLink = () => { const showGroupLink = () => {
const $cnLink = $('.cn-link'); const $cnLink = $('.cn-link');
const $filterLink = $('.filter-link'); const $filterLink = $('.filter-link');
if (!$cnLink.length || !$filterLink.length) return;
const $checkedSync = $('input[name="sync_method"]:checked').val() === 'group'; const $checkedSync = $('input[name="sync_method"]:checked').val() === 'group';
$cnLink.toggle($checkedSync); $cnLink.toggle($checkedSync);
......
...@@ -43,6 +43,9 @@ class Groups::LdapGroupLinksController < Groups::ApplicationController ...@@ -43,6 +43,9 @@ class Groups::LdapGroupLinksController < Groups::ApplicationController
end end
def ldap_group_link_params def ldap_group_link_params
params.require(:ldap_group_link).permit(:cn, :filter, :group_access, :provider) attrs = %i[cn group_access provider]
attrs << :filter if ::License.feature_available?(:ldap_group_sync_filter)
params.require(:ldap_group_link).permit(attrs)
end end
end end
...@@ -17,6 +17,6 @@ class Groups::LdapsController < Groups::ApplicationController ...@@ -17,6 +17,6 @@ class Groups::LdapsController < Groups::ApplicationController
private private
def check_enabled_extras! def check_enabled_extras!
render_404 unless Gitlab::LDAP::Config.enabled_extras? render_404 unless Gitlab::LDAP::Config.group_sync_enabled?
end end
end end
...@@ -230,20 +230,12 @@ class Group < Namespace ...@@ -230,20 +230,12 @@ class Group < Namespace
ldap_group_links.first.try(:cn) ldap_group_links.first.try(:cn)
end end
def ldap_filter
ldap_group_links.first.try(:filter)
end
def ldap_access def ldap_access
ldap_group_links.first.try(:group_access) ldap_group_links.first.try(:group_access)
end end
def ldap_cn_or_filter_present?
ldap_cn.present? || ldap_filter.present?
end
def ldap_synced? def ldap_synced?
Gitlab.config.ldap.enabled && ldap_cn_or_filter_present? Gitlab.config.ldap.enabled && ldap_group_links.any?(&:active?)
end end
def post_create_hook def post_create_hook
......
...@@ -43,6 +43,14 @@ class LdapGroupLink < ActiveRecord::Base ...@@ -43,6 +43,14 @@ class LdapGroupLink < ActiveRecord::Base
config.label config.label
end end
def active?
if filter.present?
::License.feature_available?(:ldap_group_sync_filter)
elsif cn.present?
::License.feature_available?(:ldap_group_sync)
end
end
private private
def nullify_blank_attributes def nullify_blank_attributes
......
...@@ -18,10 +18,11 @@ class License < ActiveRecord::Base ...@@ -18,10 +18,11 @@ class License < ActiveRecord::Base
issue_board_milestone issue_board_milestone
issue_weights issue_weights
jenkins_integration jenkins_integration
ldap_extras ldap_group_sync
merge_request_approvers merge_request_approvers
merge_request_rebase merge_request_rebase
merge_request_squash merge_request_squash
multiple_ldap_servers
multiple_issue_assignees multiple_issue_assignees
multiple_issue_boards multiple_issue_boards
push_rules push_rules
...@@ -42,6 +43,7 @@ class License < ActiveRecord::Base ...@@ -42,6 +43,7 @@ class License < ActiveRecord::Base
geo geo
group_issue_boards group_issue_boards
jira_dev_panel_integration jira_dev_panel_integration
ldap_group_sync_filter
object_storage object_storage
service_desk service_desk
variable_environment_scope variable_environment_scope
...@@ -108,7 +110,9 @@ class License < ActiveRecord::Base ...@@ -108,7 +110,9 @@ class License < ActiveRecord::Base
elastic_search elastic_search
extended_audit_events extended_audit_events
geo geo
ldap_extras ldap_group_sync
ldap_group_sync_filter
multiple_ldap_servers
object_storage object_storage
repository_size_limit repository_size_limit
].freeze ].freeze
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
= f.submit 'Save changes', class: "btn btn-save" = f.submit 'Save changes', class: "btn btn-save"
= link_to 'Cancel', admin_group_path(@group), class: "btn btn-cancel" = link_to 'Cancel', admin_group_path(@group), class: "btn btn-cancel"
- if ldap_enabled? && @group.persisted? - if @group.persisted? && Gitlab::LDAP::Config.group_sync_enabled?
%h3.page-title LDAP synchronizations %h3.page-title LDAP synchronizations
= render 'ldap_group_links/form', group: @group = render 'ldap_group_links/form', group: @group
= render 'ldap_group_links/ldap_group_links', group: @group = render 'ldap_group_links/ldap_group_links', group: @group
...@@ -62,11 +62,11 @@ ...@@ -62,11 +62,11 @@
= render partial: "namespaces/shared_runner_status", locals: { namespace: @group } = render partial: "namespaces/shared_runner_status", locals: { namespace: @group }
.panel.panel-default - if Gitlab::LDAP::Config.group_sync_enabled? && @group.ldap_synced?
.panel-heading Active synchronizations .panel.panel-default
%ul.well-list .panel-heading Active synchronizations
- if @group.ldap_group_links.any? %ul.well-list
- @group.ldap_group_links.each do |ldap_group_link| - @group.ldap_group_links.select(&:active?).each do |ldap_group_link|
%li %li
%strong= ldap_group_link.cn ? "Group: #{ldap_group_link.cn}" : "Filter: #{truncate(ldap_group_link.filter, length: 40)}" %strong= ldap_group_link.cn ? "Group: #{ldap_group_link.cn}" : "Filter: #{truncate(ldap_group_link.filter, length: 40)}"
as as
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
The members of this group are managed using LDAP and cannot be added or removed here. The members of this group are managed using LDAP and cannot be added or removed here.
Because LDAP permissions in GitLab get updated one user at a time and because GitLab caches LDAP check results, changes on your LDAP server or in this group's LDAP sync settings may take up to #{Gitlab.config.ldap['sync_time']}s to show in the list below. Because LDAP permissions in GitLab get updated one user at a time and because GitLab caches LDAP check results, changes on your LDAP server or in this group's LDAP sync settings may take up to #{Gitlab.config.ldap['sync_time']}s to show in the list below.
%ul %ul
- @group.ldap_group_links.each do |ldap_group_link| - @group.ldap_group_links.select(&:active?).each do |ldap_group_link|
%li %li
People in People in
%code= ldap_group_link.cn ? "cn: #{ldap_group_link.cn}" : "filter: #{truncate(ldap_group_link.filter, length: 70)}" %code= ldap_group_link.cn ? "cn: #{ldap_group_link.cn}" : "filter: #{truncate(ldap_group_link.filter, length: 70)}"
......
- page_title 'LDAP Syncrhonizations' - page_title 'LDAP Synchronization'
%h3.page-title LDAP synchronizations %h3.page-title LDAP synchronizations
= render 'ldap_group_links/form', group: @group = render 'ldap_group_links/form', group: @group
= render 'ldap_group_links/ldap_group_links', group: @group = render 'ldap_group_links/ldap_group_links', group: @group
...@@ -9,18 +9,19 @@ ...@@ -9,18 +9,19 @@
.col-sm-10 .col-sm-10
= f.select :provider, ldap_server_select_options, {}, class: 'form-control' = f.select :provider, ldap_server_select_options, {}, class: 'form-control'
.form-group.row - if ::License.feature_available?(:ldap_group_sync_filter)
= f.label :cn, class: 'control-label col-sm-2' do .form-group.row
Sync method = f.label :cn, class: 'control-label col-sm-2' do
.col-sm-10 Sync method
.radio .col-sm-10
= label_tag :sync_method_group do .radio
= radio_button_tag :sync_method, :group, true = label_tag :sync_method_group do
LDAP Group cn = radio_button_tag :sync_method, :group, true
.radio LDAP Group cn
= label_tag :sync_method_filter do .radio
= radio_button_tag :sync_method, :filter = label_tag :sync_method_filter do
LDAP user filter = radio_button_tag :sync_method, :filter
LDAP user filter
.form-group.row.cn-link .form-group.row.cn-link
= f.label :cn, class: 'control-label col-sm-2' do = f.label :cn, class: 'control-label col-sm-2' do
...@@ -32,16 +33,17 @@ ...@@ -32,16 +33,17 @@
%br %br
If you select an LDAP group you do not belong to you will lose ownership of #{group.name}. If you select an LDAP group you do not belong to you will lose ownership of #{group.name}.
.form-group.row.filter-link - if ::License.feature_available?(:ldap_group_sync_filter)
= f.label :filter, class: 'control-label col-sm-2' do .form-group.row.filter-link
LDAP User filter = f.label :filter, class: 'control-label col-sm-2' do
.col-sm-10 LDAP User filter
= f.text_field :filter, placeholder: 'Ex. (&(objectCategory=person)(objectClass=developer))', class: 'form-control xxlarge input-mn-300' .col-sm-10
.help-block = f.text_field :filter, placeholder: 'Ex. (&(objectCategory=person)(objectClass=developer))', class: 'form-control xxlarge input-mn-300'
- ldap_link = link_to 'LDAP Search Filter Syntax', 'https://msdn.microsoft.com/en-us/library/aa746475(v=vs.85).aspx' .help-block
This query must use valid #{ldap_link}. Synchronize #{group.name}'s members with this LDAP user filter. - ldap_link = link_to 'LDAP Search Filter Syntax', 'https://msdn.microsoft.com/en-us/library/aa746475(v=vs.85).aspx'
%br This query must use valid #{ldap_link}. Synchronize #{group.name}'s members with this LDAP user filter.
If you do not belong to this LDAP user filter you will lose ownership of #{group.name}. %br
If you do not belong to this LDAP user filter you will lose ownership of #{group.name}.
.form-group.row .form-group.row
= f.label :group_access, class: 'control-label col-sm-2' do = f.label :group_access, class: 'control-label col-sm-2' do
......
...@@ -13,3 +13,6 @@ ...@@ -13,3 +13,6 @@
Config for LDAP server Config for LDAP server
%code= ldap_group_link.provider %code= ldap_group_link.provider
is not present in GitLab is not present in GitLab
- unless ldap_group_link.active?
(Inactive because syncing with an LDAP user filter is not included in the current license)
...@@ -3,7 +3,7 @@ class LdapAllGroupsSyncWorker ...@@ -3,7 +3,7 @@ class LdapAllGroupsSyncWorker
include CronjobQueue include CronjobQueue
def perform def perform
return unless Gitlab::LDAP::Config.enabled_extras? return unless Gitlab::LDAP::Config.group_sync_enabled?
logger.info 'Started LDAP group sync' logger.info 'Started LDAP group sync'
EE::Gitlab::LDAP::Sync::Groups.execute EE::Gitlab::LDAP::Sync::Groups.execute
......
...@@ -3,7 +3,7 @@ class LdapGroupSyncWorker ...@@ -3,7 +3,7 @@ class LdapGroupSyncWorker
include DedicatedSidekiqQueue include DedicatedSidekiqQueue
def perform(group_ids, provider = nil) def perform(group_ids, provider = nil)
return unless Gitlab::LDAP::Config.enabled_extras? return unless Gitlab::LDAP::Config.group_sync_enabled?
groups = Group.where(id: Array(group_ids)) groups = Group.where(id: Array(group_ids))
......
...@@ -3,7 +3,7 @@ class LdapSyncWorker ...@@ -3,7 +3,7 @@ class LdapSyncWorker
include CronjobQueue include CronjobQueue
def perform def perform
return unless Gitlab::LDAP::Config.enabled_extras? return unless Gitlab::LDAP::Config.group_sync_enabled?
Rails.logger.info "Performing daily LDAP sync task." Rails.logger.info "Performing daily LDAP sync task."
User.ldap.find_each(batch_size: 100).each do |ldap_user| User.ldap.find_each(batch_size: 100).each do |ldap_user|
......
...@@ -20,7 +20,7 @@ membership syncing. ...@@ -20,7 +20,7 @@ membership syncing.
## Use-cases ## Use-cases
- User Sync: Once a day, GitLab will update users against LDAP - User Sync: Once a day, GitLab will update users against LDAP
- Group Sync: Once an hour, GitLab will update group membership - Group Sync: Once an hour, GitLab will update group membership
based on LDAP group members based on LDAP group members
## User Sync ## User Sync
...@@ -54,8 +54,8 @@ new groups they might be added to when the user logs in. That way they don't nee ...@@ -54,8 +54,8 @@ new groups they might be added to when the user logs in. That way they don't nee
to wait for the hourly sync to be granted access to the groups that they are in to wait for the hourly sync to be granted access to the groups that they are in
in LDAP. in LDAP.
We can also add a GitLab group to sync with one or multiple LDAP groups or we can In GitLab Enterprise Edition Premium, we can also add a GitLab group to sync with one or multiple LDAP groups or we can
also add a filter. The filter must comply with the syntax defined in [RFC 2254](https://tools.ietf.org/search/rfc2254). also add a filter. The filter must comply with the syntax defined in [RFC 2254](https://tools.ietf.org/search/rfc2254).
A group sync process will run every hour on the hour, and `group_base` must be set A group sync process will run every hour on the hour, and `group_base` must be set
in LDAP configuration for LDAP synchronizations based on group CN to work. This allows in LDAP configuration for LDAP synchronizations based on group CN to work. This allows
......
- if Gitlab::LDAP::Config.enabled_extras? && can?(current_user, :admin_ldap_group_links, @group) - if Gitlab::LDAP::Config.group_sync_enabled? && can?(current_user, :admin_ldap_group_links, @group)
= nav_link(path: 'ldap_group_links#index') do = nav_link(path: 'ldap_group_links#index') do
= link_to group_ldap_group_links_path(@group), title: 'LDAP Group' do = link_to group_ldap_group_links_path(@group), title: 'LDAP Group' do
%span %span
LDAP Group LDAP Synchronization
- if @group.feature_available?(:group_webhooks) || show_promotions? - if @group.feature_available?(:group_webhooks) || show_promotions?
= nav_link(path: 'hooks#index') do = nav_link(path: 'hooks#index') do
......
...@@ -5,8 +5,8 @@ module EE ...@@ -5,8 +5,8 @@ module EE
extend ActiveSupport::Concern extend ActiveSupport::Concern
class_methods do class_methods do
def enabled_extras? def group_sync_enabled?
enabled? && ::License.feature_available?(:ldap_extras) enabled? && ::License.feature_available?(:ldap_group_sync)
end end
end end
end end
......
...@@ -74,6 +74,8 @@ module EE ...@@ -74,6 +74,8 @@ module EE
access_levels = AccessLevels.new access_levels = AccessLevels.new
# Only iterate over group links for the current provider # Only iterate over group links for the current provider
group.ldap_group_links.with_provider(provider).each do |group_link| group.ldap_group_links.with_provider(provider).each do |group_link|
next unless group_link.active?
update_access_levels(access_levels, group_link) update_access_levels(access_levels, group_link)
end end
......
...@@ -213,7 +213,7 @@ module API ...@@ -213,7 +213,7 @@ module API
desc 'Sync a group with LDAP.' desc 'Sync a group with LDAP.'
post ":id/ldap_sync" do post ":id/ldap_sync" do
not_found! unless Gitlab::LDAP::Config.enabled_extras? not_found! unless Gitlab::LDAP::Config.group_sync_enabled?
group = find_group!(params[:id]) group = find_group!(params[:id])
authorize! :admin_group, group authorize! :admin_group, group
......
...@@ -27,7 +27,7 @@ module Gitlab ...@@ -27,7 +27,7 @@ module Gitlab
def self.available_servers def self.available_servers
return [] unless enabled? return [] unless enabled?
enabled_extras? ? servers : Array.wrap(servers.first) ::License.feature_available?(:multiple_ldap_servers) ? servers : Array.wrap(servers.first)
end end
def self.providers def self.providers
......
...@@ -381,6 +381,10 @@ describe EE::Gitlab::LDAP::Sync::Group do ...@@ -381,6 +381,10 @@ describe EE::Gitlab::LDAP::Sync::Group do
end end
context 'filter' do context 'filter' do
before do
stub_licensed_features(ldap_group_sync_filter: true)
end
describe '#update_permissions' do describe '#update_permissions' do
before do before do
# Safe-check because some permissions are removed when `Group#ldap_synced?` # Safe-check because some permissions are removed when `Group#ldap_synced?`
......
...@@ -19,7 +19,7 @@ feature 'Edit group settings' do ...@@ -19,7 +19,7 @@ feature 'Edit group settings' do
scenario 'is able to navigate to LDAP group section' do scenario 'is able to navigate to LDAP group section' do
visit edit_group_path(group) visit edit_group_path(group)
expect(find('.nav-sidebar')).to have_content('LDAP Group') expect(find('.nav-sidebar')).to have_content('LDAP Synchronization')
end end
context 'with owners not being able to manage LDAP' do context 'with owners not being able to manage LDAP' do
...@@ -28,7 +28,7 @@ feature 'Edit group settings' do ...@@ -28,7 +28,7 @@ feature 'Edit group settings' do
visit edit_group_path(group) visit edit_group_path(group)
expect(find('.nav-sidebar')).not_to have_content('LDAP Group') expect(find('.nav-sidebar')).not_to have_content('LDAP Synchronization')
end end
end end
end end
......
...@@ -12,23 +12,49 @@ feature 'Edit group settings', :js do ...@@ -12,23 +12,49 @@ feature 'Edit group settings', :js do
context 'LDAP sync method' do context 'LDAP sync method' do
before do before do
allow(Gitlab.config.ldap).to receive(:enabled).and_return(true) allow(Gitlab.config.ldap).to receive(:enabled).and_return(true)
visit group_ldap_group_links_path(group)
end end
scenario 'shows the LDAP filter section' do context 'when the LDAP group sync filter feature is available' do
choose('sync_method_filter') before do
stub_licensed_features(ldap_group_sync_filter: true)
visit group_ldap_group_links_path(group)
end
scenario 'shows the LDAP filter section' do
choose('sync_method_filter')
expect(page).to have_content('This query must use valid LDAP Search Filter Syntax')
expect(page).not_to have_content("Synchronize #{group.name}'s members with this LDAP group")
end
expect(page).to have_content('This query must use valid LDAP Search Filter Syntax') scenario 'shows the LDAP group section' do
expect(page).not_to have_content("Synchronize #{group.name}'s members with this LDAP group") choose('sync_method_filter') # choose filter first, as group's the default
choose('sync_method_group')
expect(page).to have_content("Synchronize #{group.name}'s members with this LDAP group")
expect(page).not_to have_content('This query must use valid LDAP Search Filter Syntax')
end
end end
scenario 'shows the LDAP group section' do context 'when the LDAP group sync filter feature is available' do
choose('sync_method_filter') # choose filter first, as group's the default before do
choose('sync_method_group') stub_licensed_features(ldap_group_sync_filter: false)
visit group_ldap_group_links_path(group)
end
scenario 'does not show the LDAP search method switcher' do
expect(page).not_to have_field('sync_method_filter')
end
scenario 'shows the LDAP group section' do
expect(page).to have_content("Synchronize #{group.name}'s members with this LDAP group")
end
expect(page).to have_content("Synchronize #{group.name}'s members with this LDAP group") scenario 'does not shows the LDAP filter section' do
expect(page).not_to have_content('This query must use valid LDAP Search Filter Syntax') expect(page).not_to have_content('This query must use valid LDAP Search Filter Syntax')
end
end end
end end
end end
...@@ -700,9 +700,13 @@ describe API::Groups do ...@@ -700,9 +700,13 @@ describe API::Groups do
end end
describe 'POST /groups/:id/ldap_sync' do describe 'POST /groups/:id/ldap_sync' do
context 'when LDAP config enabled_extras is true' do before do
allow(Gitlab::LDAP::Config).to receive(:enabled?).and_return(true)
end
context 'when the ldap_group_sync feature is available' do
before do before do
allow(Gitlab::LDAP::Config).to receive(:enabled_extras?).and_return(true) stub_licensed_features(ldap_group_sync: true)
end end
context 'when authenticated as the group owner' do context 'when authenticated as the group owner' do
...@@ -772,9 +776,9 @@ describe API::Groups do ...@@ -772,9 +776,9 @@ describe API::Groups do
end end
end end
context 'when LDAP config enabled_extras is false' do context 'when the ldap_group_sync feature is not available' do
before do before do
allow(Gitlab::LDAP::Config).to receive(:enabled_extras?).and_return(false) stub_licensed_features(ldap_group_sync: false)
end end
it 'returns 404 (same as CE would)' do it 'returns 404 (same as CE would)' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment