ldap_fluff 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
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: []
|