Class: JSS::LDAPServer
- Defined in:
- lib/jss/api_object/ldap_server.rb,
lib/jss.rb
Overview
An LDAP server in the JSS.
This class doesn’t curretly provide creation or updaing of LDAP server definitions in the JSS. Please use the JSS web UI.
However, it does provide methods for querying users and usergroups from LDAP servers, and checking group membership.
When an LDAPServer instance is created, if it uses anonymous binding for lookups (the Authentication Type is set to ‘none’) then the LDAP connection is established immediately. Otherwise, you must use the #connect method, and provide the appropriate password for the lookup account defined.
Since LDAP server connections are used to verify the validity of LDAP users & groups used in scopes, if you don’t connect to all LDAP servers before modifying any scope’s user & group limitations or exceptions, those new values may not be verifiable. Unverified limitations and exceptions, when sent to the API, will result in a REST 409 Conflict error if the user or group doesn’t exist. Unfortunately, 409 Conflict errors are very generic and don’t indicate the source of the problem (in this case, a non-existent user or group limitation or exception to the scope). The Scopable module tries to catch these errors and raise a more useful exception when they happen.
The class method LDAPServer.all_ldaps returns a Hash of JSS::LDAPServer instances. one for each server defined in the JSS.
The class methods LDAPServer.user_in_ldap? and LDAPServer.group_in_ldap? can be used to check all defined LDAP servers for a user or group. They are used by Scopable::Scope when adding user and groups to scope limitations and exceptions.
Within an LDAPServer instance, the methods #find_user and #find_group will return all matches in the server for a given search term.
Constant Summary collapse
- RSRC_BASE =
The base for REST resources of this class
"ldapservers"
- RSRC_LIST_KEY =
the hash key used for the JSON list output of all objects in the JSS
:ldap_servers
- RSRC_OBJECT_KEY =
The hash key used for the JSON object output. It’s also used in various error messages
:ldap_server
- VALID_DATA_KEYS =
these keys, as well as :id and :name, are present in valid API JSON data for this class
[]
- DEFAULT_PORT =
the default LDAP port
389
- SEARCH_SCOPES =
possible values for search scope
["All Subtrees", "First Level Only"]
- AUTH_TYPES =
possible authentication types
{'none' => :anonymous, 'simple' => :simple, 'CRAM-MD5' => :cram_md5, 'DIGEST-MD5' => :digest_md5 }
- REFERRAL_RESPONSES =
possible referral responses
['', nil, 'follow', 'ignore']
- OBJECT_CLASS_MAPPING_OPTIONS =
possible objectclass mapping options
["any", "all"]
- OBJECT_HISTORY_OBJECT_TYPE =
the object type for this object in the object history table. See APIObject#add_object_history_entry
80
Instance Attribute Summary collapse
-
#authentication_type ⇒ String
readonly
What authentication method should be used?.
-
#connected ⇒ Boolean
(also: #connected?)
readonly
We we connected to this server at the moment?.
-
#hostanme ⇒ String
readonly
The hostname of the server.
-
#lookup_dn ⇒ String
readonly
The Distinguished Name of the account used for connections/lookups?.
-
#lookup_pw_sha256 ⇒ String
readonly
The password for the connection/lookup account, as a SHA256 digest.
-
#open_close_timeout ⇒ Integer
readonly
Timeout, in seconds, for opening LDAP connections.
-
#port ⇒ Integer
readonly
The port for ldap.
-
#referral_response ⇒ String
readonly
The referral response from the server.
-
#search_timeout ⇒ Integer
readonly
Timeout, in seconds, for search queries.
-
#use_ssl ⇒ Boolean
readonly
Should the connection use ssl?.
-
#use_wildcards ⇒ Boolean
readonly
Should searches use wildcards?.
-
#user_group_mappings ⇒ Hash<Symbol=>String>
readonly
The LDAP attributes mapped to various user group data.
-
#user_group_membership_mappings ⇒ Hash<Symbol=>String>
readonly
The LDAP attributes used to identify a user as a member of a group.
-
#user_mappings ⇒ Hash<Symbol=>String>
readonly
The LDAP attributes mapped to various user data.
Class Method Summary collapse
-
.all_ldaps(refresh = false, api: JSS.api) ⇒ Hash{String => JSS::LDAPServer}
DEPRECATED: Please Use ::all_objects.
-
.group_in_ldap?(group, api: JSS.api) ⇒ Boolean
Does the group exist in any LDAP server?.
-
.user_in_ldap?(user, api: JSS.api) ⇒ Boolean
Does the user exist in any LDAP server?.
Instance Method Summary collapse
-
#check_membership(user, group) ⇒ Boolean?
Is the user a member? Nil if unable to check.
-
#connect(pw = nil) ⇒ Boolean
The connect to this LDAP server for subsequent use of the #find_user, #find_group and #check_membership methods.
-
#find_group(group, exact = false, additional_filter = nil) ⇒ Array<Hash>
The @user_group_attrs_to_get for all groups matching the query.
-
#find_user(user, exact = false, additional_filter = nil) ⇒ Array<Hash>
The @user_attrs_to_get for all usernames matching the query.
-
#initialize(args = {}) ⇒ LDAPServer
constructor
See JSS::APIObject#initialize.
Constructor Details
#initialize(args = {}) ⇒ LDAPServer
See JSS::APIObject#initialize
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 |
# File 'lib/jss/api_object/ldap_server.rb', line 268 def initialize (args = {}) require 'net/ldap' super @hostname = @init_data[:connection][:hostname] @port = @init_data[:connection][:port] @use_ssl = @init_data[:connection][:use_ssl] @authentication_type = AUTH_TYPES[@init_data[:connection][:authentication_type]] @open_close_timeout = @init_data[:connection][:open_close_timeout] @search_timeout = @init_data[:connection][:search_timeout] @referral_response = @init_data[:connection][:referral_response] @use_wildcards = @init_data[:connection][:use_wildcards] @lookup_dn = @init_data[:connection][:account][:distinguished_username] @lookup_pw_sha256 = @init_data[:connection][:account][:password_sha256] @user_mappings = @init_data[:mappings_for_users ][:user_mappings] @user_group_mappings = @init_data[:mappings_for_users ][:user_group_mappings] @user_group_membership_mappings = @init_data[:mappings_for_users ][:user_group_membership_mappings] # the ldap attributes to retrieve with user lookups # (all those defined in the user mappings) @user_attrs_to_get = { :username => @user_mappings[:map_username], :user_id => @user_mappings[:map_user_id], :department => @user_mappings[:map_department], :building => @user_mappings[:map_building], :room => @user_mappings[:map_room], :realname => @user_mappings[:map_realname], :phone => @user_mappings[:map_phone], :email_address => @user_mappings[:map_email_address], :position => @user_mappings[:map_position], :user_uuid => @user_mappings[:map_user_uuid] }.delete_if{|k,v| v.nil? } # and for groups.... @user_group_attrs_to_get = { :group_id => @user_group_mappings[:map_group_id], :group_name => @user_group_mappings[:map_group_name], :group_uuid => @user_group_mappings[:map_group_uuid] }.delete_if{|k,v| v.nil? } @connection = nil @connected = false # If we are using anonymous binding, connect now connect if @authentication_type == :anonymous end |
Instance Attribute Details
#authentication_type ⇒ String (readonly)
Returns what authentication method should be used?.
177 178 179 |
# File 'lib/jss/api_object/ldap_server.rb', line 177 def authentication_type @authentication_type end |
#connected ⇒ Boolean (readonly) Also known as: connected?
Returns we we connected to this server at the moment?.
259 260 261 |
# File 'lib/jss/api_object/ldap_server.rb', line 259 def connected @connected end |
#hostanme ⇒ String (readonly)
Returns the hostname of the server.
168 169 170 |
# File 'lib/jss/api_object/ldap_server.rb', line 168 def hostanme @hostanme end |
#lookup_dn ⇒ String (readonly)
Returns the Distinguished Name of the account used for connections/lookups?.
180 181 182 |
# File 'lib/jss/api_object/ldap_server.rb', line 180 def lookup_dn @lookup_dn end |
#lookup_pw_sha256 ⇒ String (readonly)
Returns the password for the connection/lookup account, as a SHA256 digest.
183 184 185 |
# File 'lib/jss/api_object/ldap_server.rb', line 183 def lookup_pw_sha256 @lookup_pw_sha256 end |
#open_close_timeout ⇒ Integer (readonly)
Returns timeout, in seconds, for opening LDAP connections.
186 187 188 |
# File 'lib/jss/api_object/ldap_server.rb', line 186 def open_close_timeout @open_close_timeout end |
#port ⇒ Integer (readonly)
Returns the port for ldap.
171 172 173 |
# File 'lib/jss/api_object/ldap_server.rb', line 171 def port @port end |
#referral_response ⇒ String (readonly)
Returns the referral response from the server.
192 193 194 |
# File 'lib/jss/api_object/ldap_server.rb', line 192 def referral_response @referral_response end |
#search_timeout ⇒ Integer (readonly)
Returns timeout, in seconds, for search queries.
189 190 191 |
# File 'lib/jss/api_object/ldap_server.rb', line 189 def search_timeout @search_timeout end |
#use_ssl ⇒ Boolean (readonly)
Returns should the connection use ssl?.
174 175 176 |
# File 'lib/jss/api_object/ldap_server.rb', line 174 def use_ssl @use_ssl end |
#use_wildcards ⇒ Boolean (readonly)
Returns should searches use wildcards?.
195 196 197 |
# File 'lib/jss/api_object/ldap_server.rb', line 195 def use_wildcards @use_wildcards end |
#user_group_mappings ⇒ Hash<Symbol=>String> (readonly)
The LDAP attributes mapped to various user group data
The hash keys are:
-
:search_base =>
-
:search_scope =>
-
:object_classes =>
-
:map_object_class_to_any_or_all =>
-
:map_group_id =>
-
:map_group_name =>
-
:map_group_uuid =>
235 236 237 |
# File 'lib/jss/api_object/ldap_server.rb', line 235 def user_group_mappings @user_group_mappings end |
#user_group_membership_mappings ⇒ Hash<Symbol=>String> (readonly)
The LDAP attributes used to identify a user as a member of a group
The hash keys are:
-
:user_group_membership_stored_in =>
-
:map_user_membership_use_dn =>
-
:map_group_membership_to_user_field =>
-
:group_id =>
-
:map_object_class_to_any_or_all =>
-
:append_to_username =>
-
:username =>
-
:object_classes =>
-
:use_dn =>
-
:search_base =>
-
:recursive_lookups =>
-
:search_scope =>
-
:map_user_membership_to_group_field =>
256 257 258 |
# File 'lib/jss/api_object/ldap_server.rb', line 256 def user_group_membership_mappings @user_group_membership_mappings end |
#user_mappings ⇒ Hash<Symbol=>String> (readonly)
The LDAP attributes mapped to various user data
The hash keys are:
-
:search_base =>
-
:search_scope =>
-
:object_classes =>
-
:map_object_class_to_any_or_all =>
-
:map_username =>
-
:map_user_id =>
-
:map_department =>
-
:map_building =>
-
:map_room =>
-
:map_realname =>
-
:map_phone =>
-
:map_email_address =>
-
:map_position =>
-
:map_user_uuid =>
-
:append_to_email_results =>
219 220 221 |
# File 'lib/jss/api_object/ldap_server.rb', line 219 def user_mappings @user_mappings end |
Class Method Details
.all_ldaps(refresh = false, api: JSS.api) ⇒ Hash{String => JSS::LDAPServer}
DEPRECATED: Please Use ::all_objects
89 90 91 92 93 |
# File 'lib/jss/api_object/ldap_server.rb', line 89 def self.all_ldaps(refresh = false, api: JSS.api) hash = {} all_objects(refresh, api: api) { |ls| hash[ls.name] = s } hash end |
.group_in_ldap?(group, api: JSS.api) ⇒ Boolean
Returns does the group exist in any LDAP server?.
113 114 115 116 117 118 119 |
# File 'lib/jss/api_object/ldap_server.rb', line 113 def self.group_in_ldap? (group, api: JSS.api) all_objects(refresh, api: api).each do |ldap| next if ldap.find_group(group, :exact).empty? return true end false end |
.user_in_ldap?(user, api: JSS.api) ⇒ Boolean
Returns does the user exist in any LDAP server?.
100 101 102 103 104 105 106 |
# File 'lib/jss/api_object/ldap_server.rb', line 100 def self.user_in_ldap?(user, api: JSS.api) all_objects(refresh, api: api).each do |ldap| next if ldap.find_user(user, :exact).empty? return true end false end |
Instance Method Details
#check_membership(user, group) ⇒ Boolean?
Implement checking groups membership in ‘other’ ldap area
Returns is the user a member? Nil if unable to check.
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 |
# File 'lib/jss/api_object/ldap_server.rb', line 446 def check_membership(user, group) raise JSS::InvalidConnectionError, "Not connected to LDAP server '#{@name}'. Please use #connect first." unless @connected found_user = find_user(user, :exact)[0] found_group = find_group(group, :exact)[0] raise JSS::NoSuchItemError, "No user '#{user}' in LDAP." unless found_user raise JSS::NoSuchItemError, "No group '#{group}' in LDAP." unless found_group if @user_group_membership_mappings[:user_group_membership_stored_in] == "group object" if @user_group_membership_mappings[:map_user_membership_use_dn] return found_group[:members].include? found_user[:dn] else return found_group[:members].include? user end elsif @user_group_membership_mappings[:user_group_membership_stored_in] == "user object" if @user_group_membership_mappings[:use_dn] return found_user[:groups].include? found_group[:dn] else return found_user[:groups].include? group end else ### To do!! return nil # implement a search based on the "other" settings # This will be 3 searchs # - one for the username mapping in users # - one for the gid in groups # - one for a record linking them in the "other" search base end end |
#connect(pw = nil) ⇒ Boolean
The connect to this LDAP server for subsequent use of the #find_user, #find_group and #check_membership methods
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 |
# File 'lib/jss/api_object/ldap_server.rb', line 498 def connect(pw = nil) unless @authentication_type == :anonymous # how do we get the password? password = if pw == :prompt JSS.prompt_for_password "Enter the password for the LDAP connection account '#{@lookup_dn}':" elsif pw.is_a?(Symbol) and pw.to_s.start_with?('stdin') pw.to_s =~ /^stdin(\d+)$/ line = $1 line ||= 2 JSS.stdin line else pw end raise JSS::InvalidDataError, "Incorrect password for LDAP connection account '#{@lookup_dn}'" unless @lookup_pw_sha256 == Digest::SHA2.new(256).update(password.to_s).to_s end # unless @connection = Net::LDAP.new :host => @hostname, :port => @port, :auth => {:method => @authentication_type, :username => @lookup_dn, :password => password } @connected = true end |
#find_group(group, exact = false, additional_filter = nil) ⇒ Array<Hash>
Returns The @user_group_attrs_to_get for all groups matching the query.
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 |
# File 'lib/jss/api_object/ldap_server.rb', line 389 def find_group(group, exact = false, additional_filter = nil) raise JSS::InvalidConnectionError, "Not connected to LDAP server '#{@name}'. Please use #connect first." unless @connected if @use_wildcards and not exact group_filter = Net::LDAP::Filter.contains(@user_group_mappings[:map_group_name], group) else group_filter = Net::LDAP::Filter.eq(@user_group_mappings[:map_group_name], group) end # limit the object classes ocs = @user_group_mappings[:object_classes].to_s.chomp.split(/,\s*/) anyall = @user_group_mappings[:map_object_class_to_any_or_all] oc_filter = Net::LDAP::Filter.eq("objectclass", ocs.shift) ocs.each do |oc| if anyall == "any" oc_filter = oc_filter | Net::LDAP::Filter.eq("objectclass", oc) else oc_filter = oc_filter & Net::LDAP::Filter.eq("objectclass", oc) end end full_filter = oc_filter & group_filter full_filter = full_filter & additional_filter if additional_filter treebase = @user_group_mappings[:search_base] ldap_attribs = @user_group_attrs_to_get.values # should we grab membership from the group? if @user_group_membership_mappings[:user_group_membership_stored_in] == "group object" and \ @user_group_membership_mappings[:map_user_membership_to_group_field] get_members = true ldap_attribs << @user_group_membership_mappings[:map_user_membership_to_group_field] end results = [] @connection.search(:base => treebase, :filter => full_filter, :attributes => ldap_attribs ) do |entry| hash = {:dn => entry.dn} @user_group_attrs_to_get.each do |k,attr| hash[k] = entry[attr][0] end hash[:members] = entry[@user_group_membership_mappings[:map_user_membership_to_group_field]] if get_members # to do, if the members are dns, convert to usernames results << hash end results end |
#find_user(user, exact = false, additional_filter = nil) ⇒ Array<Hash>
Returns The @user_attrs_to_get for all usernames matching the query.
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 |
# File 'lib/jss/api_object/ldap_server.rb', line 331 def find_user(user, exact = false, additional_filter = nil) raise JSS::InvalidConnectionError, "Not connected to LDAP server '#{@name}'. Please use #connect first." unless @connected if @use_wildcards and not exact user_filter = Net::LDAP::Filter.contains(@user_mappings[:map_username], user) else user_filter = Net::LDAP::Filter.eq(@user_mappings[:map_username], user) end # limit the object classes ocs = @user_mappings[:object_classes].to_s.chomp.split(/,\s*/) anyall = @user_mappings[:map_object_class_to_any_or_all] oc_filter = Net::LDAP::Filter.eq("objectclass", ocs.shift) ocs.each do |oc| if anyall == "any" oc_filter = oc_filter | Net::LDAP::Filter.eq("objectclass", oc) else oc_filter = oc_filter & Net::LDAP::Filter.eq("objectclass", oc) end end full_filter = oc_filter & user_filter full_filter = full_filter & additional_filter if additional_filter treebase = @user_mappings[:search_base] ldap_attribs = @user_attrs_to_get.values # should we grab membership from the user? if @user_group_membership_mappings[:user_group_membership_stored_in] == "user object" and \ @user_group_membership_mappings[:map_group_membership_to_user_field] get_groups = true ldap_attribs << @user_group_membership_mappings[:map_group_membership_to_user_field] end results = [] @connection.search(:base => treebase, :filter => full_filter, :attributes => ldap_attribs ) do |entry| userhash = {:dn => entry.dn} @user_attrs_to_get.each do |k,attr| userhash[k] = entry[attr][0] end userhash[:groups] = entry[@user_group_membership_mappings[:map_group_membership_to_user_field]] if get_groups # to do - if the groups are dns, convert to groupnames results << userhash end results end |