Skip to content
Snippets Groups Projects
Commit c50b98da authored by Drew Blessing's avatar Drew Blessing
Browse files

Centralize LDAP config/filter logic

Centralize all LDAP config logic in `GitLab::LDAP::Config`. Previously,
some logic was in the Devise initializer and it was not honoring the
`user_filter`. If a user outside the configured `user_filter` signed
in, an account would be created but they would then be denied access.
Now that logic is centralized, the filter is honored and users outside
the filter are never created.
parent 6eeff67c
No related branches found
No related tags found
No related merge requests found
Loading
@@ -3,7 +3,7 @@ module AuthHelper
Loading
@@ -3,7 +3,7 @@ module AuthHelper
FORM_BASED_PROVIDERS = [/\Aldap/, 'crowd'].freeze FORM_BASED_PROVIDERS = [/\Aldap/, 'crowd'].freeze
   
def ldap_enabled? def ldap_enabled?
Gitlab.config.ldap.enabled Gitlab::LDAP::Config.enabled?
end end
   
def omniauth_enabled? def omniauth_enabled?
Loading
Loading
---
title: Centralize LDAP config/filter logic
merge_request: 6606
author:
Loading
@@ -213,22 +213,9 @@ Devise.setup do |config|
Loading
@@ -213,22 +213,9 @@ Devise.setup do |config|
end end
   
if Gitlab::LDAP::Config.enabled? if Gitlab::LDAP::Config.enabled?
Gitlab.config.ldap.servers.values.each do |server| Gitlab::LDAP::Config.providers.each do |provider|
if server['allow_username_or_email_login'] ldap_config = Gitlab::LDAP::Config.new(provider)
email_stripping_proc = ->(name) {name.gsub(/@.*\z/, '')} config.omniauth(provider, ldap_config.omniauth_options)
else
email_stripping_proc = ->(name) {name}
end
config.omniauth server['provider_name'],
host: server['host'],
base: server['base'],
uid: server['uid'],
port: server['port'],
method: server['method'],
bind_dn: server['bind_dn'],
password: server['password'],
name_proc: email_stripping_proc
end end
end end
   
Loading
Loading
Loading
@@ -89,9 +89,7 @@ module Gitlab
Loading
@@ -89,9 +89,7 @@ module Gitlab
end end
   
def user_filter(filter = nil) def user_filter(filter = nil)
if config.user_filter.present? user_filter = config.constructed_user_filter if config.user_filter.present?
user_filter = Net::LDAP::Filter.construct(config.user_filter)
end
   
if user_filter && filter if user_filter && filter
Net::LDAP::Filter.join(filter, user_filter) Net::LDAP::Filter.join(filter, user_filter)
Loading
Loading
Loading
@@ -54,11 +54,9 @@ module Gitlab
Loading
@@ -54,11 +54,9 @@ module Gitlab
   
# Apply LDAP user filter if present # Apply LDAP user filter if present
if config.user_filter.present? if config.user_filter.present?
filter = Net::LDAP::Filter.join( filter = Net::LDAP::Filter.join(filter, config.constructed_user_filter)
filter,
Net::LDAP::Filter.construct(config.user_filter)
)
end end
filter filter
end end
   
Loading
Loading
Loading
@@ -13,7 +13,7 @@ module Gitlab
Loading
@@ -13,7 +13,7 @@ module Gitlab
end end
   
def self.providers def self.providers
servers.map {|server| server['provider_name'] } servers.map { |server| server['provider_name'] }
end end
   
def self.valid_provider?(provider) def self.valid_provider?(provider)
Loading
@@ -38,13 +38,31 @@ module Gitlab
Loading
@@ -38,13 +38,31 @@ module Gitlab
end end
   
def adapter_options def adapter_options
{ opts = base_options.merge(
host: options['host'], encryption: encryption,
port: options['port'], )
encryption: encryption
}.tap do |options| opts.merge!(auth_options) if has_auth?
options.merge!(auth_options) if has_auth?
opts
end
def omniauth_options
opts = base_options.merge(
base: base,
method: options['method'],
filter: omniauth_user_filter,
name_proc: name_proc
)
if has_auth?
opts.merge!(
bind_dn: options['bind_dn'],
password: options['password']
)
end end
opts
end end
   
