ldap_fluff 0.2.5 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ldap_fluff might be problematic. Click here for more details.

@@ -18,17 +18,23 @@ class LdapFluff
18
18
  end
19
19
  end
20
20
 
21
- # return true if the user password combination
22
- # authenticates the user, otherwise false
23
21
  def authenticate?(uid, password)
24
22
  if password.nil? || password.empty?
25
- # protect against passwordless auth from ldap server
26
- return false
23
+ false
27
24
  else
28
- @ldap.bind? uid, password
25
+ !!@ldap.bind?(uid, password)
29
26
  end
30
27
  end
31
28
 
29
+ def test
30
+ @ldap.ldap.open {}
31
+ end
32
+
33
+ # return a list[] of users for a given gid
34
+ def user_list(gid)
35
+ @ldap.users_for_gid(gid)
36
+ end
37
+
32
38
  # return a list[] of groups for a given uid
33
39
  def group_list(uid)
34
40
  @ldap.groups_for_uid(uid)
@@ -50,4 +56,13 @@ class LdapFluff
50
56
  @ldap.group_exists? gid
51
57
  end
52
58
 
59
+ # return ldap entry
60
+ def find_user(uid)
61
+ @ldap.member_service.find_user(uid)
62
+ end
63
+
64
+ # return ldap entry
65
+ def find_group(gid)
66
+ @ldap.member_service.find_group(gid)
67
+ end
53
68
  end
@@ -1,25 +1,14 @@
1
- class LdapFluff::Posix
2
-
3
- attr_accessor :ldap, :member_service
1
+ class LdapFluff::Posix < LdapFluff::Generic
4
2
 
5
3
  def initialize(config = {})
6
- @ldap = Net::LDAP.new(:host => config.host,
7
- :base => config.base_dn,
8
- :port => config.port,
9
- :encryption => config.encryption)
10
- @group_base = config.group_base || config.base_dn
11
4
  @base = config.base_dn
12
- @member_service = MemberService.new(@ldap, @group_base)
5
+ super
13
6
  end
14
7
 
15
8
  def bind?(uid = nil, password = nil)
16
9
  @ldap.bind_as(:filter => "(uid=#{uid})", :password => password)
17
10
  end
18
11
 
19
- def groups_for_uid(uid)
20
- @member_service.find_user_groups(uid)
21
- end
22
-
23
12
  # returns whether a user is a member of ALL or ANY particular groups
24
13
  # note: this method is much faster than groups_for_uid
25
14
  #
@@ -31,22 +20,23 @@ class LdapFluff::Posix
31
20
  (gids.empty? || @member_service.times_in_groups(uid, gids, all) > 0)
32
21
  end
33
22
 
34
- def user_exists?(uid)
35
- begin
36
- @member_service.find_user(uid)
37
- rescue MemberService::UIDNotFoundException
38
- return false
39
- end
40
- return true
41
- end
23
+ private
42
24
 
43
- def group_exists?(gid)
44
- begin
45
- @member_service.find_group(gid)
46
- rescue MemberService::GIDNotFoundException
47
- return false
25
+ def users_from_search_results(search, method)
26
+ # To find groups in standard LDAP without group membership attributes
27
+ # we have to look for OUs or posixGroups within the current group scope,
28
+ # i.e: cn=ldapusers,ou=groups,dc=example,dc=com -> cn=myusers,cn=ldapusers,ou=gr...
29
+
30
+ groups = @ldap.search(:base => search.dn,
31
+ :filter => Net::LDAP::Filter.eq('objectClass','posixGroup') |
32
+ Net::LDAP::Filter.eq('objectClass', 'organizationalunit'))
33
+
34
+ members = groups.map { |group| group.send(method) }.flatten.uniq
35
+
36
+ if method == :memberuid
37
+ members
38
+ else
39
+ @member_service.get_logins(members)
48
40
  end
49
- return true
50
41
  end
51
-
52
42
  end
@@ -1,37 +1,29 @@
1
1
  require 'net/ldap'
2
2
 
3
3
  # handles the naughty bits of posix ldap
