Commit d0c66caa authored by Nick Thomas's avatar Nick Thomas

Merge branch '2906-make-kerberos-mapping-configurable' into 'master'

Resolve "Make the mapping between Kerberos and LDAP configurable"

See merge request gitlab-org/gitlab!9962
parents 42a77036 2af3f6a8
...@@ -731,6 +731,7 @@ Gitlab.ee do ...@@ -731,6 +731,7 @@ Gitlab.ee do
Settings['kerberos'] ||= Settingslogic.new({}) Settings['kerberos'] ||= Settingslogic.new({})
Settings.kerberos['enabled'] = false if Settings.kerberos['enabled'].nil? Settings.kerberos['enabled'] = false if Settings.kerberos['enabled'].nil?
Settings.kerberos['keytab'] = nil if Settings.kerberos['keytab'].blank? # nil means use default keytab Settings.kerberos['keytab'] = nil if Settings.kerberos['keytab'].blank? # nil means use default keytab
Settings.kerberos['simple_ldap_linking_allowed_realms'] = [] if Settings.kerberos['simple_ldap_linking_allowed_realms'].blank?
Settings.kerberos['service_principal_name'] = nil if Settings.kerberos['service_principal_name'].blank? # nil means any SPN in keytab Settings.kerberos['service_principal_name'] = nil if Settings.kerberos['service_principal_name'].blank? # nil means any SPN in keytab
Settings.kerberos['use_dedicated_port'] = false if Settings.kerberos['use_dedicated_port'].nil? Settings.kerberos['use_dedicated_port'] = false if Settings.kerberos['use_dedicated_port'].nil?
Settings.kerberos['https'] = Settings.gitlab.https if Settings.kerberos['https'].nil? Settings.kerberos['https'] = Settings.gitlab.https if Settings.kerberos['https'].nil?
......
---
title: Make mapping between LDAP and Kerberos configurable
merge_request: 9962
author: Christopher Schenk
type: added
...@@ -30,15 +30,25 @@ module EE ...@@ -30,15 +30,25 @@ module EE
def find_by_kerberos_principal(principal, adapter) def find_by_kerberos_principal(principal, adapter)
uid, domain = principal.split('@', 2) uid, domain = principal.split('@', 2)
return unless uid && domain return unless uid && domain
return unless allowed_realm?(domain, adapter)
# In multi-forest setups, there may be several users with matching
# uids but differing DNs, so skip adapters configured to connect to
# non-matching domains
return unless domain.casecmp(domain_from_dn(adapter.config.base)) == 0
find_by_uid(uid, adapter) find_by_uid(uid, adapter)
end end
def allowed_realm?(domain, adapter)
return domain.casecmp(domain_from_dn(adapter.config.base)) == 0 unless simple_ldap_linking?
simple_ldap_linking_allowed_realms.select { |realm| domain.casecmp(realm) == 0 }.any?
end
def simple_ldap_linking_allowed_realms
::Gitlab.config.kerberos.simple_ldap_linking_allowed_realms
end
def simple_ldap_linking?
simple_ldap_linking_allowed_realms.present?
end
# Extracts the rightmost unbroken set of domain components from an # Extracts the rightmost unbroken set of domain components from an
# LDAP DN and constructs a domain name from them # LDAP DN and constructs a domain name from them
def domain_from_dn(dn) def domain_from_dn(dn)
......
...@@ -60,32 +60,63 @@ RSpec.describe Gitlab::Auth::Ldap::Person do ...@@ -60,32 +60,63 @@ RSpec.describe Gitlab::Auth::Ldap::Person do
describe '.find_by_kerberos_principal' do describe '.find_by_kerberos_principal' do
let(:adapter) { ldap_adapter } let(:adapter) { ldap_adapter }
let(:username) { 'foo' } let(:username) { 'foo' }
let(:principal) { username + '@' + kerberos_realm }
let(:ldap_server) { 'ad.example.com' } let(:ldap_server) { 'ad.example.com' }
subject { described_class.find_by_kerberos_principal(principal, adapter) } subject(:ldap_person) { described_class.find_by_kerberos_principal(principal, adapter) }
before do before do
stub_ldap_config(uid: 'sAMAccountName', base: 'ou=foo,dc=' + ldap_server.gsub('.', ',dc=')) stub_ldap_config(uid: 'sAMAccountName', base: 'ou=foo,dc=' + ldap_server.gsub('.', ',dc='))
end end
context 'LDAP server is not for kerberos realm' do context 'when simple LDAP linking is not configured' do
let(:kerberos_realm) { 'kerberos.example.com' } let(:principal) { username + '@' + kerberos_realm }
it 'returns nil without searching' do context 'LDAP server is not for kerberos realm' do
expect(adapter).not_to receive(:user) let(:kerberos_realm) { 'kerberos.example.com' }
is_expected.to be_nil it 'returns nil without searching' do
expect(adapter).not_to receive(:user)
is_expected.to be_nil
end
end
context 'LDAP server is for kerberos realm' do
let(:kerberos_realm) { ldap_server }
it 'searches by configured uid attribute' do
expect(adapter).to receive(:user).with('sAMAccountName', username).and_return(:fake_user)
is_expected.to eq(:fake_user)
end
end end
end end
context 'LDAP server is for kerberos realm' do context 'when simple LDAP linking is enabled' do
let(:kerberos_realm) { ldap_server } let(:allowed_realms) { ['kerberos.example.com', ldap_server] }
before do
stub_config(kerberos: { simple_ldap_linking_allowed_realms: allowed_realms })
end
context 'principal domain matches an allowed realm' do
let(:principal) { "#{username}@#{allowed_realms[0]}" }
it 'searches by configured uid attribute' do
expect(adapter).to receive(:user).with('sAMAccountName', username).and_return(:fake_user)
expect(ldap_person).to eq(:fake_user)
end
end
context 'principal domain does not match an allowed realm' do
let(:principal) { "#{username}@alternate.example.com" }
it 'searches by configured uid attribute' do it 'returns nil without searching' do
expect(adapter).to receive(:user).with('sAMAccountName', username).and_return(:fake_user) expect(adapter).not_to receive(:user)
is_expected.to eq(:fake_user) is_expected.to be_nil
end
end end
end 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