admapper 0.0.3
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/LICENSE +23 -0
- data/README.rdoc +183 -0
- data/Rakefile +34 -0
- data/init.rb +1 -0
- data/lib/admapper.rb +8 -0
- data/lib/admapper/configuration.rb +13 -0
- data/lib/admapper/connection.rb +69 -0
- data/lib/admapper/extensions.rb +8 -0
- data/lib/admapper/group.rb +90 -0
- data/lib/admapper/user.rb +165 -0
- metadata +108 -0
data/LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
LICENSE
|
2
|
+
|
3
|
+
The MIT License
|
4
|
+
|
5
|
+
Copyright (c) 2010 Brian P. Hogan
|
6
|
+
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
of this software and associated documentation files (the "Software"), to deal
|
9
|
+
in the Software without restriction, including without limitation the rights
|
10
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
copies of the Software, and to permit persons to whom the Software is
|
12
|
+
furnished to do so, subject to the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be included in
|
15
|
+
all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
+
THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,183 @@
|
|
1
|
+
==ADMapper
|
2
|
+
Library to connect to ActiveDirectory and map your users to ActiveDirectory users.
|
3
|
+
|
4
|
+
You supply your own classes and mix the User or Group module into your classes.
|
5
|
+
|
6
|
+
== Why
|
7
|
+
Because http://github.com/filefrog/activedirectory didn't work well for me and I wanted
|
8
|
+
flexibility to use my own classes, whether those are in Sinatra or
|
9
|
+
using full-blown ActiveRecord classes in a Rails app.
|
10
|
+
|
11
|
+
== Installation
|
12
|
+
|
13
|
+
It's a gem, so you can
|
14
|
+
|
15
|
+
gem install admapper
|
16
|
+
|
17
|
+
Or you can clone the repo and build it yourself with
|
18
|
+
|
19
|
+
gem build admapper.gemspec
|
20
|
+
|
21
|
+
== Usage
|
22
|
+
Basic usage is simple. Include the gem
|
23
|
+
|
24
|
+
require 'rubygems'
|
25
|
+
require 'admapper'
|
26
|
+
|
27
|
+
Then add the mixin to your class of choice
|
28
|
+
|
29
|
+
class User
|
30
|
+
attr_accessor: username
|
31
|
+
include ADMapper::Resource
|
32
|
+
end
|
33
|
+
|
34
|
+
Finally, configure the connection:
|
35
|
+
|
36
|
+
ADMapper::Configuration.connection_info = {:username => "homer",
|
37
|
+
:password=>"foo",
|
38
|
+
:host => "your_ad_host",
|
39
|
+
:port=>"636",
|
40
|
+
:ssl => true,
|
41
|
+
:domain => "example.com"}
|
42
|
+
|
43
|
+
The connection_info method takes a hash, so you can use a YML file if you'd like:
|
44
|
+
|
45
|
+
CONFIG_OPTS = YAML::load(File.open(File.expand_path(File.dirname(__FILE__) + "/admapper.yml"))).symbolize_keys
|
46
|
+
ADMapper::Configuration.connection_info
|
47
|
+
|
48
|
+
== Working with Users
|
49
|
+
|
50
|
+
=== Finding someone by username
|
51
|
+
|
52
|
+
u = User.find_in_ad_by_username("homer")
|
53
|
+
|
54
|
+
This creates a new instance of your User class. If you're using ActiveRecord, you can save this.
|
55
|
+
|
56
|
+
=== Mapping users
|
57
|
+
|
58
|
+
We use the "username" column to find stuff in ActiveDirectory by default. But you may not have a username column - you might call it "login". You may also want to easily grab other info from ActiveDirectory and map it to your own objects. In your model, add this method:
|
59
|
+
|
60
|
+
Simply map your model (keys of the hash) to ActiveDirectory (values of the hash)
|
61
|
+
|
62
|
+
def ad_map
|
63
|
+
{
|
64
|
+
:username => :samaccountname,
|
65
|
+
:full_name => :displayname
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
When you call the find_in_ad_by_username method, this method gets called.
|
70
|
+
You can also access the actual Net::LDAP::Entry object by calling
|
71
|
+
|
72
|
+
user = User.find_in_ad_by_username("homer")
|
73
|
+
user.ad_user
|
74
|
+
user.ad_user.samaccountname
|
75
|
+
user.ad_user.givenname
|
76
|
+
|
77
|
+
=== Working with an existing user
|
78
|
+
So maybe you have a user already.
|
79
|
+
|
80
|
+
u = User.find(1)
|
81
|
+
|
82
|
+
And you want his AD information? Fetch it. It'll default to looking up the user in ActiveDirectory by the <tt>username</tt> attribute.
|
83
|
+
|
84
|
+
u.find_in_ad
|
85
|
+
|
86
|
+
This will fill in the attributes you specified in your ad_map method.
|
87
|
+
|
88
|
+
You can use a different field. If you store the username as "login", do this:
|
89
|
+
|
90
|
+
u.find_in_ad(:key => "login")
|
91
|
+
|
92
|
+
|
93
|
+
=== Authenticating a user
|
94
|
+
|
95
|
+
Don't do this. Taking someone's password and passing it on to Active Directory is just stupid. Use CAS, Shibboleth, or something else that prevents your app from ever seeing a user's password. If you insist on doing this, use SSL, filter the password out of your logs, and pray. This will let you do what you want
|
96
|
+
|
97
|
+
User.authenticate_with_active_directory("homer", "1234")
|
98
|
+
|
99
|
+
It'll return true or false. It won't return a user. I assume you'll be wrapping this call in something else that will fetch the user object from your local DB.
|
100
|
+
|
101
|
+
== Groups
|
102
|
+
|
103
|
+
Working on group support. Got a few things working:
|
104
|
+
|
105
|
+
=== Getting groups
|
106
|
+
|
107
|
+
Create your own class
|
108
|
+
|
109
|
+
class Group
|
110
|
+
attr_accessor :name
|
111
|
+
include ADMapper::Group
|
112
|
+
end
|
113
|
+
|
114
|
+
Then look for a group
|
115
|
+
|
116
|
+
g = Group.find_in_ad_by_name("Marketing")
|
117
|
+
|
118
|
+
You can also look for groups
|
119
|
+
|
120
|
+
groups = Group.find_all_in_ad_by_name("HR.*")
|
121
|
+
|
122
|
+
=== Users and their groups
|
123
|
+
|
124
|
+
Need to find all groups for a user?
|
125
|
+
|
126
|
+
class Group
|
127
|
+
attr_accessor :name
|
128
|
+
include ADMapper::Group
|
129
|
+
end
|
130
|
+
|
131
|
+
class User
|
132
|
+
attr_accessor :name, :username
|
133
|
+
|
134
|
+
include ADMapper::User
|
135
|
+
set_group_class Group
|
136
|
+
end
|
137
|
+
|
138
|
+
Then get a user
|
139
|
+
|
140
|
+
u = User.find(1)
|
141
|
+
u.find_in_ad
|
142
|
+
groups = u.groups
|
143
|
+
|
144
|
+
== Testing
|
145
|
+
|
146
|
+
I'm not giving you my credentials, so you'll need to supply your own. Create the file
|
147
|
+
|
148
|
+
test/admapper.yml
|
149
|
+
|
150
|
+
and put this inside:
|
151
|
+
|
152
|
+
username: "username"
|
153
|
+
password: "password"
|
154
|
+
domain: "example.com"
|
155
|
+
host: "domain.controller.example.com"
|
156
|
+
ssl: true
|
157
|
+
port: 636
|
158
|
+
|
159
|
+
Then open test_helper and change the GROUP constant to a group that your username is a member of.
|
160
|
+
|
161
|
+
Given good credentials, the tests should pass.
|
162
|
+
|
163
|
+
== Patches
|
164
|
+
* Fork it
|
165
|
+
* Write a test
|
166
|
+
* Make a fix
|
167
|
+
* send a patch or a pull request.
|
168
|
+
* Don't touch the changelog.
|
169
|
+
* If it doesn't have a test, I'm not looking at it.
|
170
|
+
|
171
|
+
If this doesn't do what you want it to do, fork this and write your own library. I'm sharing this as a starting point and this is the bare minimum I need to get my AD tasks accomplished.
|
172
|
+
|
173
|
+
== Changelog
|
174
|
+
0.0.3 (2010-11-08)
|
175
|
+
* Added group lookup by name
|
176
|
+
* Added ability to get groups for a user
|
177
|
+
0.0.2 (2010-03-31)
|
178
|
+
* refactoring to a central configuration option
|
179
|
+
* removed ad_connect! class method from resource module. Use a single global connection
|
180
|
+
0.0.1 (2010-03-30)
|
181
|
+
* Initial mixin and basic support for finding stuff via AD
|
182
|
+
* Mapping objects
|
183
|
+
* Tests
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
|
6
|
+
require 'ADMapper'
|
7
|
+
|
8
|
+
desc "Run the tests"
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'test'
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
12
|
+
t.verbose = true
|
13
|
+
end
|
14
|
+
|
15
|
+
Rake::TestTask.new(:t) do |t|
|
16
|
+
t.libs << 'test'
|
17
|
+
t.pattern = ENV["TEST"]
|
18
|
+
t.verbose = true
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'Start an IRB session with all necessary files required.'
|
22
|
+
task :shell do |t|
|
23
|
+
chdir File.dirname(__FILE__)
|
24
|
+
exec 'irb -I lib/ -I lib/ADMapper -r rubygems -r net-ldap -r tempfile -r init'
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Generate documentation for ADMapper'
|
28
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
29
|
+
rdoc.rdoc_dir = 'doc'
|
30
|
+
rdoc.title = 'ADMapper'
|
31
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
32
|
+
rdoc.rdoc_files.include('README*')
|
33
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
34
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "lib", "admapper")
|
data/lib/admapper.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# ADMapper is a simple wrapper for ActiveRecord user lookup and authentication.
|
2
|
+
require 'yaml'
|
3
|
+
require 'net/ldap'
|
4
|
+
require 'admapper/extensions'
|
5
|
+
require 'admapper/configuration'
|
6
|
+
require 'admapper/connection'
|
7
|
+
require 'admapper/user'
|
8
|
+
require 'admapper/group'
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module ADMapper
|
2
|
+
class Connection
|
3
|
+
@@ad_connection = nil
|
4
|
+
@@ad_treebase = nil
|
5
|
+
@@ad_user_filter = nil
|
6
|
+
|
7
|
+
def self.treebase
|
8
|
+
@@ad_treebase
|
9
|
+
end
|
10
|
+
|
11
|
+
# class method to return the current connection
|
12
|
+
def self.current_connection
|
13
|
+
self.ad_connect_if_not_connected
|
14
|
+
@@ad_connection
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.current_connection=(conn)
|
18
|
+
@@ad_connection = conn
|
19
|
+
end
|
20
|
+
|
21
|
+
# config_options = {:username => "homer",
|
22
|
+
# :password => "1234",
|
23
|
+
# :domain => "springfieldnuclear.com",
|
24
|
+
# :host => "ad.springfieldnuclear.com",
|
25
|
+
# :ssl => true,
|
26
|
+
# :port => 636}
|
27
|
+
#
|
28
|
+
# if ad_connect!(config_options)
|
29
|
+
# ....
|
30
|
+
# else
|
31
|
+
# ...
|
32
|
+
# end
|
33
|
+
def self.ad_connect!(config = nil)
|
34
|
+
config ||= ADMapper::Configuration.connection_info
|
35
|
+
|
36
|
+
raise ADMapper::ConfigurationMissingError if config.nil?
|
37
|
+
username = config[:username]
|
38
|
+
password = config[:password]
|
39
|
+
domain = config[:domain]
|
40
|
+
host = config[:host]
|
41
|
+
port = config[:port]
|
42
|
+
dc1 = domain.split(".").first
|
43
|
+
dc2 = domain.split(".").last
|
44
|
+
ssl = config[:ssl] ? true : false
|
45
|
+
self.current_connection = initialize_ldap_con(username + "@#{domain}", password, host, port, ssl)
|
46
|
+
@@ad_treebase = "DC=#{dc1},DC=#{dc2}"
|
47
|
+
@@ad_user_filter = Net::LDAP::Filter.eq( "sAMAccountName", username )
|
48
|
+
self.current_connection.bind
|
49
|
+
end
|
50
|
+
|
51
|
+
# initializes the connection to the ldap server. Does not bind.
|
52
|
+
def self.initialize_ldap_con(user_name, password, host, port, ssl)
|
53
|
+
ldap = Net::LDAP.new
|
54
|
+
ldap.host = host
|
55
|
+
ldap.port = port #required for SSL connections, 389 is the default plain text port
|
56
|
+
if ssl
|
57
|
+
ldap.encryption :simple_tls #also required to tell Net:LDAP that we want SSL
|
58
|
+
end
|
59
|
+
ldap.auth "#{user_name}","#{password}"
|
60
|
+
ldap #explicitly return the ldap connection object
|
61
|
+
end
|
62
|
+
|
63
|
+
# connects if not connected already
|
64
|
+
def self.ad_connect_if_not_connected
|
65
|
+
self.ad_connect! if @@ad_connection.nil?
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module ADMapper
|
2
|
+
|
3
|
+
module Group
|
4
|
+
|
5
|
+
def self.included(model)
|
6
|
+
model.class_eval do
|
7
|
+
extend ADMapper::Group::ClassMethods
|
8
|
+
include ADMapper::Group::InstanceMethods
|
9
|
+
attr_accessor :ad_group
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
module InstanceMethods
|
15
|
+
|
16
|
+
# maps the ad_user's attributes to your class' attributes
|
17
|
+
#. Implement the ad_map method in your own class to control how fields map.
|
18
|
+
def map_group_from_ad(ad_group)
|
19
|
+
self.ad_map.each do |group_object_field, ad_object_field|
|
20
|
+
self.send("#{group_object_field}=", ad_group.send(ad_object_field).to_s)
|
21
|
+
end
|
22
|
+
self.ad_group = ad_group
|
23
|
+
end
|
24
|
+
|
25
|
+
# Default mapping of user object to active directory.
|
26
|
+
# You will most likely want to implement this in your own class
|
27
|
+
# instead of using this very basic default.
|
28
|
+
# Simply map your model (keys of the hash) to ActiveDirectory (values of the hash)
|
29
|
+
#
|
30
|
+
# def ad_map
|
31
|
+
# {
|
32
|
+
# :username => :samaccountname,
|
33
|
+
# :full_name => :displayname
|
34
|
+
# }
|
35
|
+
# end
|
36
|
+
def ad_map
|
37
|
+
{:name => :cn}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
module ClassMethods
|
42
|
+
|
43
|
+
def find_in_ad_by_name(groupname)
|
44
|
+
attrs = [ "cn", "ou" , "objectClass"]
|
45
|
+
filter = Net::LDAP::Filter.eq( "objectClass", "group" )
|
46
|
+
name_filter = Net::LDAP::Filter.eq( "cn", groupname )
|
47
|
+
ad_connection = ADMapper::Connection.current_connection
|
48
|
+
ad_group = nil
|
49
|
+
ad_connection.search( :base => ADMapper::Connection.treebase,
|
50
|
+
:attributes => attrs,
|
51
|
+
:filter => filter & name_filter ) do |entry|
|
52
|
+
if entry
|
53
|
+
ad_group = self.new
|
54
|
+
ad_group.map_group_from_ad(entry)
|
55
|
+
break
|
56
|
+
end
|
57
|
+
end
|
58
|
+
ad_group
|
59
|
+
|
60
|
+
end
|
61
|
+
def find_all_in_ad_by_name(groupname)
|
62
|
+
|
63
|
+
attrs = [ "cn", "ou" , "objectClass"]
|
64
|
+
filter = Net::LDAP::Filter.eq( "objectClass", "group" )
|
65
|
+
name_filter = Net::LDAP::Filter.eq( "cn", groupname )
|
66
|
+
ad_connection = ADMapper::Connection.current_connection
|
67
|
+
ad_groups = []
|
68
|
+
|
69
|
+
ad_connection.search( :base => ADMapper::Connection.treebase,
|
70
|
+
:attributes => attrs,
|
71
|
+
:filter => filter & name_filter ) do |entry|
|
72
|
+
ad_group = entry
|
73
|
+
if ad_group
|
74
|
+
group = self.new
|
75
|
+
group.map_group_from_ad(ad_group)
|
76
|
+
ad_groups << group
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
ad_groups
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
module ADMapper
|
2
|
+
|
3
|
+
module User
|
4
|
+
|
5
|
+
def self.included(model)
|
6
|
+
model.class_eval do
|
7
|
+
extend ADMapper::User::ClassMethods
|
8
|
+
include ADMapper::User::InstanceMethods
|
9
|
+
attr_accessor :ad_user
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
module InstanceMethods
|
15
|
+
|
16
|
+
# Returns the groups for a user.
|
17
|
+
def groups
|
18
|
+
groups = []
|
19
|
+
|
20
|
+
search_filter = Net::LDAP::Filter.eq("sAMAccountName", self.ad_user.samaccountname.first)
|
21
|
+
ad_connection = ADMapper::Connection.current_connection
|
22
|
+
ad_connection.search(:base => ADMapper::Connection.treebase,
|
23
|
+
:filter => search_filter) do |entry|
|
24
|
+
|
25
|
+
entry.each do |attribute, values|
|
26
|
+
if attribute.to_s.match(/memberof/)
|
27
|
+
values.each do |value|
|
28
|
+
a = value.split(',')
|
29
|
+
md = a[0].match(/CN=(.+)/)
|
30
|
+
|
31
|
+
groups << md[1]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
groups.collect do |g|
|
38
|
+
self.class.group_class.find_in_ad_by_name(g)
|
39
|
+
end.compact
|
40
|
+
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
def member_of?(group)
|
47
|
+
group_member = false
|
48
|
+
|
49
|
+
search_filter = Net::LDAP::Filter.eq("sAMAccountName", self.ad_user.samaccountname.first)
|
50
|
+
ad_connection = ADMapper::Connection.current_connection
|
51
|
+
ad_connection.search(:base => ADMapper::Connection.treebase,
|
52
|
+
:filter => search_filter) do |entry|
|
53
|
+
|
54
|
+
entry.each do |attribute, values|
|
55
|
+
if attribute.to_s.match(/memberof/)
|
56
|
+
values.each do |value|
|
57
|
+
a = value.split(',')
|
58
|
+
md = a[0].match(/CN=(.+)/)
|
59
|
+
|
60
|
+
# user is a member of the right group
|
61
|
+
if md[1] == group
|
62
|
+
group_member = true
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
group_member
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
# finds a user in active directory using the internal key.
|
74
|
+
# Defaults to username
|
75
|
+
def find_in_ad(options = {:key => :username})
|
76
|
+
username = send(options[:key])
|
77
|
+
ad_user = self.class.ad_query_by_username(username)
|
78
|
+
return nil if ad_user.nil?
|
79
|
+
self.map_user_from_ad(ad_user)
|
80
|
+
true
|
81
|
+
end
|
82
|
+
|
83
|
+
# maps the ad_user's attributes to your class' attributes
|
84
|
+
#. Implement the ad_map method in your own class to control how fields map.
|
85
|
+
def map_user_from_ad(ad_user)
|
86
|
+
self.ad_map.each do |user_object_field, ad_object_field|
|
87
|
+
self.send("#{user_object_field}=", ad_user.send(ad_object_field).to_s)
|
88
|
+
end
|
89
|
+
self.ad_user = ad_user
|
90
|
+
end
|
91
|
+
|
92
|
+
# Default mapping of user object to active directory.
|
93
|
+
# You will most likely want to implement this in your own class
|
94
|
+
# instead of using this very basic default.
|
95
|
+
# Simply map your model (keys of the hash) to ActiveDirectory (values of the hash)
|
96
|
+
#
|
97
|
+
# def ad_map
|
98
|
+
# {
|
99
|
+
# :username => :samaccountname,
|
100
|
+
# :full_name => :displayname
|
101
|
+
# }
|
102
|
+
# end
|
103
|
+
def ad_map
|
104
|
+
{:username => :samaccountname}
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
module ClassMethods
|
110
|
+
attr_accessor :group_class
|
111
|
+
|
112
|
+
def set_group_class(group_class)
|
113
|
+
self.group_class = group_class
|
114
|
+
end
|
115
|
+
|
116
|
+
# Authenticating users:
|
117
|
+
# Don't do this. Taking someone's password and passing it
|
118
|
+
# on to Active Directory is just stupid. Use CAS, Shibboleth, or
|
119
|
+
# something else that prevents your app from ever seeing a user's password.
|
120
|
+
# If you insist on doing this, use SSL, filter the password out of your logs,
|
121
|
+
# and pray. This will let you do what you want
|
122
|
+
#
|
123
|
+
# User.authenticate_with_active_directory("homer", "1234")
|
124
|
+
#
|
125
|
+
# It'll return true or false. It won't return a user. I assume you'll be wrapping this call in something else that will fetch the user object from your local DB.
|
126
|
+
def authenticate_with_active_directory(username, password)
|
127
|
+
auth_ldap = ADMapper::Connection.current_connection.dup.bind_as(
|
128
|
+
:filter => Net::LDAP::Filter.eq( "sAMAccountName", username ),
|
129
|
+
:base => ADMapper::Connection.treebase,
|
130
|
+
:password => password
|
131
|
+
)
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
# Find a user in AD by the given username
|
136
|
+
# Calls #map_user_from_ad on the returned results
|
137
|
+
# so you can manage it yourself.
|
138
|
+
def find_in_ad_by_username(username)
|
139
|
+
ad_user = ad_query_by_username(username)
|
140
|
+
return nil if ad_user.nil?
|
141
|
+
|
142
|
+
user = self.new
|
143
|
+
user.map_user_from_ad(ad_user)
|
144
|
+
user
|
145
|
+
end
|
146
|
+
|
147
|
+
# find a user in AD by the given userame.
|
148
|
+
# Connects if not connected
|
149
|
+
# Returns an AD object
|
150
|
+
def ad_query_by_username(username)
|
151
|
+
|
152
|
+
user = nil
|
153
|
+
search_filter = Net::LDAP::Filter.eq( "sAMAccountName", username )
|
154
|
+
ad_connection = ADMapper::Connection.current_connection
|
155
|
+
ad_connection.search(:base => ADMapper::Connection.treebase,
|
156
|
+
:filter => search_filter,
|
157
|
+
:attributes => ['dn','sAMAccountName','displayname','SN','givenName']) do |ad_user|
|
158
|
+
user = ad_user
|
159
|
+
end
|
160
|
+
user
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: admapper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 25
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 3
|
10
|
+
version: 0.0.3
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Brian Hogan
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-11-08 00:00:00 -06:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: net-ldap
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - "="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 25
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 1
|
33
|
+
- 1
|
34
|
+
version: 0.1.1
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: mocha
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - "="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 43
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
- 9
|
49
|
+
- 8
|
50
|
+
version: 0.9.8
|
51
|
+
type: :development
|
52
|
+
version_requirements: *id002
|
53
|
+
description:
|
54
|
+
email: brianhogan@napcs.com
|
55
|
+
executables: []
|
56
|
+
|
57
|
+
extensions: []
|
58
|
+
|
59
|
+
extra_rdoc_files:
|
60
|
+
- README.rdoc
|
61
|
+
files:
|
62
|
+
- README.rdoc
|
63
|
+
- LICENSE
|
64
|
+
- Rakefile
|
65
|
+
- init.rb
|
66
|
+
- lib/admapper.rb
|
67
|
+
- lib/admapper/extensions.rb
|
68
|
+
- lib/admapper/connection.rb
|
69
|
+
- lib/admapper/group.rb
|
70
|
+
- lib/admapper/configuration.rb
|
71
|
+
- lib/admapper/user.rb
|
72
|
+
has_rdoc: true
|
73
|
+
homepage: http://www.napcs.com/projects/
|
74
|
+
licenses: []
|
75
|
+
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options:
|
78
|
+
- --line-numbers
|
79
|
+
- --inline-source
|
80
|
+
require_paths:
|
81
|
+
- lib
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
hash: 3
|
88
|
+
segments:
|
89
|
+
- 0
|
90
|
+
version: "0"
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
hash: 3
|
97
|
+
segments:
|
98
|
+
- 0
|
99
|
+
version: "0"
|
100
|
+
requirements:
|
101
|
+
- net-ldap
|
102
|
+
rubyforge_project: admapper
|
103
|
+
rubygems_version: 1.3.7
|
104
|
+
signing_key:
|
105
|
+
specification_version: 3
|
106
|
+
summary: Friendly mixin for working with Microsoft's ActiveDirectory
|
107
|
+
test_files: []
|
108
|
+
|