4
- class LdapFluff::Posix::MemberService
4
+ class LdapFluff::Posix::MemberService < LdapFluff::GenericMemberService
5
5
 
6
- attr_accessor :ldap
6
+ def initialize(ldap, config)
7
+ @attr_login = (config.attr_login || 'memberuid')
8
+ super
9
+ end
7
10
 
8
- def initialize(ldap, group_base)
9
- @ldap = ldap
10
- @group_base = group_base
11
+ def find_user(uid)
12
+ user = @ldap.search(:filter => name_filter(uid), :base => @group_base)
13
+ raise UIDNotFoundException if (user.nil? || user.empty?)
14
+ user
11
15
  end
12
16
 
13
17
  # return an ldap user with groups attached
14
18
  # note : this method is not particularly fast for large ldap systems
15
19
  def find_user_groups(uid)
16
20
  groups = []
17
- find_user(uid).each do |entry|
21
+ @ldap.search(:filter => Net::LDAP::Filter.eq('memberuid', uid)).each do |entry|
18
22
  groups << entry[:cn][0]
19
23
  end
20
24
  groups
21
25
  end
22
26
 
23
- def find_user(uid)
24
- user = @ldap.search(:filter => name_filter(uid), :base => @group_base)
25
- raise UIDNotFoundException if (user.nil? || user.empty?)
26
- user
27
- end
28
-
29
- def find_group(gid)
30
- group = @ldap.search(:filter => group_filter(gid), :base => @group_base)
31
- raise GIDNotFoundException if (group.nil? || group.empty?)
32
- group
33
- end
34
-
35
27
  def times_in_groups(uid, gids, all)
36
28
  filters = []
37
29
  gids.each do |cn|
@@ -42,14 +34,6 @@ class LdapFluff::Posix::MemberService
42
34
  @ldap.search(:base => @group_base, :filter => filter).size
43
35
  end
44
36
 
45
- def name_filter(uid)
46
- Net::LDAP::Filter.eq("memberUid", uid)
47
- end
48
-
49
- def group_filter(cn)
50
- Net::LDAP::Filter.eq("cn", cn)
51
- end
52
-
53
37
  # AND or OR all of the filters together
54
38
  def merge_filters(filters = [], all = false)
55
39
  if !filters.nil? && filters.size >= 1
@@ -61,10 +45,10 @@ class LdapFluff::Posix::MemberService
61
45
  end
62
46
  end
63
47
 
64
- class UIDNotFoundException < StandardError
48
+ class UIDNotFoundException < LdapFluff::Error
65
49
  end
66
50
 
67
- class GIDNotFoundException < StandardError
51
+ class GIDNotFoundException < LdapFluff::Error
68
52
  end
69
53
 
70
54
  end
data/lib/ldap_fluff.rb CHANGED
@@ -1,5 +1,8 @@
1
+ require 'ldap_fluff/error'
1
2
  require 'ldap_fluff/config'
2
3
  require 'ldap_fluff/ldap_fluff'
4
+ require 'ldap_fluff/generic'
5
+ require 'ldap_fluff/generic_member_service'
3
6
  require 'ldap_fluff/active_directory'
4
7
  require 'ldap_fluff/ad_member_service'
5
8
  require 'ldap_fluff/posix'
@@ -4,9 +4,8 @@ class TestADMemberService < MiniTest::Test
4
4
  include LdapTestHelper
5
5
 
6
6
  def setup
7
- config
8
- @ldap = MiniTest::Mock.new
9
- @adms = LdapFluff::ActiveDirectory::MemberService.new(@ldap, @config.group_base)
7
+ super
8
+ @adms = LdapFluff::ActiveDirectory::MemberService.new(@ldap, @config)
10
9
  @gfilter = group_filter('group') & group_class_filter
11
10
  end
12
11
 
data/test/ad_test.rb CHANGED
@@ -4,40 +4,24 @@ class TestAD < MiniTest::Test
4
4
  include LdapTestHelper
5
5
 
6
6
  def setup
7
- config
7
+ super
8
8
  @ad = LdapFluff::ActiveDirectory.new(@config)
