ruby-activeldap 0.7.4 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +375 -0
- data/COPYING +340 -0
- data/LICENSE +58 -0
- data/Manifest.txt +33 -0
- data/README +63 -0
- data/Rakefile +37 -0
- data/TODO +31 -0
- data/benchmark/bench-al.rb +152 -0
- data/lib/{activeldap.rb → active_ldap.rb} +280 -263
- data/lib/active_ldap/adaptor/base.rb +29 -0
- data/lib/active_ldap/adaptor/ldap.rb +466 -0
- data/lib/active_ldap/association/belongs_to.rb +38 -0
- data/lib/active_ldap/association/belongs_to_many.rb +40 -0
- data/lib/active_ldap/association/collection.rb +80 -0
- data/lib/active_ldap/association/has_many.rb +48 -0
- data/lib/active_ldap/association/has_many_wrap.rb +56 -0
- data/lib/active_ldap/association/proxy.rb +89 -0
- data/lib/active_ldap/associations.rb +162 -0
- data/lib/active_ldap/attributes.rb +199 -0
- data/lib/active_ldap/base.rb +1343 -0
- data/lib/active_ldap/callbacks.rb +19 -0
- data/lib/active_ldap/command.rb +46 -0
- data/lib/active_ldap/configuration.rb +96 -0
- data/lib/active_ldap/connection.rb +137 -0
- data/lib/{activeldap → active_ldap}/ldap.rb +1 -1
- data/lib/active_ldap/object_class.rb +70 -0
- data/lib/active_ldap/schema.rb +258 -0
- data/lib/{activeldap → active_ldap}/timeout.rb +0 -0
- data/lib/{activeldap → active_ldap}/timeout_stub.rb +0 -0
- data/lib/active_ldap/user_password.rb +92 -0
- data/lib/active_ldap/validations.rb +78 -0
- data/rails/plugin/active_ldap/README +54 -0
- data/rails/plugin/active_ldap/init.rb +6 -0
- data/test/TODO +2 -0
- data/test/al-test-utils.rb +337 -0
- data/test/command.rb +62 -0
- data/test/config.yaml +8 -0
- data/test/config.yaml.sample +6 -0
- data/test/run-test.rb +17 -0
- data/test/test-unit-ext.rb +2 -0
- data/test/test_associations.rb +334 -0
- data/test/test_attributes.rb +71 -0
- data/test/test_base.rb +345 -0
- data/test/test_base_per_instance.rb +32 -0
- data/test/test_bind.rb +53 -0
- data/test/test_callback.rb +35 -0
- data/test/test_connection.rb +38 -0
- data/test/test_connection_per_class.rb +50 -0
- data/test/test_find.rb +36 -0
- data/test/test_groupadd.rb +50 -0
- data/test/test_groupdel.rb +46 -0
- data/test/test_groupls.rb +107 -0
- data/test/test_groupmod.rb +51 -0
- data/test/test_lpasswd.rb +75 -0
- data/test/test_object_class.rb +32 -0
- data/test/test_reflection.rb +173 -0
- data/test/test_schema.rb +166 -0
- data/test/test_user.rb +209 -0
- data/test/test_user_password.rb +93 -0
- data/test/test_useradd-binary.rb +59 -0
- data/test/test_useradd.rb +55 -0
- data/test/test_userdel.rb +48 -0
- data/test/test_userls.rb +86 -0
- data/test/test_usermod-binary-add-time.rb +62 -0
- data/test/test_usermod-binary-add.rb +61 -0
- data/test/test_usermod-binary-del.rb +64 -0
- data/test/test_usermod-lang-add.rb +57 -0
- data/test/test_usermod.rb +56 -0
- data/test/test_validation.rb +38 -0
- metadata +94 -21
- data/lib/activeldap/associations.rb +0 -170
- data/lib/activeldap/base.rb +0 -1456
- data/lib/activeldap/configuration.rb +0 -59
- data/lib/activeldap/schema2.rb +0 -217
File without changes
|
File without changes
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'English'
|
2
|
+
require 'base64'
|
3
|
+
require 'md5'
|
4
|
+
require 'sha1'
|
5
|
+
|
6
|
+
module ActiveLdap
|
7
|
+
module UserPassword
|
8
|
+
module_function
|
9
|
+
def valid?(password, hashed_password)
|
10
|
+
unless /^\{([A-Z][A-Z\d]+)\}/ =~ hashed_password
|
11
|
+
raise ArgumentError, "Invalid hashed password"
|
12
|
+
end
|
13
|
+
type = $1
|
14
|
+
hashed_password_without_type = $POSTMATCH
|
15
|
+
normalized_type = type.downcase
|
16
|
+
unless respond_to?(normalized_type)
|
17
|
+
raise ArgumentError, "Unknown Hash type #{type}"
|
18
|
+
end
|
19
|
+
salt_extractor = "extract_salt_for_#{normalized_type}"
|
20
|
+
if respond_to?(salt_extractor)
|
21
|
+
salt = send(salt_extractor, hashed_password_without_type)
|
22
|
+
if salt.nil?
|
23
|
+
raise ArgumentError, "Can't extract salt from hashed password"
|
24
|
+
end
|
25
|
+
generated_password = send(normalized_type, password, salt)
|
26
|
+
else
|
27
|
+
generated_password = send(normalized_type, password)
|
28
|
+
end
|
29
|
+
hashed_password == generated_password
|
30
|
+
end
|
31
|
+
|
32
|
+
def crypt(password, salt=nil)
|
33
|
+
salt ||= "$1$#{Salt.generate(8)}"
|
34
|
+
"{CRYPT}#{password.crypt(salt)}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def extract_salt_for_crypt(crypted_password)
|
38
|
+
if /^\$1\$/ =~ crypted_password
|
39
|
+
$MATCH + $POSTMATCH[0, 8].sub(/\$.*/, '') + "$"
|
40
|
+
else
|
41
|
+
crypted_password[0, 2]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def md5(password)
|
46
|
+
"{MD5}#{Base64.encode64(MD5.md5(password).digest).chomp}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def smd5(password, salt=nil)
|
50
|
+
if salt and salt.size != 4
|
51
|
+
raise ArgumentError.new("salt size must be == 4")
|
52
|
+
end
|
53
|
+
salt ||= Salt.generate(4)
|
54
|
+
md5_hash_with_salt = "#{MD5.md5(password + salt).digest}#{salt}"
|
55
|
+
"{SMD5}#{Base64.encode64(md5_hash_with_salt).chomp}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def extract_salt_for_smd5(smd5ed_password)
|
59
|
+
Base64.decode64(smd5ed_password)[-4, 4]
|
60
|
+
end
|
61
|
+
|
62
|
+
def sha(password)
|
63
|
+
"{SHA}#{Base64.encode64(SHA1.sha1(password).digest).chomp}"
|
64
|
+
end
|
65
|
+
|
66
|
+
def ssha(password, salt=nil)
|
67
|
+
if salt and salt.size != 4
|
68
|
+
raise ArgumentError.new("salt size must be == 4")
|
69
|
+
end
|
70
|
+
salt ||= Salt.generate(4)
|
71
|
+
sha1_hash_with_salt = "#{SHA1.sha1(password + salt).digest}#{salt}"
|
72
|
+
"{SSHA}#{Base64.encode64(sha1_hash_with_salt).chomp}"
|
73
|
+
end
|
74
|
+
|
75
|
+
def extract_salt_for_ssha(sshaed_password)
|
76
|
+
extract_salt_for_smd5(sshaed_password)
|
77
|
+
end
|
78
|
+
|
79
|
+
module Salt
|
80
|
+
CHARS = ['.', '/', '0'..'9', 'A'..'Z', 'a'..'z'].collect do |x|
|
81
|
+
x.to_a
|
82
|
+
end.flatten
|
83
|
+
|
84
|
+
module_function
|
85
|
+
def generate(length)
|
86
|
+
salt = ""
|
87
|
+
length.times {salt << CHARS[rand(CHARS.length)]}
|
88
|
+
salt
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'active_record/validations'
|
2
|
+
|
3
|
+
module ActiveLdap
|
4
|
+
module Validations
|
5
|
+
def self.append_features(base)
|
6
|
+
super
|
7
|
+
|
8
|
+
base.class_eval do
|
9
|
+
alias_method :new_record?, :new_entry?
|
10
|
+
include ActiveRecord::Validations
|
11
|
+
|
12
|
+
validate :validate_required_values
|
13
|
+
|
14
|
+
class << self
|
15
|
+
alias_method :evaluate_condition_for_active_record,
|
16
|
+
:evaluate_condition
|
17
|
+
def evaluate_condition(condition, entry)
|
18
|
+
evaluate_condition_for_active_record(condition, entry)
|
19
|
+
rescue ActiveRecord::ActiveRecordError
|
20
|
+
raise Error, $!.message
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
alias_method :save_with_validation_for_active_record!,
|
25
|
+
:save_with_validation!
|
26
|
+
def save_with_validation!
|
27
|
+
save_with_validation_for_active_record!
|
28
|
+
rescue ActiveRecord::RecordInvalid
|
29
|
+
raise EntryInvalid, $!.message
|
30
|
+
end
|
31
|
+
alias_method :save!, :save_with_validation!
|
32
|
+
|
33
|
+
def valid?
|
34
|
+
ensure_apply_object_class
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
38
|
+
# validate_required_values
|
39
|
+
#
|
40
|
+
# Basic validation:
|
41
|
+
# - Verify that every 'MUST' specified in the schema has a value defined
|
42
|
+
def validate_required_values
|
43
|
+
logger.debug {"stub: validate_required_values called"}
|
44
|
+
|
45
|
+
# Make sure all MUST attributes have a value
|
46
|
+
@musts.each do |object_class, attributes|
|
47
|
+
attributes.each do |required_attribute|
|
48
|
+
# Normalize to ensure we catch schema problems
|
49
|
+
real_name = to_real_attribute_name(required_attribute)
|
50
|
+
# # Set default if it wasn't yet set.
|
51
|
+
# @data[real_name] ||= [] # need?
|
52
|
+
value = @data[real_name] || []
|
53
|
+
# Check for missing requirements.
|
54
|
+
if value.empty?
|
55
|
+
aliases = schema.attribute_aliases(real_name) - [real_name]
|
56
|
+
message = "is required attribute "
|
57
|
+
unless aliases.empty?
|
58
|
+
message << "(aliases: #{aliases.join(', ')}) "
|
59
|
+
end
|
60
|
+
message << "by objectClass '#{object_class}'"
|
61
|
+
errors.add(real_name, message)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
logger.debug {"stub: validate_required_values finished"}
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
alias_method :run_validations_for_active_record, :run_validations
|
70
|
+
def run_validations(validation_method)
|
71
|
+
run_validations_for_active_record(validation_method)
|
72
|
+
rescue ActiveRecord::ActiveRecordError
|
73
|
+
raise Error, $!.message
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
= ActiveLdap plugin for Ruby on Rails
|
2
|
+
|
3
|
+
== Setup
|
4
|
+
|
5
|
+
You need to write RAILS_ROOT/config/ldap.yml like the following:
|
6
|
+
|
7
|
+
development:
|
8
|
+
host: 127.0.0.1
|
9
|
+
port: 389
|
10
|
+
base: dc=devel,dc=local,dc=net
|
11
|
+
bind_dn: cn=admin,dc=local,dc=net
|
12
|
+
password: secret
|
13
|
+
|
14
|
+
test:
|
15
|
+
host: 127.0.0.1
|
16
|
+
port: 389
|
17
|
+
base: dc=test,dc=local,dc=net
|
18
|
+
bind_dn: cn=admin,dc=local,dc=net
|
19
|
+
password: secret
|
20
|
+
|
21
|
+
production:
|
22
|
+
host: 127.0.0.1
|
23
|
+
port: 389
|
24
|
+
base: dc=production,dc=local,dc=net
|
25
|
+
bind_dn: cn=admin,dc=local,dc=net
|
26
|
+
password: secret
|
27
|
+
|
28
|
+
== Model
|
29
|
+
|
30
|
+
Here is some examples.
|
31
|
+
|
32
|
+
app/model/member.rb:
|
33
|
+
class Member < ActiveLdap::Base
|
34
|
+
ldap_mapping :dn_attribute => 'uid',
|
35
|
+
:classes => ['person', 'posixAccount']
|
36
|
+
belongs_to :primary_group, :class => "Group",
|
37
|
+
:foreign_key => "gidNumber", :primary_key => "gidNumber"
|
38
|
+
belongs_to :groups, :many => 'memberUid'
|
39
|
+
end
|
40
|
+
|
41
|
+
app/model/group.rb:
|
42
|
+
class Group < ActiveLdap::Base
|
43
|
+
ldap_mapping :dn_attribute => "cn", :classes => ['posixGroup']
|
44
|
+
has_many :members, :wrap => "memberUid"
|
45
|
+
has_many :primary_members,
|
46
|
+
:foreign_key => 'gidNumber',
|
47
|
+
:primary_key => 'gidNumber'
|
48
|
+
end
|
49
|
+
|
50
|
+
app/model/ou.rb:
|
51
|
+
class Ou < ActiveLdap::Base
|
52
|
+
ldap_mapping :prefix => "",
|
53
|
+
:classes => ["top", "organizationalUnit"]
|
54
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
require_dependency 'active_ldap'
|
2
|
+
ActiveLdap::Base.logger ||= RAILS_DEFAULT_LOGGER
|
3
|
+
ldap_configuration_file = File.join(RAILS_ROOT, 'config', 'ldap.yml')
|
4
|
+
configurations = YAML::load(ERB.new(IO.read(ldap_configuration_file)).result)
|
5
|
+
ActiveLdap::Base.configurations = configurations
|
6
|
+
ActiveLdap::Base.establish_connection
|
data/test/TODO
ADDED
@@ -0,0 +1,337 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'test-unit-ext'
|
3
|
+
|
4
|
+
require 'erb'
|
5
|
+
require 'yaml'
|
6
|
+
require 'socket'
|
7
|
+
require 'openssl'
|
8
|
+
require 'rbconfig'
|
9
|
+
|
10
|
+
require 'active_ldap'
|
11
|
+
|
12
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "command")
|
13
|
+
|
14
|
+
LDAP_ENV = "test" unless defined?(LDAP_ENV)
|
15
|
+
|
16
|
+
module AlTestUtils
|
17
|
+
def self.included(base)
|
18
|
+
base.class_eval do
|
19
|
+
include Config
|
20
|
+
include Connection
|
21
|
+
include Populate
|
22
|
+
include TemporaryEntry
|
23
|
+
include CommandSupport
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module Config
|
28
|
+
def setup
|
29
|
+
super
|
30
|
+
@base_dir = File.expand_path(File.dirname(__FILE__))
|
31
|
+
@top_dir = File.expand_path(File.join(@base_dir, ".."))
|
32
|
+
@example_dir = File.join(@top_dir, "examples")
|
33
|
+
@config_file = File.join(File.dirname(__FILE__), "config.yaml")
|
34
|
+
ActiveLdap::Base.configurations = read_config
|
35
|
+
end
|
36
|
+
|
37
|
+
def teardown
|
38
|
+
super
|
39
|
+
end
|
40
|
+
|
41
|
+
def current_configuration
|
42
|
+
ActiveLdap::Base.configurations[LDAP_ENV]
|
43
|
+
end
|
44
|
+
|
45
|
+
def read_config
|
46
|
+
unless File.exist?(@config_file)
|
47
|
+
raise "config file for testing doesn't exist: #{@config_file}"
|
48
|
+
end
|
49
|
+
YAML.load(ERB.new(File.read(@config_file)).result)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
module Connection
|
54
|
+
def setup
|
55
|
+
super
|
56
|
+
ActiveLdap::Base.establish_connection
|
57
|
+
end
|
58
|
+
|
59
|
+
def teardown
|
60
|
+
ActiveLdap::Base.clear_active_connections!
|
61
|
+
super
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
module Populate
|
66
|
+
def setup
|
67
|
+
@dumped_data = nil
|
68
|
+
super
|
69
|
+
begin
|
70
|
+
@dumped_data = ActiveLdap::Base.dump(:scope => :sub)
|
71
|
+
rescue ActiveLdap::ConnectionError
|
72
|
+
end
|
73
|
+
ActiveLdap::Base.delete_all(nil, :scope => :sub)
|
74
|
+
populate
|
75
|
+
end
|
76
|
+
|
77
|
+
def teardown
|
78
|
+
if @dumped_data
|
79
|
+
ActiveLdap::Base.establish_connection
|
80
|
+
ActiveLdap::Base.delete_all(nil, :scope => :sub)
|
81
|
+
ActiveLdap::Base.load(@dumped_data)
|
82
|
+
end
|
83
|
+
super
|
84
|
+
end
|
85
|
+
|
86
|
+
def populate
|
87
|
+
populate_base
|
88
|
+
populate_ou
|
89
|
+
populate_user_class
|
90
|
+
populate_group_class
|
91
|
+
populate_associations
|
92
|
+
end
|
93
|
+
|
94
|
+
def populate_base
|
95
|
+
unless ActiveLdap::Base.search(:scope => :base).empty?
|
96
|
+
return
|
97
|
+
end
|
98
|
+
|
99
|
+
suffixes = []
|
100
|
+
ActiveLdap::Base.base.split(/,/).reverse_each do |suffix|
|
101
|
+
prefix = suffixes.join(",")
|
102
|
+
suffixes.unshift(suffix)
|
103
|
+
name, value = suffix.split(/=/, 2)
|
104
|
+
next unless name == "dc"
|
105
|
+
dc_class = Class.new(ActiveLdap::Base)
|
106
|
+
dc_class.ldap_mapping :dn_attribute => "dc",
|
107
|
+
:prefix => "",
|
108
|
+
:scope => :base,
|
109
|
+
:classes => ["top", "dcObject", "organization"]
|
110
|
+
dc_class.base = prefix
|
111
|
+
next if dc_class.exists?(value, :prefix => "dc=#{value}")
|
112
|
+
dc = dc_class.new(value)
|
113
|
+
dc.o = dc.dc
|
114
|
+
dc.save
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def ou_class(prefix="")
|
119
|
+
ou_class = Class.new(ActiveLdap::Base)
|
120
|
+
ou_class.ldap_mapping :dn_attribute => "ou",
|
121
|
+
:prefix => prefix,
|
122
|
+
:classes => ["top", "organizationalUnit"]
|
123
|
+
ou_class
|
124
|
+
end
|
125
|
+
|
126
|
+
def populate_ou
|
127
|
+
%w(Users Groups).each do |name|
|
128
|
+
make_ou(name)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def make_ou(name)
|
133
|
+
ou_class.new(name).save
|
134
|
+
end
|
135
|
+
|
136
|
+
def populate_user_class
|
137
|
+
@user_class = Class.new(ActiveLdap::Base)
|
138
|
+
@user_class.ldap_mapping :dn_attribute => "uid",
|
139
|
+
:prefix => "ou=Users",
|
140
|
+
:scope => :sub,
|
141
|
+
:classes => ["posixAccount", "person"]
|
142
|
+
end
|
143
|
+
|
144
|
+
def populate_group_class
|
145
|
+
@group_class = Class.new(ActiveLdap::Base)
|
146
|
+
@group_class.ldap_mapping :prefix => "ou=Groups",
|
147
|
+
:scope => :sub,
|
148
|
+
:classes => ["posixGroup"]
|
149
|
+
end
|
150
|
+
|
151
|
+
def populate_associations
|
152
|
+
@user_class.belongs_to :groups, :many => "memberUid"
|
153
|
+
@user_class.belongs_to :primary_group,
|
154
|
+
:foreign_key => "gidNumber",
|
155
|
+
:primary_key => "gidNumber"
|
156
|
+
@group_class.has_many :members, :wrap => "memberUid"
|
157
|
+
@group_class.has_many :primary_members,
|
158
|
+
:foreign_key => "gidNumber",
|
159
|
+
:primary_key => "gidNumber"
|
160
|
+
@user_class.set_associated_class(:groups, @group_class)
|
161
|
+
@user_class.set_associated_class(:primary_group, @group_class)
|
162
|
+
@group_class.set_associated_class(:members, @user_class)
|
163
|
+
@group_class.set_associated_class(:primary_members, @user_class)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
module TemporaryEntry
|
168
|
+
@@certificate = nil
|
169
|
+
def setup
|
170
|
+
super
|
171
|
+
@user_index = 0
|
172
|
+
@group_index = 0
|
173
|
+
end
|
174
|
+
|
175
|
+
def make_temporary_user(config={})
|
176
|
+
@user_index += 1
|
177
|
+
uid = config[:uid] || "temp-user#{@user_index}"
|
178
|
+
ensure_delete_user(uid) do
|
179
|
+
password = config[:password] || "password"
|
180
|
+
uid_number = config[:uid_number] || default_uid
|
181
|
+
gid_number = config[:gid_number] || default_gid
|
182
|
+
home_directory = config[:home_directory] || "/nonexistent"
|
183
|
+
_wrap_assertion do
|
184
|
+
assert(!@user_class.exists?(uid))
|
185
|
+
assert_raise(ActiveLdap::EntryNotFound) do
|
186
|
+
@user_class.find(uid).dn
|
187
|
+
end
|
188
|
+
user = @user_class.new(uid)
|
189
|
+
assert(user.new_entry?)
|
190
|
+
user.cn = user.uid
|
191
|
+
user.sn = user.uid
|
192
|
+
user.uid_number = uid_number
|
193
|
+
user.gid_number = gid_number
|
194
|
+
user.home_directory = home_directory
|
195
|
+
user.user_password = ActiveLdap::UserPassword.ssha(password)
|
196
|
+
unless config[:simple]
|
197
|
+
user.add_class('shadowAccount', 'inetOrgPerson',
|
198
|
+
'organizationalPerson')
|
199
|
+
user.user_certificate = certificate
|
200
|
+
user.jpeg_photo = jpeg_photo
|
201
|
+
end
|
202
|
+
user.save
|
203
|
+
assert(!user.new_entry?)
|
204
|
+
yield(@user_class.find(user.uid), password)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def make_temporary_group(config={})
|
210
|
+
@group_index += 1
|
211
|
+
cn = config[:cn] || "temp-group#{@group_index}"
|
212
|
+
ensure_delete_group(cn) do
|
213
|
+
gid_number = config[:gid_number] || default_gid
|
214
|
+
_wrap_assertion do
|
215
|
+
assert(!@group_class.exists?(cn))
|
216
|
+
assert_raise(ActiveLdap::EntryNotFound) do
|
217
|
+
@group_class.find(cn)
|
218
|
+
end
|
219
|
+
group = @group_class.new(cn)
|
220
|
+
assert(group.new_entry?)
|
221
|
+
group.gid_number = gid_number
|
222
|
+
assert(group.save)
|
223
|
+
assert(!group.new_entry?)
|
224
|
+
yield(@group_class.find(group.cn))
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def ensure_delete_user(uid)
|
230
|
+
yield(uid)
|
231
|
+
ensure
|
232
|
+
@user_class.delete(uid) if @user_class.exists?(uid)
|
233
|
+
end
|
234
|
+
|
235
|
+
def ensure_delete_group(cn)
|
236
|
+
yield(cn)
|
237
|
+
ensure
|
238
|
+
@group_class.delete(cn) if @group_class.exists?(cn)
|
239
|
+
end
|
240
|
+
|
241
|
+
def default_uid
|
242
|
+
"10000#{@user_index}"
|
243
|
+
end
|
244
|
+
|
245
|
+
def default_gid
|
246
|
+
"10000#{@group_index}"
|
247
|
+
end
|
248
|
+
|
249
|
+
def certificate_path
|
250
|
+
File.join(@example_dir, 'example.der')
|
251
|
+
end
|
252
|
+
|
253
|
+
def certificate
|
254
|
+
return @@certificate if @@certificate
|
255
|
+
if File.exists?(certificate_path)
|
256
|
+
@@certificate = File.read(certificate_path)
|
257
|
+
return @@certificate
|
258
|
+
end
|
259
|
+
|
260
|
+
rsa = OpenSSL::PKey::RSA.new(512)
|
261
|
+
comment = "Generated by Ruby/OpenSSL"
|
262
|
+
|
263
|
+
cert = OpenSSL::X509::Certificate.new
|
264
|
+
cert.version = 3
|
265
|
+
cert.serial = 0
|
266
|
+
subject = [["OU", "test"],
|
267
|
+
["CN", Socket.gethostname]]
|
268
|
+
name = OpenSSL::X509::Name.new(subject)
|
269
|
+
cert.subject = name
|
270
|
+
cert.issuer = name
|
271
|
+
cert.not_before = Time.now
|
272
|
+
cert.not_after = Time.now + (365*24*60*60)
|
273
|
+
cert.public_key = rsa.public_key
|
274
|
+
|
275
|
+
ef = OpenSSL::X509::ExtensionFactory.new(nil, cert)
|
276
|
+
ef.issuer_certificate = cert
|
277
|
+
cert.extensions = [
|
278
|
+
ef.create_extension("basicConstraints","CA:FALSE"),
|
279
|
+
ef.create_extension("keyUsage", "keyEncipherment"),
|
280
|
+
ef.create_extension("subjectKeyIdentifier", "hash"),
|
281
|
+
ef.create_extension("extendedKeyUsage", "serverAuth"),
|
282
|
+
ef.create_extension("nsComment", comment),
|
283
|
+
]
|
284
|
+
aki = ef.create_extension("authorityKeyIdentifier",
|
285
|
+
"keyid:always,issuer:always")
|
286
|
+
cert.add_extension(aki)
|
287
|
+
cert.sign(rsa, OpenSSL::Digest::SHA1.new)
|
288
|
+
|
289
|
+
@@certificate = cert.to_der
|
290
|
+
@@certificate
|
291
|
+
end
|
292
|
+
|
293
|
+
def jpeg_photo_path
|
294
|
+
File.join(@example_dir, 'example.jpg')
|
295
|
+
end
|
296
|
+
|
297
|
+
def jpeg_photo
|
298
|
+
File.read(jpeg_photo_path)
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
module CommandSupport
|
303
|
+
def setup
|
304
|
+
super
|
305
|
+
@fakeroot = "fakeroot"
|
306
|
+
@ruby = File.join(::Config::CONFIG["bindir"],
|
307
|
+
::Config::CONFIG["RUBY_INSTALL_NAME"])
|
308
|
+
@top_dir = File.expand_path(File.join(File.dirname(__FILE__), ".."))
|
309
|
+
@examples_dir = File.join(@top_dir, "examples")
|
310
|
+
@lib_dir = File.join(@top_dir, "lib")
|
311
|
+
@ruby_args = [
|
312
|
+
"-I", @examples_dir,
|
313
|
+
"-I", @lib_dir,
|
314
|
+
]
|
315
|
+
end
|
316
|
+
|
317
|
+
def run_command(*args, &block)
|
318
|
+
file = Tempfile.new("al-command-support")
|
319
|
+
file.open
|
320
|
+
file.puts(ActiveLdap::Base.configurations["test"].to_yaml)
|
321
|
+
file.close
|
322
|
+
run_ruby(*[@command, "--config", file.path, *args], &block)
|
323
|
+
end
|
324
|
+
|
325
|
+
def run_ruby(*ruby_args, &block)
|
326
|
+
args = [@ruby, *@ruby_args]
|
327
|
+
args.concat(ruby_args)
|
328
|
+
Command.run(*args, &block)
|
329
|
+
end
|
330
|
+
|
331
|
+
def run_ruby_with_fakeroot(*ruby_args, &block)
|
332
|
+
args = [@fakeroot, @ruby, *@ruby_args]
|
333
|
+
args.concat(ruby_args)
|
334
|
+
Command.run(*args, &block)
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|