ldap_fluff 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c6a3d7c2ebc986e4ff3738e42f1539a93611fedff9eb399a6fc606f14f11a40a
4
- data.tar.gz: 9d53b1528ff20d5c44d547b3fc6dec041d3aa6bb6e915d8d7e96186fc77ec04d
3
+ metadata.gz: '0269885f166972ce577c89c74a20c50f09d0e82c50682a4852cd190be88ddb5c'
4
+ data.tar.gz: 9d1d464804379a4f9f73b049960e0c54e622a092e017b371f308e15326c4badb
5
5
  SHA512:
6
- metadata.gz: 85a888d7da528bfe2f4f2dfe4dea9793c5adf9812fe054c3467eba3873b9fa838dde18a44844a888beea02bf178b0f2b71b4de3c1d79444e4bf513c2c9c185af
7
- data.tar.gz: 19076c83f5ef10f0e334f430d9393b2f4bb855bedc1e2a601ccd9e59ead89600957f3469508caee8fb6b04e5a255fad3f17eae068fa41fb732fbc25bfc3eb2c2
6
+ metadata.gz: fe5f1ec44f4467341fdbdc243e30c69e36a6456e05e82f178d758e979dbf25075d23a99904f396dcc3ef06d4b1ac649649fd147ef38783500377917b3565d6ed
7
+ data.tar.gz: 105064929ca817a02117cc1781135ca81e3cd5d24056518d488b5e97571105542f3b7b03ea3e49ff228018cd546e0d5405bf1fe498b5cab00f764fa99a141b01
data/README.rdoc CHANGED
@@ -53,6 +53,8 @@ Your global configuration must provide information about your LDAP host to funct
53
53
  group_base: # base DN for your LDAP groups, eg ou=Groups,dc=redhat,dc=com
54
54
  use_netgroups: # false by default, use true if you want to use netgroup triples,
55
55
  # supported only for server type :free_ipa and :posix
56
+ use_rfc4519_group_membership: # false by default, use true if you want to use group membership extensions from RFC4519. Typically you may want to use this if your LDAP server is based on 389DS.
57
+ # supported only for server type :posix
56
58
  server_type: # type of server. default == :posix. :active_directory, :posix, :free_ipa
57
59
  ad_domain: # domain for your users if using active directory, eg redhat.com
58
60
  service_user: # service account for authenticating LDAP calls. required unless you enable anon
@@ -4,7 +4,7 @@ require 'active_support/core_ext/hash'
4
4
  class LdapFluff::Config
5
5
  ATTRIBUTES = %w[host port encryption base_dn group_base server_type service_user
6
6
  service_pass anon_queries attr_login search_filter
7
- instrumentation_service use_netgroups].freeze
7
+ instrumentation_service use_netgroups use_rfc4519_group_membership].freeze
8
8
  ATTRIBUTES.each { |attr| attr_reader attr.to_sym }
9
9
 
10
10
  DEFAULT_CONFIG = { 'port' => 389,
@@ -14,7 +14,8 @@ class LdapFluff::Config
14
14
  'server_type' => :free_ipa,
15
15
  'anon_queries' => false,
16
16
  'instrumentation_service' => nil,
17
- 'use_netgroups' => false }.freeze
17
+ 'use_netgroups' => false,
18
+ 'use_rfc4519_group_membership' => false }.freeze
18
19
 
19
20
  def initialize(config)
20
21
  raise ArgumentError unless config.respond_to?(:to_hash)
@@ -14,6 +14,7 @@ class LdapFluff::Generic
14
14
  @base = config.base_dn
15
15
  @group_base = (config.group_base.empty? ? config.base_dn : config.group_base)
16
16
  @use_netgroups = config.use_netgroups
17
+ @use_rfc4519_group_membership = config.use_rfc4519_group_membership
17
18
  @member_service = create_member_service(config)
18
19
  end
19
20
 
@@ -19,10 +19,14 @@ class LdapFluff::Posix < LdapFluff::Generic
19
19
  filter = if @use_netgroups
20
20
  Net::LDAP::Filter.eq('objectClass', 'nisNetgroup')
21
21
  else
22
- Net::LDAP::Filter.eq('objectClass', 'posixGroup') |
23
- Net::LDAP::Filter.eq('objectClass', 'organizationalunit') |
24
- Net::LDAP::Filter.eq('objectClass', 'groupOfUniqueNames') |
25
- Net::LDAP::Filter.eq('objectClass', 'groupOfNames')
22
+ filter = Net::LDAP::Filter.eq('objectClass', 'posixGroup') |
23
+ Net::LDAP::Filter.eq('objectClass', 'organizationalunit')
24
+ if @use_rfc4519_group_membership
25
+ filter = filter |
26
+ Net::LDAP::Filter.eq('objectClass', 'groupOfUniqueNames') |
27
+ Net::LDAP::Filter.eq('objectClass', 'groupOfNames')
28
+ end
29
+ filter
26
30
  end