9
- @ldap = MiniTest::Mock.new
10
9
  end
11
10
 
12
11
  # default setup for service bind users
13
12
  def service_bind
14
- @ldap.expect(:auth, nil, %w(service@internet.com pass))
15
- @ldap.expect(:bind, true)
16
- @ad.ldap = @ldap
17
- end
18
-
19
- def basic_user
20
- @md = MiniTest::Mock.new
21
- @md.expect(:find_user_groups, %w(bros), %w(john))
22
- @ad.member_service = @md
23
- end
24
-
25
- def bigtime_user
26
- @md = MiniTest::Mock.new
27
- @md.expect(:find_user_groups, %w(bros broskies), %w(john))
28
- @ad.member_service = @md
13
+ @ldap.expect(:auth, nil, %w(service pass))
14
+ super
29
15
  end
30
16
 
31
17
  def test_good_bind
32
- @ldap.expect(:auth, nil, %w(internet@internet.com password))
33
- @ldap.expect(:bind, true)
34
- @ad.ldap = @ldap
35
- assert_equal(@ad.bind?("internet", "password"), true)
18
+ service_bind
19
+ assert_equal(@ad.bind?('service', 'pass'), true)
36
20
  @ldap.verify
37
21
  end
38
22
 
39
23
  def test_bad_bind
40
- @ldap.expect(:auth, nil, %w(internet@internet.com password))
24
+ @ldap.expect(:auth, nil, %w(internet password))
41
25
  @ldap.expect(:bind, false)
42
26
  @ad.ldap = @ldap
43
27
  assert_equal(@ad.bind?("internet", "password"), false)
@@ -52,20 +36,20 @@ class TestAD < MiniTest::Test
52
36
 
53
37
  def test_bad_user
54
38
  service_bind
55
- @md = MiniTest::Mock.new
56
- @md.expect(:find_user_groups, nil, %w(john))
57
- def @md.find_user_groups(*args)
39
+ md = MiniTest::Mock.new
40
+ md.expect(:find_user_groups, nil, %w(john))
41
+ def md.find_user_groups(*args)
58
42
  raise LdapFluff::ActiveDirectory::MemberService::UIDNotFoundException
59
43
  end
60
- @ad.member_service = @md
44
+ @ad.member_service = md
61
45
  assert_equal(@ad.groups_for_uid('john'), [])
62
46
  end
63
47
 
64
48
  def test_bad_service_user
65
- @ldap.expect(:auth, nil, %w(service@internet.com pass))
49
+ @ldap.expect(:auth, nil, %w(service pass))
66
50
  @ldap.expect(:bind, false)
67
51
  @ad.ldap = @ldap
68
- assert_raises(LdapFluff::ActiveDirectory::UnauthenticatedActiveDirectoryException) do
52
+ assert_raises(LdapFluff::ActiveDirectory::UnauthenticatedException) do
69
53
  @ad.groups_for_uid('john')
70
54
  end
71
55
  end
@@ -101,41 +85,63 @@ class TestAD < MiniTest::Test
101
85
  end
102
86
 
103
87
  def test_user_exists
104
- @md = MiniTest::Mock.new
105
- @md.expect(:find_user, 'notnilluser', %w(john))
106
- @ad.member_service = @md
88
+ md = MiniTest::Mock.new
89
+ md.expect(:find_user, 'notnilluser', %w(john))
90
+ @ad.member_service = md
107
91
  service_bind
108
92
  assert(@ad.user_exists?('john'))
109
93
  end
110
94
 
111
95
  def test_missing_user
112
- @md = MiniTest::Mock.new
113
- @md.expect(:find_user, nil, %w(john))
114
- def @md.find_user(uid)
96
+ md = MiniTest::Mock.new
97
+ md.expect(:find_user, nil, %w(john))
98
+ def md.find_user(uid)
115
99
  raise LdapFluff::ActiveDirectory::MemberService::UIDNotFoundException
116
100
  end
117
- @ad.member_service = @md
101
+ @ad.member_service = md
118
102
  service_bind
119
103
  refute(@ad.user_exists?('john'))
120
104
  end
121
105
 