def base def base
Loading
@@ -68,6 +86,10 @@ module Gitlab
Loading
@@ -68,6 +86,10 @@ module Gitlab
options['user_filter'] options['user_filter']
end end
   
def constructed_user_filter
@constructed_user_filter ||= Net::LDAP::Filter.construct(user_filter)
end
def group_base def group_base
options['group_base'] options['group_base']
end end
Loading
@@ -96,8 +118,27 @@ module Gitlab
Loading
@@ -96,8 +118,27 @@ module Gitlab
options['password'] || options['bind_dn'] options['password'] || options['bind_dn']
end end
   
def allow_username_or_email_login
options['allow_username_or_email_login']
end
def name_proc
if allow_username_or_email_login
Proc.new { |name| name.gsub(/@.*\z/, '') }
else
Proc.new { |name| name }
end
end
protected protected
   
def base_options
{
host: options['host'],
port: options['port']
}
end
def base_config def base_config
Gitlab.config.ldap Gitlab.config.ldap
end end
Loading
@@ -126,6 +167,16 @@ module Gitlab
Loading
@@ -126,6 +167,16 @@ module Gitlab
} }
} }
end end
def omniauth_user_filter
uid_filter = Net::LDAP::Filter.eq(uid, '%{username}')
if user_filter.present?
Net::LDAP::Filter.join(uid_filter, constructed_user_filter).to_s
else
uid_filter.to_s
end
end
end end
end end
end end
Loading
@@ -19,6 +19,87 @@ describe Gitlab::LDAP::Config, lib: true do
Loading
@@ -19,6 +19,87 @@ describe Gitlab::LDAP::Config, lib: true do
end end
end end
   
describe '#adapter_options' do
it 'constructs basic options' do
stub_ldap_config(
options: {
'host' => 'ldap.example.com',
'port' => 386,
'method' => 'plain'
}
)
expect(config.adapter_options).to eq(
host: 'ldap.example.com',
port: 386,
encryption: nil
)
end
it 'includes authentication options when auth is configured' do
stub_ldap_config(
options: {
'host' => 'ldap.example.com',
'port' => 686,
'method' => 'ssl',
'bind_dn' => 'uid=admin,dc=example,dc=com',
'password' => 'super_secret'
}
)
expect(config.adapter_options).to eq(
host: 'ldap.example.com',
port: 686,
encryption: :simple_tls,
auth: {
method: :simple,
username: 'uid=admin,dc=example,dc=com',
password: 'super_secret'
}
)
end
end
describe '#omniauth_options' do
it 'constructs basic options' do
stub_ldap_config(
options: {
'host' => 'ldap.example.com',
'port' => 386,
'base' => 'ou=users,dc=example,dc=com',
'method' => 'plain',
'uid' => 'uid'
}
)
expect(config.omniauth_options).to include(
host: 'ldap.example.com',
port: 386,
base: 'ou=users,dc=example,dc=com',
method: 'plain',
filter: '(uid=%{username})'
)
expect(config.omniauth_options.keys).not_to include(:bind_dn, :password)
end
it 'includes authentication options when auth is configured' do
stub_ldap_config(
options: {
'uid' => 'sAMAccountName',
'user_filter' => '(memberOf=cn=group1,ou=groups,dc=example,dc=com)',
'bind_dn' => 'uid=admin,dc=example,dc=com',
'password' => 'super_secret'
}
)
expect(config.omniauth_options).to include(
filter: '(&(sAMAccountName=%{username})(memberOf=cn=group1,ou=groups,dc=example,dc=com))',
bind_dn: 'uid=admin,dc=example,dc=com',
password: 'super_secret'
)
end
end
describe '#has_auth?' do describe '#has_auth?' do
it 'is true when password is set' do it 'is true when password is set' do
stub_ldap_config( stub_ldap_config(
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment