Commit e02f4141 authored by Stan Hu's avatar Stan Hu

Merge branch...

Merge branch '7309-geo-secondary-with-ldap-configured-can-t-update-last_credential_check_at-due-to-read-only-db' into 'master'

Resolve "Geo:  Secondary with LDAP configured can't update last_credential_check_at due to read-only DB"

Closes #7309

See merge request gitlab-org/gitlab-ee!6965
parents 963faeee 06809f6d
---
title: LDAP - Does not update permissions on a read-only database
merge_request: 6965
author:
type: fixed
...@@ -6,6 +6,19 @@ module EE ...@@ -6,6 +6,19 @@ module EE
extend ActiveSupport::Concern extend ActiveSupport::Concern
extend ::Gitlab::Utils::Override extend ::Gitlab::Utils::Override
override :update_user
def update_user
return if ::Gitlab::Database.read_only?
update_email
update_memberships
update_identity
update_ssh_keys if sync_ssh_keys?
update_kerberos_identity if import_kerberos_identities?
end
private
override :find_ldap_user override :find_ldap_user
def find_ldap_user def find_ldap_user
found_user = super found_user = super
...@@ -16,15 +29,6 @@ module EE ...@@ -16,15 +29,6 @@ module EE
end end
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 # Update user ssh keys if they changed in LDAP
def update_ssh_keys def update_ssh_keys
remove_old_ssh_keys remove_old_ssh_keys
......
...@@ -3,151 +3,164 @@ require 'spec_helper' ...@@ -3,151 +3,164 @@ require 'spec_helper'
describe Gitlab::Auth::LDAP::Access do describe Gitlab::Auth::LDAP::Access do
include LdapHelpers include LdapHelpers
let(:access) { described_class.new user }
let(:user) { create(:omniauth_user) } let(:user) { create(:omniauth_user) }
let(:provider) { user.ldap_identity.provider }
describe '#find_ldap_user' do subject(:access) { described_class.new(user) }
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 describe '#allowed?' do
end context 'LDAP user' do
it 'finds a user by dn first' do
expect(Gitlab::Auth::LDAP::Person).to receive(:find_by_dn).and_return(:ldap_user)
expect(Gitlab::Auth::LDAP::Person).not_to receive(:find_by_email)
access.allowed?
end end
describe '#allowed?' do it 'finds a user by email if not found by dn' do
subject { access.allowed? } expect(Gitlab::Auth::LDAP::Person).to receive(:find_by_dn).and_return(nil)
expect(Gitlab::Auth::LDAP::Person).to receive(:find_by_email)
context 'when the user cannot be found' do access.allowed?
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 end
context 'when looking for a user by email' do it 'returns false if user cannot be found' do
let(:user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'my-provider') } stub_ldap_person_find_by_dn(nil)
stub_ldap_person_find_by_email(user.email, nil)
it { is_expected.to be_falsey } expect(access.allowed?).to be_falsey
end end
end end
end end
describe '#update_user' do describe '#update_user' do
subject { access.update_user } let(:entry) { Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com") }
let(:entry) do
Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com") context 'email address' do
end
before do before do
allow(access).to( stub_ldap_person_find_by_dn(entry, provider)
receive_messages(
ldap_user: Gitlab::Auth::LDAP::Person.new(entry, user.ldap_identity.provider)
)
)
end end
it 'updates email address' do it 'does not update email if email attribute is not set' do
expect(access).to receive(:update_email).once expect { access.update_user }.not_to change(user, :email)
subject
end end
it 'updates the group memberships' do it 'does not update the email if the user has the same email in GitLab and in LDAP' do
expect(access).to receive(:update_memberships).once entry['mail'] = [user.email]
subject expect { access.update_user }.not_to change(user, :email)
end end
it 'syncs ssh keys if enabled by configuration' do it 'does not update the email if the user has the same email GitLab and in LDAP, but with upper case in LDAP' do
allow(access).to receive_messages(group_base: '', sync_ssh_keys?: true) entry['mail'] = [user.email.upcase]
expect(access).to receive(:update_ssh_keys).once
subject expect { access.update_user }.not_to change(user, :email)
end end
it 'update_kerberos_identity' do it 'does not update the email when in a read-only GitLab instance' do
allow(access).to receive_messages(import_kerberos_identities?: true) allow(Gitlab::Database).to receive(:read_only?).and_return(true)
expect(access).to receive(:update_kerberos_identity).once
entry['mail'] = ['new_email@example.com']
subject expect { access.update_user }.not_to change(user, :email)
end end
it 'updates the ldap identity' do it 'updates the email if the user email is different' do
expect(access).to receive(:update_identity) entry['mail'] = ['new_email@example.com']
subject expect { access.update_user }.to change(user, :email)
end end
end end
describe '#update_kerberos_identity' do context 'group memberships' do
let(:entry) do context 'when there is `memberof` param' do
Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com")
end
before do before do
allow(access).to receive_messages(ldap_user: Gitlab::Auth::LDAP::Person.new(entry, user.ldap_identity.provider)) entry['memberof'] = [
'CN=Group1,CN=Users,DC=The dc,DC=com',
'CN=Group2,CN=Builtin,DC=The dc,DC=com'
]
stub_ldap_person_find_by_dn(entry, provider)
end end
it "adds a Kerberos identity if it is in Active Directory but not in GitLab" do it 'triggers a sync for all groups found in `memberof`' do
allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: "mylogin@FOO.COM") 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)
expect(LdapGroupSyncWorker).to receive(:perform_async)
.with(a_collection_containing_exactly(*group_ids), provider)
expect { access.update_kerberos_identity }.to change(user.identities.where(provider: :kerberos), :count).from(0).to(1) access.update_user
expect(user.identities.where(provider: "kerberos").last.extern_uid).to eq("mylogin@FOO.COM")
end end
it "updates existing Kerberos identity in GitLab if Active Directory has a different one" do it "doesn't trigger a sync when in a read-only GitLab instance" do
allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: "otherlogin@BAR.COM") allow(Gitlab::Database).to receive(:read_only?).and_return(true)
user.identities.build(provider: "kerberos", extern_uid: "mylogin@FOO.COM").save create(:ldap_group_link, cn: 'Group1', provider: provider)
create(:ldap_group_link, cn: 'Group2', provider: provider)
expect { access.update_kerberos_identity }.not_to change(user.identities.where(provider: "kerberos"), :count) expect(LdapGroupSyncWorker).not_to receive(:perform_async)
expect(user.identities.where(provider: "kerberos").last.extern_uid).to eq("otherlogin@BAR.COM")
access.update_user
end end
it "does not remove Kerberos identities from GitLab if they are none in the LDAP provider" do it "doesn't trigger a sync when there are no links for the provider" do
allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: nil) _another_provider = create(:ldap_group_link,
user.identities.build(provider: "kerberos", extern_uid: "otherlogin@BAR.COM").save cn: 'Group1',
provider: 'not-this-ldap')
expect { access.update_kerberos_identity }.not_to change(user.identities.where(provider: "kerberos"), :count) expect(LdapGroupSyncWorker).not_to receive(:perform_async)
expect(user.identities.where(provider: "kerberos").last.extern_uid).to eq("otherlogin@BAR.COM")
access.update_user
end
end end
it "does not modify identities in GitLab if they are no kerberos principal in the LDAP provider" do it "doesn't continue when there is no `memberOf` param" do
allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: nil) stub_ldap_person_find_by_dn(entry, provider)
expect(LdapGroupLink).not_to receive(:where)
expect(LdapGroupSyncWorker).not_to receive(:perform_async)
expect { access.update_kerberos_identity }.not_to change(user.identities, :count) access.update_user
end end
end end
describe '#update_ssh_keys' do context '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) { 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCrSQHff6a1rMqBdHFt+FwIbytMZ+hJKN3KLkTtOWtSvNIriGhnTdn4rs+tjD/w+z+revytyWnMDM9dS7J8vQi006B16+hc9Xf82crqRoPRDnBytgAFFQY1G/55ql2zdfsC5yvpDOFzuwIJq5dNGsojS82t6HNmmKPq130fzsenFnj5v1pl3OJvk513oduUyKiZBGTroWTn7H/eOPtu7s9MD7pAdEjqYKFLeaKmyidiLmLqQlCRj3Tl2U9oyFg4PYNc0bL5FZJ/Z6t0Ds3i/a2RanQiKxrvgu3GSnUKMx7WIX373baL4jeM7cprRGiOY/1NcS+1cAjfJ8oaxQF/1dYj' }
let(:ssh_key_attribute_name) { 'altSecurityIdentities' } let(:ssh_key_attribute_name) { 'altSecurityIdentities' }
let(:entry) do let(:entry) { 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") }
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 before do
allow_any_instance_of(Gitlab::Auth::LDAP::Config).to receive_messages(sync_ssh_keys: ssh_key_attribute_name) stub_ldap_config(sync_ssh_keys: ssh_key_attribute_name, sync_ssh_keys?: true)
allow(access).to receive_messages(sync_ssh_keys?: true)
end end
it "adds a SSH key if it is in LDAP but not in gitlab" do 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') } stub_ldap_person_find_by_dn(entry, provider)
expect { access.update_ssh_keys }.to change(user.keys, :count).from(0).to(1) expect { access.update_user }.to change(user.keys, :count).from(0).to(1)
end end
it "adds a SSH key and give it a proper name" do 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') } stub_ldap_person_find_by_dn(entry, provider)
access.update_user
access.update_ssh_keys
expect(user.keys.last.title).to match(/LDAP/) expect(user.keys.last.title).to match(/LDAP/)
expect(user.keys.last.title).to match(/#{access.ldap_config.sync_ssh_keys}/) expect(user.keys.last.title).to match(/#{ssh_key_attribute_name}/)
end end
it "does not add a SSH key if it is invalid" do 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") 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') } stub_ldap_person_find_by_dn(entry, provider)
expect { access.update_user }.not_to change(user.keys, :count)
end
it 'does not add a SSH key when in a read-only GitLab instance' do
allow(Gitlab::Database).to receive(:read_only?).and_return(true)
stub_ldap_person_find_by_dn(entry, provider)
expect { access.update_ssh_keys }.not_to change(user.keys, :count) expect { access.update_user }.not_to change(user.keys, :count)
end end
context 'user has at least one LDAPKey' do context 'user has at least one LDAPKey' do
...@@ -155,107 +168,87 @@ describe Gitlab::Auth::LDAP::Access do ...@@ -155,107 +168,87 @@ describe Gitlab::Auth::LDAP::Access do
user.keys.ldap.create key: ssh_key, title: 'to be removed' user.keys.ldap.create key: ssh_key, title: 'to be removed'
end end
it "removes a SSH key if it is no longer in LDAP" do 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") 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') } stub_ldap_person_find_by_dn(entry, provider)
expect { access.update_ssh_keys }.to change(user.keys, :count).from(1).to(0) expect { access.update_user }.to change(user.keys, :count).from(1).to(0)
end end
it "removes a SSH key if the ldap attribute was removed" do 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") 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') } stub_ldap_person_find_by_dn(entry, provider)
expect { access.update_ssh_keys }.to change(user.keys, :count).from(1).to(0) expect { access.update_user }.to change(user.keys, :count).from(1).to(0)
end end
end end
end end
describe '#update_user_email' do context 'kerberos identity' do
let(:entry) { Net::LDAP::Entry.new }
before do before do
allow(access).to receive_messages(ldap_user: Gitlab::Auth::LDAP::Person.new(entry, user.ldap_identity.provider)) stub_ldap_config(active_directory: true)
stub_kerberos_setting(enabled: true)
stub_ldap_person_find_by_dn(entry, provider)
end end
it "does not update email if email attribute is not set" do it 'adds a Kerberos identity if it is in Active Directory but not in GitLab' do
expect { access.update_email }.not_to change(user, :email) allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: 'mylogin@FOO.COM')
end
it "does not update the email if the user has the same email in GitLab and in LDAP" do expect { access.update_user }.to change(user.identities.where(provider: :kerberos), :count).from(0).to(1)
entry['mail'] = [user.email] expect(user.identities.where(provider: 'kerberos').last.extern_uid).to eq('mylogin@FOO.COM')
expect { access.update_email }.not_to change(user, :email)
end 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 it 'updates existing Kerberos identity in GitLab if Active Directory has a different one' do
entry['mail'] = [user.email.upcase] allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: 'otherlogin@BAR.COM')
expect { access.update_email }.not_to change(user, :email) user.identities.build(provider: 'kerberos', extern_uid: 'mylogin@FOO.COM').save
end
it "updates the email if the user email is different" do expect { access.update_user }.not_to change(user.identities.where(provider: 'kerberos'), :count)
entry['mail'] = ["new_email@example.com"] expect(user.identities.where(provider: 'kerberos').last.extern_uid).to eq('otherlogin@BAR.COM')
expect { access.update_email }.to change(user, :email)
end
end end
describe '#update_memberships' do it 'does not remove Kerberos identities from GitLab if they are none in the LDAP provider' do
let(:provider) { user.ldap_identity.provider } allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: nil)
let(:entry) { ldap_user_entry(user.ldap_identity.extern_uid) } user.identities.build(provider: 'kerberos', extern_uid: 'otherlogin@BAR.COM').save
let(:person_with_memberof) do expect { access.update_user }.not_to change(user.identities.where(provider: 'kerberos'), :count)
entry['memberof'] = ['CN=Group1,CN=Users,DC=The dc,DC=com', expect(user.identities.where(provider: 'kerberos').last.extern_uid).to eq('otherlogin@BAR.COM')
'CN=Group2,CN=Builtin,DC=The dc,DC=com']
Gitlab::Auth::LDAP::Person.new(entry, provider)
end end
it 'triggers a sync for all groups found in `memberof`' do it 'does not modify identities in GitLab if they are no kerberos principal in the LDAP provider' do
group_link_1 = create(:ldap_group_link, cn: 'Group1', provider: provider) allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: nil)
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 { access.update_user }.not_to change(user.identities, :count)
end
expect(LdapGroupSyncWorker).to receive(:perform_async) it 'does not add a Kerberos identity when in a read-only GitLab instance' do
.with(a_collection_containing_exactly(*group_ids), provider) allow(Gitlab::Database).to receive(:read_only?).and_return(true)
allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: 'mylogin@FOO.COM')
access.update_memberships expect { access.update_user }.not_to change(user.identities.where(provider: :kerberos), :count)
end
end end
it "doesn't continue when there is no `memberOf` param" do context 'LDAP entity' do
allow(access).to receive(:ldap_user) context 'whent external UID changed in the entry' do
.and_return(Gitlab::Auth::LDAP::Person.new(entry, provider)) before do
stub_ldap_person_find_by_dn(ldap_user_entry('another uid'), provider)
end
expect(LdapGroupLink).not_to receive(:where) it 'updates the external UID' do
expect(LdapGroupSyncWorker).not_to receive(:perform_async) access.update_user
access.update_memberships expect(user.ldap_identity.reload.extern_uid)
.to eq('uid=another uid,ou=users,dc=example,dc=com')
end end
it "doesn't trigger a sync when there are no links for the provider" do it 'does not update the external UID when in a read-only GitLab instance' do
_another_provider = create(:ldap_group_link, allow(Gitlab::Database).to receive(:read_only?).and_return(true)
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_user
access.update_memberships expect(user.ldap_identity.reload.extern_uid).to eq('123456')
end end
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 end
end end
...@@ -21,8 +21,10 @@ module Gitlab ...@@ -21,8 +21,10 @@ module Gitlab
# Whether user is allowed, or not, we should update # Whether user is allowed, or not, we should update
# permissions to keep things clean # permissions to keep things clean
if access.allowed? if access.allowed?
unless Gitlab::Database.read_only?
access.update_user access.update_user
Users::UpdateService.new(user, user: user, last_credential_check_at: Time.now).execute Users::UpdateService.new(user, user: user, last_credential_check_at: Time.now).execute
end
true true
else else
...@@ -62,6 +64,12 @@ module Gitlab ...@@ -62,6 +64,12 @@ module Gitlab
false false
end end
def update_user
# no-op in CE
end
private
def adapter def adapter
@adapter ||= Gitlab::Auth::LDAP::Adapter.new(provider) @adapter ||= Gitlab::Auth::LDAP::Adapter.new(provider)
end end
...@@ -70,16 +78,16 @@ module Gitlab ...@@ -70,16 +78,16 @@ module Gitlab
Gitlab::Auth::LDAP::Config.new(provider) Gitlab::Auth::LDAP::Config.new(provider)
end end
def find_ldap_user
Gitlab::Auth::LDAP::Person.find_by_dn(ldap_identity.extern_uid, adapter)
end
def ldap_user def ldap_user
return unless provider return unless provider
@ldap_user ||= find_ldap_user @ldap_user ||= find_ldap_user
end end
def find_ldap_user
Gitlab::Auth::LDAP::Person.find_by_dn(ldap_identity.extern_uid, adapter)
end
def block_user(user, reason) def block_user(user, reason)
user.ldap_block user.ldap_block
...@@ -104,10 +112,6 @@ module Gitlab ...@@ -104,10 +112,6 @@ module Gitlab
"unblocking Gitlab user \"#{user.name}\" (#{user.email})" "unblocking Gitlab user \"#{user.name}\" (#{user.email})"
) )
end end
def update_user
# no-op in CE
end
end end
end end
end end
......
...@@ -3,51 +3,61 @@ require 'spec_helper' ...@@ -3,51 +3,61 @@ require 'spec_helper'
describe Gitlab::Auth::LDAP::Access do describe Gitlab::Auth::LDAP::Access do
include LdapHelpers include LdapHelpers
let(:access) { described_class.new user }
let(:user) { create(:omniauth_user) } let(:user) { create(:omniauth_user) }
subject(:access) { described_class.new(user) }
describe '.allowed?' do describe '.allowed?' do
it 'updates the users `last_credential_check_at' do before do
allow(access).to receive(:update_user) allow(access).to receive(:update_user)
expect(access).to receive(:allowed?) { true } allow(access).to receive(:allowed?).and_return(true)
expect(described_class).to receive(:open).and_yield(access) allow(described_class).to receive(:open).and_yield(access)
end
it "updates the user's `last_credential_check_at`" do
expect { described_class.allowed?(user) } expect { described_class.allowed?(user) }
.to change { user.last_credential_check_at } .to change { user.last_credential_check_at }
end end
end
describe '#find_ldap_user' do it "does not update user's `last_credential_check_at` when in a read-only GitLab instance" do
it 'finds a user by dn first' do allow(Gitlab::Database).to receive(:read_only?).and_return(true)
expect(Gitlab::Auth::LDAP::Person).to receive(:find_by_dn).and_return(:ldap_user)
access.find_ldap_user expect { described_class.allowed?(user) }
.not_to change { user.last_credential_check_at }
end end
end end
describe '#allowed?' do describe '#allowed?' do
subject { access.allowed? }
context 'when the user cannot be found' do context 'when the user cannot be found' do
before do before do
allow(Gitlab::Auth::LDAP::Person).to receive(:find_by_dn).and_return(nil) stub_ldap_person_find_by_dn(nil)
allow(Gitlab::Auth::LDAP::Person).to receive(:find_by_email).and_return(nil) stub_ldap_person_find_by_email(user.email, nil)
end end
it { is_expected.to be_falsey } it 'returns false' do
expect(access.allowed?).to be_falsey
end
it 'blocks user in GitLab' do it 'blocks user in GitLab' do
expect(access).to receive(:block_user).with(user, 'does not exist anymore') access.allowed?
expect(user).to be_blocked
expect(user).to be_ldap_blocked
end
it 'logs the reason' do
expect(Gitlab::AppLogger).to receive(:info).with(
"LDAP account \"123456\" does not exist anymore, " \
"blocking Gitlab user \"#{user.name}\" (#{user.email})"
)
access.allowed? access.allowed?
end end
end end
context 'when the user is found' do context 'when the user is found' do
let(:ldap_user) { Gitlab::Auth::LDAP::Person.new(Net::LDAP::Entry.new, 'ldapmain') }
before do before do
allow(Gitlab::Auth::LDAP::Person).to receive(:find_by_dn).and_return(ldap_user) stub_ldap_person_find_by_dn(Net::LDAP::Entry.new)
end end
context 'and the user is disabled via active directory' do context 'and the user is disabled via active directory' do
...@@ -55,10 +65,22 @@ describe Gitlab::Auth::LDAP::Access do ...@@ -55,10 +65,22 @@ describe Gitlab::Auth::LDAP::Access do
allow(Gitlab::Auth::LDAP::Person).to receive(:disabled_via_active_directory?).and_return(true) allow(Gitlab::Auth::LDAP::Person).to receive(:disabled_via_active_directory?).and_return(true)
end end
it { is_expected.to be_falsey } it 'returns false' do
expect(access.allowed?).to be_falsey
end
it 'blocks user in GitLab' do it 'blocks user in GitLab' do
expect(access).to receive(:block_user).with(user, 'is disabled in Active Directory') access.allowed?
expect(user).to be_blocked
expect(user).to be_ldap_blocked
end
it 'logs the reason' do
expect(Gitlab::AppLogger).to receive(:info).with(
"LDAP account \"123456\" is disabled in Active Directory, " \
"blocking Gitlab user \"#{user.name}\" (#{user.email})"
)
access.allowed? access.allowed?
end end
...@@ -92,7 +114,17 @@ describe Gitlab::Auth::LDAP::Access do ...@@ -92,7 +114,17 @@ describe Gitlab::Auth::LDAP::Access do
end end
it 'unblocks user in GitLab' do it 'unblocks user in GitLab' do
expect(access).to receive(:unblock_user).with(user, 'is not disabled anymore') access.allowed?
expect(user).not_to be_blocked
expect(user).not_to be_ldap_blocked
end
it 'logs the reason' do
expect(Gitlab::AppLogger).to receive(:info).with(
"LDAP account \"123456\" is not disabled anymore, " \
"unblocking Gitlab user \"#{user.name}\" (#{user.email})"
)
access.allowed? access.allowed?
end end
...@@ -105,18 +137,32 @@ describe Gitlab::Auth::LDAP::Access do ...@@ -105,18 +137,32 @@ describe Gitlab::Auth::LDAP::Access do
allow_any_instance_of(Gitlab::Auth::LDAP::Config).to receive(:active_directory).and_return(false) allow_any_instance_of(Gitlab::Auth::LDAP::Config).to receive(:active_directory).and_return(false)
end end
it { is_expected.to be_truthy } it 'returns true' do
expect(access.allowed?).to be_truthy
end
context 'when user cannot be found' do context 'when user cannot be found' do
before do before do
allow(Gitlab::Auth::LDAP::Person).to receive(:find_by_dn).and_return(nil) stub_ldap_person_find_by_dn(nil)
allow(Gitlab::Auth::LDAP::Person).to receive(:find_by_email).and_return(nil) stub_ldap_person_find_by_email(user.email, nil)
end end
it { is_expected.to be_falsey } it 'returns false' do
expect(access.allowed?).to be_falsey
end
it 'blocks user in GitLab' do it 'blocks user in GitLab' do
expect(access).to receive(:block_user).with(user, 'does not exist anymore') access.allowed?
expect(user).to be_blocked
expect(user).to be_ldap_blocked
end
it 'logs the reason' do
expect(Gitlab::AppLogger).to receive(:info).with(
"LDAP account \"123456\" does not exist anymore, " \
"blocking Gitlab user \"#{user.name}\" (#{user.email})"
)
access.allowed? access.allowed?
end end
...@@ -128,7 +174,17 @@ describe Gitlab::Auth::LDAP::Access do ...@@ -128,7 +174,17 @@ describe Gitlab::Auth::LDAP::Access do
end end
it 'unblocks the user if it exists' do it 'unblocks the user if it exists' do
expect(access).to receive(:unblock_user).with(user, 'is available again') access.allowed?
expect(user).not_to be_blocked
expect(user).not_to be_ldap_blocked
end
it 'logs the reason' do
expect(Gitlab::AppLogger).to receive(:info).with(
"LDAP account \"123456\" is available again, " \
"unblocking Gitlab user \"#{user.name}\" (#{user.email})"
)
access.allowed? access.allowed?
end end
...@@ -152,46 +208,4 @@ describe Gitlab::Auth::LDAP::Access do ...@@ -152,46 +208,4 @@ describe Gitlab::Auth::LDAP::Access do
end end
end end
end end
describe '#block_user' do
before do
user.activate
allow(Gitlab::AppLogger).to receive(:info)
access.block_user user, 'reason'
end
it 'blocks the user' do
expect(user).to be_blocked
expect(user).to be_ldap_blocked
end
it 'logs the reason' do
expect(Gitlab::AppLogger).to have_received(:info).with(
"LDAP account \"123456\" reason, " \
"blocking Gitlab user \"#{user.name}\" (#{user.email})"
)
end
end
describe '#unblock_user' do
before do
user.ldap_block
allow(Gitlab::AppLogger).to receive(:info)
access.unblock_user user, 'reason'
end
it 'activates the user' do
expect(user).not_to be_blocked
expect(user).not_to be_ldap_blocked
end
it 'logs the reason' do
Gitlab::AppLogger.info(
"LDAP account \"123456\" reason, " \
"unblocking Gitlab user \"#{user.name}\" (#{user.email})"
)
end
end
end end
...@@ -45,6 +45,23 @@ module LdapHelpers ...@@ -45,6 +45,23 @@ module LdapHelpers
.to receive(:find_by_uid).with(uid, any_args).and_return(return_value) .to receive(:find_by_uid).with(uid, any_args).and_return(return_value)
end end
def stub_ldap_person_find_by_dn(entry, provider = 'ldapmain')
person = ::Gitlab::Auth::LDAP::Person.new(entry, provider) if entry.present?
allow(::Gitlab::Auth::LDAP::Person)
.to receive(:find_by_dn)
.and_return(person)
end
def stub_ldap_person_find_by_email(email, entry, provider = 'ldapmain')
person = ::Gitlab::Auth::LDAP::Person.new(entry, provider) if entry.present?
allow(::Gitlab::Auth::LDAP::Person)
.to receive(:find_by_email)
.with(email, anything)
.and_return(person)
end
# Create a simple LDAP user entry. # Create a simple LDAP user entry.
def ldap_user_entry(uid) def ldap_user_entry(uid)
entry = Net::LDAP::Entry.new entry = Net::LDAP::Entry.new
......
...@@ -82,6 +82,10 @@ module StubConfiguration ...@@ -82,6 +82,10 @@ module StubConfiguration
allow(Gitlab.config.repositories).to receive(:storages).and_return(Settingslogic.new(messages)) allow(Gitlab.config.repositories).to receive(:storages).and_return(Settingslogic.new(messages))
end end
def stub_kerberos_setting(messages)
allow(Gitlab.config.kerberos).to receive_messages(to_settings(messages))
end
private private
# Modifies stubbed messages to also stub possible predicate versions # Modifies stubbed messages to also stub possible predicate versions
......
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