122
106
  def test_group_exists
123
- @md = MiniTest::Mock.new
124
- @md.expect(:find_group, 'notnillgroup', %w(broskies))
125
- @ad.member_service = @md
107
+ md = MiniTest::Mock.new
108
+ md.expect(:find_group, 'notnillgroup', %w(broskies))
109
+ @ad.member_service = md
126
110
  service_bind
127
111
  assert(@ad.group_exists?('broskies'))
128
112
  end
129
113
 
130
114
  def test_missing_group
131
- @md = MiniTest::Mock.new
132
- @md.expect(:find_group, nil, %w(broskies))
133
- def @md.find_group(uid)
115
+ md = MiniTest::Mock.new
116
+ md.expect(:find_group, nil, %w(broskies))
117
+ def md.find_group(uid)
134
118
  raise LdapFluff::ActiveDirectory::MemberService::GIDNotFoundException
135
119
  end
136
- @ad.member_service = @md
120
+ @ad.member_service = md
137
121
  service_bind
138
122
  refute(@ad.group_exists?('broskies'))
139
123
  end
140
124
 
125
+ def test_find_users_in_nested_groups
126
+ group = Net::LDAP::Entry.new('foremaners')
127
+ nested_group = Net::LDAP::Entry.new('katellers')
128
+ nested_user = Net::LDAP::Entry.new('testuser')
129
+
130
+ group[:member] = ['CN=katellers,DC=corp,DC=windows,DC=com']
131
+ nested_group[:member] = ['CN=testuser,CN=Users,DC=corp,DC=windows,DC=com']
132
+ nested_group[:objectclass] = ['organizationalunit']
133
+ nested_user[:objectclass] = ['person']
134
+
135
+ md = MiniTest::Mock.new
136
+ 2.times { md.expect(:find_group, [group], ['foremaners']) }
137
+ 2.times { md.expect(:find_group, [nested_group], ['katellers']) }
138
+ 2.times { service_bind }
139
+
140
+ md.expect(:find_user, [nested_group], ['katellers'])
141
+ md.expect(:find_user, [nested_user], ['testuser'])
142
+ md.expect(:get_logins, 'testuser', [nested_group.member])
143
+ @ad.member_service = md
144
+ assert_equal @ad.users_for_gid('foremaners'), ['testuser']
145
+ end
146
+
141
147
  end
data/test/config_test.rb CHANGED
@@ -4,7 +4,7 @@ class ConfigTest < MiniTest::Test
4
4
  include LdapTestHelper
5
5
 
6
6
  def test_unsupported_type
7
- assert_raises(LdapFluff::ConfigError) { LdapFluff.new(config_hash.update :server_type => 'inactive_directory') }
7
+ assert_raises(LdapFluff::Config::ConfigError) { LdapFluff.new(config_hash.update :server_type => 'inactive_directory') }
8
8
  end
9
9
 
10
10
  def test_load_posix
@@ -4,9 +4,8 @@ class TestIPAMemberService < MiniTest::Test
4
4
  include LdapTestHelper
5
5
 
6
6
  def setup
7
- config
8
- @ldap = MiniTest::Mock.new
9
- @ipams = LdapFluff::FreeIPA::MemberService.new(@ldap, @config.group_base)
7
+ super
8
+ @ipams = LdapFluff::FreeIPA::MemberService.new(@ldap, @config)
10
9
  end
11
10
 
12
11
  def basic_user
data/test/ipa_test.rb CHANGED
@@ -4,35 +4,19 @@ class TestIPA < MiniTest::Test
4
4
  include LdapTestHelper
5
5
 
6
6
  def setup
7
- config
8
- @ipa = LdapFluff::FreeIPA.new(@config)
9
- @ldap = MiniTest::Mock.new
7
+ super
8
+ @ipa = LdapFluff::FreeIPA.new(@config)
10
9
  end
11
10
 
12
11
  # default setup for service bind users
13
12
  def service_bind
14
13
  @ldap.expect(:auth, nil, [ipa_user_bind('service'), "pass"])
