github-ldap 1.7.1 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 86f3bd21421aabe109b8af71be658b017b08047b
4
- data.tar.gz: 49bd35020463ab9de002862722002b710de18a4d
3
+ metadata.gz: 63e7bb9628728108464971db755993e0e5458935
4
+ data.tar.gz: 9391bca357f0499ad0b15dbc0ff78188ef1889d6
5
5
  SHA512:
6
- metadata.gz: 35ff3762ffbf255ac0fdaedfbe13ef12ee06b1f10b60dade2aa5e1a0ee412db9faaba4d5fc28941755fd227f1146814247e4115311ddafb487ba023663c83732
7
- data.tar.gz: 452730b8945d65395ce3b977b232c83c1596753527cc6b142d696bb0e2e7d0e2827eb2a5a62e6343eb519acf771a4628de2f63491930793860795494415a9c01
6
+ metadata.gz: 2652b4a99be3d991f5ee4364001acd394b1709271131b1c99f6c7d749e5b59a44f5111637f2c0f7728886ce823e6ec630d2375874334b89f59dc8a269704fffd
7
+ data.tar.gz: 4f86400238df2e26b07faac9a199ef276e5a3a94ece6d47e634bdaac63ee27c178f52cd87b0d2ed74250881ca7c9636c6ada932f8a40a0a5db5e034b89e722ce
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # CHANGELOG
2
2
 
3
+ # v1.8.0
4
+
5
+ * Optimize Recursive *Member Search* strategy [#78](https://github.com/github/github-ldap/pull/78)
6
+
3
7
  # v1.7.1
4
8
 
5
9
  * Add Active Directory group filter [#75](https://github.com/github/github-ldap/pull/75)
data/github-ldap.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "github-ldap"
5
- spec.version = "1.7.1"
5
+ spec.version = "1.8.0"
6
6
  spec.authors = ["David Calavera", "Matt Todd"]
7
7
  spec.email = ["david.calavera@gmail.com", "chiology@gmail.com"]
8
8
  spec.description = %q{LDAP authentication for humans}
@@ -34,73 +34,98 @@ module GitHub
34
34
  #
35
35
  # Returns Array of Net::LDAP::Entry objects.
36
36
  def perform(group)
37
+ # track groups found
37
38
  found = Hash.new
38
39
 
39
- # find members (N queries)
40
- entries = member_entries(group)
41
- return [] if entries.empty?
40
+ # track all DNs searched for (so we don't repeat searches)
41
+ searched = Set.new
42
42
 
43
- # track found entries
44
- entries.each do |entry|
45
- found[entry.dn] = entry
43
+ # if this is a posixGroup, return members immediately (no nesting)
44
+ uids = member_uids(group)
45
+ return entries_by_uid(uids) if uids.any?
46
+
47
+ # track group
48
+ searched << group.dn
49
+ found[group.dn] = group
50
+
51
+ # pull out base group's member DNs
52
+ dns = member_dns(group)
53
+
54
+ # search for base group's subgroups
55
+ groups = dns.each_with_object([]) do |dn, groups|
56
+ groups.concat find_groups_by_dn(dn)
57
+ searched << dn
46
58
  end
47
59
 
48
- # descend to `depth` levels, at most
49
- depth.times do |n|
50
- # find every (new, unique) member entry
51
- depth_subentries = entries.each_with_object([]) do |entry, depth_entries|
52
- submembers = entry["member"]
60
+ # track found groups
61
+ groups.each { |g| found[g.dn] = g }
53
62
 
54
- # skip any members we've already found
55
- submembers.reject! { |dn| found.key?(dn) }
63
+ # recursively find subgroups
64
+ unless groups.empty?
65
+ depth.times do |n|
66
+ # pull out subgroups' member DNs to search through
67
+ sub_dns = groups.each_with_object([]) do |subgroup, sub_dns|
68
+ sub_dns.concat member_dns(subgroup)
69
+ end
56
70
 
57
- # find members of subgroup, including subgroups (N queries)
58
- subentries = member_entries(entry)
59
- next if subentries.empty?
71
+ # filter out if already searched for
72
+ sub_dns.reject! { |dn| searched.include?(dn) }
60
73
 
61
- # track found subentries
62
- subentries.each { |entry| found[entry.dn] = entry }
74
+ # give up if there's nothing else to search for
75
+ break if sub_dns.empty?
63
76
 
64
- # collect all entries for this depth
65
- depth_entries.concat subentries
66
- end
77
+ # search for subgroups
78
+ subgroups = sub_dns.each_with_object([]) do |dn, subgroups|
79
+ subgroups.concat find_groups_by_dn(dn)
80
+ searched << dn
81
+ end
67
82
 
68
- # stop if there are no more subgroups to search
69
- break if depth_subentries.empty?
83
+ # give up if there were no subgroups found
84
+ break if subgroups.empty?
70
85
 
71
- # go one level deeper
72
- entries = depth_subentries
86
+ # track found subgroups
87
+ subgroups.each { |g| found[g.dn] = g }
88
+
89
+ # descend another level
90
+ groups = subgroups
91
+ end
73
92
  end
74
93
 
75
- # return all found entries
76
- found.values
77
- end
94
+ # entries to return
95
+ entries = []
78
96
 
79
- # Internal: Fetch member entries, including subgroups, for the given
80
- # entry.
81
- #
82
- # Returns an Array of Net::LDAP::Entry objects.
83
- def member_entries(entry)
84
- entries = []
85
- dns = member_dns(entry)
86
- uids = member_uids(entry)
97
+ # collect all member DNs, discarding dupes and subgroup DNs
98
+ members = found.values.each_with_object([]) do |group, dns|
99
+ entries << group
100
+ dns.concat member_dns(group)
101
+ end.uniq.reject { |dn| found.key?(dn) }
87
102
 
88
- entries.concat entries_by_uid(uids) unless uids.empty?
89
- entries.concat entries_by_dn(dns) unless dns.empty?
103
+ # wrap member DNs in Net::LDAP::Entry objects
104
+ entries.concat members.map! { |dn| Net::LDAP::Entry.new(dn) }
90
105
 
91
106
  entries
92
107
  end
93
- private :member_entries
94
108
 
95
- # Internal: Bind a list of DNs to their respective entries.
109
+ # Internal: Search for Groups by DN.
96
110
  #
97
- # Returns an Array of Net::LDAP::Entry objects.
98
- def entries_by_dn(members)
99
- members.map do |dn|
100
- ldap.domain(dn).bind(attributes: attrs)
101
- end.compact
111
+ # Given a Distinguished Name (DN) String value, find the Group entry
112
+ # that matches it. The DN may map to a `person` entry, but we want to
113
+ # filter those out.
114
+ #
115
+ # This will find zero or one entry most of the time, but it's not
116
+ # guaranteed so we account for the possibility of more.
117
+ #
118
+ # This method is intended to be used with `Array#concat` by the caller.
119
+ #
120
+ # Returns an Array of zero or more Net::LDAP::Entry objects.
121
+ def find_groups_by_dn(dn)
122
+ ldap.search \
123
+ base: dn,
124
+ scope: Net::LDAP::SearchScope_BaseObject,
125
+ attributes: attrs,
126
+ filter: ALL_GROUPS_FILTER
102
127
  end
103
- private :entries_by_dn
128
+ private :find_groups_by_dn
104
129
 
105
130
  # Internal: Fetch entries by UID.
106
131
  #
data/test/domain_test.rb CHANGED
@@ -227,11 +227,11 @@ end
227
227
 
228
228
  class GitHubLdapActiveDirectoryGroupsTest < GitHub::Ldap::Test
229
229
  def run(*)
230
- self.class.test_env != "activedirectory" ? super : self
230
+ self.class.test_env == "activedirectory" ? super : self
231
231
  end
232
232
 
233
233
  def test_filter_groups
234
- domain = @ldap.domain("DC=ad,DC=ghe,DC=local")
234
+ domain = GitHub::Ldap.new(options).domain("DC=ad,DC=ghe,DC=local")
235
235
  results = domain.filter_groups("ghe-admins")
236
236
  assert_equal 1, results.size
237
237
  end
data/test/filter_test.rb CHANGED
@@ -78,8 +78,4 @@ class FilterTest < Minitest::Test
78
78
  assert_equal "(|(uid=calavera)(uid=mtodd))",
79
79
  @subject.all_members_by_uid(%w(calavera mtodd), :uid).to_s
80
80
  end
81
-
82
- def test_active_directory_group
83
-
84
- end
85
81
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: github-ldap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.1
4
+ version: 1.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Calavera
@@ -9,76 +9,76 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-12-24 00:00:00.000000000 Z
12
+ date: 2015-01-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: net-ldap
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ~>
18
+ - - "~>"
19
19
  - !ruby/object:Gem::Version
20
20
  version: 0.10.0
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - ~>
25
+ - - "~>"
26
26
  - !ruby/object:Gem::Version
27
27
  version: 0.10.0
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: bundler
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - ~>
32
+ - - "~>"
33
33
  - !ruby/object:Gem::Version
34
34
  version: '1.3'
35
35
  type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - ~>
39
+ - - "~>"
40
40
  - !ruby/object:Gem::Version
41
41
  version: '1.3'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: ladle
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - '>='
46
+ - - ">="
47
47
  - !ruby/object:Gem::Version
48
48
  version: '0'
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - '>='
53
+ - - ">="
54
54
  - !ruby/object:Gem::Version
55
55
  version: '0'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: minitest
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
- - - ~>
60
+ - - "~>"
61
61
  - !ruby/object:Gem::Version
62
62
  version: '5'
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
- - - ~>
67
+ - - "~>"
68
68
  - !ruby/object:Gem::Version
69
69
  version: '5'
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: rake
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
- - - '>='
74
+ - - ">="
75
75
  - !ruby/object:Gem::Version
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
- - - '>='
81
+ - - ">="
82
82
  - !ruby/object:Gem::Version
83
83
  version: '0'
84
84
  description: LDAP authentication for humans
@@ -89,8 +89,8 @@ executables: []
89
89
  extensions: []
90
90
  extra_rdoc_files: []
91
91
  files:
92
- - .gitignore
93
- - .travis.yml
92
+ - ".gitignore"
93
+ - ".travis.yml"
94
94
  - CHANGELOG.md
95
95
  - Gemfile
96
96
  - LICENSE.txt
@@ -156,17 +156,17 @@ require_paths:
156
156
  - lib
157
157
  required_ruby_version: !ruby/object:Gem::Requirement
158
158
  requirements:
159
- - - '>='
159
+ - - ">="
160
160
  - !ruby/object:Gem::Version
161
161
  version: '0'
162
162
  required_rubygems_version: !ruby/object:Gem::Requirement
163
163
  requirements:
164
- - - '>='
164
+ - - ">="
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0'
167
167
  requirements: []
168
168
  rubyforge_project:
169
- rubygems_version: 2.0.14
169
+ rubygems_version: 2.2.2
170
170
  signing_key:
171
171
  specification_version: 4
172
172
  summary: LDAP client authentication wrapper without all the boilerplate