Commit daa7f077db81f3ecc3417419b7f74b157bb3fda3

Authored by Dmitriy Zaporozhets
1 parent 0142aa5a

Port LDAP code from EE

Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
lib/gitlab/ldap/access.rb 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +#-------------------------------------------------------------------
  2 +#
  3 +# Copyright (C) 2013 GitLab.com - Distributed under the MIT Expat License
  4 +#
  5 +#-------------------------------------------------------------------
  6 +
  7 +module Gitlab
  8 + module LDAP
  9 + class Access
  10 + def allowed?(user)
  11 + !!Gitlab::LDAP::Person.find_by_dn(user.extern_uid)
  12 + rescue
  13 + false
  14 + end
  15 + end
  16 + end
  17 +end
... ...
lib/gitlab/ldap/adapter.rb 0 → 100644
... ... @@ -0,0 +1,78 @@
  1 +#-------------------------------------------------------------------
  2 +#
  3 +# Copyright (C) 2013 GitLab.com - Distributed under the MIT Expat License
  4 +#
  5 +#-------------------------------------------------------------------
  6 +
  7 +module Gitlab
  8 + module LDAP
  9 + class Adapter
  10 + attr_reader :ldap
  11 +
  12 + def initialize
  13 + encryption = config['method'].to_s == 'ssl' ? :simple_tls : nil
  14 +
  15 + options = {
  16 + host: config['host'],
  17 + port: config['port'],
  18 + encryption: encryption
  19 + }
  20 +
  21 + auth_options = {
  22 + auth: {
  23 + method: :simple,
  24 + username: config['bind_dn'],
  25 + password: config['password']
  26 + }
  27 + }
  28 +
  29 + if config['password'] || config['bind_dn']
  30 + options.merge!(auth_options)
  31 + end
  32 +
  33 + @ldap = Net::LDAP.new(options)
  34 + end
  35 +
  36 + def users(field, value)
  37 + if field.to_sym == :dn
  38 + options = {
  39 + base: value
  40 + }
  41 + else
  42 + options = {
  43 + base: config['base'],
  44 + filter: Net::LDAP::Filter.eq(field, value)
  45 + }
  46 + end
  47 +
  48 + if config['user_filter'].present?
  49 + user_filter = Net::LDAP::Filter.construct(config['user_filter'])
  50 +
  51 + options[:filter] = if options[:filter]
  52 + Net::LDAP::Filter.join(options[:filter], user_filter)
  53 + else
  54 + user_filter
  55 + end
  56 + end
  57 +
  58 + entries = ldap.search(options).select do |entry|
  59 + entry.respond_to? config.uid
  60 + end
  61 +
  62 + entries.map do |entry|
  63 + Gitlab::LDAP::Person.new(entry)
  64 + end
  65 + end
  66 +
  67 + def user(*args)
  68 + users(*args).first
  69 + end
  70 +
  71 + private
  72 +
  73 + def config
  74 + @config ||= Gitlab.config.ldap
  75 + end
  76 + end
  77 + end
  78 +end
... ...
lib/gitlab/ldap/person.rb 0 → 100644
... ... @@ -0,0 +1,54 @@
  1 +#-------------------------------------------------------------------
  2 +#
  3 +# Copyright (C) 2013 GitLab.com - Distributed under the MIT Expat License
  4 +#
  5 +#-------------------------------------------------------------------
  6 +
  7 +module Gitlab
  8 + module LDAP
  9 + class Person
  10 + def self.find_by_uid(uid)
  11 + Gitlab::LDAP::Adapter.new.user(config.uid, uid)
  12 + end
  13 +
  14 + def self.find_by_dn(dn)
  15 + Gitlab::LDAP::Adapter.new.user('dn', dn)
  16 + end
  17 +
  18 + def initialize(entry)
  19 + Rails.logger.debug { "Instantiating #{self.class.name} with LDIF:\n#{entry.to_ldif}" }
  20 + @entry = entry
  21 + end
  22 +
  23 + def name
  24 + entry.cn.first
  25 + end
  26 +
  27 + def uid
  28 + entry.send(config.uid).first
  29 + end
  30 +
  31 + def username
  32 + uid
  33 + end
  34 +
  35 + def dn
  36 + entry.dn
  37 + end
  38 +
  39 + private
  40 +
  41 + def entry
  42 + @entry
  43 + end
  44 +
  45 + def adapter
  46 + @adapter ||= Gitlab::LDAP::Adapter.new
  47 + end
  48 +
  49 + def config
  50 + @config ||= Gitlab.config.ldap
  51 + end
  52 + end
  53 + end
  54 +end
... ...
lib/gitlab/ldap/user.rb
... ... @@ -13,8 +13,8 @@ module Gitlab
13 13 def find_or_create(auth)
14 14 @auth = auth
15 15  
16   - if uid.blank? || email.blank?
17   - raise_error("Account must provide an uid and email address")
  16 + if uid.blank? || email.blank? || username.blank?
  17 + raise_error("Account must provide a dn, uid and email address")
18 18 end
19 19  
20 20 user = find(auth)
... ... @@ -62,8 +62,16 @@ module Gitlab
62 62 return nil unless ldap_conf.enabled && login.present? && password.present?
63 63  
64 64 ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf)
  65 + filter = Net::LDAP::Filter.eq(ldap.uid, login)
  66 +
  67 + # Apply LDAP user filter if present
  68 + if ldap_conf['user_filter'].present?
  69 + user_filter = Net::LDAP::Filter.construct(ldap_conf['user_filter'])
  70 + filter = Net::LDAP::Filter.join(filter, user_filter)
  71 + end
  72 +
65 73 ldap_user = ldap.bind_as(
66   - filter: Net::LDAP::Filter.eq(ldap.uid, login),
  74 + filter: filter,
67 75 size: 1,
68 76 password: password
69 77 )
... ... @@ -71,22 +79,20 @@ module Gitlab
71 79 find_by_uid(ldap_user.dn) if ldap_user
72 80 end
73 81  
74   - # Check LDAP user existance by dn. User in git over ssh check
75   - #
76   - # It covers 2 cases:
77   - # * when ldap account was removed
78   - # * when ldap account was deactivated by change of OU membership in 'dn'
79   - def blocked?(dn)
80   - ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf)
81   - ldap.connection.search(base: dn, scope: Net::LDAP::SearchScope_BaseObject, size: 1).blank?
82   - end
83   -
84 82 private
85 83  
86 84 def find_by_uid(uid)
87 85 model.where(provider: provider, extern_uid: uid).last
88 86 end
89 87  
  88 + def username
  89 + (auth.info.nickname || samaccountname).to_s.force_encoding("utf-8")
  90 + end
  91 +
  92 + def samaccountname
  93 + (auth.extra[:raw_info][:samaccountname] || []).first
  94 + end
  95 +
90 96 def provider
91 97 'ldap'
92 98 end
... ...