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,259 +3,252 @@ require 'spec_helper' ...@@ -3,259 +3,252 @@ 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
end
end
describe '#allowed?' do describe '#allowed?' do
subject { access.allowed? } 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)
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 'finds a user by email if not found by dn' do
let(:user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'my-provider') } expect(Gitlab::Auth::LDAP::Person).to receive(:find_by_dn).and_return(nil)
expect(Gitlab::Auth::LDAP::Person).to receive(:find_by_email)
it { is_expected.to be_falsey } access.allowed?
end
it 'returns false if user cannot be found' do
stub_ldap_person_find_by_dn(nil)
stub_ldap_person_find_by_email(user.email, nil)
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")
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 context 'email address' do
expect(access).to receive(:update_email).once before do
stub_ldap_person_find_by_dn(entry, provider)
end
subject it 'does not update email if email attribute is not set' do
end expect { access.update_user }.not_to change(user, :email)
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
subject entry['mail'] = ['new_email@example.com']
end
it 'updates the ldap identity' do expect { access.update_user }.not_to change(user, :email)
expect(access).to receive(:update_identity) end
subject it 'updates the email if the user email is different' do
end entry['mail'] = ['new_email@example.com']
end
describe '#update_kerberos_identity' do expect { access.update_user }.to change(user, :email)
let(:entry) do end
Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com")
end end
before do context 'group memberships' do
allow(access).to receive_messages(ldap_user: Gitlab::Auth::LDAP::Person.new(entry, user.ldap_identity.provider)) context 'when there is `memberof` param' do
end before do
entry['memberof'] = [
'CN=Group1,CN=Users,DC=The dc,DC=com',
'CN=Group2,CN=Builtin,DC=The dc,DC=com'
]
it "adds a Kerberos identity if it is in Active Directory but not in GitLab" do stub_ldap_person_find_by_dn(entry, provider)
allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: "mylogin@FOO.COM") end
expect { access.update_kerberos_identity }.to change(user.identities.where(provider: :kerberos), :count).from(0).to(1) it 'triggers a sync for all groups found in `memberof`' do
expect(user.identities.where(provider: "kerberos").last.extern_uid).to eq("mylogin@FOO.COM") group_link_1 = create(:ldap_group_link, cn: 'Group1', provider: provider)
end group_link_2 = create(:ldap_group_link, cn: 'Group2', provider: provider)
group_ids = [group_link_1, group_link_2].map(&:group_id)
it "updates existing Kerberos identity in GitLab if Active Directory has a different one" do expect(LdapGroupSyncWorker).to receive(:perform_async)
allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: "otherlogin@BAR.COM") .with(a_collection_containing_exactly(*group_ids), provider)
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) access.update_user
expect(user.identities.where(provider: "kerberos").last.extern_uid).to eq("otherlogin@BAR.COM") 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 in a read-only GitLab instance" do
allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: nil) allow(Gitlab::Database).to receive(:read_only?).and_return(true)
user.identities.build(provider: "kerberos", extern_uid: "otherlogin@BAR.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")
end
it "does not modify identities in GitLab if they are no kerberos principal in the LDAP provider" do access.update_user
allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: nil) end
expect { access.update_kerberos_identity }.not_to change(user.identities, :count) it "doesn't trigger a sync when there are no links for the provider" do
end _another_provider = create(:ldap_group_link,
end cn: 'Group1',
provider: 'not-this-ldap')
describe '#update_ssh_keys' do expect(LdapGroupSyncWorker).not_to receive(:perform_async)
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 access.update_user
allow_any_instance_of(Gitlab::Auth::LDAP::Adapter).to receive(:user) { Gitlab::Auth::LDAP::Person.new(entry, 'ldapmain') } end
end
expect { access.update_ssh_keys }.to change(user.keys, :count).from(0).to(1) it "doesn't continue when there is no `memberOf` param" do
end stub_ldap_person_find_by_dn(entry, provider)
it "adds a SSH key and give it a proper name" do expect(LdapGroupLink).not_to receive(:where)
allow_any_instance_of(Gitlab::Auth::LDAP::Adapter).to receive(:user) { Gitlab::Auth::LDAP::Person.new(entry, 'ldapmain') } expect(LdapGroupSyncWorker).not_to receive(:perform_async)
access.update_ssh_keys access.update_user
expect(user.keys.last.title).to match(/LDAP/) end
expect(user.keys.last.title).to match(/#{access.ldap_config.sync_ssh_keys}/)
end end
it "does not add a SSH key if it is invalid" do context 'SSH keys' 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") let(:ssh_key) { 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCrSQHff6a1rMqBdHFt+FwIbytMZ+hJKN3KLkTtOWtSvNIriGhnTdn4rs+tjD/w+z+revytyWnMDM9dS7J8vQi006B16+hc9Xf82crqRoPRDnBytgAFFQY1G/55ql2zdfsC5yvpDOFzuwIJq5dNGsojS82t6HNmmKPq130fzsenFnj5v1pl3OJvk513oduUyKiZBGTroWTn7H/eOPtu7s9MD7pAdEjqYKFLeaKmyidiLmLqQlCRj3Tl2U9oyFg4PYNc0bL5FZJ/Z6t0Ds3i/a2RanQiKxrvgu3GSnUKMx7WIX373baL4jeM7cprRGiOY/1NcS+1cAjfJ8oaxQF/1dYj' }
allow_any_instance_of(Gitlab::Auth::LDAP::Adapter).to receive(:user) { Gitlab::Auth::LDAP::Person.new(entry, 'ldapmain') } let(:ssh_key_attribute_name) { 'altSecurityIdentities' }
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") }
expect { access.update_ssh_keys }.not_to change(user.keys, :count)
end
context 'user has at least one LDAPKey' do
before do before do
user.keys.ldap.create key: ssh_key, title: 'to be removed' stub_ldap_config(sync_ssh_keys: ssh_key_attribute_name, sync_ssh_keys?: true)
end end
it "removes a SSH key if it is no longer in LDAP" do it 'adds a SSH key if it is in LDAP but not in gitlab' do
entry = Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com\n#{ssh_key_attribute_name}:\n") stub_ldap_person_find_by_dn(entry, provider)
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) expect { access.update_user }.to change(user.keys, :count).from(0).to(1)
end end
it "removes a SSH key if the ldap attribute was removed" do it 'adds a SSH key and give it a proper name' do
entry = Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com") stub_ldap_person_find_by_dn(entry, provider)
allow_any_instance_of(Gitlab::Auth::LDAP::Adapter).to receive(:user) { Gitlab::Auth::LDAP::Person.new(entry, 'ldapmain') }
access.update_user
expect { access.update_ssh_keys }.to change(user.keys, :count).from(1).to(0) expect(user.keys.last.title).to match(/LDAP/)
expect(user.keys.last.title).to match(/#{ssh_key_attribute_name}/)
end end
end
end
describe '#update_user_email' do it 'does not add a SSH key if it is invalid' do
let(:entry) { Net::LDAP::Entry.new } 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")
stub_ldap_person_find_by_dn(entry, provider)
before do expect { access.update_user }.not_to change(user.keys, :count)
allow(access).to receive_messages(ldap_user: Gitlab::Auth::LDAP::Person.new(entry, user.ldap_identity.provider)) end
end
it "does not update email if email attribute is not set" do it 'does not add a SSH key when in a read-only GitLab instance' do
expect { access.update_email }.not_to change(user, :email) allow(Gitlab::Database).to receive(:read_only?).and_return(true)
end stub_ldap_person_find_by_dn(entry, provider)
it "does not update the email if the user has the same email in GitLab and in LDAP" do expect { access.update_user }.not_to change(user.keys, :count)
entry['mail'] = [user.email] end
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 context 'user has at least one LDAPKey' do
entry['mail'] = [user.email.upcase] before do
expect { access.update_email }.not_to change(user, :email) user.keys.ldap.create key: ssh_key, title: 'to be removed'
end end
it "updates the email if the user email is different" do it 'removes a SSH key if it is no longer in LDAP' do
entry['mail'] = ["new_email@example.com"] entry = Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com\n#{ssh_key_attribute_name}:\n")
expect { access.update_email }.to change(user, :email) stub_ldap_person_find_by_dn(entry, provider)
end
end
describe '#update_memberships' do expect { access.update_user }.to change(user.keys, :count).from(1).to(0)
let(:provider) { user.ldap_identity.provider } end
let(:entry) { ldap_user_entry(user.ldap_identity.extern_uid) }
let(:person_with_memberof) do it 'removes a SSH key if the ldap attribute was removed' do
entry['memberof'] = ['CN=Group1,CN=Users,DC=The dc,DC=com', entry = Net::LDAP::Entry.from_single_ldif_string("dn: cn=foo, dc=bar, dc=com")
'CN=Group2,CN=Builtin,DC=The dc,DC=com'] stub_ldap_person_find_by_dn(entry, provider)
Gitlab::Auth::LDAP::Person.new(entry, provider)
expect { access.update_user }.to change(user.keys, :count).from(1).to(0)
end
end
end end
it 'triggers a sync for all groups found in `memberof`' do context 'kerberos identity' do
group_link_1 = create(:ldap_group_link, cn: 'Group1', provider: provider) before do
group_link_2 = create(:ldap_group_link, cn: 'Group2', provider: provider) stub_ldap_config(active_directory: true)
group_ids = [group_link_1, group_link_2].map(&:group_id) stub_kerberos_setting(enabled: true)
stub_ldap_person_find_by_dn(entry, provider)
end
allow(access).to receive(:ldap_user).and_return(person_with_memberof) 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(LdapGroupSyncWorker).to receive(:perform_async) expect { access.update_user }.to change(user.identities.where(provider: :kerberos), :count).from(0).to(1)
.with(a_collection_containing_exactly(*group_ids), provider) expect(user.identities.where(provider: 'kerberos').last.extern_uid).to eq('mylogin@FOO.COM')
end
access.update_memberships it 'updates existing Kerberos identity in GitLab if Active Directory has a different one' do
end 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
it "doesn't continue when there is no `memberOf` param" do expect { access.update_user }.not_to change(user.identities.where(provider: 'kerberos'), :count)
allow(access).to receive(:ldap_user) expect(user.identities.where(provider: 'kerberos').last.extern_uid).to eq('otherlogin@BAR.COM')
.and_return(Gitlab::Auth::LDAP::Person.new(entry, provider)) end
expect(LdapGroupLink).not_to receive(:where) it 'does not remove Kerberos identities from GitLab if they are none in the LDAP provider' do
expect(LdapGroupSyncWorker).not_to receive(:perform_async) 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
access.update_memberships expect { access.update_user }.not_to change(user.identities.where(provider: 'kerberos'), :count)
end expect(user.identities.where(provider: 'kerberos').last.extern_uid).to eq('otherlogin@BAR.COM')
end
it "doesn't trigger a sync when there are no links for the provider" do it 'does not modify identities in GitLab if they are no kerberos principal in the LDAP provider' do
_another_provider = create(:ldap_group_link, allow_any_instance_of(EE::Gitlab::Auth::LDAP::Person).to receive_messages(kerberos_principal: nil)
cn: 'Group1',
provider: 'not-this-ldap')
allow(access).to receive(:ldap_user).and_return(person_with_memberof) expect { access.update_user }.not_to change(user.identities, :count)
end
expect(LdapGroupSyncWorker).not_to receive(:perform_async) it 'does not add a Kerberos identity when in a read-only GitLab instance' do
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
end
describe '#update_identity' do context 'LDAP entity' do
it 'updates the external UID if it changed in the entry' do context 'whent external UID changed in the entry' do
entry = ldap_user_entry('another uid') before do
provider = user.ldap_identity.provider stub_ldap_person_find_by_dn(ldap_user_entry('another uid'), provider)
person = Gitlab::Auth::LDAP::Person.new(entry, provider) end
allow(access).to receive(:ldap_user).and_return(person) it 'updates the external UID' do
access.update_user
access.update_identity expect(user.ldap_identity.reload.extern_uid)
.to eq('uid=another uid,ou=users,dc=example,dc=com')
end
expect(user.ldap_identity.reload.extern_uid) it 'does not update the external UID when in a read-only GitLab instance' do
.to eq('uid=another uid,ou=users,dc=example,dc=com') allow(Gitlab::Database).to receive(:read_only?).and_return(true)
access.update_user
expect(user.ldap_identity.reload.extern_uid).to eq('123456')
end
end
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?
access.update_user unless Gitlab::Database.read_only?
Users::UpdateService.new(user, user: user, last_credential_check_at: Time.now).execute access.update_user
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