15
- @ldap.expect(:bind, true)
16
- @ipa.ldap = @ldap
17
- end
18
-
19
- def basic_user
20
- @md = MiniTest::Mock.new
21
- @md.expect(:find_user_groups, %w(bros), %w(john))
22
- @ipa.member_service = @md
23
- end
24
-
25
- def bigtime_user
26
- @md = MiniTest::Mock.new
27
- @md.expect(:find_user_groups, %w(bros broskies), %w(john))
28
- @ipa.member_service = @md
14
+ super
29
15
  end
30
16
 
31
17
  def test_good_bind
32
- @ldap.expect(:auth, nil, [ipa_user_bind('internet'), "password"])
33
- @ldap.expect(:bind, true)
34
- @ipa.ldap = @ldap
35
- assert_equal(@ipa.bind?("internet", "password"), true)
18
+ service_bind
19
+ assert_equal(@ipa.bind?('service', 'pass'), true)
36
20
  @ldap.verify
37
21
  end
38
22
 
@@ -65,7 +49,7 @@ class TestIPA < MiniTest::Test
65
49
  @ldap.expect(:auth, nil, [ipa_user_bind('service'), "pass"])
66
50
  @ldap.expect(:bind, false)
67
51
  @ipa.ldap = @ldap
68
- assert_raises(LdapFluff::FreeIPA::UnauthenticatedFreeIPAException) do
52
+ assert_raises(LdapFluff::FreeIPA::UnauthenticatedException) do
69
53
  @ipa.groups_for_uid('john')
70
54
  end
71
55
  end
@@ -138,5 +122,23 @@ class TestIPA < MiniTest::Test
138
122
  refute(@ipa.group_exists?('broskies'))
139
123
  end
140
124
 
125
+ def test_find_users_in_nested_groups
126
+ group = Net::LDAP::Entry.new('gid=foremaners,cn=Groups,cn=accounts,dc=localdomain')
127
+ group[:member] = ['gid=katellers,cn=Groups,cn=accounts,dc=localdomain']
128
+ nested_group = Net::LDAP::Entry.new('gid=katellers,cn=Groups,cn=accounts,dc=localdomain')
129
+ nested_group[:member] = ['uid=testuser,cn=users,cn=accounts,dc=localdomain']
130
+
131
+ md = MiniTest::Mock.new
132
+ 2.times { md.expect(:find_group, [group], ['foremaners']) }
133
+ 2.times { md.expect(:find_group, [nested_group], ['katellers']) }
134
+ 2.times { service_bind }
135
+ md.expect(:get_logins, ['testuser'], [['uid=testuser,cn=users,cn=accounts,dc=localdomain']])
136
+
137
+ @ipa.member_service = md
138
+
139
+ assert_equal @ipa.users_for_gid('foremaners'), ['testuser']
140
+ md.verify
141
+ end
142
+
141
143
  end
142
144
 
data/test/ldap_test.rb CHANGED
@@ -4,8 +4,7 @@ class TestLDAP < MiniTest::Test
4
4
  include LdapTestHelper
5
5
 
6
6
  def setup
7
- config
8
- @ldap = MiniTest::Mock.new
7
+ super
9
8
  @fluff = LdapFluff.new(config_hash)
10
9
  end
11
10
 
@@ -7,22 +7,45 @@ module LdapTestHelper
7
7
  attr_accessor :group_base, :class_filter, :user
8
8
 
9
9
  def config_hash
