Class: ActiveDirectory::Base
- Inherits:
-
Object
- Object
- ActiveDirectory::Base
- Defined in:
- lib/active_directory/base.rb
Overview
The ActiveDirectory module contains the classes used for communicating with Active Directory LDAP servers. ActiveDirectory::Base is the basis from which all classes derive.
Constant Summary collapse
- @@server_settings =
Configuration
{ :host => "localhost", :port => 389, :username => nil, :password => nil, :domain => nil, :base_dn => nil }
Class Method Summary collapse
-
.close ⇒ Object
Unbinds (if bound) and closes the current connection.
-
.connect ⇒ Object
Opens and returns a connection to the Active Directory instance.
-
.connection ⇒ Object
Returns a connection to the configured Active Directory instance.
-
.find(*args) ⇒ Object
Search interface for querying for objects within the directory, such as users and groups.
- .logger ⇒ Object
-
.reconnect ⇒ Object
Attempts to reconnect to the server by closing the existing connection and reconnecting.
Class Method Details
.close ⇒ Object
Unbinds (if bound) and closes the current connection.
119 120 121 122 123 124 125 |
# File 'lib/active_directory/base.rb', line 119 def self.close begin @@connection.unbind unless @@connection.nil? rescue end @@connection = nil end |
.connect ⇒ Object
Opens and returns a connection to the Active Directory instance. By default, secure connections will be attempted first while gracefully falling back to lesser secure methods.
The order by which connections are attempted are: TLS, SSL, unencrypted.
Calling #connection will automatically call this method if a connection has not already been established.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/active_directory/base.rb', line 74 def self.connect host = @@server_settings[:host] port = @@server_settings[:port] || 389 # Attempt to connect using TLS begin connection = LDAP::SSLConn.new(host, port, true) connection.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3) bind(connection) logger.info("ActiveDirectory: Connected to #{@@server_settings[:host]} using TLS...") unless logger.nil? rescue logger.debug("ActiveDirectory: Failed to connect to #{@@server_settings[:host]} using TLS!") unless logger.nil? # Attempt to connect using SSL begin connection = LDAP::SSLConn.new(host, port, false) connection.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3) bind(connection) logger.info("ActiveDirectory: Connected to #{@@server_settings[:host]} over SSL...") unless logger.nil? rescue logger.debug("ActiveDirectory: Failed to connect to #{@@server_settings[:host]} over SSL!") unless logger.nil? # Attempt to connect without encryption begin connection = LDAP::Conn.new(host, port) connection.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3) bind(connection) logger.info("ActiveDirectory: Connected to #{@@server_settings[:host]} without encryption!") unless logger.nil? rescue logger.error("ActiveDirectory: Failed to connect to #{@@server_settings[:host]}!") unless logger.nil? puts "EXCEPTION: #{$!}" connection = nil raise end end end connection.set_option(LDAP::LDAP_OPT_REFERRALS, 0) connection end |
.connection ⇒ Object
Returns a connection to the configured Active Directory instance. If a connection is not already established, it will attempt to establish the connection.
60 61 62 |
# File 'lib/active_directory/base.rb', line 60 def self.connection @@connection ||= connect end |
.find(*args) ⇒ Object
Search interface for querying for objects within the directory, such as users and groups. Searching the directory is quite similar to a normal LDAP search, but with a better API.
If you call this method from User or Group, it will narrow your searches to those specific objects by default. Calling this method on Base will return objects of any class and provides the most flexibility.
Searching Users
Users may be located within the directory by their distinguished name (DN), their username (sAMAccountName), or through any other valid LDAP filter and optional search base.
# Load all users (including disabled) within the default Base DN.
all_users = ActiveDirectory::User.find(:all)
# Load all disabled users within the default Base DN.
disabled_users = ActiveDirectory::User.find(:all,
:filter => "(userAccountControl=514)")
# Load all users who are in the Managers organizational unit whose
# accounts are not disabled.
managers = ActiveDirectory::User.find(:all,
:base => "OU=Managers,DC=example,DC=com",
:filter => "(userAccountControl=512)")
# Load the user "John Doe" by his sAMAccountName.
user = ActiveDirectory::User.find("jdoe")
# Load the user "John Doe" by his distinguished name (DN).
user = ActiveDirectory::User.find("CN=John Doe,CN=Users,DC=example,DC=com")
Searching Groups
Groups may be located within the diretctory by their distinguished name (DN) or through any other valid LDAP filter and optional search base.
# Load all groups within the default Base DN.
all_groups = ActiveDirectory::Group.find(:all)
# Load the "Developers" group by its distinguished name (DN).
developers = ActiveDirectory::Group.find("CN=Developers,DC=example,DC=com")
More Advanced Examples
By calling ActiveDirectory::Base#find you can query objects across classes, allowing you to pull in both Groups and Users that match your criteria.
# Load all Contacts
contacts = ActiveDirectory::Base.find(:all,
:filter => "(&(objectClass=User)(objectCategory=Contact))")
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
# File 'lib/active_directory/base.rb', line 191 def self.find(*args) = (args) attributes = [ "distinguishedName", "objectClass" ] # Determine the appropriate search filter if self.name == "ActiveDirectory::Base" if [:filter] filter = [:filter] else filter = "(|(&(objectCategory=Person)(objectClass=User))(objectClass=Group))" end else subklass = class_name_of_active_directory_descendent(self) if subklass == "ActiveDirectory::User" filter = "(&(objectCategory=Person)(objectClass=User)#{[:filter]})" elsif subklass == "ActiveDirectory::Group" filter = "(&(objectClass=Group)#{[:filter]})" end end # Determine the appropriate search base base_dn = [:base] ? [:base] : @@server_settings[:base_dn] # Determine the appropriate scope scope = [:scope] ? [:scope] : LDAP::LDAP_SCOPE_SUBTREE # Load all matching objects if args.first == :all logger.debug "Searching Active Directory" \ " - Filter: #{filter}" \ " - Search Base: #{base_dn} " \ " - Scope: #{scope}" # Perform search entries = self.search(base_dn, scope, filter, attributes) result = Array.new unless entries.nil? for entry in entries if entry['objectClass'].include? "person" result << User.new(entry['distinguishedName'][0]) elsif entry['objectClass'].include? "group" result << Group.new(entry['distinguishedName'][0]) end end end result else # Load a single matching object by either a common name or a # sAMAccountName if args.first =~ /(CN|cn)=/ base_dn = args.first else filter = "(&(objectCategory=Person)(objectClass=User)(samAccountName=#{args.first})#{[:filter]})" end logger.debug "Searching Active Directory" \ " - Filter: #{filter}" \ " - Search Base: #{base_dn} " \ " - Scope: #{scope}" begin entry = self.search(base_dn, scope, filter, attributes) rescue if $!. == "No such object" raise UnknownUserError else raise end end entry = entry[0] if entry['objectClass'].include? "person" User.new(entry['distinguishedName'][0]) elsif entry['objectClass'].include? "group" Group.new(entry['distinguishedName'][0]) end end end |
.logger ⇒ Object
51 52 53 |
# File 'lib/active_directory/base.rb', line 51 def self.logger @@logger || Logger.new(STDOUT) end |
.reconnect ⇒ Object
Attempts to reconnect to the server by closing the existing connection and reconnecting.
131 132 133 134 |
# File 'lib/active_directory/base.rb', line 131 def self.reconnect close @@connection = connect end |