27
31
  groups = @ldap.search(:base => search.dn, :filter => filter)
28
32
  members = groups.map { |group| group.send(method) }.flatten.uniq
@@ -4,6 +4,7 @@ require 'net/ldap'
4
4
  class LdapFluff::Posix::MemberService < LdapFluff::GenericMemberService
5
5
  def initialize(ldap, config)
6
6
  @attr_login = (config.attr_login || 'memberuid')
7
+ @use_rfc4519_group_membership = config.use_rfc4519_group_membership
7
8
  super
8
9
  end
9
10
 
@@ -16,8 +17,9 @@ class LdapFluff::Posix::MemberService < LdapFluff::GenericMemberService
16
17
  # return an ldap user with groups attached
17
18
  # note : this method is not particularly fast for large ldap systems
18
19
  def find_user_groups(uid)
20
+ user = find_user(uid).first
19
21
  @ldap.search(
20
- :filter => Net::LDAP::Filter.eq('memberuid', uid),
22
+ :filter => user_group_filter(uid, user[:dn].first),
21
23
  :base => @group_base, :attributes => ["cn"]
22
24
  ).map { |entry| entry[:cn][0] }
23
25
  end
@@ -27,4 +29,17 @@ class LdapFluff::Posix::MemberService < LdapFluff::GenericMemberService
27
29
 
28
30
  class GIDNotFoundException < LdapFluff::Error
29
31
  end
32
+
33
+ private
34
+
35
+ def user_group_filter(uid, user_dn)
36
+ by_member = Net::LDAP::Filter.eq('memberuid', uid)
37
+ return by_member unless @use_rfc4519_group_membership
38
+
39
+ by_name = Net::LDAP::Filter.eq('member', user_dn) &
40
+ Net::LDAP::Filter.eq('objectClass', 'groupOfNames')
41
+ by_unique_name = Net::LDAP::Filter.eq('uniquemember', user_dn) &
42
+ Net::LDAP::Filter.eq('objectClass', 'groupOfUniqueNames')
43
+ by_member | by_name | by_unique_name
44
+ end
30
45
  end
@@ -121,7 +121,7 @@ module LdapTestHelper
121
121
  end
122
122
 
123
123
  def posix_user_payload
124
- [{ :cn => ["john"] }]
124
+ [{ :cn => ["john"], :dn => ["cn=john,ou=people,dc=internet,dc=com"] }]
125
125
  end
126
126
 
127
127
  def posix_group_payload
data/test/netiq_test.rb CHANGED
@@ -128,9 +128,7 @@ class TestNetIQ < Minitest::Test
128
128
  [nested_group],
129
129
  [{ :base => group.dn,
130
130
  :filter => Net::LDAP::Filter.eq('objectClass', 'posixGroup') |
131
- Net::LDAP::Filter.eq('objectClass', 'organizationalunit') |
132
- Net::LDAP::Filter.eq('objectClass', 'groupOfUniqueNames') |
133
- Net::LDAP::Filter.eq('objectClass', 'groupOfNames') }])
131
+ Net::LDAP::Filter.eq('objectClass', 'organizationalunit') }])
134
132
  @netiq.ldap = @ldap
135
133
 
136
134
  md = Minitest::Mock.new
@@ -18,21 +18,54 @@ class TestPosixMemberService < Minitest::Test
18
18
  end
19
19
 
20
20
  def test_find_user_groups