10
- { :host => "internet.com",
11
- :port => "387",
12
- :encryption => :start_tls,
13
- :base_dn => "dc=internet,dc=com",
14
- :group_base => "ou=group,dc=internet,dc=com",
15
- :service_user => "service",
16
- :service_pass => "pass",
17
- :ad_domain => "internet.com",
18
- :server_type => :free_ipa
10
+ { :host => "internet.com",
11
+ :port => "387",
12
+ :encryption => :start_tls,
13
+ :base_dn => "dc=internet,dc=com",
14
+ :group_base => "ou=group,dc=internet,dc=com",
15
+ :service_user => "service",
16
+ :service_pass => "pass",
17
+ :server_type => :free_ipa,
18
+ :attr_login => nil,
19
+ :search_filter => nil
19
20
  }
20
21
  end
21
22
 
23
+ def setup
24
+ config
25
+ @ldap = MiniTest::Mock.new
26
+ end
27
+
22
28
  def config
23
29
  @config ||= LdapFluff::Config.new config_hash
24
30
  end
25
31
 
32
+ def service_bind
33
+ @ldap.expect(:bind, true)
34
+ get_test_instance_variable.ldap = @ldap
35
+ end
36
+
37
+ def basic_user
38
+ @md = MiniTest::Mock.new
39
+ @md.expect(:find_user_groups, %w(bros), %w(john))
40
+ get_test_instance_variable.member_service = @md
41
+ end
42
+
43
+ def bigtime_user
44
+ @md = MiniTest::Mock.new
45
+ @md.expect(:find_user_groups, %w(bros broskies), %w(john))
46
+ get_test_instance_variable.member_service = @md
47
+ end
48
+
26
49
  def ad_name_filter(name)
27
50
  Net::LDAP::Filter.eq("samaccountname", name)
28
51
  end
@@ -52,19 +75,19 @@ module LdapTestHelper
52
75
  end
53
76
 
54
77
  def ad_user_payload
55
- [{ :memberof => ["CN=group,dc=internet,dc=com"] }]
78
+ [{ :memberof => ["cn=group,dc=internet,dc=com"] }]
56
79
  end
57
80
 
58
81
  def ad_group_payload
59
- [{ :cn => "broze", :memberof => ["CN=group,dc=internet,dc=com"] }]
82
+ [{ :cn => "broze", :memberof => ["cn=group,dc=internet,dc=com"] }]
60
83
  end
61
84
 
62
85
  def ad_parent_payload(num)
63
- [{ :memberof => ["CN=bros#{num},dc=internet,dc=com"] }]
86
+ [{ :memberof => ["cn=bros#{num},dc=internet,dc=com"] }]
64
87
  end
65
88
 
66
89
  def ad_double_payload(num)
67
- [{ :memberof => ["CN=bros#{num},dc=internet,dc=com", "CN=broskies#{num},dc=internet,dc=com"] }]
90
+ [{ :memberof => ["cn=bros#{num},dc=internet,dc=com", "cn=broskies#{num},dc=internet,dc=com"] }]
68
91
  end
69
92
 
70
93
  def posix_user_payload
@@ -82,4 +105,10 @@ module LdapTestHelper
82
105
  def ipa_group_payload
83
106
  [{ :cn => 'group' }, { :memberof => ['cn=group,dc=internet,dc=com', 'cn=bros,dc=internet,dc=com'] }]
84
107
  end
108
+
109
+ private
110
+
111
+ def get_test_instance_variable
112
+ instance_variable_get("@#{self.class.to_s.underscore.split('_')[1..-1].join}")
113
+ end
85
114
  end
@@ -4,9 +4,8 @@ class TestPosixMemberService < MiniTest::Test
4
4
  include LdapTestHelper
5
5
 
6
6
  def setup
7
- config
8
- @ldap = MiniTest::Mock.new
9
- @ms = LdapFluff::Posix::MemberService.new(@ldap, @config.group_base)
7
+ super
8
+ @ms = LdapFluff::Posix::MemberService.new(@ldap, @config)
10
9
  end
11
10
 
12
11
  def test_find_user
@@ -14,6 +13,14 @@ class TestPosixMemberService < MiniTest::Test
14
13
  @ldap.expect(:search, user, [:filter => @ms.name_filter('john'),
15
14
  :base => config.group_base])
16
15
  @ms.ldap = @ldap
16
+ assert_equal posix_user_payload, @ms.find_user('john')
17
+ @ldap.verify
18
+ end
19
+
20
+ def test_find_user_groups
21
+ user = posix_user_payload
22
+ @ldap.expect(:search, user, [:filter => @ms.name_filter('john')])
23
+ @ms.ldap = @ldap
17
24
  assert_equal ['bros'], @ms.find_user_groups('john')
18
25
  @ldap.verify
19
26
  end