github-ldap 1.7.1 → 1.8.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
  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