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"]
- @@all_ldaps =
Class Variables
nil
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) ⇒ Hash{String => JSS::LDAPServer}
JSS::LDAPServer instances for all defined servers.
-
.group_in_ldap?(group) ⇒ Boolean
Does the group exist in any LDAP server?.
-
.user_in_ldap?(user) ⇒ 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
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 316 317 318 319 |
# File 'lib/jss/api_object/ldap_server.rb', line 272 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?.
181 182 183 |
# File 'lib/jss/api_object/ldap_server.rb', line 181 def authentication_type @authentication_type end |
#connected ⇒ Boolean (readonly) Also known as: connected?
Returns we we connected to this server at the moment?.
263 264 265 |
# File 'lib/jss/api_object/ldap_server.rb', line 263 def connected @connected end |
#hostanme ⇒ String (readonly)
Returns the hostname of the server.
172 173 174 |
# File 'lib/jss/api_object/ldap_server.rb', line 172 def hostanme @hostanme end |
#lookup_dn ⇒ String (readonly)
Returns the Distinguished Name of the account used for connections/lookups?.
184 185 186 |
# File 'lib/jss/api_object/ldap_server.rb', line 184 def lookup_dn @lookup_dn end |
#lookup_pw_sha256 ⇒ String (readonly)
Returns the password for the connection/lookup account, as a SHA256 digest.
187 188 189 |
# File 'lib/jss/api_object/ldap_server.rb', line 187 def lookup_pw_sha256 @lookup_pw_sha256 end |
#open_close_timeout ⇒ Integer (readonly)
Returns timeout, in seconds, for opening LDAP connections.
190 191 192 |
# File 'lib/jss/api_object/ldap_server.rb', line 190 def open_close_timeout @open_close_timeout end |
#port ⇒ Integer (readonly)
Returns the port for ldap.
175 176 177 |
# File 'lib/jss/api_object/ldap_server.rb', line 175 def port @port end |
#referral_response ⇒ String (readonly)
Returns the referral response from the server.
196 197 198 |
# File 'lib/jss/api_object/ldap_server.rb', line 196 def referral_response @referral_response end |
#search_timeout ⇒ Integer (readonly)
Returns timeout, in seconds, for search queries.
193 194 195 |
# File 'lib/jss/api_object/ldap_server.rb', line 193 def search_timeout @search_timeout end |
#use_ssl ⇒ Boolean (readonly)
Returns should the connection use ssl?.
178 179 180 |
# File 'lib/jss/api_object/ldap_server.rb', line 178 def use_ssl @use_ssl end |
#use_wildcards ⇒ Boolean (readonly)
Returns should searches use wildcards?.
199 200 201 |
# File 'lib/jss/api_object/ldap_server.rb', line 199 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 =>
239 240 241 |
# File 'lib/jss/api_object/ldap_server.rb', line 239 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 =>
260 261 262 |
# File 'lib/jss/api_object/ldap_server.rb', line 260 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 =>
223 224 225 |
# File 'lib/jss/api_object/ldap_server.rb', line 223 def user_mappings @user_mappings end |
Class Method Details
.all_ldaps(refresh = false) ⇒ Hash{String => JSS::LDAPServer}
Returns JSS::LDAPServer instances for all defined servers.
98 99 100 101 102 103 104 105 106 |
# File 'lib/jss/api_object/ldap_server.rb', line 98 def self.all_ldaps(refresh = false) @@all_ldaps = nil if refresh return @@all_ldaps if @@all_ldaps @@all_ldaps = {} JSS::LDAPServer.all.each { |svr| @@all_ldaps[svr[:name]] = JSS::LDAPServer.new(:id =>svr[:id])} @@all_ldaps end |
.group_in_ldap?(group) ⇒ Boolean
Returns does the group exist in any LDAP server?.
124 125 126 127 128 |
# File 'lib/jss/api_object/ldap_server.rb', line 124 def self.group_in_ldap? (group) gotgroup = false self.all_ldaps.values.each{|ldap| gotgroup = true unless ldap.find_group(group, :exact).empty? } return gotgroup end |
.user_in_ldap?(user) ⇒ Boolean
Returns does the user exist in any LDAP server?.
113 114 115 116 117 |
# File 'lib/jss/api_object/ldap_server.rb', line 113 def self.user_in_ldap? (user) gotuser = false self.all_ldaps.values.each{|ldap| gotuser = true unless ldap.find_user(user, :exact).empty? } return gotuser 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.
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 482 483 484 485 |
# File 'lib/jss/api_object/ldap_server.rb', line 450 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
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 |
# File 'lib/jss/api_object/ldap_server.rb', line 502 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.
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 435 436 437 438 |
# File 'lib/jss/api_object/ldap_server.rb', line 393 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.
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 378 379 380 381 |
# File 'lib/jss/api_object/ldap_server.rb', line 335 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 |