ldap_fluff 0.1.1
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.
Potentially problematic release.
This version of ldap_fluff might be problematic. Click here for more details.
- data/etc/ldap_fluff.yml +9 -0
- data/lib/ldap_fluff/active_directory.rb +63 -0
- data/lib/ldap_fluff/ad_member_service.rb +75 -0
- data/lib/ldap_fluff/config.rb +51 -0
- data/lib/ldap_fluff/freeipa.rb +65 -0
- data/lib/ldap_fluff/freeipa_member_service.rb +39 -0
- data/lib/ldap_fluff/ldap_fluff.rb +40 -0
- data/lib/ldap_fluff/posix.rb +36 -0
- data/lib/ldap_fluff/posix_member_service.rb +56 -0
- data/lib/ldap_fluff.rb +8 -0
- data/test/ad_member_services_test.rb +85 -0
- data/test/ad_test.rb +100 -0
- data/test/config_test.rb +34 -0
- data/test/ipa_member_services_test.rb +36 -0
- data/test/ipa_test.rb +101 -0
- data/test/ldap_test.rb +34 -0
- data/test/lib/ldap_test_helper.rb +59 -0
- data/test/posix_member_services_test.rb +25 -0
- data/test/posix_test.rb +64 -0
- metadata +98 -0
data/etc/ldap_fluff.yml
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
---
|
2
|
+
host: ## ip address or hostname
|
3
|
+
encryption: ## blank or :start_tls
|
4
|
+
base_dn: ## baseDN for ldap auth, eg dc=redhat,dc=com
|
5
|
+
group_base: ##baseDN for your ldap groups, eg ou=Groups,dc=redhat,dc=com
|
6
|
+
server_type: ## type of server. default == posix. :active_directory, :posix, :free_ipa
|
7
|
+
ad_domain: ## domain for your users if using active directory, eg redhat.com
|
8
|
+
ad_service_user: ## service account for authenticating ldap calls in active directory
|
9
|
+
ad_service_pass: ## service password for authenticating ldap calls in active directory
|
@@ -0,0 +1,63 @@
|
|
1
|
+
class LdapFluff::ActiveDirectory
|
2
|
+
attr_accessor :ldap, :member_service
|
3
|
+
|
4
|
+
def initialize(config={})
|
5
|
+
@ldap = Net::LDAP.new :host => config.host,
|
6
|
+
:base => config.base_dn,
|
7
|
+
:port => config.port,
|
8
|
+
:encryption => config.encryption
|
9
|
+
@group_base = config.group_base
|
10
|
+
@group_base ||= config.base_dn
|
11
|
+
@ad_domain = config.domain
|
12
|
+
@bind_user = config.service_user
|
13
|
+
@bind_pass = config.service_pass
|
14
|
+
@anon = config.ad_anon_queries
|
15
|
+
|
16
|
+
@member_service = MemberService.new(@ldap,@group_base)
|
17
|
+
end
|
18
|
+
|
19
|
+
def bind?(uid=nil, password=nil)
|
20
|
+
@ldap.auth "#{uid}@#{@ad_domain}", password
|
21
|
+
@ldap.bind
|
22
|
+
end
|
23
|
+
|
24
|
+
# AD generally does not support un-authenticated searching
|
25
|
+
# Typically AD admins configure a public user for searching
|
26
|
+
def service_bind
|
27
|
+
unless @anon || bind?(@bind_user, @bind_pass)
|
28
|
+
raise UnauthenticatedActiveDirectoryException, "Could not bind to AD Service User"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# returns the list of groups to which a user belongs
|
33
|
+
# this query is simpler in active directory
|
34
|
+
def groups_for_uid(uid)
|
35
|
+
service_bind
|
36
|
+
begin
|
37
|
+
@member_service.find_user_groups(uid)
|
38
|
+
rescue MemberService::UIDNotFoundException
|
39
|
+
return []
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# active directory stores group membership on a users model
|
44
|
+
# TODO query by group individually not like this
|
45
|
+
def is_in_groups(uid, gids = [], all = false)
|
46
|
+
service_bind
|
47
|
+
return true if gids == []
|
48
|
+
begin
|
49
|
+
groups = @member_service.find_user_groups(uid)
|
50
|
+
intersection = gids & groups
|
51
|
+
if all
|
52
|
+
return intersection == gids
|
53
|
+
else
|
54
|
+
return intersection.size > 0
|
55
|
+
end
|
56
|
+
rescue MemberService::UIDNotFoundException
|
57
|
+
return false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class UnauthenticatedActiveDirectoryException < StandardError
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'net/ldap'
|
2
|
+
|
3
|
+
# Naughty bits of active directory ldap queries
|
4
|
+
class LdapFluff::ActiveDirectory::MemberService
|
5
|
+
|
6
|
+
attr_accessor :ldap
|
7
|
+
|
8
|
+
def initialize(ldap,group_base)
|
9
|
+
@ldap = ldap
|
10
|
+
@group_base = group_base
|
11
|
+
end
|
12
|
+
|
13
|
+
# get a list [] of ldap groups for a given user
|
14
|
+
# in active directory, this means a recursive lookup
|
15
|
+
def find_user_groups(uid)
|
16
|
+
data = @ldap.search(:filter => name_filter(uid))
|
17
|
+
raise UIDNotFoundException if (data == nil || data.empty?)
|
18
|
+
_groups_from_ldap_data(data.first)
|
19
|
+
end
|
20
|
+
|
21
|
+
# return the :memberof attrs + parents, recursively
|
22
|
+
def _groups_from_ldap_data(payload)
|
23
|
+
data = []
|
24
|
+
if payload != nil
|
25
|
+
first_level = _group_names_from_cn(payload[:memberof])
|
26
|
+
total_groups = _walk_group_ancestry(first_level)
|
27
|
+
data = (first_level + total_groups).uniq
|
28
|
+
end
|
29
|
+
data
|
30
|
+
end
|
31
|
+
|
32
|
+
# recursively loop over the parent list
|
33
|
+
def _walk_group_ancestry(gids=[])
|
34
|
+
set = []
|
35
|
+
gids.each do |g|
|
36
|
+
filter = group_filter(g) & class_filter
|
37
|
+
search = @ldap.search(:filter => filter, :base => @group_base)
|
38
|
+
if search != nil && search.first != nil
|
39
|
+
group = search.first
|
40
|
+
set += _group_names_from_cn(group[:memberof])
|
41
|
+
set += _walk_group_ancestry(set)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
set
|
45
|
+
end
|
46
|
+
|
47
|
+
def group_filter(gid)
|
48
|
+
Net::LDAP::Filter.eq("cn", gid)
|
49
|
+
end
|
50
|
+
|
51
|
+
def class_filter
|
52
|
+
Net::LDAP::Filter.eq("objectclass","group")
|
53
|
+
end
|
54
|
+
|
55
|
+
def name_filter(uid)
|
56
|
+
Net::LDAP::Filter.eq("samaccountname",uid)
|
57
|
+
end
|
58
|
+
|
59
|
+
# extract the group names from the LDAP style response,
|
60
|
+
# return string will be something like
|
61
|
+
# CN=bros,OU=bropeeps,DC=jomara,DC=redhat,DC=com
|
62
|
+
#
|
63
|
+
# AD group proc from
|
64
|
+
# http://erniemiller.org/2008/04/04/simplified-active-directory-authentication/
|
65
|
+
#
|
66
|
+
# I think we would normally want to just do the collect at the end,
|
67
|
+
# but we need the individual names for recursive queries
|
68
|
+
def _group_names_from_cn(grouplist)
|
69
|
+
p = Proc.new { |g| g.sub(/.*?CN=(.*?),.*/, '\1') }
|
70
|
+
grouplist.collect(&p)
|
71
|
+
end
|
72
|
+
|
73
|
+
class UIDNotFoundException < StandardError
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
class LdapFluff
|
5
|
+
####################################################################
|
6
|
+
# Module constants
|
7
|
+
####################################################################
|
8
|
+
CONFIG = "/etc/ldap_fluff.yml"
|
9
|
+
####################################################################
|
10
|
+
# Module class definitions
|
11
|
+
####################################################################
|
12
|
+
class Config
|
13
|
+
include Singleton
|
14
|
+
attr_accessor :host,
|
15
|
+
:port,
|
16
|
+
:encryption,
|
17
|
+
:base_dn,
|
18
|
+
:group_base,
|
19
|
+
:server_type,
|
20
|
+
:ad_domain,
|
21
|
+
:service_user,
|
22
|
+
:service_pass,
|
23
|
+
:anon_queries
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
begin
|
27
|
+
config = YAML.load_file(LdapFluff::CONFIG)
|
28
|
+
@host = config["host"]
|
29
|
+
@port = config["port"]
|
30
|
+
if config["encryption"].respond_to? :to_sym
|
31
|
+
@encryption = config["encryption"].to_sym
|
32
|
+
else
|
33
|
+
@encryption = nil
|
34
|
+
end
|
35
|
+
@base_dn = config["base_dn"]
|
36
|
+
@group_base = config["group_base"]
|
37
|
+
@ad_domain = config["ad_domain"]
|
38
|
+
@service_user = config["service_user"]
|
39
|
+
@service_pass = config["service_pass"]
|
40
|
+
@anon_queries = config["anon_queries"]
|
41
|
+
@server_type = config["server_type"]
|
42
|
+
rescue Errno::ENOENT
|
43
|
+
$stderr.puts("The #{LdapFluff::CONFIG} config file you specified was not found")
|
44
|
+
exit
|
45
|
+
rescue Errno::EACCES
|
46
|
+
$stderr.puts("The #{LdapFluff::CONFIG} config file you specified is not readable")
|
47
|
+
exit
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
class LdapFluff::FreeIPA
|
2
|
+
|
3
|
+
attr_accessor :ldap, :member_service
|
4
|
+
|
5
|
+
def initialize(config={})
|
6
|
+
@ldap = Net::LDAP.new :host => config.host,
|
7
|
+
:base => config.base_dn,
|
8
|
+
:port => config.port,
|
9
|
+
:encryption => config.encryption
|
10
|
+
@group_base = config.group_base
|
11
|
+
@group_base ||= config.base
|
12
|
+
@base = config.base_dn
|
13
|
+
@bind_user = config.service_user
|
14
|
+
@bind_pass = config.service_pass
|
15
|
+
@anon = config.anon_queries
|
16
|
+
|
17
|
+
@member_service = MemberService.new(@ldap,@group_base)
|
18
|
+
end
|
19
|
+
|
20
|
+
def bind?(uid=nil, password=nil)
|
21
|
+
@ldap.auth "uid=#{uid},cn=users,cn=accounts,#{@base}", password
|
22
|
+
@ldap.bind
|
23
|
+
end
|
24
|
+
|
25
|
+
def groups_for_uid(uid)
|
26
|
+
service_bind
|
27
|
+
begin
|
28
|
+
@member_service.find_user_groups(uid)
|
29
|
+
rescue MemberService::UIDNotFoundException
|
30
|
+
return []
|
31
|
+
rescue MemberService::InsufficientQueryPrivilegesException
|
32
|
+
raise UnauthenticatedFreeIPAException, "Insufficient Privileges to query groups data"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# AD generally does not support un-authenticated searching
|
37
|
+
# Typically AD admins configure a public user for searching
|
38
|
+
def service_bind
|
39
|
+
unless @anon || bind?(@bind_user, @bind_pass)
|
40
|
+
raise UnauthenticatedFreeIPAException, "Could not bind to FreeIPA Query User"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# In freeipa, a simple user query returns a full set
|
45
|
+
# of nested groups! yipee
|
46
|
+
#
|
47
|
+
# gids should be an array of group common names
|
48
|
+
#
|
49
|
+
# returns true if owner is in ALL of the groups if all=true, otherwise
|
50
|
+
# returns true if owner is in ANY of the groups
|
51
|
+
def is_in_groups(uid, gids = [], all=true)
|
52
|
+
service_bind
|
53
|
+
groups = @member_service.find_user_groups(uid)
|
54
|
+
if all
|
55
|
+
return groups & gids == gids
|
56
|
+
else
|
57
|
+
return groups & gids != []
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class UnauthenticatedFreeIPAException < StandardError
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'net/ldap'
|
2
|
+
|
3
|
+
# handles the naughty bits of posix ldap
|
4
|
+
class LdapFluff::FreeIPA::MemberService
|
5
|
+
|
6
|
+
attr_accessor :ldap
|
7
|
+
|
8
|
+
def initialize(ldap,group_base)
|
9
|
+
@ldap = ldap
|
10
|
+
@group_base = group_base
|
11
|
+
end
|
12
|
+
|
13
|
+
# return an ldap user with groups attached
|
14
|
+
# note : this method is not particularly fast for large ldap systems
|
15
|
+
def find_user_groups(uid)
|
16
|
+
user = @ldap.search(:filter => name_filter(uid))
|
17
|
+
raise UIDNotFoundException if (user == nil || user.empty?)
|
18
|
+
# if group data is missing, they aren't querying with a user
|
19
|
+
# with enough privileges
|
20
|
+
raise InsufficientQueryPrivilegesException if user.size <= 1
|
21
|
+
_group_names_from_cn(user[1][:memberof])
|
22
|
+
end
|
23
|
+
|
24
|
+
def name_filter(uid)
|
25
|
+
Net::LDAP::Filter.eq("uid",uid)
|
26
|
+
end
|
27
|
+
|
28
|
+
def _group_names_from_cn(grouplist)
|
29
|
+
p = Proc.new { |g| g.sub(/.*?cn=(.*?),.*/, '\1') }
|
30
|
+
grouplist.collect(&p)
|
31
|
+
end
|
32
|
+
|
33
|
+
class UIDNotFoundException < StandardError
|
34
|
+
end
|
35
|
+
|
36
|
+
class InsufficientQueryPrivilegesException < StandardError
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'net/ldap'
|
2
|
+
|
3
|
+
class LdapFluff
|
4
|
+
|
5
|
+
attr_accessor :ldap
|
6
|
+
|
7
|
+
def initialize(config=nil)
|
8
|
+
config ||= LdapFluff::Config.instance
|
9
|
+
type = config.server_type
|
10
|
+
if type.respond_to? :to_sym
|
11
|
+
if type.to_sym == :posix
|
12
|
+
@ldap = Posix.new(config)
|
13
|
+
elsif type.to_sym == :active_directory
|
14
|
+
@ldap = ActiveDirectory.new(config)
|
15
|
+
elsif type.to_sym == :free_ipa
|
16
|
+
@ldap = FreeIPA.new(config)
|
17
|
+
else
|
18
|
+
raise Exception, "Unsupported connection type. Supported types = :active_directory, :posix, :free_ipa"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# return true if the user password combination
|
24
|
+
# authenticates the user, otherwise false
|
25
|
+
def authenticate?(uid, password)
|
26
|
+
@ldap.bind? uid, password
|
27
|
+
end
|
28
|
+
|
29
|
+
# return a list[] of groups for a given uid
|
30
|
+
def group_list(uid)
|
31
|
+
@ldap.groups_for_uid(uid)
|
32
|
+
end
|
33
|
+
|
34
|
+
# return true if a user is in all of the groups
|
35
|
+
# in grouplist
|
36
|
+
def is_in_groups?(uid, grouplist)
|
37
|
+
@ldap.is_in_groups(uid, grouplist, true)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class LdapFluff::Posix
|
2
|
+
|
3
|
+
attr_accessor :ldap, :member_service
|
4
|
+
|
5
|
+
def initialize(config={})
|
6
|
+
@ldap = Net::LDAP.new :host => config.host,
|
7
|
+
:base => config.base_dn,
|
8
|
+
:port => config.port,
|
9
|
+
:encryption => config.encryption
|
10
|
+
@group_base = config.group_base
|
11
|
+
@group_base ||= config.base
|
12
|
+
@base = config.base_dn
|
13
|
+
@member_service = MemberService.new(@ldap,@group_base)
|
14
|
+
end
|
15
|
+
|
16
|
+
def bind?(uid=nil, password=nil)
|
17
|
+
@ldap.auth "uid=#{uid},#{@base}", password
|
18
|
+
@ldap.bind
|
19
|
+
end
|
20
|
+
|
21
|
+
def groups_for_uid(uid)
|
22
|
+
@member_service.find_user_groups(uid)
|
23
|
+
end
|
24
|
+
|
25
|
+
# returns whether a user is a member of ALL or ANY particular groups
|
26
|
+
# note: this method is much faster than groups_for_uid
|
27
|
+
#
|
28
|
+
# gids should be an array of group common names
|
29
|
+
#
|
30
|
+
# returns true if owner is in ALL of the groups if all=true, otherwise
|
31
|
+
# returns true if owner is in ANY of the groups
|
32
|
+
def is_in_groups(uid, gids = [], all=true)
|
33
|
+
(gids.empty? || @member_service.times_in_groups(uid, gids, all) > 0)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'net/ldap'
|
2
|
+
|
3
|
+
# handles the naughty bits of posix ldap
|
4
|
+
class LdapFluff::Posix::MemberService
|
5
|
+
|
6
|
+
attr_accessor :ldap
|
7
|
+
|
8
|
+
def initialize(ldap,group_base)
|
9
|
+
@ldap = ldap
|
10
|
+
@group_base = group_base
|
11
|
+
end
|
12
|
+
|
13
|
+
# return an ldap user with groups attached
|
14
|
+
# note : this method is not particularly fast for large ldap systems
|
15
|
+
def find_user_groups(uid)
|
16
|
+
groups = []
|
17
|
+
@ldap.search(:filter => name_filter(uid), :base => @group_base).each do |entry|
|
18
|
+
groups << entry[:cn][0]
|
19
|
+
end
|
20
|
+
groups
|
21
|
+
end
|
22
|
+
|
23
|
+
def times_in_groups(uid, gids, all)
|
24
|
+
matches = 0
|
25
|
+
filters = []
|
26
|
+
gids.each do |cn|
|
27
|
+
filters << group_filter(cn)
|
28
|
+
end
|
29
|
+
group_filters = merge_filters(filters,all)
|
30
|
+
filter = name_filter(uid) & group_filters
|
31
|
+
@ldap.search(:base => @group_base, :filter => filter).size
|
32
|
+
end
|
33
|
+
|
34
|
+
def name_filter(uid)
|
35
|
+
Net::LDAP::Filter.eq("memberUid",uid)
|
36
|
+
end
|
37
|
+
|
38
|
+
def group_filter(cn)
|
39
|
+
Net::LDAP::Filter.eq("cn", cn)
|
40
|
+
end
|
41
|
+
|
42
|
+
# AND or OR all of the filters together
|
43
|
+
def merge_filters(filters = [], all=false)
|
44
|
+
if filters != nil && filters.size >= 1
|
45
|
+
filter = filters[0]
|
46
|
+
filters[1..filters.size-1].each do |gfilter|
|
47
|
+
if all
|
48
|
+
filter = filter & gfilter
|
49
|
+
else
|
50
|
+
filter = filter | gfilter
|
51
|
+
end
|
52
|
+
end
|
53
|
+
return filter
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/ldap_fluff.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
require 'ldap_fluff/config'
|
2
|
+
require 'ldap_fluff/ldap_fluff'
|
3
|
+
require 'ldap_fluff/active_directory'
|
4
|
+
require 'ldap_fluff/ad_member_service'
|
5
|
+
require 'ldap_fluff/posix'
|
6
|
+
require 'ldap_fluff/posix_member_service'
|
7
|
+
require 'ldap_fluff/freeipa'
|
8
|
+
require 'ldap_fluff/freeipa_member_service'
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
|
3
|
+
class TestADMemberService < MiniTest::Unit::TestCase
|
4
|
+
include LdapTestHelper
|
5
|
+
|
6
|
+
def setup
|
7
|
+
config
|
8
|
+
@ldap = MiniTest::Mock.new
|
9
|
+
@adms = LdapFluff::ActiveDirectory::MemberService.new(@ldap,@config.group_base)
|
10
|
+
@gfilter = group_filter('group') & group_class_filter
|
11
|
+
end
|
12
|
+
|
13
|
+
def basic_user
|
14
|
+
@ldap.expect(:search, ad_user_payload, [:filter => ad_name_filter("john")])
|
15
|
+
@ldap.expect(:search, ad_parent_payload(1), [:filter => @gfilter, :base => @config.group_base])
|
16
|
+
end
|
17
|
+
|
18
|
+
def nest_deep(n)
|
19
|
+
# add all the expects
|
20
|
+
for i in 1..(n-1)
|
21
|
+
gfilter_bros = group_filter("bros#{i}") & group_class_filter
|
22
|
+
@ldap.expect(:search, ad_parent_payload(i+1), [:filter => gfilter_bros, :base => @config.group_base])
|
23
|
+
end
|
24
|
+
# terminate or we loop FOREVER
|
25
|
+
@ldap.expect(:search,[], [:filter => group_filter("bros#{n}") & group_class_filter, :base => @config.group_base])
|
26
|
+
end
|
27
|
+
|
28
|
+
def double_nested(n)
|
29
|
+
# add all the expects
|
30
|
+
for i in 1..(n-1)
|
31
|
+
gfilter_bros = group_filter("bros#{i}") & group_class_filter
|
32
|
+
@ldap.expect(:search, ad_double_payload(i+1), [:filter => gfilter_bros, :base => @config.group_base])
|
33
|
+
end
|
34
|
+
# terminate or we loop FOREVER
|
35
|
+
@ldap.expect(:search,[], [:filter => group_filter("bros#{n}") & group_class_filter, :base => @config.group_base])
|
36
|
+
(n-1).downto(1) do |i|
|
37
|
+
gfilter_bros = group_filter("broskies#{i+1}") & group_class_filter
|
38
|
+
@ldap.expect(:search,[], [:filter => gfilter_bros, :base => @config.group_base])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_find_user
|
43
|
+
basic_user
|
44
|
+
gfilter_bros = group_filter('bros1') & group_class_filter
|
45
|
+
@ldap.expect(:search, [], [:filter => gfilter_bros, :base => @config.group_base])
|
46
|
+
@adms.ldap = @ldap
|
47
|
+
assert_equal ['group', 'bros1'], @adms.find_user_groups("john")
|
48
|
+
@ldap.verify
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_missing_user
|
52
|
+
@ldap.expect(:search, nil, [:filter => ad_name_filter("john")])
|
53
|
+
@adms.ldap = @ldap
|
54
|
+
assert_raises(LdapFluff::ActiveDirectory::MemberService::UIDNotFoundException) { @adms.find_user_groups("john").data }
|
55
|
+
@ldap.verify
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_some_deep_recursion
|
59
|
+
basic_user
|
60
|
+
nest_deep(25)
|
61
|
+
@adms.ldap = @ldap
|
62
|
+
assert_equal 26, @adms.find_user_groups('john').size
|
63
|
+
@ldap.verify
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_complex_recursion
|
67
|
+
basic_user
|
68
|
+
double_nested(5)
|
69
|
+
@adms.ldap = @ldap
|
70
|
+
assert_equal 10, @adms.find_user_groups('john').size
|
71
|
+
@ldap.verify
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_nil_payload
|
75
|
+
assert_equal [], @adms._groups_from_ldap_data(nil)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_empty_user
|
79
|
+
@ldap.expect(:search, [], [:filter => ad_name_filter("john")])
|
80
|
+
@adms.ldap = @ldap
|
81
|
+
assert_raises(LdapFluff::ActiveDirectory::MemberService::UIDNotFoundException) { @adms.find_user_groups("john").data }
|
82
|
+
@ldap.verify
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
data/test/ad_test.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
|
3
|
+
class TestAD < MiniTest::Unit::TestCase
|
4
|
+
include LdapTestHelper
|
5
|
+
|
6
|
+
def setup
|
7
|
+
config
|
8
|
+
@ad = LdapFluff::ActiveDirectory.new(@config)
|
9
|
+
@ldap = MiniTest::Mock.new
|
10
|
+
end
|
11
|
+
|
12
|
+
# default setup for service bind users
|
13
|
+
def service_bind
|
14
|
+
@ldap.expect(:auth, nil, ["service@internet.com","pass"])
|
15
|
+
@ldap.expect(:bind, true)
|
16
|
+
@ad.ldap = @ldap
|
17
|
+
end
|
18
|
+
|
19
|
+
def basic_user
|
20
|
+
@md = MiniTest::Mock.new
|
21
|
+
@md.expect(:find_user_groups, ['bros'], ["john"])
|
22
|
+
@ad.member_service = @md
|
23
|
+
end
|
24
|
+
|
25
|
+
def bigtime_user
|
26
|
+
@md = MiniTest::Mock.new
|
27
|
+
@md.expect(:find_user_groups, ['bros','broskies'], ["john"])
|
28
|
+
@ad.member_service = @md
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_good_bind
|
32
|
+
@ldap.expect(:auth, nil, ["internet@internet.com","password"])
|
33
|
+
@ldap.expect(:bind, true)
|
34
|
+
@ad.ldap = @ldap
|
35
|
+
assert_equal @ad.bind?("internet", "password"), true
|
36
|
+
@ldap.verify
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_bad_bind
|
40
|
+
@ldap.expect(:auth, nil, ["internet@internet.com","password"])
|
41
|
+
@ldap.expect(:bind, false)
|
42
|
+
@ad.ldap = @ldap
|
43
|
+
assert_equal @ad.bind?("internet", "password"), false
|
44
|
+
@ldap.verify
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_groups
|
48
|
+
service_bind
|
49
|
+
basic_user
|
50
|
+
assert_equal @ad.groups_for_uid('john'), ['bros']
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_bad_user
|
54
|
+
service_bind
|
55
|
+
@md = MiniTest::Mock.new
|
56
|
+
@md.expect(:find_user_groups, nil, ["john"])
|
57
|
+
def @md.find_user_groups(*args)
|
58
|
+
raise LdapFluff::ActiveDirectory::MemberService::UIDNotFoundException
|
59
|
+
end
|
60
|
+
@ad.member_service = @md
|
61
|
+
assert_equal @ad.groups_for_uid('john'), []
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_bad_service_user
|
65
|
+
@ldap.expect(:auth, nil, ["service@internet.com","pass"])
|
66
|
+
@ldap.expect(:bind, false)
|
67
|
+
@ad.ldap = @ldap
|
68
|
+
assert_raises(LdapFluff::ActiveDirectory::UnauthenticatedActiveDirectoryException) { @ad.groups_for_uid('john') }
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_is_in_groups
|
72
|
+
service_bind
|
73
|
+
basic_user
|
74
|
+
assert_equal @ad.is_in_groups("john",["bros"],false), true
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_is_some_groups
|
78
|
+
service_bind
|
79
|
+
basic_user
|
80
|
+
assert_equal @ad.is_in_groups("john",["bros","buds"],false), true
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_isnt_in_all_groups
|
84
|
+
service_bind
|
85
|
+
basic_user
|
86
|
+
assert_equal @ad.is_in_groups("john",["bros","buds"],true), false
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_isnt_in_groups
|
90
|
+
service_bind
|
91
|
+
basic_user
|
92
|
+
assert_equal @ad.is_in_groups("john", ["broskies"],false), false
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_group_subset
|
96
|
+
service_bind
|
97
|
+
bigtime_user
|
98
|
+
assert_equal @ad.is_in_groups("john", ["broskies"],true), true
|
99
|
+
end
|
100
|
+
end
|
data/test/config_test.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'ldap_fluff'
|
3
|
+
|
4
|
+
class ConfigTest < MiniTest::Unit::TestCase
|
5
|
+
include LdapTestHelper
|
6
|
+
|
7
|
+
def setup
|
8
|
+
config
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_unsupported_type
|
12
|
+
@config.server_type = "inactive_directory"
|
13
|
+
assert_raises(Exception) { LdapFluff.new(@config) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_load_posix
|
17
|
+
@config.server_type = "posix"
|
18
|
+
l = LdapFluff.new(@config)
|
19
|
+
assert_instance_of LdapFluff::Posix, l.ldap
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_load_ad
|
23
|
+
@config.server_type = "active_directory"
|
24
|
+
l = LdapFluff.new(@config)
|
25
|
+
assert_instance_of LdapFluff::ActiveDirectory, l.ldap
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_load_ad
|
29
|
+
@config.server_type = "free_ipa"
|
30
|
+
l = LdapFluff.new(@config)
|
31
|
+
assert_instance_of LdapFluff::FreeIPA, l.ldap
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
|
3
|
+
class TestIPAMemberService < MiniTest::Unit::TestCase
|
4
|
+
include LdapTestHelper
|
5
|
+
|
6
|
+
def setup
|
7
|
+
config
|
8
|
+
@ldap = MiniTest::Mock.new
|
9
|
+
@ipams = LdapFluff::FreeIPA::MemberService.new(@ldap,@config.group_base)
|
10
|
+
end
|
11
|
+
|
12
|
+
def basic_user
|
13
|
+
@ldap.expect(:search, ipa_user_payload, [:filter => ipa_name_filter("john")])
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_find_user
|
17
|
+
basic_user
|
18
|
+
@ipams.ldap = @ldap
|
19
|
+
assert_equal ['group', 'bros'], @ipams.find_user_groups("john")
|
20
|
+
@ldap.verify
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_missing_user
|
24
|
+
@ldap.expect(:search, nil, [:filter => ipa_name_filter("john")])
|
25
|
+
@ipams.ldap = @ldap
|
26
|
+
assert_raises(LdapFluff::FreeIPA::MemberService::UIDNotFoundException) { @ipams.find_user_groups("john").data }
|
27
|
+
@ldap.verify
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_no_groups
|
31
|
+
@ldap.expect(:search, ['',{:memberof=>[]}], [:filter => ipa_name_filter("john")])
|
32
|
+
@ipams.ldap = @ldap
|
33
|
+
assert_equal [], @ipams.find_user_groups('john')
|
34
|
+
@ldap.verify
|
35
|
+
end
|
36
|
+
end
|
data/test/ipa_test.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
|
3
|
+
class TestIPA < MiniTest::Unit::TestCase
|
4
|
+
include LdapTestHelper
|
5
|
+
|
6
|
+
def setup
|
7
|
+
config
|
8
|
+
@ipa = LdapFluff::FreeIPA.new(@config)
|
9
|
+
@ldap = MiniTest::Mock.new
|
10
|
+
end
|
11
|
+
|
12
|
+
# default setup for service bind users
|
13
|
+
def service_bind
|
14
|
+
@ldap.expect(:auth, nil, [ipa_user_bind('service'),"pass"])
|
15
|
+
@ldap.expect(:bind, true)
|
16
|
+
@ipa.ldap = @ldap
|
17
|
+
end
|
18
|
+
|
19
|
+
def basic_user
|
20
|
+
@md = MiniTest::Mock.new
|
21
|
+
@md.expect(:find_user_groups, ['bros'], ["john"])
|
22
|
+
@ipa.member_service = @md
|
23
|
+
end
|
24
|
+
|
25
|
+
def bigtime_user
|
26
|
+
@md = MiniTest::Mock.new
|
27
|
+
@md.expect(:find_user_groups, ['bros','broskies'], ["john"])
|
28
|
+
@ipa.member_service = @md
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_good_bind
|
32
|
+
@ldap.expect(:auth, nil, [ipa_user_bind('internet'),"password"])
|
33
|
+
@ldap.expect(:bind, true)
|
34
|
+
@ipa.ldap = @ldap
|
35
|
+
assert_equal @ipa.bind?("internet", "password"), true
|
36
|
+
@ldap.verify
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_bad_bind
|
40
|
+
@ldap.expect(:auth, nil, [ipa_user_bind('internet'),"password"])
|
41
|
+
@ldap.expect(:bind, false)
|
42
|
+
@ipa.ldap = @ldap
|
43
|
+
assert_equal @ipa.bind?("internet", "password"), false
|
44
|
+
@ldap.verify
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_groups
|
48
|
+
service_bind
|
49
|
+
basic_user
|
50
|
+
assert_equal @ipa.groups_for_uid('john'), ['bros']
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_bad_user
|
54
|
+
service_bind
|
55
|
+
@md = MiniTest::Mock.new
|
56
|
+
@md.expect(:find_user_groups, nil, ["john"])
|
57
|
+
def @md.find_user_groups(*args)
|
58
|
+
raise LdapFluff::FreeIPA::MemberService::UIDNotFoundException
|
59
|
+
end
|
60
|
+
@ipa.member_service = @md
|
61
|
+
assert_equal @ipa.groups_for_uid('john'), []
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_bad_service_user
|
65
|
+
@ldap.expect(:auth, nil, [ipa_user_bind('service'),"pass"])
|
66
|
+
@ldap.expect(:bind, false)
|
67
|
+
@ipa.ldap = @ldap
|
68
|
+
assert_raises(LdapFluff::FreeIPA::UnauthenticatedFreeIPAException) { @ipa.groups_for_uid('john') }
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_is_in_groups
|
72
|
+
service_bind
|
73
|
+
basic_user
|
74
|
+
assert_equal @ipa.is_in_groups("john",["bros"],false), true
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_is_some_groups
|
78
|
+
service_bind
|
79
|
+
basic_user
|
80
|
+
assert_equal @ipa.is_in_groups("john",["bros","buds"],false), true
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_isnt_in_all_groups
|
84
|
+
service_bind
|
85
|
+
basic_user
|
86
|
+
assert_equal @ipa.is_in_groups("john",["bros","buds"],true), false
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_isnt_in_groups
|
90
|
+
service_bind
|
91
|
+
basic_user
|
92
|
+
assert_equal @ipa.is_in_groups("john", ["broskies"],false), false
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_group_subset
|
96
|
+
service_bind
|
97
|
+
bigtime_user
|
98
|
+
assert_equal @ipa.is_in_groups('john',["broskies"],true), true
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
data/test/ldap_test.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
|
3
|
+
class TestLDAP < MiniTest::Unit::TestCase
|
4
|
+
include LdapTestHelper
|
5
|
+
|
6
|
+
def setup
|
7
|
+
config
|
8
|
+
@ldap = MiniTest::Mock.new
|
9
|
+
@fluff = LdapFluff.new(@config)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_bind
|
13
|
+
@ldap.expect(:bind?, true, ['john','password'])
|
14
|
+
@fluff.ldap = @ldap
|
15
|
+
assert_equal @fluff.authenticate?("john","password"), true
|
16
|
+
@ldap.verify
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_groups
|
20
|
+
@ldap.expect(:groups_for_uid, ['bros'], ['john'])
|
21
|
+
@fluff.ldap = @ldap
|
22
|
+
assert_equal @fluff.group_list('john'), ['bros']
|
23
|
+
@ldap.verify
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_group_membership
|
27
|
+
@ldap.expect(:is_in_groups, false, ['john',['broskies','girlfriends'],true])
|
28
|
+
@fluff.ldap = @ldap
|
29
|
+
assert_equal @fluff.is_in_groups?('john',['broskies','girlfriends']), false
|
30
|
+
@ldap.verify
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'net/ldap'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
module LdapTestHelper
|
5
|
+
attr_accessor :group_base, :class_filter, :user
|
6
|
+
|
7
|
+
def config
|
8
|
+
@config = OpenStruct.new(
|
9
|
+
:host => "internet.com",
|
10
|
+
:port => "387",
|
11
|
+
:encryption => :start_tls,
|
12
|
+
:base_dn => "dc=internet,dc=com",
|
13
|
+
:group_base => "ou=group,dc=internet,dc=com",
|
14
|
+
:service_user => "service",
|
15
|
+
:service_pass => "pass",
|
16
|
+
:domain => "internet.com"
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
def ad_name_filter(name)
|
21
|
+
Net::LDAP::Filter.eq("samaccountname",name)
|
22
|
+
end
|
23
|
+
|
24
|
+
def ipa_name_filter(name)
|
25
|
+
Net::LDAP::Filter.eq("uid",name)
|
26
|
+
end
|
27
|
+
|
28
|
+
def group_filter(g)
|
29
|
+
Net::LDAP::Filter.eq("cn", g)
|
30
|
+
end
|
31
|
+
|
32
|
+
def group_class_filter
|
33
|
+
Net::LDAP::Filter.eq("objectclass","group")
|
34
|
+
end
|
35
|
+
|
36
|
+
def ipa_user_bind(uid)
|
37
|
+
"uid=#{uid},cn=users,cn=accounts,#{@config.base_dn}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def ad_user_payload
|
41
|
+
[{ :memberof => ["CN=group,dc=internet,dc=com"] }]
|
42
|
+
end
|
43
|
+
|
44
|
+
def ad_parent_payload(num)
|
45
|
+
[{ :memberof => ["CN=bros#{num},dc=internet,dc=com"] }]
|
46
|
+
end
|
47
|
+
|
48
|
+
def ad_double_payload(num)
|
49
|
+
[{ :memberof => ["CN=bros#{num},dc=internet,dc=com", "CN=broskies#{num},dc=internet,dc=com"] }]
|
50
|
+
end
|
51
|
+
|
52
|
+
def posix_user_payload
|
53
|
+
[{:cn => ["bros"]}]
|
54
|
+
end
|
55
|
+
|
56
|
+
def ipa_user_payload
|
57
|
+
[{:cn => 'user'},{:memberof => ['cn=group,dc=internet,dc=com','cn=bros,dc=internet,dc=com']}]
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
|
3
|
+
class TestPosixMemberService < MiniTest::Unit::TestCase
|
4
|
+
include LdapTestHelper
|
5
|
+
|
6
|
+
def setup
|
7
|
+
config
|
8
|
+
@ldap = MiniTest::Mock.new
|
9
|
+
@ms = LdapFluff::Posix::MemberService.new(@ldap, @config.group_base)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_find_user
|
13
|
+
user = posix_user_payload
|
14
|
+
@ldap.expect(:search,
|
15
|
+
user,
|
16
|
+
[
|
17
|
+
:filter => @ms.name_filter('john'),
|
18
|
+
:base =>config.group_base
|
19
|
+
]
|
20
|
+
)
|
21
|
+
@ms.ldap = @ldap
|
22
|
+
assert_equal ['bros'], @ms.find_user_groups('john')
|
23
|
+
@ldap.verify
|
24
|
+
end
|
25
|
+
end
|
data/test/posix_test.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
|
3
|
+
class TestPosix < MiniTest::Unit::TestCase
|
4
|
+
include LdapTestHelper
|
5
|
+
|
6
|
+
def setup
|
7
|
+
config
|
8
|
+
@posix = LdapFluff::Posix.new(@config)
|
9
|
+
@ldap = MiniTest::Mock.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def basic_user
|
13
|
+
@md = MiniTest::Mock.new
|
14
|
+
@md.expect(:find_user_groups, ['bros'], ["john"])
|
15
|
+
@posix.member_service = @md
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_groups
|
19
|
+
basic_user
|
20
|
+
assert_equal @posix.groups_for_uid("john"), ['bros']
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_missing_user
|
24
|
+
@md = MiniTest::Mock.new
|
25
|
+
@md.expect(:find_user_groups, [], ['john'])
|
26
|
+
@posix.member_service = @md
|
27
|
+
assert_equal [], @posix.groups_for_uid('john')
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_isnt_in_groups
|
31
|
+
basic_user
|
32
|
+
@md = MiniTest::Mock.new
|
33
|
+
@md.expect(:times_in_groups, 0, ['john', ['bros'], true])
|
34
|
+
@posix.member_service = @md
|
35
|
+
assert_equal @posix.is_in_groups('john', ['bros'], true), false
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_is_in_groups
|
39
|
+
basic_user
|
40
|
+
@md = MiniTest::Mock.new
|
41
|
+
@md.expect(:times_in_groups, 1, ['john', ['bros'], true])
|
42
|
+
@posix.member_service = @md
|
43
|
+
assert_equal @posix.is_in_groups('john', ['bros'], true), true
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_is_in_no_groups
|
47
|
+
basic_user
|
48
|
+
assert_equal @posix.is_in_groups('john', [], true), true
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_good_bind
|
52
|
+
@ldap.expect(:auth, nil, ["uid=internet,dc=internet,dc=com","password"])
|
53
|
+
@ldap.expect(:bind, true)
|
54
|
+
@posix.ldap = @ldap
|
55
|
+
assert_equal @posix.bind?("internet", "password"), true
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_bad_bind
|
59
|
+
@ldap.expect(:auth, nil, ["uid=internet,dc=internet,dc=com","password"])
|
60
|
+
@ldap.expect(:bind, false)
|
61
|
+
@posix.ldap = @ldap
|
62
|
+
assert_equal @posix.bind?("internet", "password"), false
|
63
|
+
end
|
64
|
+
end
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ldap_fluff
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jordan OMara
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-07-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: net-ldap
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: minitest
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: ! 'Simple library for binding & group querying on top of various ldap
|
47
|
+
implementations
|
48
|
+
|
49
|
+
'
|
50
|
+
email: jomara@redhat.com
|
51
|
+
executables: []
|
52
|
+
extensions: []
|
53
|
+
extra_rdoc_files: []
|
54
|
+
files:
|
55
|
+
- etc/ldap_fluff.yml
|
56
|
+
- lib/ldap_fluff.rb
|
57
|
+
- lib/ldap_fluff/active_directory.rb
|
58
|
+
- lib/ldap_fluff/posix.rb
|
59
|
+
- lib/ldap_fluff/freeipa.rb
|
60
|
+
- lib/ldap_fluff/ldap_fluff.rb
|
61
|
+
- lib/ldap_fluff/config.rb
|
62
|
+
- lib/ldap_fluff/ad_member_service.rb
|
63
|
+
- lib/ldap_fluff/posix_member_service.rb
|
64
|
+
- lib/ldap_fluff/freeipa_member_service.rb
|
65
|
+
- test/ldap_test.rb
|
66
|
+
- test/ipa_member_services_test.rb
|
67
|
+
- test/posix_test.rb
|
68
|
+
- test/config_test.rb
|
69
|
+
- test/ipa_test.rb
|
70
|
+
- test/ad_test.rb
|
71
|
+
- test/ad_member_services_test.rb
|
72
|
+
- test/posix_member_services_test.rb
|
73
|
+
- test/lib/ldap_test_helper.rb
|
74
|
+
homepage: http://www.redhat.com
|
75
|
+
licenses: []
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options: []
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ! '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
requirements: []
|
93
|
+
rubyforge_project:
|
94
|
+
rubygems_version: 1.8.24
|
95
|
+
signing_key:
|
96
|
+
specification_version: 3
|
97
|
+
summary: LDAP Querying tools for Active Directory, FreeIPA and Posix-style
|
98
|
+
test_files: []
|