github-ldap 1.1.5 → 1.2.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 +4 -4
- data/.travis.yml +2 -2
- data/github-ldap.gemspec +1 -1
- data/lib/github/ldap.rb +57 -29
- data/lib/github/ldap/domain.rb +4 -8
- data/lib/github/ldap/filter.rb +19 -8
- data/lib/github/ldap/group.rb +12 -6
- data/lib/github/ldap/posix_group.rb +81 -0
- data/test/filter_test.rb +6 -6
- data/test/fixtures/github-with-subgroups.ldif +10 -1
- data/test/ldap_test.rb +9 -0
- data/test/posix_group_test.rb +120 -0
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 64ef77cae7b6d41804fd11a87a169001313320ec
|
|
4
|
+
data.tar.gz: 0d9fc6ed121d40dfcead6c8cd1c29cedc7598672
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 55c95dda73fffdce9e46a9718a8d1d58f32c9e47fc367b73c835a0f2e17b161a764c46cdeac24fc67331978764289696a99ea5586fc6c0382bf7d77ece583ad0
|
|
7
|
+
data.tar.gz: 8cb01bc061b35bf11f00b34c4340fe08ebe826f419f142c4e3949c720d0e54857ac15066d0c49ef29f26d60f8b85402718fabd13c0e2c648f4b04017ce7bbd7b
|
data/.travis.yml
CHANGED
data/github-ldap.gemspec
CHANGED
data/lib/github/ldap.rb
CHANGED
|
@@ -5,18 +5,12 @@ module GitHub
|
|
|
5
5
|
require 'github/ldap/filter'
|
|
6
6
|
require 'github/ldap/domain'
|
|
7
7
|
require 'github/ldap/group'
|
|
8
|
+
require 'github/ldap/posix_group'
|
|
8
9
|
require 'github/ldap/virtual_group'
|
|
9
10
|
require 'github/ldap/virtual_attributes'
|
|
10
11
|
|
|
11
12
|
extend Forwardable
|
|
12
13
|
|
|
13
|
-
# Utility method to perform searches against the ldap server.
|
|
14
|
-
#
|
|
15
|
-
# It takes the same arguments than Net::LDAP::Connection#search.
|
|
16
|
-
# Returns an Array with the entries that match the search.
|
|
17
|
-
# Returns nil if there are no entries that match the search.
|
|
18
|
-
def_delegator :@connection, :search
|
|
19
|
-
|
|
20
14
|
# Utility method to get the last operation result with a human friendly message.
|
|
21
15
|
#
|
|
22
16
|
# Returns an OpenStruct with `code` and `message`.
|
|
@@ -29,7 +23,7 @@ module GitHub
|
|
|
29
23
|
# Returns a Net::LDAP::Entry if the operation succeeded.
|
|
30
24
|
def_delegator :@connection, :bind
|
|
31
25
|
|
|
32
|
-
attr_reader :virtual_attributes
|
|
26
|
+
attr_reader :uid, :virtual_attributes, :search_domains
|
|
33
27
|
|
|
34
28
|
def initialize(options = {})
|
|
35
29
|
@uid = options[:uid] || "sAMAccountName"
|
|
@@ -45,25 +39,13 @@ module GitHub
|
|
|
45
39
|
end
|
|
46
40
|
|
|
47
41
|
configure_virtual_attributes(options[:virtual_attributes])
|
|
48
|
-
end
|
|
49
42
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
#
|
|
54
|
-
# Returns the real encryption type.
|
|
55
|
-
def check_encryption(encryption)
|
|
56
|
-
return unless encryption
|
|
57
|
-
|
|
58
|
-
case encryption.downcase.to_sym
|
|
59
|
-
when :ssl, :simple_tls
|
|
60
|
-
:simple_tls
|
|
61
|
-
when :tls, :start_tls
|
|
62
|
-
:start_tls
|
|
63
|
-
end
|
|
43
|
+
# search_domains is a connection of bases to perform searches
|
|
44
|
+
# when a base is not explicitly provided.
|
|
45
|
+
@search_domains = Array(options[:search_domains])
|
|
64
46
|
end
|
|
65
47
|
|
|
66
|
-
# Utility method to check if the connection with the server can be stablished.
|
|
48
|
+
# Public - Utility method to check if the connection with the server can be stablished.
|
|
67
49
|
# It tries to bind with the ldap auth default configuration.
|
|
68
50
|
#
|
|
69
51
|
# Returns an OpenStruct with `code` and `message`.
|
|
@@ -73,7 +55,7 @@ module GitHub
|
|
|
73
55
|
last_operation_result
|
|
74
56
|
end
|
|
75
57
|
|
|
76
|
-
# Creates a new domain object to perform operations
|
|
58
|
+
# Public - Creates a new domain object to perform operations
|
|
77
59
|
#
|
|
78
60
|
# base_name: is the dn of the base root.
|
|
79
61
|
#
|
|
@@ -82,7 +64,7 @@ module GitHub
|
|
|
82
64
|
Domain.new(self, base_name, @uid)
|
|
83
65
|
end
|
|
84
66
|
|
|
85
|
-
# Creates a new group object to perform operations
|
|
67
|
+
# Public - Creates a new group object to perform operations
|
|
86
68
|
#
|
|
87
69
|
# base_name: is the dn of the base root.
|
|
88
70
|
#
|
|
@@ -92,14 +74,60 @@ module GitHub
|
|
|
92
74
|
entry = domain(base_name).bind
|
|
93
75
|
return unless entry
|
|
94
76
|
|
|
77
|
+
load_group(entry)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Public - Create a new group object based on a Net::LDAP::Entry.
|
|
81
|
+
#
|
|
82
|
+
# group_entry: is a Net::LDAP::Entry.
|
|
83
|
+
#
|
|
84
|
+
# Returns a Group, PosixGroup or VirtualGroup object.
|
|
85
|
+
def load_group(group_entry)
|
|
95
86
|
if @virtual_attributes.enabled?
|
|
96
|
-
VirtualGroup.new(self,
|
|
87
|
+
VirtualGroup.new(self, group_entry)
|
|
88
|
+
elsif PosixGroup.valid?(group_entry)
|
|
89
|
+
PosixGroup.new(self, group_entry)
|
|
90
|
+
else
|
|
91
|
+
Group.new(self, group_entry)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Public - Search entries in the ldap server.
|
|
96
|
+
#
|
|
97
|
+
# options: is a hash with the same options that Net::LDAP::Connection#search supports.
|
|
98
|
+
#
|
|
99
|
+
# Returns an Array of Net::LDAP::Entry.
|
|
100
|
+
def search(options)
|
|
101
|
+
result = if options[:base]
|
|
102
|
+
@connection.search(options)
|
|
97
103
|
else
|
|
98
|
-
|
|
104
|
+
search_domains.each_with_object([]) do |base, result|
|
|
105
|
+
rs = @connection.search(options.merge(:base => base))
|
|
106
|
+
result.concat Array(rs) unless rs == false
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
return [] if result == false
|
|
111
|
+
Array(result)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Internal - Determine whether to use encryption or not.
|
|
115
|
+
#
|
|
116
|
+
# encryption: is the encryption method, either 'ssl', 'tls', 'simple_tls' or 'start_tls'.
|
|
117
|
+
#
|
|
118
|
+
# Returns the real encryption type.
|
|
119
|
+
def check_encryption(encryption)
|
|
120
|
+
return unless encryption
|
|
121
|
+
|
|
122
|
+
case encryption.downcase.to_sym
|
|
123
|
+
when :ssl, :simple_tls
|
|
124
|
+
:simple_tls
|
|
125
|
+
when :tls, :start_tls
|
|
126
|
+
:start_tls
|
|
99
127
|
end
|
|
100
128
|
end
|
|
101
129
|
|
|
102
|
-
# Configure virtual attributes for this server.
|
|
130
|
+
# Internal - Configure virtual attributes for this server.
|
|
103
131
|
# If the option is `true`, we'll use the default virual attributes.
|
|
104
132
|
# If it's a Hash we'll map the attributes in the hash.
|
|
105
133
|
#
|
data/lib/github/ldap/domain.rb
CHANGED
|
@@ -55,8 +55,8 @@ module GitHub
|
|
|
55
55
|
member_of = groups_map.keys & user_entry[@ldap.virtual_attributes.virtual_membership]
|
|
56
56
|
member_of.map {|dn| groups_map[dn]}
|
|
57
57
|
else
|
|
58
|
-
groups_map.each_with_object([]) do |(dn,
|
|
59
|
-
acc <<
|
|
58
|
+
groups_map.each_with_object([]) do |(dn, group_entry), acc|
|
|
59
|
+
acc << group_entry if @ldap.load_group(group_entry).is_member?(user_entry)
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
end
|
|
@@ -134,13 +134,9 @@ module GitHub
|
|
|
134
134
|
def search(options)
|
|
135
135
|
options[:base] = @base_name
|
|
136
136
|
options[:attributes] ||= []
|
|
137
|
-
options[:
|
|
138
|
-
options[:paged_searches_supported] ||= true
|
|
137
|
+
options[:paged_searches_supported] = true
|
|
139
138
|
|
|
140
|
-
|
|
141
|
-
return [] if rs == false
|
|
142
|
-
|
|
143
|
-
Array(rs)
|
|
139
|
+
@ldap.search(options)
|
|
144
140
|
end
|
|
145
141
|
|
|
146
142
|
# Provide a meaningful result after a protocol operation (for example,
|
data/lib/github/ldap/filter.rb
CHANGED
|
@@ -2,19 +2,20 @@ module GitHub
|
|
|
2
2
|
class Ldap
|
|
3
3
|
module Filter
|
|
4
4
|
ALL_GROUPS_FILTER = Net::LDAP::Filter.eq("objectClass", "groupOfNames") |
|
|
5
|
-
Net::LDAP::Filter.eq("objectClass", "groupOfUniqueNames")
|
|
5
|
+
Net::LDAP::Filter.eq("objectClass", "groupOfUniqueNames") |
|
|
6
|
+
Net::LDAP::Filter.eq("objectClass", "posixGroup")
|
|
7
|
+
|
|
8
|
+
MEMBERSHIP_NAMES = %w(member uniqueMember)
|
|
6
9
|
|
|
7
10
|
# Filter to get the configured groups in the ldap server.
|
|
8
11
|
# Takes the list of the group names and generate a filter for the groups
|
|
9
|
-
# with cn that match
|
|
12
|
+
# with cn that match.
|
|
10
13
|
#
|
|
11
14
|
# group_names: is an array of group CNs.
|
|
12
|
-
# user_dn: is an optional member to scope the search to.
|
|
13
15
|
#
|
|
14
16
|
# Returns a Net::LDAP::Filter.
|
|
15
|
-
def group_filter(group_names
|
|
16
|
-
|
|
17
|
-
member_filter(user_dn) & or_filters
|
|
17
|
+
def group_filter(group_names)
|
|
18
|
+
group_names.map {|g| Net::LDAP::Filter.eq("cn", g)}.reduce(:|)
|
|
18
19
|
end
|
|
19
20
|
|
|
20
21
|
# Filter to check a group membership.
|
|
@@ -24,9 +25,9 @@ module GitHub
|
|
|
24
25
|
# Returns a Net::LDAP::Filter.
|
|
25
26
|
def member_filter(user_dn = nil)
|
|
26
27
|
if user_dn
|
|
27
|
-
|
|
28
|
+
MEMBERSHIP_NAMES.map {|n| Net::LDAP::Filter.eq(n, user_dn)}.reduce(:|)
|
|
28
29
|
else
|
|
29
|
-
|
|
30
|
+
MEMBERSHIP_NAMES.map {|n| Net::LDAP::Filter.pres(n)}.reduce(:|)
|
|
30
31
|
end
|
|
31
32
|
end
|
|
32
33
|
|
|
@@ -69,6 +70,16 @@ module GitHub
|
|
|
69
70
|
def subgroups_of_group(group_dn, attr = 'memberOf')
|
|
70
71
|
Net::LDAP::Filter.eq(attr, group_dn) & ALL_GROUPS_FILTER
|
|
71
72
|
end
|
|
73
|
+
|
|
74
|
+
# Filter to get all the members of a group which uid is included in `memberUid`.
|
|
75
|
+
#
|
|
76
|
+
# uids: is an array with all the uids to search.
|
|
77
|
+
# uid_attr: is the names of the uid attribute in the directory.
|
|
78
|
+
#
|
|
79
|
+
# Returns a Net::LDAP::Filter
|
|
80
|
+
def all_members_by_uid(uids, uid_attr)
|
|
81
|
+
uids.map {|uid| Net::LDAP::Filter.eq(uid_attr, uid)}.reduce(:|)
|
|
82
|
+
end
|
|
72
83
|
end
|
|
73
84
|
end
|
|
74
85
|
end
|
data/lib/github/ldap/group.rb
CHANGED
|
@@ -10,7 +10,11 @@ module GitHub
|
|
|
10
10
|
# domain = GitHub::Ldap.new(options).group("cn=enterprise,dc=github,dc=com")
|
|
11
11
|
#
|
|
12
12
|
class Group
|
|
13
|
-
|
|
13
|
+
include Filter
|
|
14
|
+
|
|
15
|
+
GROUP_CLASS_NAMES = %w(groupOfNames groupOfUniqueNames posixGroup)
|
|
16
|
+
|
|
17
|
+
attr_reader :ldap, :entry
|
|
14
18
|
|
|
15
19
|
def initialize(ldap, entry)
|
|
16
20
|
@ldap, @entry = ldap, entry
|
|
@@ -37,12 +41,12 @@ module GitHub
|
|
|
37
41
|
|
|
38
42
|
# Public - Check if a user dn is included in the members of this group and its subgroups.
|
|
39
43
|
#
|
|
40
|
-
#
|
|
44
|
+
# user_entry: is the user entry to check the membership.
|
|
41
45
|
#
|
|
42
46
|
# Returns true if the dn is in the list of members.
|
|
43
|
-
def is_member?(
|
|
44
|
-
member_names.include?(
|
|
45
|
-
members.detect {|entry| entry.dn ==
|
|
47
|
+
def is_member?(user_entry)
|
|
48
|
+
member_names.include?(user_entry.dn) ||
|
|
49
|
+
members.detect {|entry| entry.dn == user_entry.dn}
|
|
46
50
|
end
|
|
47
51
|
|
|
48
52
|
|
|
@@ -60,7 +64,9 @@ module GitHub
|
|
|
60
64
|
#
|
|
61
65
|
# Returns an array with all the DN members.
|
|
62
66
|
def member_names
|
|
63
|
-
|
|
67
|
+
MEMBERSHIP_NAMES.each_with_object([]) do |n, cache|
|
|
68
|
+
cache.concat @entry[n]
|
|
69
|
+
end
|
|
64
70
|
end
|
|
65
71
|
|
|
66
72
|
# Internal - Check if an object class includes the member names
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module GitHub
|
|
2
|
+
class Ldap
|
|
3
|
+
# This class represents a POSIX group.
|
|
4
|
+
#
|
|
5
|
+
# To get a POSIX group, you'll need to create a `Ldap` object and then call the method `group`.
|
|
6
|
+
# The parameter for `group` must be a dn to a group entry with `posixGroup` amongs the values for the attribute `objectClass`.
|
|
7
|
+
#
|
|
8
|
+
# For example:
|
|
9
|
+
#
|
|
10
|
+
# domain = GitHub::Ldap.new(options).group("cn=enterprise,dc=github,dc=com")
|
|
11
|
+
#
|
|
12
|
+
class PosixGroup < Group
|
|
13
|
+
# Public - Check if an ldap entry is a valid posixGroup.
|
|
14
|
+
#
|
|
15
|
+
# entry: is the ldap entry to check.
|
|
16
|
+
#
|
|
17
|
+
# Returns true if the entry includes the objectClass `posixGroup`.
|
|
18
|
+
def self.valid?(entry)
|
|
19
|
+
entry[:objectClass].any? {|oc| oc.downcase == 'posixgroup'}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Public - Overrides Group#members
|
|
23
|
+
#
|
|
24
|
+
# Search the entries corresponding to the members in the `memberUid` attribute.
|
|
25
|
+
# It calls `super` if the group entry includes `member` or `uniqueMember`.
|
|
26
|
+
#
|
|
27
|
+
# Returns an array with the members of this group and its submembers if there is any.
|
|
28
|
+
def members
|
|
29
|
+
return @all_posix_members if @all_posix_members
|
|
30
|
+
|
|
31
|
+
@all_posix_members = search_members_by_uids
|
|
32
|
+
@all_posix_members.concat super if combined_group?
|
|
33
|
+
|
|
34
|
+
@all_posix_members.uniq! {|m| m.dn }
|
|
35
|
+
@all_posix_members
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Public - Overrides Group#subgroups
|
|
39
|
+
#
|
|
40
|
+
# Prevent to call super when the group entry does not include `member` or `uniqueMember`.
|
|
41
|
+
#
|
|
42
|
+
# Returns an array with the subgroups of this group.
|
|
43
|
+
def subgroups
|
|
44
|
+
return [] unless combined_group?
|
|
45
|
+
|
|
46
|
+
super
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Public - Overrides Group#is_member?
|
|
50
|
+
#
|
|
51
|
+
# Chech if the user entry uid exists in the collection of `memberUid`.
|
|
52
|
+
# It calls `super` if the group entry includes `member` or `uniqueMember`.
|
|
53
|
+
#
|
|
54
|
+
# Return true if the user is member if this group or any subgroup.
|
|
55
|
+
def is_member?(user_entry)
|
|
56
|
+
entry_uids = user_entry[ldap.uid]
|
|
57
|
+
return true if !(entry_uids & entry[:memberUid]).empty?
|
|
58
|
+
|
|
59
|
+
super if combined_group?
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Internal - Check if this posix group also includes `member` and `uniqueMember` entries.
|
|
63
|
+
#
|
|
64
|
+
# Returns true if any of the membership names is include in this group entry.
|
|
65
|
+
def combined_group?
|
|
66
|
+
MEMBERSHIP_NAMES.any? {|name| !entry[name].empty? }
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Internal - Search all members by uid.
|
|
70
|
+
#
|
|
71
|
+
# Return an array of user entries.
|
|
72
|
+
def search_members_by_uids
|
|
73
|
+
member_uids = entry[:memberUid]
|
|
74
|
+
return [] if member_uids.empty?
|
|
75
|
+
|
|
76
|
+
filter = all_members_by_uid(member_uids, ldap.uid)
|
|
77
|
+
ldap.search(filter: filter)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
data/test/filter_test.rb
CHANGED
|
@@ -17,15 +17,10 @@ class FilterTest < Minitest::Test
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def test_groups_reduced
|
|
20
|
-
assert_equal "(
|
|
20
|
+
assert_equal "(|(cn=Enterprise)(cn=People))",
|
|
21
21
|
@subject.group_filter(%w(Enterprise People)).to_s
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
def test_groups_for_member
|
|
25
|
-
assert_equal "(&(|(member=#{@me})(uniqueMember=#{@me}))(|(cn=Enterprise)(cn=People)))",
|
|
26
|
-
@subject.group_filter(%w(Enterprise People), @me).to_s
|
|
27
|
-
end
|
|
28
|
-
|
|
29
24
|
def test_members_of_group
|
|
30
25
|
assert_equal "(memberOf=cn=group,dc=github,dc=com)",
|
|
31
26
|
@subject.members_of_group('cn=group,dc=github,dc=com').to_s
|
|
@@ -41,4 +36,9 @@ class FilterTest < Minitest::Test
|
|
|
41
36
|
assert_equal "(&(isMemberOf=cn=group,dc=github,dc=com)#{Subject::ALL_GROUPS_FILTER})",
|
|
42
37
|
@subject.subgroups_of_group('cn=group,dc=github,dc=com', 'isMemberOf').to_s
|
|
43
38
|
end
|
|
39
|
+
|
|
40
|
+
def test_all_members_by_uid
|
|
41
|
+
assert_equal "(|(uid=calavera)(uid=mtodd))",
|
|
42
|
+
@subject.all_members_by_uid(%w(calavera mtodd), :uid).to_s
|
|
43
|
+
end
|
|
44
44
|
end
|
|
@@ -3,7 +3,6 @@ version: 1
|
|
|
3
3
|
# Organizations
|
|
4
4
|
|
|
5
5
|
dn: dc=github,dc=com
|
|
6
|
-
cn: github
|
|
7
6
|
objectClass: dcObject
|
|
8
7
|
objectClass: organization
|
|
9
8
|
dc: github
|
|
@@ -26,6 +25,7 @@ userPassword: secret
|
|
|
26
25
|
|
|
27
26
|
dn: ou=groups,dc=github,dc=com
|
|
28
27
|
objectclass: organizationalUnit
|
|
28
|
+
ou: groups
|
|
29
29
|
|
|
30
30
|
dn: cn=enterprise,ou=groups,dc=github,dc=com
|
|
31
31
|
cn: Enterprise
|
|
@@ -55,6 +55,7 @@ member: uid=rubiojr,ou=users,dc=github,dc=com
|
|
|
55
55
|
|
|
56
56
|
dn: ou=users,dc=github,dc=com
|
|
57
57
|
objectclass: organizationalUnit
|
|
58
|
+
ou: users
|
|
58
59
|
|
|
59
60
|
dn: uid=calavera,ou=users,dc=github,dc=com
|
|
60
61
|
cn: David Calavera
|
|
@@ -88,3 +89,11 @@ uid: rubiojr
|
|
|
88
89
|
userPassword: passworD1
|
|
89
90
|
mail: rubiojr@github.com
|
|
90
91
|
objectClass: inetOrgPerson
|
|
92
|
+
|
|
93
|
+
dn: uid=mtodd,ou=users,dc=github,dc=com
|
|
94
|
+
cn: mtodd
|
|
95
|
+
sn: mtodd
|
|
96
|
+
uid: mtodd
|
|
97
|
+
userPassword: passworD1
|
|
98
|
+
mail: mtodd@github.com
|
|
99
|
+
objectClass: inetOrgPerson
|
data/test/ldap_test.rb
CHANGED
|
@@ -29,6 +29,7 @@ module GitHubLdapTestCases
|
|
|
29
29
|
:attributes => %w(uid),
|
|
30
30
|
:filter => Net::LDAP::Filter.eq('uid', 'calavera')})
|
|
31
31
|
|
|
32
|
+
refute result.empty?
|
|
32
33
|
assert_equal 'calavera', result.first[:uid].first
|
|
33
34
|
end
|
|
34
35
|
|
|
@@ -56,6 +57,14 @@ module GitHubLdapTestCases
|
|
|
56
57
|
def test_virtual_attributes_disabled
|
|
57
58
|
refute @ldap.virtual_attributes.enabled?, "Expected to have virtual attributes disabled"
|
|
58
59
|
end
|
|
60
|
+
|
|
61
|
+
def test_search_domains
|
|
62
|
+
ldap = GitHub::Ldap.new(options.merge(search_domains: ['dc=github,dc=com']))
|
|
63
|
+
result = ldap.search(filter: Net::LDAP::Filter.eq('uid', 'calavera'))
|
|
64
|
+
|
|
65
|
+
refute result.empty?
|
|
66
|
+
assert_equal 'calavera', result.first[:uid].first
|
|
67
|
+
end
|
|
59
68
|
end
|
|
60
69
|
|
|
61
70
|
class GitHubLdapTest < GitHub::Ldap::Test
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class GitHubLdapPosixGroupTest < GitHub::Ldap::Test
|
|
4
|
+
def self.test_server_options
|
|
5
|
+
{user_fixtures: FIXTURES.join('github-with-subgroups.ldif').to_s}
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def setup
|
|
9
|
+
@simple_group = Net::LDAP::Entry._load("""
|
|
10
|
+
dn: cn=enterprise-posix-devs,ou=groups,dc=github,dc=com
|
|
11
|
+
cn: enterprise-posix-devs
|
|
12
|
+
objectClass: posixGroup
|
|
13
|
+
memberUid: benburkert
|
|
14
|
+
memberUid: mtodd""")
|
|
15
|
+
|
|
16
|
+
@one_level_deep_group = Net::LDAP::Entry._load("""
|
|
17
|
+
dn: cn=enterprise-posix-ops,ou=groups,dc=github,dc=com
|
|
18
|
+
cn: enterprise-posix-ops
|
|
19
|
+
objectClass: posixGroup
|
|
20
|
+
objectClass: groupOfNames
|
|
21
|
+
memberUid: sbryant
|
|
22
|
+
member: cn=spaniards,ou=groups,dc=github,dc=com""")
|
|
23
|
+
|
|
24
|
+
@two_levels_deep_group = Net::LDAP::Entry._load("""
|
|
25
|
+
dn: cn=enterprise-posix,ou=groups,dc=github,dc=com
|
|
26
|
+
cn: Enterprise Posix
|
|
27
|
+
objectClass: posixGroup
|
|
28
|
+
objectClass: groupOfNames
|
|
29
|
+
memberUid: calavera
|
|
30
|
+
member: cn=enterprise-devs,ou=groups,dc=github,dc=com
|
|
31
|
+
member: cn=enterprise-ops,ou=groups,dc=github,dc=com""")
|
|
32
|
+
|
|
33
|
+
@empty_group = Net::LDAP::Entry._load("""
|
|
34
|
+
dn: cn=enterprise-posix-empty,ou=groups,dc=github,dc=com
|
|
35
|
+
cn: enterprise-posix-empty
|
|
36
|
+
objectClass: posixGroup""")
|
|
37
|
+
|
|
38
|
+
@ldap = GitHub::Ldap.new(options.merge(search_domains: %w(dc=github,dc=com)))
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def test_posix_group
|
|
42
|
+
assert GitHub::Ldap::PosixGroup.valid?(@simple_group),
|
|
43
|
+
"Expected entry to be a valid posixGroup"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def test_posix_simple_members
|
|
47
|
+
group = GitHub::Ldap::PosixGroup.new(@ldap, @simple_group)
|
|
48
|
+
members = group.members
|
|
49
|
+
|
|
50
|
+
assert_equal 2, members.size
|
|
51
|
+
assert_equal 'benburkert', members.first[:uid].first
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def test_posix_combined_group
|
|
55
|
+
group = GitHub::Ldap::PosixGroup.new(@ldap, @one_level_deep_group)
|
|
56
|
+
members = group.members
|
|
57
|
+
|
|
58
|
+
assert_equal 3, members.size
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def test_posix_combined_group_unique_members
|
|
62
|
+
group = GitHub::Ldap::PosixGroup.new(@ldap, @two_levels_deep_group)
|
|
63
|
+
members = group.members
|
|
64
|
+
|
|
65
|
+
assert_equal 4, members.size
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def test_empty_subgroups
|
|
69
|
+
group = GitHub::Ldap::PosixGroup.new(@ldap, @simple_group)
|
|
70
|
+
subgroups = group.subgroups
|
|
71
|
+
|
|
72
|
+
assert subgroups.empty?, "Simple posixgroup expected to not have subgroups"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def test_posix_combined_group_subgroups
|
|
76
|
+
group = GitHub::Ldap::PosixGroup.new(@ldap, @one_level_deep_group)
|
|
77
|
+
subgroups = group.subgroups
|
|
78
|
+
|
|
79
|
+
assert_equal 1, subgroups.size
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def test_is_member_simple_group
|
|
83
|
+
group = GitHub::Ldap::PosixGroup.new(@ldap, @simple_group)
|
|
84
|
+
user = @ldap.domain("uid=benburkert,ou=users,dc=github,dc=com").bind
|
|
85
|
+
|
|
86
|
+
assert group.is_member?(user),
|
|
87
|
+
"Expected user in the memberUid list to be a member of the posixgroup"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def test_is_member_combined_group
|
|
91
|
+
group = GitHub::Ldap::PosixGroup.new(@ldap, @one_level_deep_group)
|
|
92
|
+
user = @ldap.domain("uid=calavera,ou=users,dc=github,dc=com").bind
|
|
93
|
+
|
|
94
|
+
assert group.is_member?(user),
|
|
95
|
+
"Expected user in a subgroup to be a member of the posixgroup"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def test_is_not_member_simple_group
|
|
99
|
+
group = GitHub::Ldap::PosixGroup.new(@ldap, @simple_group)
|
|
100
|
+
user = @ldap.domain("uid=calavera,ou=users,dc=github,dc=com").bind
|
|
101
|
+
|
|
102
|
+
refute group.is_member?(user),
|
|
103
|
+
"Expected user to not be member when her uid is not in the list of memberUid"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def test_is_member_combined_group
|
|
107
|
+
group = GitHub::Ldap::PosixGroup.new(@ldap, @one_level_deep_group)
|
|
108
|
+
user = @ldap.domain("uid=benburkert,ou=users,dc=github,dc=com").bind
|
|
109
|
+
|
|
110
|
+
refute group.is_member?(user),
|
|
111
|
+
"Expected user to not be member when she's not member of any subgroup"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def test_empty_posix_group
|
|
115
|
+
group = GitHub::Ldap::PosixGroup.new(@ldap, @empty_group)
|
|
116
|
+
|
|
117
|
+
assert group.members.empty?,
|
|
118
|
+
"Expected members to be an empty array"
|
|
119
|
+
end
|
|
120
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: github-ldap
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.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-
|
|
11
|
+
date: 2014-03-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: net-ldap
|
|
@@ -99,6 +99,7 @@ files:
|
|
|
99
99
|
- lib/github/ldap/filter.rb
|
|
100
100
|
- lib/github/ldap/fixtures.ldif
|
|
101
101
|
- lib/github/ldap/group.rb
|
|
102
|
+
- lib/github/ldap/posix_group.rb
|
|
102
103
|
- lib/github/ldap/server.rb
|
|
103
104
|
- lib/github/ldap/virtual_attributes.rb
|
|
104
105
|
- lib/github/ldap/virtual_group.rb
|
|
@@ -109,6 +110,7 @@ files:
|
|
|
109
110
|
- test/fixtures/github-with-subgroups.ldif
|
|
110
111
|
- test/group_test.rb
|
|
111
112
|
- test/ldap_test.rb
|
|
113
|
+
- test/posix_group_test.rb
|
|
112
114
|
- test/test_helper.rb
|
|
113
115
|
homepage: https://github.com/github/github-ldap
|
|
114
116
|
licenses:
|
|
@@ -142,5 +144,6 @@ test_files:
|
|
|
142
144
|
- test/fixtures/github-with-subgroups.ldif
|
|
143
145
|
- test/group_test.rb
|
|
144
146
|
- test/ldap_test.rb
|
|
147
|
+
- test/posix_group_test.rb
|
|
145
148
|
- test/test_helper.rb
|
|
146
149
|
has_rdoc:
|