adauth 1.2.1 → 2.0.0pre
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/.travis.yml +12 -0
- data/Gemfile.lock +13 -26
- data/Rakefile +1 -0
- data/Readme.md +48 -0
- data/adauth.gemspec +2 -1
- data/lib/adauth.rb +40 -28
- data/lib/adauth/ad_object.rb +104 -0
- data/lib/adauth/ad_objects/computer.rb +28 -0
- data/lib/adauth/ad_objects/group.rb +40 -0
- data/lib/adauth/ad_objects/ou.rb +41 -0
- data/lib/adauth/ad_objects/user.rb +45 -0
- data/lib/adauth/authenticate.rb +25 -46
- data/lib/adauth/config.rb +11 -28
- data/lib/adauth/connection.rb +19 -18
- data/lib/adauth/rails.rb +9 -0
- data/lib/adauth/rails/helpers.rb +29 -0
- data/lib/adauth/rails/model_bridge.rb +59 -0
- data/lib/adauth/version.rb +2 -3
- data/lib/generators/adauth/config/config_generator.rb +1 -1
- data/lib/generators/adauth/config/templates/config.rb.erb +18 -22
- data/lib/generators/adauth/sessions/sessions_generator.rb +2 -3
- data/lib/generators/adauth/sessions/templates/sessions_controller.rb.erb +1 -1
- data/spec/adauth_ad_object_computer_spec.rb +15 -0
- data/spec/adauth_ad_object_group_spec.rb +21 -0
- data/spec/adauth_ad_object_ou_spec.rb +18 -0
- data/spec/adauth_ad_object_user_spec.rb +27 -0
- data/spec/adauth_authenticate_spec.rb +39 -0
- data/spec/adauth_config_spec.rb +15 -0
- data/spec/adauth_rails_model_bridge_spec.rb +37 -0
- data/spec/adauth_spec.rb +2 -30
- data/spec/spec_helper.rb +34 -0
- metadata +52 -38
- data/Readme.rdoc +0 -66
- data/lib/adauth/admin_connection.rb +0 -26
- data/lib/adauth/group.rb +0 -100
- data/lib/adauth/helpers.rb +0 -28
- data/lib/adauth/user.rb +0 -114
- data/lib/adauth/user_model.rb +0 -76
- data/lib/generators/adauth/all/USAGE +0 -5
- data/lib/generators/adauth/all/all_generator.rb +0 -18
- data/lib/generators/adauth/user_model/USAGE +0 -14
- data/lib/generators/adauth/user_model/templates/model.rb.erb +0 -3
- data/lib/generators/adauth/user_model/user_model_generator.rb +0 -32
- data/spec/adauth_group_spec.rb +0 -51
- data/spec/adauth_user_model_spec.rb +0 -80
- data/spec/adauth_user_spec.rb +0 -213
data/.travis.yml
ADDED
data/Gemfile.lock
CHANGED
@@ -1,41 +1,28 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
adauth (
|
4
|
+
adauth (2.0.0pre)
|
5
5
|
net-ldap
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: http://rubygems.org/
|
9
9
|
specs:
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
builder (2.1.2)
|
22
|
-
diff-lcs (1.1.2)
|
23
|
-
i18n (0.5.0)
|
24
|
-
net-ldap (0.2.2)
|
25
|
-
rspec (2.6.0)
|
26
|
-
rspec-core (~> 2.6.0)
|
27
|
-
rspec-expectations (~> 2.6.0)
|
28
|
-
rspec-mocks (~> 2.6.0)
|
29
|
-
rspec-core (2.6.1)
|
30
|
-
rspec-expectations (2.6.0)
|
31
|
-
diff-lcs (~> 1.1.2)
|
32
|
-
rspec-mocks (2.6.0)
|
33
|
-
tzinfo (0.3.29)
|
10
|
+
diff-lcs (1.1.3)
|
11
|
+
net-ldap (0.3.1)
|
12
|
+
rake (0.9.2.2)
|
13
|
+
rspec (2.11.0)
|
14
|
+
rspec-core (~> 2.11.0)
|
15
|
+
rspec-expectations (~> 2.11.0)
|
16
|
+
rspec-mocks (~> 2.11.0)
|
17
|
+
rspec-core (2.11.1)
|
18
|
+
rspec-expectations (2.11.2)
|
19
|
+
diff-lcs (~> 1.1.3)
|
20
|
+
rspec-mocks (2.11.2)
|
34
21
|
|
35
22
|
PLATFORMS
|
36
23
|
ruby
|
37
24
|
|
38
25
|
DEPENDENCIES
|
39
|
-
activerecord
|
40
26
|
adauth!
|
27
|
+
rake
|
41
28
|
rspec
|
data/Rakefile
CHANGED
data/Readme.md
ADDED
@@ -0,0 +1,48 @@
|
|
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)
|
3
|
+
|
4
|
+
Easy to use Active Directory Authentication for Rails.
|
5
|
+
|
6
|
+
## Install
|
7
|
+
|
8
|
+
Add the Adauth gem to your Gemfile:
|
9
|
+
|
10
|
+
gem 'adauth'
|
11
|
+
|
12
|
+
and run a bundle install
|
13
|
+
|
14
|
+
## Usage
|
15
|
+
|
16
|
+
First off create a new config file by running the config generator
|
17
|
+
|
18
|
+
rails g adauth:config
|
19
|
+
|
20
|
+
Fill out the config values in _config/initializers/adauth.rb_
|
21
|
+
|
22
|
+
### Joining a model to Adauth
|
23
|
+
|
24
|
+
If you want to link your user model to Adauth you can use this simple code:
|
25
|
+
|
26
|
+
class User < ActiveRecord::Base
|
27
|
+
include Adauth::Rails::ModelBridge
|
28
|
+
|
29
|
+
AdauthMappings = {
|
30
|
+
:login => :login
|
31
|
+
:group_strings => :cn_groups
|
32
|
+
}
|
33
|
+
|
34
|
+
AdauthSearchField = [:login, :login]
|
35
|
+
end
|
36
|
+
|
37
|
+
This gives you a bridge between Adauth and your model. When you call `User.create_from_adauth(adauth_model)` it does:
|
38
|
+
|
39
|
+
u = User.new
|
40
|
+
u.login = adauth_model.login
|
41
|
+
u.group_strings = adauth_model.cn_groups
|
42
|
+
u.save
|
43
|
+
|
44
|
+
This can be used for any model and anything that you pull over through adauth.
|
45
|
+
|
46
|
+
### SessionsController
|
47
|
+
|
48
|
+
TODO
|
data/adauth.gemspec
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
2
|
$:.push File.expand_path("../lib", __FILE__)
|
3
3
|
require 'adauth/version'
|
4
4
|
|
@@ -11,6 +11,7 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.homepage = "http://adauth.arcath.net"
|
12
12
|
s.summary = "Provides Active Directory authentication for Rails"
|
13
13
|
|
14
|
+
s.add_development_dependency "rake"
|
14
15
|
s.add_development_dependency "rspec"
|
15
16
|
s.add_dependency "net-ldap"
|
16
17
|
|
data/lib/adauth.rb
CHANGED
@@ -1,41 +1,53 @@
|
|
1
|
+
# Requires
|
1
2
|
require 'net/ldap'
|
2
3
|
require 'timeout'
|
4
|
+
# Version
|
3
5
|
require 'adauth/version'
|
4
|
-
|
6
|
+
# Classes
|
7
|
+
require 'adauth/ad_object'
|
8
|
+
require 'adauth/authenticate'
|
5
9
|
require 'adauth/config'
|
6
|
-
require 'adauth/helpers'
|
7
10
|
require 'adauth/connection'
|
8
|
-
|
9
|
-
require 'adauth/
|
10
|
-
require 'adauth/
|
11
|
-
require 'adauth/
|
11
|
+
# AdObjects
|
12
|
+
require 'adauth/ad_objects/computer'
|
13
|
+
require 'adauth/ad_objects/group'
|
14
|
+
require 'adauth/ad_objects/ou'
|
15
|
+
require 'adauth/ad_objects/user'
|
16
|
+
# Rails
|
17
|
+
require 'adauth/rails'
|
18
|
+
require 'adauth/rails/helpers'
|
19
|
+
require 'adauth/rails/model_bridge'
|
12
20
|
|
13
|
-
#
|
14
|
-
#
|
15
|
-
# For Adauths documentation please see the github wiki.
|
21
|
+
# Adauth Container Module
|
16
22
|
module Adauth
|
17
|
-
|
18
|
-
# Used to configure Adauth
|
19
|
-
#
|
20
|
-
# Called as
|
21
|
-
# Adauth.configure do |c|
|
22
|
-
# c.foo = "bar"
|
23
|
-
# end
|
24
|
-
#
|
25
|
-
# Configures Adauth and is required for Adauth to work.
|
23
|
+
# Yields a new config object and then sets it as the Adauth Config
|
26
24
|
def self.configure
|
27
|
-
|
28
|
-
|
25
|
+
@config = Config.new
|
26
|
+
yield(@config)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns Adauths current connection to ActiveDirectory
|
30
|
+
def self.connection
|
31
|
+
raise "Adauth needs configuring before use" if @config == nil
|
32
|
+
connect unless @connection
|
33
|
+
@connection
|
29
34
|
end
|
30
35
|
|
31
|
-
#
|
32
|
-
|
33
|
-
|
34
|
-
def self.config
|
35
|
-
@config
|
36
|
+
# Connects to ActiveDirectory using the query user details
|
37
|
+
def self.connect
|
38
|
+
@connection = Adauth::Connection.new(connection_hash(@config.query_user, @config.query_password)).bind
|
36
39
|
end
|
37
40
|
|
38
|
-
#
|
39
|
-
|
41
|
+
# Generates a hash for the connection class, takes a username and password
|
42
|
+
def self.connection_hash(user, password)
|
43
|
+
{
|
44
|
+
:domain => @config.domain,
|
45
|
+
:server => @config.server,
|
46
|
+
:port => @config.port,
|
47
|
+
:base => @config.base,
|
48
|
+
:encryption => @config.encryption,
|
49
|
+
:username => user,
|
50
|
+
:password => password
|
51
|
+
}
|
40
52
|
end
|
41
|
-
end
|
53
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Adauth
|
2
|
+
# Active Directory Interface Object
|
3
|
+
#
|
4
|
+
# Objects inherit from this class.
|
5
|
+
#
|
6
|
+
# Provides all the common functions for Active Directory.
|
7
|
+
class AdObject
|
8
|
+
# Returns all objects which have the ObjectClass of the inherited class
|
9
|
+
def self.all
|
10
|
+
results = []
|
11
|
+
Adauth.connection.search(:filter => self::ObjectFilter).each do |result|
|
12
|
+
results.push self.new(result)
|
13
|
+
end
|
14
|
+
results
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns all the objects which match the supplied query
|
18
|
+
#
|
19
|
+
# Uses ObjectFilter to restrict to the current object
|
20
|
+
def self.where(field, value)
|
21
|
+
results = []
|
22
|
+
search_filter = Net::LDAP::Filter.eq(field, value)
|
23
|
+
joined_filter = search_filter & self::ObjectFilter
|
24
|
+
Adauth.connection.search(:filter => joined_filter).each do |result|
|
25
|
+
results.push self.new(result)
|
26
|
+
end
|
27
|
+
results
|
28
|
+
end
|
29
|
+
|
30
|
+
# Creates a new instance of the object and sets @ldap_object to the passed Net::LDAP entity
|
31
|
+
def initialize(ldap_object)
|
32
|
+
@ldap_object = ldap_object
|
33
|
+
end
|
34
|
+
|
35
|
+
# Allows direct access to @ldap_object
|
36
|
+
def ldap_object
|
37
|
+
@ldap_object
|
38
|
+
end
|
39
|
+
|
40
|
+
# Over rides method_missing and interacts with @ldap_object
|
41
|
+
def method_missing(method, *args)
|
42
|
+
if self.class::Fields.keys.include?(method)
|
43
|
+
field = self.class::Fields[method]
|
44
|
+
if field.is_a? Symbol
|
45
|
+
return @ldap_object.send(field).to_s
|
46
|
+
elsif field.is_a? Array
|
47
|
+
@ldap_object.send(field.first).collect(&field.last)
|
48
|
+
end
|
49
|
+
else
|
50
|
+
super
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns all the groups the object is a member of
|
55
|
+
def groups
|
56
|
+
unless @groups
|
57
|
+
@groups = convert_to_objects(cn_groups)
|
58
|
+
end
|
59
|
+
@groups
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns all the ous the object is in
|
63
|
+
def ous
|
64
|
+
unless @ous
|
65
|
+
@ous = []
|
66
|
+
@ldap_object.dn.split(/,/).each do |entry|
|
67
|
+
@ous.push Adauth::AdObjects::OU.where('name', entry.gsub(/OU=/, '')).first if entry =~ /OU=/
|
68
|
+
end
|
69
|
+
end
|
70
|
+
@ous
|
71
|
+
end
|
72
|
+
|
73
|
+
# CSV Version of the ous list (can't be pulled over from AD)
|
74
|
+
def dn_ous
|
75
|
+
unless @dn_ous
|
76
|
+
@dn_ous = []
|
77
|
+
@ldap_object.dn.split(/,/).each do |entry|
|
78
|
+
@dn_ous.push entry.gsub(/OU=/, '').gsub(/CN=/,'') if entry =~ /OU=/ or entry == "CN=Users"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
@dn_ous
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def convert_to_objects(array)
|
87
|
+
out = []
|
88
|
+
array.each do |entity|
|
89
|
+
out.push convert_to_object(entity)
|
90
|
+
end
|
91
|
+
out
|
92
|
+
end
|
93
|
+
|
94
|
+
def convert_to_object(entity)
|
95
|
+
user = Adauth::AdObjects::User.where('sAMAccountName', entity).first
|
96
|
+
group = Adauth::AdObjects::Group.where('sAMAccountName', entity).first
|
97
|
+
(user || group)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Container for Objects which inherit from Adauth::AdObject
|
102
|
+
module AdObjects
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Adauth
|
2
|
+
module AdObjects
|
3
|
+
# Active Directory Computer Object
|
4
|
+
#
|
5
|
+
# Inherits from Adauth::AdObject
|
6
|
+
class Computer < Adauth::AdObject
|
7
|
+
# Field mapping
|
8
|
+
#
|
9
|
+
# Maps methods to LDAP fields e.g.
|
10
|
+
#
|
11
|
+
# :foo => :bar
|
12
|
+
#
|
13
|
+
# Becomes
|
14
|
+
#
|
15
|
+
# Computer.name
|
16
|
+
#
|
17
|
+
# Which calls .name on the LDAP object
|
18
|
+
Fields = {
|
19
|
+
:name => :name
|
20
|
+
}
|
21
|
+
|
22
|
+
# Object Net::LDAP filter
|
23
|
+
#
|
24
|
+
# Used to restrict searches to just this object
|
25
|
+
ObjectFilter = Net::LDAP::Filter.eq("objectClass", "computer")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Adauth
|
2
|
+
module AdObjects
|
3
|
+
# Active Directory Group Object
|
4
|
+
#
|
5
|
+
# Inherits from Adauth::AdObject
|
6
|
+
class Group < Adauth::AdObject
|
7
|
+
# Field mapping
|
8
|
+
#
|
9
|
+
# Maps methods to LDAP fields e.g.
|
10
|
+
#
|
11
|
+
# :foo => :bar
|
12
|
+
#
|
13
|
+
# Becomes
|
14
|
+
#
|
15
|
+
# Computer.name
|
16
|
+
#
|
17
|
+
# Which calls .name on the LDAP object
|
18
|
+
Fields = {
|
19
|
+
:name => :samaccountname,
|
20
|
+
:cn_members => [ :member,
|
21
|
+
Proc.new {|g| g.sub(/.*?CN=(.*?),.*/, '\1')} ],
|
22
|
+
:cn_groups => [ :memberof,
|
23
|
+
Proc.new {|g| g.sub(/.*?CN=(.*?),.*/, '\1')} ]
|
24
|
+
}
|
25
|
+
|
26
|
+
# Object Net::LDAP filter
|
27
|
+
#
|
28
|
+
# Used to restrict searches to just this object
|
29
|
+
ObjectFilter = Net::LDAP::Filter.eq("objectClass", "group")
|
30
|
+
|
31
|
+
# Returns all the objects which are members of this group
|
32
|
+
def members
|
33
|
+
unless @members
|
34
|
+
@members = convert_to_objects(cn_members)
|
35
|
+
end
|
36
|
+
@members
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Adauth
|
2
|
+
module AdObjects
|
3
|
+
# Active Directory OU Object
|
4
|
+
#
|
5
|
+
# Inherits from Adauth::AdObject
|
6
|
+
class OU < Adauth::AdObject
|
7
|
+
# Field mapping
|
8
|
+
#
|
9
|
+
# Maps methods to LDAP fields e.g.
|
10
|
+
#
|
11
|
+
# :foo => :bar
|
12
|
+
#
|
13
|
+
# Becomes
|
14
|
+
#
|
15
|
+
# Computer.name
|
16
|
+
#
|
17
|
+
# Which calls .name on the LDAP object
|
18
|
+
Fields = {
|
19
|
+
:name => :name
|
20
|
+
}
|
21
|
+
|
22
|
+
# Object Net::LDAP filter
|
23
|
+
#
|
24
|
+
# Used to restrict searches to just this object
|
25
|
+
ObjectFilter = Net::LDAP::Filter.eq("objectClass", "organizationalUnit")
|
26
|
+
|
27
|
+
# Returns all objects contained with in this OU
|
28
|
+
def members
|
29
|
+
unless @members
|
30
|
+
@members = []
|
31
|
+
[Adauth::AdObjects::Computer, Adauth::AdObjects::Group, Adauth::AdObjects::User].each do |object|
|
32
|
+
object.all.each do |entity|
|
33
|
+
@members.push entity if entity.ldap_object.dn =~ /#{@ldap_object.dn}/
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
@members
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Adauth
|
2
|
+
module AdObjects
|
3
|
+
# Active Directory User Object
|
4
|
+
#
|
5
|
+
# Inherits from Adauth::AdObject
|
6
|
+
class User < Adauth::AdObject
|
7
|
+
# Field mapping
|
8
|
+
#
|
9
|
+
# Maps methods to LDAP fields e.g.
|
10
|
+
#
|
11
|
+
# :foo => :bar
|
12
|
+
#
|
13
|
+
# Becomes
|
14
|
+
#
|
15
|
+
# Computer.name
|
16
|
+
#
|
17
|
+
# Which calls .name on the LDAP object
|
18
|
+
Fields = { :login => :samaccountname,
|
19
|
+
:first_name => :givenname,
|
20
|
+
:last_name => :sn,
|
21
|
+
:email => :mail,
|
22
|
+
:name => :name,
|
23
|
+
:cn_groups => [ :memberof,
|
24
|
+
Proc.new {|g| g.sub(/.*?CN=(.*?),.*/, '\1')} ]
|
25
|
+
}
|
26
|
+
|
27
|
+
# Object Net::LDAP filter
|
28
|
+
#
|
29
|
+
# Used to restrict searches to just this object
|
30
|
+
ObjectFilter = Net::LDAP::Filter.eq("objectClass", "user")
|
31
|
+
|
32
|
+
# Returns a connection to AD within the users context, used to check a user credentails
|
33
|
+
#
|
34
|
+
# Using this would by pass the group and OU Filtering provided by Adauth#authenticate
|
35
|
+
def self.authenticate(user, password)
|
36
|
+
user_connection = Adauth::Connection.new(Adauth.connection_hash(user, password)).bind
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns True/False if the user is member of the cupplied group
|
40
|
+
def member_of?(group)
|
41
|
+
cn_groups.include?(group)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|