require 'net/ldap' module SheffieldLdapLookup class LdapFinder attr_accessor :keyword attr_accessor :custom_search_attribute def initialize(keyword = nil, config_prefix = nil, custom_search_attribute = nil) self.keyword = keyword @config_prefix = config_prefix self.custom_search_attribute = custom_search_attribute end class << self attr_accessor :ldap_config attr_accessor :error_notification_proc end def lookup all_results[0] end def all_results begin @all_results ||= connection.search(filter: ldap_filter) rescue Exception => exception if self.class.error_notification_proc.is_a?(Proc) self.class.error_notification_proc.call(exception) end raise exception end end def ldap_filter(filter_class = Net::LDAP::Filter) filter_class.eq(search_attribute, keyword) end def search_attribute return custom_search_attribute if custom_search_attribute keyword =~ /\A[^@]+@[^@]+\z/ ? 'mail' : 'sAMAccountName' end def ldap_config self.class.ldap_config end def connection(ldap_class = Net::LDAP) @connection ||= ldap_class.new(connection_settings) end def connection_settings base_settings = { host: ldap_config["#{@config_prefix}host"], port: ldap_config["#{@config_prefix}port"], base: ldap_config["#{@config_prefix}base"] } if ldap_config.key?("#{@config_prefix}username") && ldap_config.key?("#{@config_prefix}password") base_settings[:auth] = { method: :simple, username: ldap_config["#{@config_prefix}username"], password: ldap_config["#{@config_prefix}password"] } end if ldap_config["#{@config_prefix}ssl"] == true base_settings[:port] ||= 636 base_settings[:encryption] = { method: :simple_tls, tls_options: OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.merge( # Default min version (in Ruby 2.7) is TLS 1.0, but server always responds and says provide TLS 1.2 # (and, to be honest, we shouldn't use anything less than TLS 1.2 these days) min_version: OpenSSL::SSL::TLS1_2_VERSION ) } end # Avoid two LDAP queries per connection by forcing unpaged results base_settings[:force_no_page] = true base_settings end end end