adauth 2.0.0 → 2.0.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.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.travis.yml +8 -1
- data/Gemfile +1 -1
- data/Gemfile.lock +10 -2
- data/LICENSE.txt +21 -0
- data/Rakefile +10 -1
- data/Readme.md +2 -1
- data/adauth.gemspec +2 -0
- data/lib/adauth.rb +6 -2
- data/lib/adauth/ad_object.rb +41 -15
- data/lib/adauth/ad_objects/group.rb +8 -3
- data/lib/adauth/ad_objects/user.rb +5 -5
- data/lib/adauth/authenticate.rb +11 -61
- data/lib/adauth/config.rb +2 -1
- data/lib/adauth/connection.rb +6 -0
- data/lib/adauth/net-ldap/string.rb +1 -0
- data/lib/adauth/version.rb +1 -1
- data/rspec_results.txt +10 -0
- data/spec/adauth_ad_object_computer_spec.rb +9 -4
- data/spec/adauth_ad_object_folder_spec.rb +7 -3
- data/spec/adauth_ad_object_group_spec.rb +8 -6
- data/spec/adauth_ad_object_ou_spec.rb +4 -0
- data/spec/adauth_ad_object_spec.rb +22 -0
- data/spec/adauth_ad_object_user_spec.rb +30 -20
- data/spec/adauth_authenticate_spec.rb +26 -0
- data/spec/adauth_connection_spec.rb +33 -0
- data/spec/adauth_rails_model_bridge_spec.rb +1 -1
- data/spec/spec_helper.rb +12 -9
- data/spec/test_data.example.yml +6 -2
- metadata +47 -21
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cffe1ba97471be1224d557a5df97bd0e16e5eb59
|
4
|
+
data.tar.gz: d080e1a4e3a065c57da6c7281c60c79e0fe82f07
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 12b8d3a9a46735f4528a890272db9c52434883bbc922f46f243957e87fb6acdf1e7f4abf42d70ca0bed4af8ad2ade0947b5918496af5fbca9e89495e8acab224
|
7
|
+
data.tar.gz: 94ec81bf3fb570be993eb87d51de4543ff11c91de5742e30ef26a7f7acefef8aca2866d76fdde8f87750eb71ffccf7e53f2c05acef3e381959b067d95e0db6a3
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -2,11 +2,18 @@ language: ruby
|
|
2
2
|
rvm:
|
3
3
|
- 1.8.7
|
4
4
|
- 1.9.3
|
5
|
+
- 2.0.0
|
5
6
|
- rbx-18mode
|
6
7
|
- rbx-19mode
|
8
|
+
- ruby-head
|
7
9
|
env:
|
8
|
-
- "rake=0.8"
|
9
10
|
- "rake=0.9"
|
10
11
|
script: "bundle exec rspec -t no_ad"
|
12
|
+
before_script: "mkdir log"
|
11
13
|
notifications:
|
12
14
|
email: false
|
15
|
+
matrix:
|
16
|
+
allow_failures:
|
17
|
+
- rvm: 1.8.7
|
18
|
+
- rvm: rbx-18mode
|
19
|
+
- rvm: ruby-head
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
adauth (2.0.
|
4
|
+
adauth (2.0.0)
|
5
5
|
net-ldap
|
6
6
|
|
7
7
|
GEM
|
8
|
-
remote:
|
8
|
+
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
10
|
diff-lcs (1.1.3)
|
11
|
+
multi_json (1.7.7)
|
11
12
|
net-ldap (0.3.1)
|
12
13
|
rake (0.9.2.2)
|
13
14
|
rspec (2.11.0)
|
@@ -18,6 +19,11 @@ GEM
|
|
18
19
|
rspec-expectations (2.11.2)
|
19
20
|
diff-lcs (~> 1.1.3)
|
20
21
|
rspec-mocks (2.11.2)
|
22
|
+
simplecov (0.7.1)
|
23
|
+
multi_json (~> 1.0)
|
24
|
+
simplecov-html (~> 0.7.1)
|
25
|
+
simplecov-html (0.7.1)
|
26
|
+
yard (0.8.6.2)
|
21
27
|
|
22
28
|
PLATFORMS
|
23
29
|
ruby
|
@@ -26,3 +32,5 @@ DEPENDENCIES
|
|
26
32
|
adauth!
|
27
33
|
rake
|
28
34
|
rspec
|
35
|
+
simplecov
|
36
|
+
yard
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Adam Laycock
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/Rakefile
CHANGED
@@ -1,4 +1,13 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'bundler'
|
3
3
|
|
4
|
-
Bundler::GemHelper.install_tasks
|
4
|
+
Bundler::GemHelper.install_tasks
|
5
|
+
|
6
|
+
desc "Save test results to a file"
|
7
|
+
task :generate_test_results do
|
8
|
+
puts "Running Tests"
|
9
|
+
system("rspec -c > rspec_results.txt")
|
10
|
+
puts "Saved!"
|
11
|
+
puts "Results:"
|
12
|
+
system("cat rspec_results.txt")
|
13
|
+
end
|
data/Readme.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# Adauth
|
2
|
-
[RDoc](http://rubydoc.info/github/Arcath/Adauth/master/frames) | [www](http://adauth.arcath.net) | [Gempage](http://rubygems.org/gems/adauth) | [](http://travis-ci.org/Arcath/Adauth)
|
2
|
+
[RDoc](http://rubydoc.info/github/Arcath/Adauth/master/frames) | [www](http://adauth.arcath.net) | [Gempage](http://rubygems.org/gems/adauth) | [](http://travis-ci.org/Arcath/Adauth) | [](https://codeclimate.com/github/Arcath/Adauth) | [](https://gemnasium.com/Arcath/Adauth)
|
3
|
+
|
3
4
|
|
4
5
|
Easy to use Active Directory Authentication for Rails.
|
5
6
|
|
data/adauth.gemspec
CHANGED
@@ -14,6 +14,8 @@ Gem::Specification.new do |s|
|
|
14
14
|
|
15
15
|
s.add_development_dependency "rake"
|
16
16
|
s.add_development_dependency "rspec"
|
17
|
+
s.add_development_dependency "simplecov"
|
18
|
+
s.add_development_dependency "yard"
|
17
19
|
s.add_dependency "net-ldap"
|
18
20
|
|
19
21
|
s.files = `git ls-files`.split("\n")
|
data/lib/adauth.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Requires
|
2
|
+
require 'logger'
|
2
3
|
require 'net/ldap'
|
3
4
|
require 'timeout'
|
4
|
-
require 'logger'
|
5
5
|
# Version
|
6
6
|
require 'adauth/version'
|
7
7
|
# Classes
|
@@ -28,6 +28,7 @@ module Adauth
|
|
28
28
|
def self.configure
|
29
29
|
@logger ||= Logger.new('log/adauth.log', 'weekly')
|
30
30
|
@logger.info('load') { "Loading new config" }
|
31
|
+
@connection = nil
|
31
32
|
@config = Config.new
|
32
33
|
yield(@config)
|
33
34
|
end
|
@@ -53,16 +54,19 @@ module Adauth
|
|
53
54
|
:server => @config.server,
|
54
55
|
:port => @config.port,
|
55
56
|
:base => @config.base,
|
56
|
-
:encryption => @config.encryption,
|
57
|
+
:encryption => @config.encryption,
|
58
|
+
:allow_fallback => @config.allow_fallback,
|
57
59
|
:username => user,
|
58
60
|
:password => password
|
59
61
|
}
|
60
62
|
end
|
61
63
|
|
64
|
+
# Returns the logger object
|
62
65
|
def self.logger
|
63
66
|
@logger
|
64
67
|
end
|
65
68
|
|
69
|
+
# Lets you set a new logger
|
66
70
|
def self.logger=(inputs)
|
67
71
|
@logger = inputs
|
68
72
|
end
|
data/lib/adauth/ad_object.rb
CHANGED
@@ -14,10 +14,10 @@ module Adauth
|
|
14
14
|
# Objects inherit from this class.
|
15
15
|
#
|
16
16
|
# Provides all the common functions for Active Directory.
|
17
|
-
class AdObject
|
17
|
+
class AdObject
|
18
18
|
# Returns all objects which have the ObjectClass of the inherited class
|
19
19
|
def self.all
|
20
|
-
Adauth.logger.info(self.inspect) { "Searching for all objects matching filter \"#{self::ObjectFilter}\"" }
|
20
|
+
Adauth.logger.info(self.class.inspect) { "Searching for all objects matching filter \"#{self::ObjectFilter}\"" }
|
21
21
|
self.filter(self::ObjectFilter)
|
22
22
|
end
|
23
23
|
|
@@ -26,7 +26,7 @@ module Adauth
|
|
26
26
|
# Uses ObjectFilter to restrict to the current object
|
27
27
|
def self.where(field, value)
|
28
28
|
search_filter = Net::LDAP::Filter.eq(field, value)
|
29
|
-
Adauth.logger.info(self.inspect) { "Searching for all \"#{self::ObjectFilter}\" where #{field} = #{value}" }
|
29
|
+
Adauth.logger.info(self.class.inspect) { "Searching for all \"#{self::ObjectFilter}\" where #{field} = #{value}" }
|
30
30
|
filter(add_object_filter(search_filter))
|
31
31
|
end
|
32
32
|
|
@@ -62,18 +62,19 @@ module Adauth
|
|
62
62
|
@ldap_object
|
63
63
|
end
|
64
64
|
|
65
|
-
# Over
|
65
|
+
# Over ride method missing to see if the object has a field by that name
|
66
66
|
def method_missing(method, *args)
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
67
|
+
field = self.class::Fields[method]
|
68
|
+
return handle_field(field) if field
|
69
|
+
return super
|
70
|
+
end
|
71
|
+
|
72
|
+
# Handle the output for the given field
|
73
|
+
def handle_field(field)
|
74
|
+
case field
|
75
|
+
when Symbol then return return_symbol_value(field)
|
76
|
+
when Array then return @ldap_object.send(field.first).collect(&field.last)
|
77
|
+
end
|
77
78
|
end
|
78
79
|
|
79
80
|
# Returns all the groups the object is a member of
|
@@ -84,6 +85,19 @@ module Adauth
|
|
84
85
|
@groups
|
85
86
|
end
|
86
87
|
|
88
|
+
# The same as cn_groups, but with the parent groups included
|
89
|
+
def cn_groups_nested
|
90
|
+
@cn_groups_nested = cn_groups
|
91
|
+
cn_groups.each do |group|
|
92
|
+
ado = Adauth::AdObjects::Group.where('name', group).first
|
93
|
+
groups = convert_to_objects ado.cn_groups
|
94
|
+
groups.each do |g|
|
95
|
+
@cn_groups_nested.push g if !(@cn_groups_nested.include?(g))
|
96
|
+
end
|
97
|
+
end
|
98
|
+
return @cn_groups_nested
|
99
|
+
end
|
100
|
+
|
87
101
|
# Returns all the ous the object is in
|
88
102
|
def ous
|
89
103
|
unless @ous
|
@@ -108,7 +122,11 @@ module Adauth
|
|
108
122
|
|
109
123
|
# Runs a modify action on the current object, takes an aray of operations
|
110
124
|
def modify(operations)
|
111
|
-
|
125
|
+
Adauth.logger.info(self.class.inspect) { "Attempting modify operation" }
|
126
|
+
unless Adauth.connection.modify :dn => @ldap_object.dn, :operations => operations
|
127
|
+
Adauth.logger.fatal(self.class.inspect) { "Modify Operation Failed! Code: #{Adauth.connection.get_operation_result.code} Message: #{Adauth.connection.get_operation_result.message}" }
|
128
|
+
raise 'Modify Operation Failed (see log for details)'
|
129
|
+
end
|
112
130
|
end
|
113
131
|
|
114
132
|
# Returns an array of member objects for this object
|
@@ -149,5 +167,13 @@ module Adauth
|
|
149
167
|
group = Adauth::AdObjects::Group.where('sAMAccountName', entity).first
|
150
168
|
(user || group)
|
151
169
|
end
|
170
|
+
|
171
|
+
def return_symbol_value(field)
|
172
|
+
value = @ldap_object.send(field)
|
173
|
+
case value
|
174
|
+
when String then return value
|
175
|
+
when Net::BER::BerIdentifiedArray then return value.first
|
176
|
+
end
|
177
|
+
end
|
152
178
|
end
|
153
179
|
end
|
@@ -19,8 +19,9 @@ module Adauth
|
|
19
19
|
:name => :samaccountname,
|
20
20
|
:cn_members => [ :member,
|
21
21
|
Proc.new {|g| g.sub(/.*?CN=(.*?),.*/, '\1')} ],
|
22
|
-
:
|
23
|
-
|
22
|
+
:memberof => :member
|
23
|
+
#:cn_groups => [ :memberof,
|
24
|
+
# Proc.new {|g| g.sub(/.*?CN=(.*?),.*/, '\1')} ]
|
24
25
|
}
|
25
26
|
|
26
27
|
# Object Net::LDAP filter
|
@@ -30,12 +31,16 @@ module Adauth
|
|
30
31
|
|
31
32
|
# Returns all the objects which are members of this group
|
32
33
|
def members
|
33
|
-
Adauth.logger.info(self.inspect) { "Getting group members for #{self.name}" }
|
34
|
+
Adauth.logger.info(self.class.inspect) { "Getting group members for #{self.name}" }
|
34
35
|
unless @members
|
35
36
|
@members = convert_to_objects(cn_members)
|
36
37
|
end
|
37
38
|
@members
|
38
39
|
end
|
40
|
+
|
41
|
+
def cn_groups
|
42
|
+
memberof.split(/.*?CN=(.*?),.*/)
|
43
|
+
end
|
39
44
|
end
|
40
45
|
end
|
41
46
|
end
|
@@ -42,11 +42,11 @@ module Adauth
|
|
42
42
|
end
|
43
43
|
|
44
44
|
# Changes the password to the supplied value
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
45
|
+
def set_password(new_password)
|
46
|
+
Adauth.logger.info("password management") { "Attempting password reset for #{self.login}" }
|
47
|
+
password = microsoft_encode_password(new_password)
|
48
|
+
modify([[:replace, :unicodePwd, password]])
|
49
|
+
end
|
50
50
|
|
51
51
|
private
|
52
52
|
|
data/lib/adauth/authenticate.rb
CHANGED
@@ -7,16 +7,13 @@ module Adauth
|
|
7
7
|
Adauth.logger.info("authentication") { "Attempting to authenticate as #{username}" }
|
8
8
|
if Adauth::AdObjects::User.authenticate(username, password)
|
9
9
|
user = Adauth::AdObjects::User.where('sAMAccountName', username).first
|
10
|
-
if
|
10
|
+
if allowed_to_login(user)
|
11
11
|
Adauth.logger.info("authentication") { "Authentication succesful" }
|
12
12
|
return user
|
13
13
|
else
|
14
|
-
Adauth.logger.info("authentication") { "Authentication failed (not in allowed group)" }
|
14
|
+
Adauth.logger.info("authentication") { "Authentication failed (not in allowed group or ou)" }
|
15
15
|
return false
|
16
16
|
end
|
17
|
-
else
|
18
|
-
Adauth.logger.info("authentication") { "Authentication failed (bad username/password)" }
|
19
|
-
return false
|
20
17
|
end
|
21
18
|
rescue RuntimeError
|
22
19
|
Adauth.logger.info("authentication") { "Authentication failed (RuntimeError)" }
|
@@ -24,63 +21,16 @@ module Adauth
|
|
24
21
|
end
|
25
22
|
end
|
26
23
|
|
27
|
-
#
|
28
|
-
def self.
|
29
|
-
|
30
|
-
allowed = (user && @config.allowed_groups != (@config.allowed_groups - user.cn_groups)) ? user : nil
|
31
|
-
|
32
|
-
if allowed == nil
|
33
|
-
allowed = is_group_in_group(user) != nil ? user : nil
|
34
|
-
end
|
35
|
-
else
|
36
|
-
allowed = user
|
37
|
-
end
|
38
|
-
|
39
|
-
if @config.denied_groups != []
|
40
|
-
denied = (user && @config.denied_groups == (@config.denied_groups - user.cn_groups)) ? user : nil
|
41
|
-
else
|
42
|
-
denied = user
|
43
|
-
end
|
44
|
-
|
45
|
-
allowed == denied
|
24
|
+
# Check if the user is allowed to login
|
25
|
+
def self.allowed_to_login(user)
|
26
|
+
(allowed_from_arrays(@config.allowed_groups, @config.denied_groups, user.cn_groups_nested) && allowed_from_arrays(@config.allowed_ous, @config.denied_ous, user.dn_ous))
|
46
27
|
end
|
47
28
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
55
|
-
|
56
|
-
if @config.denied_ous != []
|
57
|
-
denied = (user && @config.denied_ous == (@config.denied_ous - user.dn_ous)) ? user : nil
|
58
|
-
else
|
59
|
-
denied = user
|
60
|
-
end
|
61
|
-
|
62
|
-
allowed == denied
|
63
|
-
end
|
64
|
-
|
65
|
-
def self.is_group_in_group(adobject)
|
66
|
-
# Loop through each users group and see if it's a member of an allowed group
|
67
|
-
begin
|
68
|
-
adobject.cn_groups.each do |group|
|
69
|
-
|
70
|
-
if @config.allowed_groups.include?(group)
|
71
|
-
return group
|
72
|
-
end
|
73
|
-
|
74
|
-
adGroup = Adauth::AdObjects::Group.where('name', group).first
|
75
|
-
|
76
|
-
unless self.is_group_in_group(adGroup) == nil
|
77
|
-
return true
|
78
|
-
end
|
79
|
-
end
|
80
|
-
rescue
|
81
|
-
return nil
|
29
|
+
private
|
30
|
+
|
31
|
+
def self.allowed_from_arrays(allowed, denied, test)
|
32
|
+
return true if allowed.empty? && denied.empty?
|
33
|
+
return true if !((allowed & test).empty?)
|
34
|
+
return false if !((denied & test).empty?)
|
82
35
|
end
|
83
|
-
|
84
|
-
nil
|
85
|
-
end
|
86
36
|
end
|
data/lib/adauth/config.rb
CHANGED
@@ -3,7 +3,7 @@ module Adauth
|
|
3
3
|
#
|
4
4
|
# Sets the defaults an create and generates guess values.
|
5
5
|
class Config
|
6
|
-
attr_accessor :domain, :port, :base, :server, :encryption, :query_user, :query_password,
|
6
|
+
attr_accessor :domain, :port, :base, :server, :encryption, :query_user, :query_password, :allow_fallback,
|
7
7
|
:allowed_groups, :denied_groups, :allowed_ous, :denied_ous, :contains_nested_groups
|
8
8
|
|
9
9
|
def initialize
|
@@ -12,6 +12,7 @@ module Adauth
|
|
12
12
|
@allowed_ous = []
|
13
13
|
@denied_groups =[]
|
14
14
|
@denied_ous = []
|
15
|
+
@allow_fallback = false
|
15
16
|
@contains_nested_groups = false
|
16
17
|
end
|
17
18
|
|
data/lib/adauth/connection.rb
CHANGED
@@ -32,6 +32,12 @@ module Adauth
|
|
32
32
|
}
|
33
33
|
rescue Timeout::Error
|
34
34
|
raise 'Unable to connect to LDAP Server'
|
35
|
+
rescue Errno::ECONNRESET
|
36
|
+
if @config[:allow_fallback]
|
37
|
+
@config[:port] = @config[:allow_fallback]
|
38
|
+
@config[:encryption] = false
|
39
|
+
return Adauth::Connection.new(@config).bind
|
40
|
+
end
|
35
41
|
end
|
36
42
|
end
|
37
43
|
end
|
data/lib/adauth/version.rb
CHANGED
data/rspec_results.txt
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
...................*...............
|
2
|
+
|
3
|
+
Pending:
|
4
|
+
Adauth::AdObjects::User should allow you to reset the password
|
5
|
+
# Insecure connection, unable to test change password
|
6
|
+
# ./spec/adauth_ad_object_user_spec.rb:49
|
7
|
+
|
8
|
+
Finished in 12.3 seconds
|
9
|
+
35 examples, 0 failures, 1 pending
|
10
|
+
Coverage report generated for RSpec to /Users/arcath/Code/Gems/Adauth/coverage. 472 / 489 LOC (96.52%) covered.
|
@@ -1,9 +1,14 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Adauth::AdObjects::Computer do
|
4
|
+
let(:computer) do
|
5
|
+
ou = Adauth::AdObjects::OU.where('name', 'Domain Controllers').first
|
6
|
+
ou.members.first
|
7
|
+
end
|
8
|
+
|
4
9
|
it "Should find a computer" do
|
5
10
|
default_config
|
6
|
-
|
11
|
+
computer.should be_a Adauth::AdObjects::Computer
|
7
12
|
end
|
8
13
|
|
9
14
|
it "should only find computers" do
|
@@ -15,8 +20,8 @@ describe Adauth::AdObjects::Computer do
|
|
15
20
|
|
16
21
|
it "should be in an ou" do
|
17
22
|
default_config
|
18
|
-
|
19
|
-
|
20
|
-
|
23
|
+
computer.ous.should be_a Array
|
24
|
+
computer.ous.first.should be_a Adauth::AdObjects::OU
|
25
|
+
computer.ous.first.name.should eq "Domain Controllers"
|
21
26
|
end
|
22
27
|
end
|
@@ -1,13 +1,17 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Adauth::AdObjects::Folder do
|
4
|
-
|
4
|
+
let(:root_folder) do
|
5
|
+
Adauth::AdObjects::Folder.root
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should find the root of the domain" do
|
5
9
|
default_config
|
6
|
-
|
10
|
+
root_folder.should be_a Adauth::AdObjects::Folder
|
7
11
|
end
|
8
12
|
|
9
13
|
it "should have members" do
|
10
14
|
default_config
|
11
|
-
|
15
|
+
root_folder.members.should be_a Array
|
12
16
|
end
|
13
17
|
end
|
@@ -1,21 +1,23 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Adauth::AdObjects::Group do
|
4
|
+
let(:domain_admins) do
|
5
|
+
Adauth::AdObjects::Group.where('name', 'Domain Admins').first
|
6
|
+
end
|
7
|
+
|
4
8
|
it "should have a name" do
|
5
9
|
default_config
|
6
|
-
|
7
|
-
group.name.should eq "Domain Admins"
|
10
|
+
domain_admins.name.should eq "Domain Admins"
|
8
11
|
end
|
9
12
|
|
10
13
|
it "should have a members list" do
|
11
14
|
default_config
|
12
|
-
|
13
|
-
|
15
|
+
domain_admins.members.should be_a Array
|
16
|
+
domain_admins.members.first.name.should be_a String
|
14
17
|
end
|
15
18
|
|
16
19
|
it "should be a member of" do
|
17
20
|
default_config
|
18
|
-
|
19
|
-
group.groups.should be_a Array
|
21
|
+
domain_admins.groups.should be_a Array
|
20
22
|
end
|
21
23
|
end
|
@@ -1,6 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Adauth::AdObjects::OU do
|
4
|
+
let(:domain_controllers) do
|
5
|
+
Adauth::AdObjects::OU.where('name', 'Domain Controllers').first
|
6
|
+
end
|
7
|
+
|
4
8
|
it "should find Domain Controllers" do
|
5
9
|
default_config
|
6
10
|
domain_controllers.should be_a Adauth::AdObjects::OU
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Adauth::AdObject do
|
4
|
+
let(:computer) do
|
5
|
+
ou = Adauth::AdObjects::OU.where('name', 'Domain Controllers').first
|
6
|
+
ou.members.first
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:user) do
|
10
|
+
Adauth::AdObjects::User.where('sAMAccountName', test_data("domain", "breakable_user")).first
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should still have method missing" do
|
14
|
+
default_config
|
15
|
+
computer.should be_a Adauth::AdObjects::Computer
|
16
|
+
lambda { computer.foo_bar }.should raise_exception NoMethodError
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should generate a nested group list" do
|
20
|
+
user.cn_groups.should_not eq user.cn_groups_nested
|
21
|
+
end
|
22
|
+
end
|
@@ -1,10 +1,13 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Adauth::AdObjects::User do
|
4
|
+
let(:user) do
|
5
|
+
Adauth::AdObjects::User.where('sAMAccountName', test_data("domain", "breakable_user")).first
|
6
|
+
end
|
7
|
+
|
4
8
|
it "should find administrator" do
|
5
9
|
default_config
|
6
|
-
user
|
7
|
-
user.login.should eq "Administrator"
|
10
|
+
user.login.should eq test_data("domain", "breakable_user")
|
8
11
|
end
|
9
12
|
|
10
13
|
it "should authenticate a user" do
|
@@ -14,40 +17,47 @@ describe Adauth::AdObjects::User do
|
|
14
17
|
|
15
18
|
it "should find groups" do
|
16
19
|
default_config
|
17
|
-
user = administrator
|
18
20
|
user.groups.should be_a Array
|
19
21
|
user.groups.first.should be_a Adauth::AdObjects::Group
|
20
22
|
end
|
21
23
|
|
22
|
-
it "should return
|
24
|
+
it "should return boolean for member_of" do
|
23
25
|
default_config
|
24
|
-
user
|
25
|
-
user.member_of?("Domain Admins").should be_true
|
26
|
+
user.member_of?("A Group").should be_false
|
26
27
|
end
|
27
28
|
|
28
29
|
it "should allow for modification" do
|
29
30
|
default_config
|
30
31
|
Adauth.add_field(Adauth::AdObjects::User, :phone, :homePhone)
|
31
|
-
number =
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
number = user.phone
|
33
|
+
user.modify([[:replace, :homephone, "8765"]])
|
34
|
+
new_user = Adauth::AdObjects::User.where('sAMAccountName', test_data("domain", "breakable_user")).first
|
35
|
+
new_user.phone.should eq "8765"
|
36
|
+
new_user.modify([[:replace, :homephone, number]])
|
37
|
+
new2_user = Adauth::AdObjects::User.where('sAMAccountName', test_data("domain", "breakable_user")).first
|
38
|
+
new2_user.phone.should eq number
|
35
39
|
end
|
36
40
|
|
37
41
|
it "should allow for additional methods" do
|
38
42
|
default_config
|
39
43
|
Adauth.add_field(Adauth::AdObjects::User, :description, :description)
|
40
44
|
administrator.description.should be_a String
|
45
|
+
Adauth.add_field(Adauth::AdObjects::User, :objectguid, :objectguid)
|
46
|
+
administrator.objectguid.should be_a String
|
41
47
|
end
|
42
48
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
49
|
+
it "should allow you to reset the password" do
|
50
|
+
default_config
|
51
|
+
begin
|
52
|
+
Adauth::AdObjects::User.authenticate(test_data("domain", "breakable_user"), test_data("domain", "breakable_password")).should be_true
|
53
|
+
user = Adauth::AdObjects::User.where('sAMAccountName', test_data("domain", "breakable_user")).first
|
54
|
+
user.login.should eq test_data("domain", "breakable_user")
|
55
|
+
user.set_password("adauth_test")
|
56
|
+
Adauth::AdObjects::User.authenticate(test_data("domain", "breakable_user"), "adauth_test").should be_true
|
57
|
+
user.set_password(test_data("domain", "breakable_password"))
|
58
|
+
Adauth::AdObjects::User.authenticate(test_data("domain", "breakable_user"), test_data("domain", "breakable_password")).should be_true
|
59
|
+
rescue RuntimeError
|
60
|
+
pending("Insecure connection, unable to test change password")
|
61
|
+
end
|
62
|
+
end
|
53
63
|
end
|
@@ -11,6 +11,32 @@ describe Adauth, "#authenticate" do
|
|
11
11
|
Adauth.authenticate(test_data("domain", "query_user"), "foo").should be_false
|
12
12
|
end
|
13
13
|
|
14
|
+
it "should allow the user if allowed groups are used" do
|
15
|
+
Adauth.configure do |c|
|
16
|
+
c.domain = test_data("domain", "domain")
|
17
|
+
c.port = test_data("domain", "port")
|
18
|
+
c.base = test_data("domain", "base")
|
19
|
+
c.server = test_data("domain", "server")
|
20
|
+
c.query_user = test_data("domain", "query_user")
|
21
|
+
c.query_password = test_data("domain", "query_password")
|
22
|
+
c.allowed_groups = ["Administrators"]
|
23
|
+
end
|
24
|
+
Adauth.authenticate(test_data("domain", "query_user"), test_data("domain", "query_password")).should be_a Adauth::AdObjects::User
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should allow the user if allowed ous are used" do
|
28
|
+
Adauth.configure do |c|
|
29
|
+
c.domain = test_data("domain", "domain")
|
30
|
+
c.port = test_data("domain", "port")
|
31
|
+
c.base = test_data("domain", "base")
|
32
|
+
c.server = test_data("domain", "server")
|
33
|
+
c.query_user = test_data("domain", "query_user")
|
34
|
+
c.query_password = test_data("domain", "query_password")
|
35
|
+
c.allowed_ous = ["Users"]
|
36
|
+
end
|
37
|
+
Adauth.authenticate(test_data("domain", "query_user"), test_data("domain", "query_password")).should be_a Adauth::AdObjects::User
|
38
|
+
end
|
39
|
+
|
14
40
|
it "should reject a user if denied group is used" do
|
15
41
|
Adauth.configure do |c|
|
16
42
|
c.domain = test_data("domain", "domain")
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Adauth::Connection do
|
4
|
+
it "should support encryption" do
|
5
|
+
Adauth.configure do |c|
|
6
|
+
c.domain = test_data("domain", "domain")
|
7
|
+
c.port = test_data("domain", "port")
|
8
|
+
c.base = test_data("domain", "base")
|
9
|
+
c.server = test_data("domain", "server")
|
10
|
+
c.encryption = :simple_tls
|
11
|
+
c.query_user = test_data("domain", "query_user")
|
12
|
+
c.query_password = test_data("domain", "query_password")
|
13
|
+
end
|
14
|
+
begin
|
15
|
+
Adauth.authenticate(test_data("domain", "query_user"), test_data("domain", "query_password"))
|
16
|
+
rescue
|
17
|
+
# Failed to authenticate due to encryption (not what we are testing here)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should timeout if asked to connect to a server that doesn't exist" do
|
22
|
+
Adauth.configure do |c|
|
23
|
+
c.domain = test_data("domain", "domain")
|
24
|
+
c.port = test_data("domain", "port")
|
25
|
+
c.base = test_data("domain", "base")
|
26
|
+
c.server = "127.0.0.2"
|
27
|
+
c.query_user = test_data("domain", "query_user")
|
28
|
+
c.query_password = test_data("domain", "query_password")
|
29
|
+
end
|
30
|
+
|
31
|
+
lambda { Adauth::AdObjects::User.all }.should raise_exception
|
32
|
+
end
|
33
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
# Test coverage
|
2
|
+
require 'simplecov'
|
3
|
+
SimpleCov.start
|
4
|
+
|
5
|
+
# Requires
|
1
6
|
require 'adauth'
|
2
7
|
require 'yaml'
|
3
8
|
|
@@ -7,6 +12,8 @@ def default_config
|
|
7
12
|
c.port = test_data("domain", "port")
|
8
13
|
c.base = test_data("domain", "base")
|
9
14
|
c.server = test_data("domain", "server")
|
15
|
+
c.encryption = test_data("domain", "encryption").to_sym if test_data("domain", "encryption")
|
16
|
+
c.allow_fallback = test_data("domain", "allow_fallback") if test_data("domain", "allow_fallback")
|
10
17
|
c.query_user = test_data("domain", "query_user")
|
11
18
|
c.query_password = test_data("domain", "query_password")
|
12
19
|
end
|
@@ -21,14 +28,10 @@ def administrator
|
|
21
28
|
Adauth::AdObjects::User.where('sAMAccountName', "administrator").first
|
22
29
|
end
|
23
30
|
|
24
|
-
def
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
def domain_controllers
|
29
|
-
Adauth::AdObjects::OU.where('name', 'Domain Controllers').first
|
30
|
-
end
|
31
|
+
#def breakable_user
|
32
|
+
# Adauth::AdObjects::User.where('sAMAccountName', test_data("domain", "breakable_user")).first
|
33
|
+
#end
|
31
34
|
|
32
|
-
def
|
33
|
-
|
35
|
+
def query_user
|
36
|
+
Adauth::AdObjects::User.where('sAMAccountName', test_data("domain", "query_user")).first
|
34
37
|
end
|
data/spec/test_data.example.yml
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
domain:
|
2
2
|
domain: example.com
|
3
|
-
port: 389
|
3
|
+
port: 389 # Change to 636 for ssl encryption
|
4
|
+
#encryption: simple_tls
|
5
|
+
#allow_fallback: 389 # Used to fallback to insecure
|
4
6
|
base: "dc=example, dc=com"
|
5
7
|
server: dc1.example.com
|
6
8
|
query_user: User.Name
|
7
|
-
query_password: Password
|
9
|
+
query_password: Password
|
10
|
+
breakable_user: User.Name
|
11
|
+
breakable_password: Password
|
metadata
CHANGED
@@ -1,62 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adauth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
5
|
-
prerelease:
|
4
|
+
version: 2.0.1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Adam "Arcath" Laycock
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-07-14 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rake
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: rspec
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - '>='
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: simplecov
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: yard
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
44
67
|
- !ruby/object:Gem::Version
|
45
68
|
version: '0'
|
46
69
|
- !ruby/object:Gem::Dependency
|
47
70
|
name: net-ldap
|
48
71
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
72
|
requirements:
|
51
|
-
- -
|
73
|
+
- - '>='
|
52
74
|
- !ruby/object:Gem::Version
|
53
75
|
version: '0'
|
54
76
|
type: :runtime
|
55
77
|
prerelease: false
|
56
78
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
79
|
requirements:
|
59
|
-
- -
|
80
|
+
- - '>='
|
60
81
|
- !ruby/object:Gem::Version
|
61
82
|
version: '0'
|
62
83
|
description: A full featured library for working with Microsofts Active Directory
|
@@ -71,6 +92,7 @@ files:
|
|
71
92
|
- .travis.yml
|
72
93
|
- Gemfile
|
73
94
|
- Gemfile.lock
|
95
|
+
- LICENSE.txt
|
74
96
|
- Rakefile
|
75
97
|
- Readme.md
|
76
98
|
- adauth.gemspec
|
@@ -96,49 +118,53 @@ files:
|
|
96
118
|
- lib/generators/adauth/sessions/sessions_generator.rb
|
97
119
|
- lib/generators/adauth/sessions/templates/new.html.erb
|
98
120
|
- lib/generators/adauth/sessions/templates/sessions_controller.rb.erb
|
121
|
+
- rspec_results.txt
|
99
122
|
- spec/adauth_ad_object_computer_spec.rb
|
100
123
|
- spec/adauth_ad_object_folder_spec.rb
|
101
124
|
- spec/adauth_ad_object_group_spec.rb
|
102
125
|
- spec/adauth_ad_object_ou_spec.rb
|
126
|
+
- spec/adauth_ad_object_spec.rb
|
103
127
|
- spec/adauth_ad_object_user_spec.rb
|
104
128
|
- spec/adauth_authenticate_spec.rb
|
105
129
|
- spec/adauth_config_spec.rb
|
130
|
+
- spec/adauth_connection_spec.rb
|
106
131
|
- spec/adauth_rails_model_bridge_spec.rb
|
107
132
|
- spec/adauth_spec.rb
|
108
133
|
- spec/spec_helper.rb
|
109
134
|
- spec/test_data.example.yml
|
110
135
|
homepage: http://adauth.arcath.net
|
111
136
|
licenses: []
|
137
|
+
metadata: {}
|
112
138
|
post_install_message:
|
113
139
|
rdoc_options: []
|
114
140
|
require_paths:
|
115
141
|
- lib
|
116
142
|
required_ruby_version: !ruby/object:Gem::Requirement
|
117
|
-
none: false
|
118
143
|
requirements:
|
119
|
-
- -
|
144
|
+
- - '>='
|
120
145
|
- !ruby/object:Gem::Version
|
121
146
|
version: '0'
|
122
147
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
|
-
none: false
|
124
148
|
requirements:
|
125
|
-
- -
|
149
|
+
- - '>='
|
126
150
|
- !ruby/object:Gem::Version
|
127
151
|
version: '0'
|
128
152
|
requirements: []
|
129
153
|
rubyforge_project:
|
130
|
-
rubygems_version:
|
154
|
+
rubygems_version: 2.0.0
|
131
155
|
signing_key:
|
132
|
-
specification_version:
|
156
|
+
specification_version: 4
|
133
157
|
summary: Provides Active Directory authentication for Rails
|
134
158
|
test_files:
|
135
159
|
- spec/adauth_ad_object_computer_spec.rb
|
136
160
|
- spec/adauth_ad_object_folder_spec.rb
|
137
161
|
- spec/adauth_ad_object_group_spec.rb
|
138
162
|
- spec/adauth_ad_object_ou_spec.rb
|
163
|
+
- spec/adauth_ad_object_spec.rb
|
139
164
|
- spec/adauth_ad_object_user_spec.rb
|
140
165
|
- spec/adauth_authenticate_spec.rb
|
141
166
|
- spec/adauth_config_spec.rb
|
167
|
+
- spec/adauth_connection_spec.rb
|
142
168
|
- spec/adauth_rails_model_bridge_spec.rb
|
143
169
|
- spec/adauth_spec.rb
|
144
170
|
- spec/spec_helper.rb
|