21
- user = posix_group_payload
22
- @ldap.expect(:search, user, [:filter => @ms.name_filter('john'),
21
+ group = posix_group_payload
22
+ user = posix_user_payload
23
+ username = 'john'
24
+
25
+ @ldap.expect(:search, user, [:filter => @ms.name_filter(username),
26
+ :base => config.base_dn])
27
+ filter = Net::LDAP::Filter.eq('memberuid', username)
28
+ @ldap.expect(:search, group, [:filter => filter,
23
29
  :base => config.group_base,
24
30
  :attributes => ["cn"]])
25
31
  @ms.ldap = @ldap
26
- assert_equal ['broze'], @ms.find_user_groups('john')
32
+ assert_equal ['broze'], @ms.find_user_groups(username)
33
+ @ldap.verify
34
+ end
35
+
36
+ def test_find_user_groups_rfc4519
37
+ @ms.instance_variable_set('@use_rfc4519_group_membership', true)
38
+
39
+ group = posix_group_payload
40
+ user = posix_user_payload
41
+ username = 'john'
42
+
43
+ @ldap.expect(:search, user, [:filter => @ms.name_filter(username),
44
+ :base => config.base_dn])
45
+ filter = [Net::LDAP::Filter.eq('memberuid', username),
46
+ Net::LDAP::Filter.eq('member', user.first[:dn].first) & Net::LDAP::Filter.eq('objectClass', 'groupOfNames'),
47
+ Net::LDAP::Filter.eq('uniquemember', user.first[:dn].first) & Net::LDAP::Filter.eq('objectClass', 'groupOfUniqueNames')
48
+ ].reduce(&:|)
49
+
50
+ @ldap.expect(:search, group, [:filter => filter,
51
+ :base => config.group_base,
52
+ :attributes => ["cn"]])
53
+ @ms.ldap = @ldap
54
+ assert_equal ['broze'], @ms.find_user_groups(username)
27
55
  @ldap.verify
28
56
  end
29
57
 
30
58
  def test_find_no_groups
31
- @ldap.expect(:search, [], [:filter => @ms.name_filter("john"),
59
+ user = posix_user_payload
60
+ username = 'john'
61
+ @ldap.expect(:search, user, [:filter => @ms.name_filter(username),
62
+ :base => config.base_dn])
63
+ filter = @ms.send(:user_group_filter, username, user.first[:dn].first)
64
+ @ldap.expect(:search, [], [:filter => filter,
32
65
  :base => config.group_base,
33
66
  :attributes => ["cn"]])
34
67
  @ms.ldap = @ldap
35
- assert_equal [], @ms.find_user_groups('john')
68
+ assert_equal [], @ms.find_user_groups(username)
36
69
  @ldap.verify
37
70
  end
38
71
 
data/test/posix_test.rb CHANGED
@@ -119,13 +119,40 @@ class TestPosix < Minitest::Test
119
119
  nested_group = Net::LDAP::Entry.new('CN=katellers,CN=foremaners,DC=example,DC=com')
120
120
  nested_group[:memberuid] = ['testuser']
121
121
 
122
+ @ldap.expect(:search,
123
+ [nested_group],
124
+ [{ :base => group.dn,
125
+ :filter => Net::LDAP::Filter.eq('objectClass', 'posixGroup') |
126
+ Net::LDAP::Filter.eq('objectClass', 'organizationalunit') }])
127
+ @posix.ldap = @ldap
128
+
129
+ md = Minitest::Mock.new
130
+ 2.times { md.expect(:find_group, [group], ['foremaners']) }
131
+ @posix.member_service = md
132
+
133
+ assert_equal @posix.users_for_gid('foremaners'), ['testuser']
134
+
135
+ md.verify
136
+ @ldap.verify
137
+ end
138
+
139
+ def test_find_users_in_nested_groups_with_rfc4519
140
+ @posix.instance_variable_set('@use_rfc4519_group_membership', true)
141
+
142
+ service_bind
143
+ group = Net::LDAP::Entry.new('CN=foremaners,DC=example,DC=com')
144
+ group[:memberuid] = ['katellers']
145
+ nested_group = Net::LDAP::Entry.new('CN=katellers,CN=foremaners,DC=example,DC=com')
146
+ nested_group[:memberuid] = ['testuser']
147
+
122
148
  @ldap.expect(:search,
123
149
  [nested_group],
124
150
  [{ :base => group.dn,
125
151
  :filter => Net::LDAP::Filter.eq('objectClass', 'posixGroup') |
126
152
  Net::LDAP::Filter.eq('objectClass', 'organizationalunit') |
127
153
  Net::LDAP::Filter.eq('objectClass', 'groupOfUniqueNames') |
128
- Net::LDAP::Filter.eq('objectClass', 'groupOfNames')}])
154
+ Net::LDAP::Filter.eq('objectClass', 'groupOfNames')
155
+ }])
129
156
  @posix.ldap = @ldap
130
157
 
131
158
  md = Minitest::Mock.new
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ldap_fluff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jordan O'Mara
@@ -10,10 +10,9 @@ authors:
10
10
  - Adam Price
11
11
  - Marek Hulan
12
12
  - Dominic Cleal
13
- autorequire:
14
13
  bindir: bin
15
14
  cert_chain: []
16
- date: 2024-10-18 00:00:00.000000000 Z
15
+ date: 1980-01-02 00:00:00.000000000 Z
17
16
  dependencies:
18
17
  - !ruby/object:Gem::Dependency
19
18
  name: activesupport
@@ -94,8 +93,8 @@ email:
94
93
  executables: []
95
94
  extensions: []
96
95
  extra_rdoc_files:
97
- - README.rdoc
98
96
  - LICENSE
97
+ - README.rdoc
99
98
  files:
100
99
  - LICENSE
101
100
  - README.rdoc
@@ -132,7 +131,6 @@ homepage: https://github.com/theforeman/ldap_fluff
132
131
  licenses:
133
132
  - GPL-2.0-only
134
133
  metadata: {}
135
- post_install_message:
136
134
  rdoc_options: []
137
135
  require_paths:
138
136
  - lib
@@ -150,8 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
148
  - !ruby/object:Gem::Version
151
149
  version: '0'
152
150
  requirements: []
153
- rubygems_version: 3.3.27
154
- signing_key:
151
+ rubygems_version: 3.6.7
155
152
  specification_version: 4
156
153
  summary: LDAP querying tools for Active Directory, FreeIPA and POSIX-style
157
154
  test_files: