github-ldap 1.2.1 → 1.3.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: a23a62005338f49107b2e82997fbdb9c02d4004c
4
- data.tar.gz: bb3a1b3bed1dfb66a1b110bf2e7b31e5a74d7378
3
+ metadata.gz: 8c05560a6e80e800f35e6d9173fa14492b8d7201
4
+ data.tar.gz: 95dd52b0e87152cd37d22b1f804ad336499fd47a
5
5
  SHA512:
6
- metadata.gz: 24548e4cf5b738fb303b635297fd12c634d5a85d42076e367763e833fd0f59e107e398a3f9ff00ce8a69bb4a5d119bf91f5180661d5274e7c6f79e3445ed2bb3
7
- data.tar.gz: 56669b0b27287bdd8cdf3b7820690e2b2832ac9adf12eacb5b882c6d71e687b05c1aa0f4459231738e0001dda538fed02817b13496bbf7e8c4366cc52dacc5c6
6
+ metadata.gz: 6162767914b01776e7d2e8bcab9101f2f7a70acafeee389295abb0caa4953f79e4992181ef01f3465b7f19c576a1781a2b9972de3f815801277937cffa980f96
7
+ data.tar.gz: 381cc12fde5eaba702d4c6abfe7caa07cc75f85f85f644cbd2947fe0bbbb7003c0ca5274ef48a36a28bb89e913ad9271ef78c2276cecf80d1a4fed020fc244e7
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.2.1"
5
+ spec.version = "1.3.0"
6
6
  spec.authors = ["David Calavera"]
7
7
  spec.email = ["david.calavera@gmail.com"]
8
8
  spec.description = %q{Ldap authentication for humans}
@@ -15,7 +15,7 @@ Gem::Specification.new do |spec|
15
15
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
16
16
  spec.require_paths = ["lib"]
17
17
 
18
- spec.add_dependency 'net-ldap', '>= 0.2.2'
18
+ spec.add_dependency 'net-ldap', '~> 0.7.0'
19
19
 
20
20
  spec.add_development_dependency "bundler", "~> 1.3"
21
21
  spec.add_development_dependency 'ladle'
data/lib/github/ldap.rb CHANGED
@@ -40,11 +40,24 @@ module GitHub
40
40
 
41
41
  configure_virtual_attributes(options[:virtual_attributes])
42
42
 
43
+ # enable fallback recursive group search unless option is false
44
+ @recursive_group_search_fallback = (options[:recursive_group_search_fallback] != false)
45
+
43
46
  # search_domains is a connection of bases to perform searches
44
47
  # when a base is not explicitly provided.
45
48
  @search_domains = Array(options[:search_domains])
46
49
  end
47
50
 
51
+ # Public - Whether membership checks should recurse into nested groups when
52
+ # virtual attributes aren't enabled. The fallback search has poor
53
+ # performance characteristics in some cases, in which case this should be
54
+ # disabled by passing :recursive_group_search_fallback => false.
55
+ #
56
+ # Returns true or false.
57
+ def recursive_group_search_fallback?
58
+ @recursive_group_search_fallback
59
+ end
60
+
48
61
  # Public - Utility method to check if the connection with the server can be stablished.
49
62
  # It tries to bind with the ldap auth default configuration.
50
63
  #
@@ -52,16 +52,22 @@ module GitHub
52
52
  #
53
53
  # Return an Array with the groups that the given user is member of that belong to the given group list.
54
54
  def membership(user_entry, group_names)
55
- all_groups = search(filter: group_filter(group_names))
56
- groups_map = all_groups.each_with_object({}) {|entry, hash| hash[entry.dn] = entry}
57
-
58
- if @ldap.virtual_attributes.enabled?
59
- member_of = groups_map.keys & user_entry[@ldap.virtual_attributes.virtual_membership]
60
- member_of.map {|dn| groups_map[dn]}
61
- else
62
- groups_map.each_with_object([]) do |(dn, group_entry), acc|
63
- acc << group_entry if @ldap.load_group(group_entry).is_member?(user_entry)
55
+ if @ldap.virtual_attributes.enabled? || @ldap.recursive_group_search_fallback?
56
+ all_groups = search(filter: group_filter(group_names))
57
+ groups_map = all_groups.each_with_object({}) {|entry, hash| hash[entry.dn] = entry}
58
+
59
+ if @ldap.virtual_attributes.enabled?
60
+ member_of = groups_map.keys & user_entry[@ldap.virtual_attributes.virtual_membership]
61
+ member_of.map {|dn| groups_map[dn]}
62
+ else # recursive group search fallback
63
+ groups_map.each_with_object([]) do |(dn, group_entry), acc|
64
+ acc << group_entry if @ldap.load_group(group_entry).is_member?(user_entry)
65
+ end
64
66
  end
67
+ else
68
+ # fallback to non-recursive group membership search
69
+ filter = member_filter(user_entry) & group_filter(group_names)
70
+ search(filter: filter)
65
71
  end
66
72
  end
67
73
 
@@ -143,16 +149,6 @@ module GitHub
143
149
  @ldap.search(options, &block)
144
150
  end
145
151
 
146
- # Provide a meaningful result after a protocol operation (for example,
147
- # bind or search) has completed.
148
- #
149
- # Returns an OpenStruct containing an LDAP result code and a
150
- # human-readable string.
151
- # See http://tools.ietf.org/html/rfc4511#appendix-A
152
- def get_operation_result
153
- @ldap.get_operation_result
154
- end
155
-
156
152
  # Get the entry for this domain.
157
153
  #
158
154
  # Returns a Net::LDAP::Entry
@@ -18,16 +18,21 @@ module GitHub
18
18
  group_names.map {|g| Net::LDAP::Filter.eq("cn", g)}.reduce(:|)
19
19
  end
20
20
 
21
- # Filter to check a group membership.
21
+ # Filter to check group membership.
22
22
  #
23
- # user_dn: is an optional user_dn to scope the search to.
23
+ # entry: finds groups this Net::LDAP::Entry is a member of (optional)
24
+ # uid_attr: specifies the memberUid attribute to match with (optional)
24
25
  #
25
26
  # Returns a Net::LDAP::Filter.
26
- def member_filter(user_dn = nil)
27
- if user_dn
28
- MEMBERSHIP_NAMES.map {|n| Net::LDAP::Filter.eq(n, user_dn)}.reduce(:|)
27
+ def member_filter(entry = nil, uid_attr = @ldap.uid)
28
+ if entry
29
+ MEMBERSHIP_NAMES.map {|n| Net::LDAP::Filter.eq(n, entry.dn) }.
30
+ reduce(:|) |
31
+ entry[uid_attr]. map { |uid| Net::LDAP::Filter.eq("memberUid", uid) }.
32
+ reduce(:|)
29
33
  else
30
- MEMBERSHIP_NAMES.map {|n| Net::LDAP::Filter.pres(n)}.reduce(:|)
34
+ (MEMBERSHIP_NAMES + %w(memberUid)).
35
+ map {|n| Net::LDAP::Filter.pres(n)}.reduce(:|)
31
36
  end
32
37
  end
33
38
 
@@ -1,12 +1,5 @@
1
1
  version: 1
2
2
 
3
- # Organizations
4
- dn: dc=github,dc=com
5
- objectClass: dcObject
6
- objectClass: organization
7
- dc: github
8
- o: GitHub Inc.
9
-
10
3
  dn: ou=Group,dc=github,dc=com
11
4
  objectclass: organizationalUnit
12
5
  ou: Group
@@ -1,6 +1,8 @@
1
1
  module GitHub
2
2
  class Ldap
3
3
  class VirtualGroup < Group
4
+ include Filter
5
+
4
6
  def members
5
7
  @ldap.search(filter: members_of_group(@entry.dn, membership_attribute))
6
8
  end
@@ -17,7 +19,7 @@ module GitHub
17
19
  #
18
20
  # Returns a string.
19
21
  def membership_attribute
20
- @ldap.virual_attributes.virtual_membership
22
+ @ldap.virtual_attributes.virtual_membership
21
23
  end
22
24
  end
23
25
  end
data/test/domain_test.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'test_helper'
1
+ require_relative 'test_helper'
2
2
 
3
3
  module GitHubLdapDomainTestCases
4
4
  def setup
@@ -159,3 +159,63 @@ class GitHubLdapDomainNestedGroupsTest < GitHub::Ldap::Test
159
159
  "Expected `enterprise-ops` to include the member `#{user.dn}`"
160
160
  end
161
161
  end
162
+
163
+ class GitHubLdapPosixGroupsWithRecursionFallbackTest < GitHub::Ldap::Test
164
+ def self.test_server_options
165
+ {
166
+ custom_schemas: FIXTURES.join('posixGroup.schema.ldif'),
167
+ user_fixtures: FIXTURES.join('github-with-posixGroups.ldif').to_s,
168
+ # so we exercise the recursive group search fallback
169
+ recursive_group_search_fallback: true
170
+ }
171
+ end
172
+
173
+ def setup
174
+ @ldap = GitHub::Ldap.new(options)
175
+ @domain = @ldap.domain("dc=github,dc=com")
176
+
177
+ @group = Net::LDAP::Entry._load("""
178
+ dn: cn=enterprise-posix-devs,ou=groups,dc=github,dc=com
179
+ cn: enterprise-posix-devs
180
+ objectClass: posixGroup
181
+ memberUid: benburkert
182
+ memberUid: mtodd""")
183
+ end
184
+
185
+ def test_membership_for_posixGroups
186
+ assert user = @ldap.domain('uid=mtodd,ou=users,dc=github,dc=com').bind
187
+
188
+ assert @domain.is_member?(user, @group.cn),
189
+ "Expected `#{@group.cn.first}` to include the member `#{user.dn}`"
190
+ end
191
+ end
192
+
193
+ class GitHubLdapPosixGroupsTest < GitHub::Ldap::Test
194
+ def self.test_server_options
195
+ {
196
+ custom_schemas: FIXTURES.join('posixGroup.schema.ldif'),
197
+ user_fixtures: FIXTURES.join('github-with-posixGroups.ldif').to_s,
198
+ # so we test the test the non-recursive group membership search
199
+ recursive_group_search_fallback: false
200
+ }
201
+ end
202
+
203
+ def setup
204
+ @ldap = GitHub::Ldap.new(options)
205
+ @domain = @ldap.domain("dc=github,dc=com")
206
+
207
+ @group = Net::LDAP::Entry._load("""
208
+ dn: cn=enterprise-posix-devs,ou=groups,dc=github,dc=com
209
+ cn: enterprise-posix-devs
210
+ objectClass: posixGroup
211
+ memberUid: benburkert
212
+ memberUid: mtodd""")
213
+ end
214
+
215
+ def test_membership_for_posixGroups
216
+ assert user = @ldap.domain('uid=mtodd,ou=users,dc=github,dc=com').bind
217
+
218
+ assert @domain.is_member?(user, @group.cn),
219
+ "Expected `#{@group.cn.first}` to include the member `#{user.dn}`"
220
+ end
221
+ end
data/test/filter_test.rb CHANGED
@@ -1,19 +1,35 @@
1
- require 'test_helper'
1
+ require_relative 'test_helper'
2
2
 
3
3
  class FilterTest < Minitest::Test
4
- class Subject; include GitHub::Ldap::Filter; end
4
+ class Subject
5
+ include GitHub::Ldap::Filter
6
+ def initialize(ldap)
7
+ @ldap = ldap
8
+ end
9
+ end
10
+
11
+ # Fake a Net::LDAP::Entry
12
+ class Entry < Struct.new(:dn, :uid)
13
+ def [](field)
14
+ Array(send(field))
15
+ end
16
+ end
5
17
 
6
18
  def setup
7
- @subject = Subject.new
8
- @me = 'uid=calavera,dc=github,dc=com'
19
+ @ldap = GitHub::Ldap.new(:uid => 'uid')
20
+ @subject = Subject.new(@ldap)
21
+ @me = 'uid=calavera,dc=github,dc=com'
22
+ @uid = "calavera"
23
+ @entry = Entry.new(@me, @uid)
9
24
  end
10
25
 
11
26
  def test_member_present
12
- assert_equal "(|(member=*)(uniqueMember=*))", @subject.member_filter.to_s
27
+ assert_equal "(|(|(member=*)(uniqueMember=*))(memberUid=*))", @subject.member_filter.to_s
13
28
  end
14
29
 
15
30
  def test_member_equal
16
- assert_equal "(|(member=#{@me})(uniqueMember=#{@me}))", @subject.member_filter(@me).to_s
31
+ assert_equal "(|(|(member=#{@me})(uniqueMember=#{@me}))(memberUid=#{@uid}))",
32
+ @subject.member_filter(@entry).to_s
17
33
  end
18
34
 
19
35
  def test_groups_reduced
@@ -1,14 +1,5 @@
1
1
  version: 1
2
2
 
3
- # Organizations
4
-
5
- dn: dc=github,dc=com
6
- cn: github
7
- objectClass: dcObject
8
- objectClass: organization
9
- dc: github
10
- o: GitHub Inc.
11
-
12
3
  # Admin user
13
4
 
14
5
  dn: uid=admin,dc=github,dc=com
@@ -1,14 +1,5 @@
1
1
  version: 1
2
2
 
3
- # Organizations
4
-
5
- dn: dc=github,dc=com
6
- cn: github
7
- objectClass: dcObject
8
- objectClass: organization
9
- dc: github
10
- o: GitHub Inc.
11
-
12
3
  # Admin user
13
4
 
14
5
  dn: uid=admin,dc=github,dc=com
@@ -0,0 +1,50 @@
1
+ version: 1
2
+
3
+ # Admin user
4
+
5
+ dn: uid=admin,dc=github,dc=com
6
+ objectClass: top
7
+ objectClass: person
8
+ objectClass: organizationalPerson
9
+ objectClass: inetOrgPerson
10
+ cn: system administrator
11
+ sn: administrator
12
+ displayName: Directory Superuser
13
+ uid: admin
14
+ userPassword: secret
15
+
16
+ # Groups
17
+
18
+ dn: ou=groups,dc=github,dc=com
19
+ objectclass: organizationalUnit
20
+ ou: groups
21
+
22
+ # Posix Groups
23
+
24
+ dn: cn=enterprise-posix-devs,ou=groups,dc=github,dc=com
25
+ cn: enterprise-posix-devs
26
+ objectClass: posixGroup
27
+ memberUid: benburkert
28
+ memberUid: mtodd
29
+
30
+ # Users
31
+
32
+ dn: ou=users,dc=github,dc=com
33
+ objectclass: organizationalUnit
34
+ ou: users
35
+
36
+ dn: uid=benburkert,ou=users,dc=github,dc=com
37
+ cn: benburkert
38
+ sn: benburkert
39
+ uid: benburkert
40
+ userPassword: passworD1
41
+ mail: benburkert@github.com
42
+ objectClass: inetOrgPerson
43
+
44
+ dn: uid=mtodd,ou=users,dc=github,dc=com
45
+ cn: mtodd
46
+ sn: mtodd
47
+ uid: mtodd
48
+ userPassword: passworD1
49
+ mail: mtodd@github.com
50
+ objectClass: inetOrgPerson
@@ -1,13 +1,5 @@
1
1
  version: 1
2
2
 
3
- # Organizations
4
-
5
- dn: dc=github,dc=com
6
- objectClass: dcObject
7
- objectClass: organization
8
- dc: github
9
- o: GitHub Inc.
10
-
11
3
  # Admin user
12
4
 
13
5
  dn: uid=admin,dc=github,dc=com
@@ -0,0 +1,26 @@
1
+ version: 1
2
+
3
+ dn: m-oid=1.3.6.1.4.1.18055.0.4.1.2.1001,ou=attributeTypes,cn=other,ou=schema
4
+ objectClass: metaAttributeType
5
+ objectClass: metaTop
6
+ objectClass: top
7
+ m-collective: FALSE
8
+ m-description: memberUid
9
+ m-equality: caseExactMatch
10
+ m-name: memberUid
11
+ m-syntax: 1.3.6.1.4.1.1466.115.121.1.15
12
+ m-usage: USER_APPLICATIONS
13
+ m-oid: 1.3.6.1.4.1.18055.0.4.1.2.1001
14
+
15
+ dn: m-oid=1.3.6.1.4.1.18055.0.4.1.3.1001,ou=objectClasses,cn=other,ou=schema
16
+ objectClass: metaObjectClass
17
+ objectClass: metaTop
18
+ objectClass: top
19
+ m-description: posixGroup
20
+ m-may: cn
21
+ m-may: sn
22
+ m-may: memberUid
23
+ m-supobjectclass: top
24
+ m-name: posixGroup
25
+ m-oid: 1.3.6.1.4.1.18055.0.4.1.3.1001
26
+ m-typeobjectclass: STRUCTURAL
data/test/group_test.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'test_helper'
1
+ require_relative 'test_helper'
2
2
 
3
3
  class GitHubLdapGroupTest < GitHub::Ldap::Test
4
4
  def self.test_server_options
data/test/ldap_test.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'test_helper'
1
+ require_relative 'test_helper'
2
2
 
3
3
  module GitHubLdapTestCases
4
4
  def setup
@@ -1,4 +1,4 @@
1
- require 'test_helper'
1
+ require_relative 'test_helper'
2
2
 
3
3
  class GitHubLdapPosixGroupTest < GitHub::Ldap::Test
4
4
  def self.test_server_options
@@ -48,7 +48,7 @@ objectClass: posixGroup""")
48
48
  members = group.members
49
49
 
50
50
  assert_equal 2, members.size
51
- assert_equal 'benburkert', members.first[:uid].first
51
+ assert_equal %w(benburkert mtodd), members.map(&:uid).flatten.sort
52
52
  end
53
53
 
54
54
  def test_posix_combined_group
metadata CHANGED
@@ -1,83 +1,83 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: github-ldap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Calavera
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-20 00:00:00.000000000 Z
11
+ date: 2014-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: net-ldap
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.2.2
19
+ version: 0.7.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.2.2
26
+ version: 0.7.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '1.3'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.3'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: ladle
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: minitest
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: '5'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '5'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  description: Ldap authentication for humans
@@ -87,8 +87,8 @@ executables: []
87
87
  extensions: []
88
88
  extra_rdoc_files: []
89
89
  files:
90
- - .gitignore
91
- - .travis.yml
90
+ - ".gitignore"
91
+ - ".travis.yml"
92
92
  - Gemfile
93
93
  - LICENSE.txt
94
94
  - README.md
@@ -107,7 +107,9 @@ files:
107
107
  - test/filter_test.rb
108
108
  - test/fixtures/github-with-looped-subgroups.ldif
109
109
  - test/fixtures/github-with-missing-entries.ldif
110
+ - test/fixtures/github-with-posixGroups.ldif
110
111
  - test/fixtures/github-with-subgroups.ldif
112
+ - test/fixtures/posixGroup.schema.ldif
111
113
  - test/group_test.rb
112
114
  - test/ldap_test.rb
113
115
  - test/posix_group_test.rb
@@ -122,17 +124,17 @@ require_paths:
122
124
  - lib
123
125
  required_ruby_version: !ruby/object:Gem::Requirement
124
126
  requirements:
125
- - - '>='
127
+ - - ">="
126
128
  - !ruby/object:Gem::Version
127
129
  version: '0'
128
130
  required_rubygems_version: !ruby/object:Gem::Requirement
129
131
  requirements:
130
- - - '>='
132
+ - - ">="
131
133
  - !ruby/object:Gem::Version
132
134
  version: '0'
133
135
  requirements: []
134
136
  rubyforge_project:
135
- rubygems_version: 2.0.3
137
+ rubygems_version: 2.2.2
136
138
  signing_key:
137
139
  specification_version: 4
138
140
  summary: Ldap client authentication wrapper without all the boilerplate
@@ -141,9 +143,10 @@ test_files:
141
143
  - test/filter_test.rb
142
144
  - test/fixtures/github-with-looped-subgroups.ldif
143
145
  - test/fixtures/github-with-missing-entries.ldif
146
+ - test/fixtures/github-with-posixGroups.ldif
144
147
  - test/fixtures/github-with-subgroups.ldif
148
+ - test/fixtures/posixGroup.schema.ldif
145
149
  - test/group_test.rb
146
150
  - test/ldap_test.rb
147
151
  - test/posix_group_test.rb
148
152
  - test/test_helper.rb
149
- has_rdoc: