Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJan-Willem van der Meer <mail@jewilmeer.nl>2014-10-13 19:24:05 +0400
committerJan-Willem van der Meer <mail@jewilmeer.nl>2014-10-13 19:24:05 +0400
commit01b791237cf6a1b7deaee3da3df6541e0b5107d1 (patch)
treeab0ce5fae35c83d3f5e70f001616352df4eee33a /lib
parent6c0994a3b3197fe177ac804b0cd25096ff478263 (diff)
Refactor lib files for multiple LDAP groups
Diffstat (limited to 'lib')
-rw-r--r--lib/gitlab/auth.rb6
-rw-r--r--lib/gitlab/ldap/access.rb32
-rw-r--r--lib/gitlab/ldap/adapter.rb63
-rw-r--r--lib/gitlab/ldap/authentication.rb68
-rw-r--r--lib/gitlab/ldap/config.rb115
-rw-r--r--lib/gitlab/ldap/person.rb34
-rw-r--r--lib/gitlab/ldap/user.rb48
7 files changed, 252 insertions, 114 deletions
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index 955abc1bedd..f97c0247b6f 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -3,11 +3,13 @@ module Gitlab
def find(login, password)
user = User.find_by(email: login) || User.find_by(username: login)
+ # If no user is found, or it's an LDAP server, try LDAP.
+ # LDAP users are only authenticated via LDAP
if user.nil? || user.ldap_user?
# Second chance - try LDAP authentication
- return nil unless ldap_conf.enabled
+ return nil unless Gitlab::LDAP::Config.enabled?
- Gitlab::LDAP::User.authenticate(login, password)
+ Gitlab::LDAP::Authentication.login(login, password)
else
user if user.valid_password?(password)
end
diff --git a/lib/gitlab/ldap/access.rb b/lib/gitlab/ldap/access.rb
index d2235d2e3bc..111c750226f 100644
--- a/lib/gitlab/ldap/access.rb
+++ b/lib/gitlab/ldap/access.rb
@@ -1,18 +1,21 @@
+# LDAP authorization model
+#
+# * Check if we are allowed access (not blocked)
+#
module Gitlab
module LDAP
class Access
- attr_reader :adapter
+ attr_reader :adapter, :provider, :user
- def self.open(&block)
- Gitlab::LDAP::Adapter.open do |adapter|
- block.call(self.new(adapter))
+ def self.open(user, &block)
+ Gitlab::LDAP::Adapter.open(user.provider) do |adapter|
+ block.call(self.new(user, adapter))
end
end
def self.allowed?(user)
- self.open do |access|
- if access.allowed?(user)
- # GitLab EE LDAP code goes here
+ self.open(user) do |access|
+ if access.allowed?
user.last_credential_check_at = Time.now
user.save
true
@@ -22,21 +25,26 @@ module Gitlab
end
end
- def initialize(adapter=nil)
+ def initialize(user, adapter=nil)
@adapter = adapter
+ @user = user
+ @provider = user.provider
end
- def allowed?(user)
+ def allowed?
if Gitlab::LDAP::Person.find_by_dn(user.extern_uid, adapter)
- if Gitlab.config.ldap.active_directory
- !Gitlab::LDAP::Person.disabled_via_active_directory?(user.extern_uid, adapter)
- end
+ return true unless ldap_config.active_directory
+ !Gitlab::LDAP::Person.disabled_via_active_directory?(user.extern_uid, adapter)
else
false
end
rescue
false
end
+
+ def adapter
+ @adapter ||= Gitlab::LDAP::Adapter.new(provider)
+ end
end
end
end
diff --git a/lib/gitlab/ldap/adapter.rb b/lib/gitlab/ldap/adapter.rb
index 68ac1b22909..c4d0a20d89a 100644
--- a/lib/gitlab/ldap/adapter.rb
+++ b/lib/gitlab/ldap/adapter.rb
@@ -1,52 +1,25 @@
module Gitlab
module LDAP
class Adapter
- attr_reader :ldap
+ attr_reader :provider, :ldap
- def self.open(&block)
- Net::LDAP.open(adapter_options) do |ldap|
- block.call(self.new(ldap))
+ def self.open(provider, &block)
+ Net::LDAP.open(config(provider).adapter_options) do |ldap|
+ block.call(self.new(provider, ldap))
end
end
- def self.config
- Gitlab.config.ldap
+ def self.config(provider)
+ Gitlab::LDAP::Config.new(provider)
end
- def self.adapter_options
- encryption =
- case config['method'].to_s
- when 'ssl'
- :simple_tls
- when 'tls'
- :start_tls
- else
- nil
- end
-
- options = {
- host: config['host'],
- port: config['port'],
- encryption: encryption
- }
-
- auth_options = {
- auth: {
- method: :simple,
- username: config['bind_dn'],
- password: config['password']
- }
- }
-
- if config['password'] || config['bind_dn']
- options.merge!(auth_options)
- end
- options
+ def initialize(provider, ldap=nil)
+ @provider = provider
+ @ldap = ldap || Net::LDAP.new(config.adapter_options)
end
-
- def initialize(ldap=nil)
- @ldap = ldap || Net::LDAP.new(self.class.adapter_options)
+ def config
+ Gitlab::LDAP::Config.new(provider)
end
def users(field, value)
@@ -57,13 +30,13 @@ module Gitlab
}
else
options = {
- base: config['base'],
+ base: config.base,
filter: Net::LDAP::Filter.eq(field, value)
}
end
- if config['user_filter'].present?
- user_filter = Net::LDAP::Filter.construct(config['user_filter'])
+ if config.user_filter.present?
+ user_filter = Net::LDAP::Filter.construct(config.user_filter)
options[:filter] = if options[:filter]
Net::LDAP::Filter.join(options[:filter], user_filter)
@@ -77,7 +50,7 @@ module Gitlab
end
entries.map do |entry|
- Gitlab::LDAP::Person.new(entry)
+ Gitlab::LDAP::Person.new(entry, provider)
end
end
@@ -105,12 +78,6 @@ module Gitlab
results
end
end
-
- private
-
- def config
- @config ||= self.class.config
- end
end
end
end
diff --git a/lib/gitlab/ldap/authentication.rb b/lib/gitlab/ldap/authentication.rb
new file mode 100644
index 00000000000..0eca9b26133
--- /dev/null
+++ b/lib/gitlab/ldap/authentication.rb
@@ -0,0 +1,68 @@
+# This calls helps to authenticate to LDAP by providing username and password
+#
+# Since multiple LDAP servers are supported, it will loop through all of them
+# until a valid bind is found
+#
+
+module Gitlab
+ module LDAP
+ class Authentication
+ def self.login(login, password)
+ return unless Gitlab::LDAP::Config.enabled?
+ return unless login.present? && password.present?
+
+ auth = nil
+ # loop through providers until valid bind
+ providers.find do |provider|
+ auth = new(provider)
+ auth.login(login, password) # true will exit the loop
+ end
+
+ auth.user
+ end
+
+ def self.providers
+ Gitlab::LDAP::Config.providers
+ end
+
+ attr_accessor :provider, :ldap_user
+
+ def initialize(provider)
+ @provider = provider
+ end
+
+ def login(login, password)
+ @ldap_user = adapter.bind_as(
+ filter: user_filter(login),
+ size: 1,
+ password: password
+ )
+ end
+
+ def adapter
+ OmniAuth::LDAP::Adaptor.new(config.options)
+ end
+
+ def config
+ Gitlab::LDAP::Config.new(provider)
+ end
+
+ def user_filter(login)
+ Net::LDAP::Filter.eq(config.uid, login).tap do |filter|
+ # Apply LDAP user filter if present
+ if config.user_filter.present?
+ Net::LDAP::Filter.join(
+ filter,
+ Net::LDAP::Filter.construct(config.user_filter)
+ )
+ end
+ end
+ end
+
+ def user
+ return nil unless ldap_user
+ Gitlab::LDAP::User.find_by_uid_and_provider(ldap_user.dn, provider)
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/lib/gitlab/ldap/config.rb b/lib/gitlab/ldap/config.rb
new file mode 100644
index 00000000000..697b66dcdaa
--- /dev/null
+++ b/lib/gitlab/ldap/config.rb
@@ -0,0 +1,115 @@
+# Load a specific server configuration
+module Gitlab
+ module LDAP
+ class Config
+ attr_accessor :provider, :options
+
+ def self.enabled?
+ Gitlab.config.ldap.enabled
+ end
+
+ def self.servers
+ Gitlab.config.ldap.servers
+ end
+
+ def self.providers
+ servers.map &:provider_name
+ end
+
+ def initialize(provider)
+ @provider = provider
+ invalid_provider unless valid_provider?
+ @options = config_for(provider)
+ end
+
+ def enabled?
+ base_config.enabled
+ end
+
+ def adapter_options
+ {
+ host: options['host'],
+ port: options['port'],
+ encryption: encryption
+ }.tap do |options|
+ options.merge!(auth_options) if has_auth?
+ end
+ end
+
+ def base
+ options['base']
+ end
+
+ def uid
+ options['uid']
+ end
+
+ def sync_ssh_keys?
+ sync_ssh_keys.present?
+ end
+
+ # The LDAP attribute in which the ssh keys are stored
+ def sync_ssh_keys
+ options['sync_ssh_keys']
+ end
+
+ def user_filter
+ options['user_filter']
+ end
+
+ def group_base
+ options['group_base']
+ end
+
+ def admin_group
+ options['admin_group']
+ end
+
+ def active_directory
+ options['active_directory']
+ end
+
+ protected
+ def base_config
+ Gitlab.config.ldap
+ end
+
+ def config_for(provider)
+ base_config.servers.find { |server| server.provider_name == provider }
+ end
+
+ def encryption
+ case options['method'].to_s
+ when 'ssl'
+ :simple_tls
+ when 'tls'
+ :start_tls
+ else
+ nil
+ end
+ end
+
+ def valid_provider?
+ self.class.providers.include?(provider)
+ end
+
+ def invalid_provider
+ raise "Unknown provider (#{provider}). Available providers: #{self.class.providers}"
+ end
+
+ def auth_options
+ {
+ auth: {
+ method: :simple,
+ username: options['bind_dn'],
+ password: options['password']
+ }
+ }
+ end
+
+ def has_auth?
+ options['password'] || options['bind_dn']
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ldap/person.rb b/lib/gitlab/ldap/person.rb
index 87c3d711db4..a35fd22073e 100644
--- a/lib/gitlab/ldap/person.rb
+++ b/lib/gitlab/ldap/person.rb
@@ -6,24 +6,24 @@ module Gitlab
# Source: http://ctogonewild.com/2009/09/03/bitmask-searches-in-ldap/
AD_USER_DISABLED = Net::LDAP::Filter.ex("userAccountControl:1.2.840.113556.1.4.803", "2")
- def self.find_by_uid(uid, adapter=nil)
- adapter ||= Gitlab::LDAP::Adapter.new
- adapter.user(config.uid, uid)
+ attr_accessor :entry, :provider
+
+ def self.find_by_uid(uid, adapter)
+ adapter.user(Gitlab.config.ldap.uid, uid)
end
- def self.find_by_dn(dn, adapter=nil)
- adapter ||= Gitlab::LDAP::Adapter.new
+ def self.find_by_dn(dn, adapter)
adapter.user('dn', dn)
end
- def self.disabled_via_active_directory?(dn, adapter=nil)
- adapter ||= Gitlab::LDAP::Adapter.new
+ def self.disabled_via_active_directory?(dn, adapter)
adapter.dn_matches_filter?(dn, AD_USER_DISABLED)
end
- def initialize(entry)
+ def initialize(entry, provider)
Rails.logger.debug { "Instantiating #{self.class.name} with LDIF:\n#{entry.to_ldif}" }
@entry = entry
+ @provider = provider
end
def name
@@ -38,22 +38,30 @@ module Gitlab
uid
end
+ def email
+ entry.try(:mail)
+ end
+
def dn
entry.dn
end
+ def ssh_keys
+ if config.sync_ssh_keys? && entry.respond_to?(config.sync_ssh_keys)
+ entry[config.sync_ssh_keys.to_sym]
+ else
+ []
+ end
+ end
+
private
def entry
@entry
end
- def adapter
- @adapter ||= Gitlab::LDAP::Adapter.new
- end
-
def config
- @config ||= Gitlab.config.ldap
+ @config ||= Gitlab::LDAP::Config.new(provider)
end
end
end
diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb
index 006ef170726..3069027a421 100644
--- a/lib/gitlab/ldap/user.rb
+++ b/lib/gitlab/ldap/user.rb
@@ -10,45 +10,11 @@ module Gitlab
module LDAP
class User < Gitlab::OAuth::User
class << self
- def authenticate(login, password)
- # Check user against LDAP backend if user is not authenticated
- # Only check with valid login and password to prevent anonymous bind results
- return nil unless ldap_conf.enabled && login.present? && password.present?
-
- ldap_user = adapter.bind_as(
- filter: user_filter(login),
- size: 1,
- password: password
- )
-
- find_by_uid(ldap_user.dn) if ldap_user
- end
-
- def adapter
- @adapter ||= OmniAuth::LDAP::Adaptor.new(ldap_conf)
- end
-
- def user_filter(login)
- filter = Net::LDAP::Filter.eq(adapter.uid, login)
- # Apply LDAP user filter if present
- if ldap_conf['user_filter'].present?
- user_filter = Net::LDAP::Filter.construct(ldap_conf['user_filter'])
- filter = Net::LDAP::Filter.join(filter, user_filter)
- end
- filter
- end
-
- def ldap_conf
- Gitlab.config.ldap
- end
-
- def find_by_uid(uid)
+ def find_by_uid_and_provider(uid, provider)
# LDAP distinguished name is case-insensitive
- model.where("provider = ? and lower(extern_uid) = ?", provider, uid.downcase).last
- end
-
- def provider
- 'ldap'
+ ::User.
+ where(provider: [provider, :ldap]).
+ where('lower(extern_uid) = ?', uid.downcase).last
end
end
@@ -65,7 +31,7 @@ module Gitlab
def find_by_uid_and_provider
# LDAP distinguished name is case-insensitive
model.
- where(provider: auth_hash.provider).
+ where(provider: [auth_hash.provider, :ldap]).
where('lower(extern_uid) = ?', auth_hash.uid.downcase).last
end
@@ -88,6 +54,10 @@ module Gitlab
def needs_blocking?
false
end
+
+ def allowed?
+ Gitlab::LDAP::Access.allowed?(gl_user)
+ end
end
end
end