Commit a8298021 authored by Rémy Coutable's avatar Rémy Coutable

Extract EE-specific lines to EE::Gitlab::Auth::LDAP::Access

Signed-off-by: default avatarRémy Coutable <remy@rymai.me>
parent a9f0b56c
module EE
module Gitlab
module Auth
module LDAP
module Access
extend ActiveSupport::Concern
extend ::Gitlab::Utils::Override
override :find_ldap_user
def find_ldap_user
found_user = super
return found_user if found_user
if ldap_identity
::Gitlab::Auth::LDAP::Person.find_by_email(user.email, adapter)
end
end
override :update_user
def update_user
update_email
update_memberships
update_identity
update_ssh_keys if sync_ssh_keys?
update_kerberos_identity if import_kerberos_identities?
end
# Update user ssh keys if they changed in LDAP
def update_ssh_keys
remove_old_ssh_keys
add_new_ssh_keys
end
# Add ssh keys that are in LDAP but not in GitLab
def add_new_ssh_keys
keys = ldap_user.ssh_keys - user.keys.ldap.pluck(:key)
keys.each do |key|
::Rails.logger.info "#{self.class.name}: adding LDAP SSH key #{key.inspect} to #{user.name} (#{user.id})"
new_key = ::LDAPKey.new(title: "LDAP - #{ldap_config.sync_ssh_keys}", key: key)
new_key.user = user
unless new_key.save
::Rails.logger.error "#{self.class.name}: failed to add LDAP SSH key #{key.inspect} to #{user.name} (#{user.id})\n"\
"error messages: #{new_key.errors.messages}"
end
end
end
# Remove ssh keys that do not exist in LDAP any more
def remove_old_ssh_keys
keys = user.keys.ldap.where.not(key: ldap_user.ssh_keys)
keys.each do |deleted_key|
::Rails.logger.info "#{self.class.name}: removing LDAP SSH key #{deleted_key.key} from #{user.name} (#{user.id})"
unless deleted_key.destroy
::Rails.logger.error "#{self.class.name}: failed to remove LDAP SSH key #{key.inspect} from #{user.name} (#{user.id})"
end
end
end
# Update user Kerberos identity with Kerberos principal name from Active Directory
def update_kerberos_identity
# there can be only one Kerberos identity in GitLab; if the user has a Kerberos identity in AD,
# replace any existing Kerberos identity for the user
return unless ldap_user.kerberos_principal.present?
kerberos_identity = user.identities.where(provider: :kerberos).first
return if kerberos_identity && kerberos_identity.extern_uid == ldap_user.kerberos_principal
kerberos_identity ||= ::Identity.new(provider: :kerberos, user: user)
kerberos_identity.extern_uid = ldap_user.kerberos_principal
unless kerberos_identity.save
::Rails.logger.error "#{self.class.name}: failed to add Kerberos principal #{principal} to #{user.name} (#{user.id})\n"\
"error messages: #{new_identity.errors.messages}"
end
end
# Update user email if it changed in LDAP
def update_email
return false unless ldap_user.try(:email)
ldap_email = ldap_user.email.last.to_s.downcase
return false if user.email == ldap_email
::Users::UpdateService.new(user, user: user, email: ldap_email).execute do |user|
user.skip_reconfirmation!
end
end
def update_identity
return if ldap_user.dn.empty? || ldap_user.dn == ldap_identity.extern_uid
unless ldap_identity.update(extern_uid: ldap_user.dn)
::Rails.logger.error "Could not update DN for #{user.name} (#{user.id})\n"\
"error messages: #{user.ldap_identity.errors.messages}"
end
end
delegate :sync_ssh_keys?, to: :ldap_config
def import_kerberos_identities?
# Kerberos may be enabled for Git HTTP access and/or as an Omniauth provider
ldap_config.active_directory && (::Gitlab.config.kerberos.enabled || ::AuthHelper.kerberos_enabled? )
end
def update_memberships
return if ldap_user.nil? || ldap_user.group_cns.empty?
group_ids = ::LdapGroupLink.where(cn: ldap_user.group_cns, provider: provider)
.distinct(:group_id)
.pluck(:group_id)
::LdapGroupSyncWorker.perform_async(group_ids, provider) if group_ids.any?
end
end
end
end
end
end
require 'spec_helper'
describe Gitlab::Auth::LDAP::Access do
include LdapHelpers
let(:access) { described_class.new user }
let(:user) { create(:omniauth_user) }
describe '#find_ldap_user' do
it 'finds a user by email if the email came from LDAP' do
expect(Gitlab::Auth::LDAP::Person).to receive(:find_by_dn).and_return(nil)
expect(Gitlab::Auth::LDAP::Person).to receive(:find_by_email)
access.find_ldap_user
end
end
describe '#allowed?' do
subject { access.allowed? }
context 'when the user cannot be found' do
before do
allow(Gitlab::Auth::LDAP::Person).to receive(:find_by_dn).and_return(nil)
allow(Gitlab::Auth::LDAP::Person).to receive(:find_by_email).and_return(nil)
end
context 'when looking for a user by email' do
let(:user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'my-provider') }
it { is_expected.to be_falsey }
end
end
end
describe '#update_user' do
subject { access.update_user }
let(:entry) do
Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com")
end
before do
allow(access).to(
receive_messages(
ldap_user: Gitlab::Auth::LDAP::Person.new(entry, user.ldap_identity.provider)
)
)
end
it 'updates email address' do
expect(access).to receive(:update_email).once
subject
end
it 'updates the group memberships' do
expect(access).to receive(:update_memberships).once
subject
end
it 'syncs ssh keys if enabled by configuration' do
allow(access).to receive_messages(group_base: '', sync_ssh_keys?: true)
expect(access).to receive(:update_ssh_keys).once
subject
end
it 'update_kerberos_identity' do
allow(access).to receive_messages(import_kerberos_identities?: true)
expect(access).to receive(:update_kerberos_identity).once
subject
end
it 'updates the ldap identity' do
expect(access).to receive(:update_identity)
subject
end
end
describe '#update_kerberos_identity' do
let(:entry) do
Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com")
end
before do
allow(access).to receive_messages(ldap_user: Gitlab::Auth::LDAP::Person.new(entry, user.ldap_identity.provider))
end
it "adds a Kerberos identity if it is in Active Directory but not in GitLab" do
allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: "mylogin@FOO.COM")
expect { access.update_kerberos_identity }.to change(user.identities.where(provider: :kerberos), :count).from(0).to(1)
expect(user.identities.where(provider: "kerberos").last.extern_uid).to eq("mylogin@FOO.COM")
end
it "updates existing Kerberos identity in GitLab if Active Directory has a different one" do
allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: "otherlogin@BAR.COM")
user.identities.build(provider: "kerberos", extern_uid: "mylogin@FOO.COM").save
expect { access.update_kerberos_identity }.not_to change(user.identities.where(provider: "kerberos"), :count)
expect(user.identities.where(provider: "kerberos").last.extern_uid).to eq("otherlogin@BAR.COM")
end
it "does not remove Kerberos identities from GitLab if they are none in the LDAP provider" do
allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: nil)
user.identities.build(provider: "kerberos", extern_uid: "otherlogin@BAR.COM").save
expect { access.update_kerberos_identity }.not_to change(user.identities.where(provider: "kerberos"), :count)
expect(user.identities.where(provider: "kerberos").last.extern_uid).to eq("otherlogin@BAR.COM")
end
it "does not modify identities in GitLab if they are no kerberos principal in the LDAP provider" do
allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: nil)
expect { access.update_kerberos_identity }.not_to change(user.identities, :count)
end
end
describe '#update_ssh_keys' do
let(:ssh_key) { "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCrSQHff6a1rMqBdHFt+FwIbytMZ+hJKN3KLkTtOWtSvNIriGhnTdn4rs+tjD/w+z+revytyWnMDM9dS7J8vQi006B16+hc9Xf82crqRoPRDnBytgAFFQY1G/55ql2zdfsC5yvpDOFzuwIJq5dNGsojS82t6HNmmKPq130fzsenFnj5v1pl3OJvk513oduUyKiZBGTroWTn7H/eOPtu7s9MD7pAdEjqYKFLeaKmyidiLmLqQlCRj3Tl2U9oyFg4PYNc0bL5FZJ/Z6t0Ds3i/a2RanQiKxrvgu3GSnUKMx7WIX373baL4jeM7cprRGiOY/1NcS+1cAjfJ8oaxQF/1dYj" }
let(:ssh_key_attribute_name) { 'altSecurityIdentities' }
let(:entry) do
Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com\n#{ssh_key_attribute_name}: SSHKey:#{ssh_key}\n#{ssh_key_attribute_name}: KerberosKey:bogus")
end
before do
allow_any_instance_of(Gitlab::Auth::LDAP::Config).to receive_messages(sync_ssh_keys: ssh_key_attribute_name)
allow(access).to receive_messages(sync_ssh_keys?: true)
end
it "adds a SSH key if it is in LDAP but not in gitlab" do
allow_any_instance_of(Gitlab::Auth::LDAP::Adapter).to receive(:user) { Gitlab::Auth::LDAP::Person.new(entry, 'ldapmain') }
expect { access.update_ssh_keys }.to change(user.keys, :count).from(0).to(1)
end
it "adds a SSH key and give it a proper name" do
allow_any_instance_of(Gitlab::Auth::LDAP::Adapter).to receive(:user) { Gitlab::Auth::LDAP::Person.new(entry, 'ldapmain') }
access.update_ssh_keys
expect(user.keys.last.title).to match(/LDAP/)
expect(user.keys.last.title).to match(/#{access.ldap_config.sync_ssh_keys}/)
end
it "does not add a SSH key if it is invalid" do
entry = Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com\n#{ssh_key_attribute_name}: I am not a valid key")
allow_any_instance_of(Gitlab::Auth::LDAP::Adapter).to receive(:user) { Gitlab::Auth::LDAP::Person.new(entry, 'ldapmain') }
expect { access.update_ssh_keys }.not_to change(user.keys, :count)
end
context 'user has at least one LDAPKey' do
before do
user.keys.ldap.create key: ssh_key, title: 'to be removed'
end
it "removes a SSH key if it is no longer in LDAP" do
entry = Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com\n#{ssh_key_attribute_name}:\n")
allow_any_instance_of(Gitlab::Auth::LDAP::Adapter).to receive(:user) { Gitlab::Auth::LDAP::Person.new(entry, 'ldapmain') }
expect { access.update_ssh_keys }.to change(user.keys, :count).from(1).to(0)
end
it "removes a SSH key if the ldap attribute was removed" do
entry = Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com")
allow_any_instance_of(Gitlab::Auth::LDAP::Adapter).to receive(:user) { Gitlab::Auth::LDAP::Person.new(entry, 'ldapmain') }
expect { access.update_ssh_keys }.to change(user.keys, :count).from(1).to(0)
end
end
end
describe '#update_user_email' do
let(:entry) { Net::LDAP::Entry.new }
before do
allow(access).to receive_messages(ldap_user: Gitlab::Auth::LDAP::Person.new(entry, user.ldap_identity.provider))
end
it "does not update email if email attribute is not set" do
expect { access.update_email }.not_to change(user, :email)
end
it "does not update the email if the user has the same email in GitLab and in LDAP" do
entry['mail'] = [user.email]
expect { access.update_email }.not_to change(user, :email)
end
it "does not update the email if the user has the same email GitLab and in LDAP, but with upper case in LDAP" do
entry['mail'] = [user.email.upcase]
expect { access.update_email }.not_to change(user, :email)
end
it "updates the email if the user email is different" do
entry['mail'] = ["new_email@example.com"]
expect { access.update_email }.to change(user, :email)
end
end
describe '#update_memberships' do
let(:provider) { user.ldap_identity.provider }
let(:entry) { ldap_user_entry(user.ldap_identity.extern_uid) }
let(:person_with_memberof) do
entry['memberof'] = ['CN=Group1,CN=Users,DC=The dc,DC=com',
'CN=Group2,CN=Builtin,DC=The dc,DC=com']
Gitlab::Auth::LDAP::Person.new(entry, provider)
end
it 'triggers a sync for all groups found in `memberof`' do
group_link_1 = create(:ldap_group_link, cn: 'Group1', provider: provider)
group_link_2 = create(:ldap_group_link, cn: 'Group2', provider: provider)
group_ids = [group_link_1, group_link_2].map(&:group_id)
allow(access).to receive(:ldap_user).and_return(person_with_memberof)
expect(LdapGroupSyncWorker).to receive(:perform_async)
.with(a_collection_containing_exactly(*group_ids), provider)
access.update_memberships
end
it "doesn't continue when there is no `memberOf` param" do
allow(access).to receive(:ldap_user)
.and_return(Gitlab::Auth::LDAP::Person.new(entry, provider))
expect(LdapGroupLink).not_to receive(:where)
expect(LdapGroupSyncWorker).not_to receive(:perform_async)
access.update_memberships
end
it "doesn't trigger a sync when there are no links for the provider" do
_another_provider = create(:ldap_group_link,
cn: 'Group1',
provider: 'not-this-ldap')
allow(access).to receive(:ldap_user).and_return(person_with_memberof)
expect(LdapGroupSyncWorker).not_to receive(:perform_async)
access.update_memberships
end
end
describe '#update_identity' do
it 'updates the external UID if it changed in the entry' do
entry = ldap_user_entry('another uid')
provider = user.ldap_identity.provider
person = Gitlab::Auth::LDAP::Person.new(entry, provider)
allow(access).to receive(:ldap_user).and_return(person)
access.update_identity
expect(user.ldap_identity.reload.extern_uid)
.to eq('uid=another uid,ou=users,dc=example,dc=com')
end
end
end
......@@ -6,6 +6,8 @@ module Gitlab
module Auth
module LDAP
class Access
prepend ::EE::Gitlab::Auth::LDAP::Access
attr_reader :provider, :user, :ldap_identity
def self.open(user, &block)
......@@ -33,7 +35,7 @@ module Gitlab
@adapter = adapter
@user = user
@ldap_identity = user.ldap_identity
@provider = adapter&.provider || @ldap_identity&.provider
@provider = adapter&.provider || ldap_identity&.provider
end
def allowed?
......@@ -69,17 +71,12 @@ module Gitlab
end
def find_ldap_user
return unless provider
found_user = Gitlab::Auth::LDAP::Person.find_by_dn(ldap_identity.extern_uid, adapter)
return found_user if found_user
if ldap_identity
Gitlab::Auth::LDAP::Person.find_by_email(user.email, adapter)
end
Gitlab::Auth::LDAP::Person.find_by_dn(ldap_identity.extern_uid, adapter)
end
def ldap_user
return unless provider
@ldap_user ||= find_ldap_user
end
......@@ -109,108 +106,7 @@ module Gitlab
end
def update_user
update_email
update_memberships
update_identity
update_ssh_keys if sync_ssh_keys?
update_kerberos_identity if import_kerberos_identities?
end
# Update user ssh keys if they changed in LDAP
def update_ssh_keys
remove_old_ssh_keys
add_new_ssh_keys
end
# Add ssh keys that are in LDAP but not in GitLab
def add_new_ssh_keys
keys = ldap_user.ssh_keys - user.keys.ldap.pluck(:key)
keys.each do |key|
logger.info "#{self.class.name}: adding LDAP SSH key #{key.inspect} to #{user.name} (#{user.id})"
new_key = LDAPKey.new(title: "LDAP - #{ldap_config.sync_ssh_keys}", key: key)
new_key.user = user
unless new_key.save
logger.error "#{self.class.name}: failed to add LDAP SSH key #{key.inspect} to #{user.name} (#{user.id})\n"\
"error messages: #{new_key.errors.messages}"
end
end
end
# Remove ssh keys that do not exist in LDAP any more
def remove_old_ssh_keys
keys = user.keys.ldap.where.not(key: ldap_user.ssh_keys)
keys.each do |deleted_key|
logger.info "#{self.class.name}: removing LDAP SSH key #{deleted_key.key} from #{user.name} (#{user.id})"
unless deleted_key.destroy
logger.error "#{self.class.name}: failed to remove LDAP SSH key #{key.inspect} from #{user.name} (#{user.id})"
end
end
end
# Update user Kerberos identity with Kerberos principal name from Active Directory
def update_kerberos_identity
# there can be only one Kerberos identity in GitLab; if the user has a Kerberos identity in AD,
# replace any existing Kerberos identity for the user
return unless ldap_user.kerberos_principal.present?
kerberos_identity = user.identities.where(provider: :kerberos).first
return if kerberos_identity && kerberos_identity.extern_uid == ldap_user.kerberos_principal
kerberos_identity ||= Identity.new(provider: :kerberos, user: user)
kerberos_identity.extern_uid = ldap_user.kerberos_principal
unless kerberos_identity.save
Rails.logger.error "#{self.class.name}: failed to add Kerberos principal #{principal} to #{user.name} (#{user.id})\n"\
"error messages: #{new_identity.errors.messages}"
end
end
# Update user email if it changed in LDAP
def update_email
return false unless ldap_user.try(:email)
ldap_email = ldap_user.email.last.to_s.downcase
return false if user.email == ldap_email
Users::UpdateService.new(user, user: user, email: ldap_email).execute do |user|
user.skip_reconfirmation!
end
end
def update_identity
return if ldap_user.dn.empty? || ldap_user.dn == ldap_identity.extern_uid
unless ldap_identity.update(extern_uid: ldap_user.dn)
Rails.logger.error "Could not update DN for #{user.name} (#{user.id})\n"\
"error messages: #{user.ldap_identity.errors.messages}"
end
end
delegate :sync_ssh_keys?, to: :ldap_config
def import_kerberos_identities?
# Kerberos may be enabled for Git HTTP access and/or as an Omniauth provider
ldap_config.active_directory && (Gitlab.config.kerberos.enabled || AuthHelper.kerberos_enabled? )
end
def update_memberships
return if ldap_user.nil? || ldap_user.group_cns.empty?
group_ids = LdapGroupLink.where(cn: ldap_user.group_cns, provider: provider)
.distinct(:group_id)
.pluck(:group_id)
LdapGroupSyncWorker.perform_async(group_ids, provider) if group_ids.any?
end
private
def logger
Rails.logger
# no-op in CE
end
end
end
......
......@@ -23,13 +23,6 @@ describe Gitlab::Auth::LDAP::Access do
access.find_ldap_user
end
it 'finds a user by email if the email came from LDAP' do
expect(Gitlab::Auth::LDAP::Person).to receive(:find_by_dn).and_return(nil)
expect(Gitlab::Auth::LDAP::Person).to receive(:find_by_email)
access.find_ldap_user
end
end
describe '#allowed?' do
......@@ -48,12 +41,6 @@ describe Gitlab::Auth::LDAP::Access do
access.allowed?
end
context 'when looking for a user by email' do
let(:user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'my-provider') }
it { is_expected.to be_falsey }
end
end
context 'when the user is found' do
......@@ -146,34 +133,6 @@ describe Gitlab::Auth::LDAP::Access do
access.allowed?
end
end
context 'when user was previously ldap_blocked' do
before do
user.ldap_block
end
it 'unblocks the user if it exists' do
expect(access).to receive(:unblock_user).with(user, 'is available again')
access.allowed?
end
end
end
end
context 'when the connection fails' do
before do
raise_ldap_connection_error
end
it 'does not block the user' do
access.allowed?
expect(user.ldap_blocked?).to be_falsey
end
it 'denies access' do
expect(access.allowed?).to be_falsey
end
end
......@@ -235,231 +194,4 @@ describe Gitlab::Auth::LDAP::Access do
)
end
end
describe '#update_user' do
subject { access.update_user }
let(:entry) do
Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com")
end
before do
allow(access).to(
receive_messages(
ldap_user: Gitlab::Auth::LDAP::Person.new(entry, user.ldap_identity.provider)
)
)
end
it 'updates email address' do
expect(access).to receive(:update_email).once
subject
end
it 'updates the group memberships' do
expect(access).to receive(:update_memberships).once
subject
end
it 'syncs ssh keys if enabled by configuration' do
allow(access).to receive_messages(group_base: '', sync_ssh_keys?: true)
expect(access).to receive(:update_ssh_keys).once
subject
end
it 'update_kerberos_identity' do
allow(access).to receive_messages(import_kerberos_identities?: true)
expect(access).to receive(:update_kerberos_identity).once
subject
end
it 'updates the ldap identity' do
expect(access).to receive(:update_identity)
subject
end
end
describe '#update_kerberos_identity' do
let(:entry) do
Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com")
end
before do
allow(access).to receive_messages(ldap_user: Gitlab::Auth::LDAP::Person.new(entry, user.ldap_identity.provider))
end
it "adds a Kerberos identity if it is in Active Directory but not in GitLab" do
allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: "mylogin@FOO.COM")
expect { access.update_kerberos_identity }.to change(user.identities.where(provider: :kerberos), :count).from(0).to(1)
expect(user.identities.where(provider: "kerberos").last.extern_uid).to eq("mylogin@FOO.COM")
end
it "updates existing Kerberos identity in GitLab if Active Directory has a different one" do
allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: "otherlogin@BAR.COM")
user.identities.build(provider: "kerberos", extern_uid: "mylogin@FOO.COM").save
expect { access.update_kerberos_identity }.not_to change(user.identities.where(provider: "kerberos"), :count)
expect(user.identities.where(provider: "kerberos").last.extern_uid).to eq("otherlogin@BAR.COM")
end
it "does not remove Kerberos identities from GitLab if they are none in the LDAP provider" do
allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: nil)
user.identities.build(provider: "kerberos", extern_uid: "otherlogin@BAR.COM").save
expect { access.update_kerberos_identity }.not_to change(user.identities.where(provider: "kerberos"), :count)
expect(user.identities.where(provider: "kerberos").last.extern_uid).to eq("otherlogin@BAR.COM")
end
it "does not modify identities in GitLab if they are no kerberos principal in the LDAP provider" do
allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: nil)
expect { access.update_kerberos_identity }.not_to change(user.identities, :count)
end
end
describe '#update_ssh_keys' do
let(:ssh_key) { "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCrSQHff6a1rMqBdHFt+FwIbytMZ+hJKN3KLkTtOWtSvNIriGhnTdn4rs+tjD/w+z+revytyWnMDM9dS7J8vQi006B16+hc9Xf82crqRoPRDnBytgAFFQY1G/55ql2zdfsC5yvpDOFzuwIJq5dNGsojS82t6HNmmKPq130fzsenFnj5v1pl3OJvk513oduUyKiZBGTroWTn7H/eOPtu7s9MD7pAdEjqYKFLeaKmyidiLmLqQlCRj3Tl2U9oyFg4PYNc0bL5FZJ/Z6t0Ds3i/a2RanQiKxrvgu3GSnUKMx7WIX373baL4jeM7cprRGiOY/1NcS+1cAjfJ8oaxQF/1dYj" }
let(:ssh_key_attribute_name) { 'altSecurityIdentities' }
let(:entry) do
Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com\n#{ssh_key_attribute_name}: SSHKey:#{ssh_key}\n#{ssh_key_attribute_name}: KerberosKey:bogus")
end
before do
allow_any_instance_of(Gitlab::Auth::LDAP::Config).to receive_messages(sync_ssh_keys: ssh_key_attribute_name)
allow(access).to receive_messages(sync_ssh_keys?: true)
end
it "adds a SSH key if it is in LDAP but not in gitlab" do
allow_any_instance_of(Gitlab::Auth::LDAP::Adapter).to receive(:user) { Gitlab::Auth::LDAP::Person.new(entry, 'ldapmain') }
expect { access.update_ssh_keys }.to change(user.keys, :count).from(0).to(1)
end
it "adds a SSH key and give it a proper name" do
allow_any_instance_of(Gitlab::Auth::LDAP::Adapter).to receive(:user) { Gitlab::Auth::LDAP::Person.new(entry, 'ldapmain') }
access.update_ssh_keys
expect(user.keys.last.title).to match(/LDAP/)
expect(user.keys.last.title).to match(/#{access.ldap_config.sync_ssh_keys}/)
end
it "does not add a SSH key if it is invalid" do
entry = Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com\n#{ssh_key_attribute_name}: I am not a valid key")
allow_any_instance_of(Gitlab::Auth::LDAP::Adapter).to receive(:user) { Gitlab::Auth::LDAP::Person.new(entry, 'ldapmain') }
expect { access.update_ssh_keys }.not_to change(user.keys, :count)
end
context 'user has at least one LDAPKey' do
before do
user.keys.ldap.create key: ssh_key, title: 'to be removed'
end
it "removes a SSH key if it is no longer in LDAP" do
entry = Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com\n#{ssh_key_attribute_name}:\n")
allow_any_instance_of(Gitlab::Auth::LDAP::Adapter).to receive(:user) { Gitlab::Auth::LDAP::Person.new(entry, 'ldapmain') }
expect { access.update_ssh_keys }.to change(user.keys, :count).from(1).to(0)
end
it "removes a SSH key if the ldap attribute was removed" do
entry = Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com")
allow_any_instance_of(Gitlab::Auth::LDAP::Adapter).to receive(:user) { Gitlab::Auth::LDAP::Person.new(entry, 'ldapmain') }
expect { access.update_ssh_keys }.to change(user.keys, :count).from(1).to(0)
end
end
end
describe '#update_user_email' do
let(:entry) { Net::LDAP::Entry.new }
before do
allow(access).to receive_messages(ldap_user: Gitlab::Auth::LDAP::Person.new(entry, user.ldap_identity.provider))
end
it "does not update email if email attribute is not set" do
expect { access.update_email }.not_to change(user, :email)
end
it "does not update the email if the user has the same email in GitLab and in LDAP" do
entry['mail'] = [user.email]
expect { access.update_email }.not_to change(user, :email)
end
it "does not update the email if the user has the same email GitLab and in LDAP, but with upper case in LDAP" do
entry['mail'] = [user.email.upcase]
expect { access.update_email }.not_to change(user, :email)
end
it "updates the email if the user email is different" do
entry['mail'] = ["new_email@example.com"]
expect { access.update_email }.to change(user, :email)
end
end
describe '#update_memberships' do
let(:provider) { user.ldap_identity.provider }
let(:entry) { ldap_user_entry(user.ldap_identity.extern_uid) }
let(:person_with_memberof) do
entry['memberof'] = ['CN=Group1,CN=Users,DC=The dc,DC=com',
'CN=Group2,CN=Builtin,DC=The dc,DC=com']
Gitlab::Auth::LDAP::Person.new(entry, provider)
end
it 'triggers a sync for all groups found in `memberof`' do
group_link_1 = create(:ldap_group_link, cn: 'Group1', provider: provider)
group_link_2 = create(:ldap_group_link, cn: 'Group2', provider: provider)
group_ids = [group_link_1, group_link_2].map(&:group_id)
allow(access).to receive(:ldap_user).and_return(person_with_memberof)
expect(LdapGroupSyncWorker).to receive(:perform_async)
.with(a_collection_containing_exactly(*group_ids), provider)
access.update_memberships
end
it "doesn't continue when there is no `memberOf` param" do
allow(access).to receive(:ldap_user)
.and_return(Gitlab::Auth::LDAP::Person.new(entry, provider))
expect(LdapGroupLink).not_to receive(:where)
expect(LdapGroupSyncWorker).not_to receive(:perform_async)
access.update_memberships
end
it "doesn't trigger a sync when there are no links for the provider" do
_another_provider = create(:ldap_group_link,
cn: 'Group1',
provider: 'not-this-ldap')
allow(access).to receive(:ldap_user).and_return(person_with_memberof)
expect(LdapGroupSyncWorker).not_to receive(:perform_async)
access.update_memberships
end
end
describe '#update_identity' do
it 'updates the external UID if it changed in the entry' do
entry = ldap_user_entry('another uid')
provider = user.ldap_identity.provider
person = Gitlab::Auth::LDAP::Person.new(entry, provider)
allow(access).to receive(:ldap_user).and_return(person)
access.update_identity
expect(user.ldap_identity.reload.extern_uid)
.to eq('uid=another uid,ou=users,dc=example,dc=com')
end
end
end
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