lib/chaltron/ldap/connection.rb in chaltron-1.0.10 vs lib/chaltron/ldap/connection.rb in chaltron-1.1.0
- old
+ new
@@ -2,10 +2,16 @@
require 'chaltron/ldap/person'
module Chaltron
module LDAP
class Connection
+ NET_LDAP_ENCRYPTION_METHOD = {
+ simple_tls: :simple_tls,
+ start_tls: :start_tls,
+ plain: nil
+ }.freeze
+
attr_reader :ldap
def initialize(params = {})
@ldap = Net::LDAP.new(adapter_options)
end
@@ -14,11 +20,13 @@
filter = Net::LDAP::Filter.eq(uid, login)
ldap.bind_as(base: base, filter: filter, password: password)
end
def find_by_uid(id)
- find_user(uid: id)
+ opts = {}
+ opts[uid.to_sym] = id
+ ret = find_user(opts)
end
def find_user(*args)
find_users(*args).first
end
@@ -45,74 +53,125 @@
options = {
base: args[:dn],
scope: Net::LDAP::SearchScope_BaseObject
}
else
- filters = []
- fields.each do |field|
- filters << Net::LDAP::Filter.eq(field, args[field])
+ filters = fields.map do |field|
+ f = translate_field(field)
+ Net::LDAP::Filter.eq(f, args[field]) if f
end
options = {
base: base,
filter: filters.inject { |sum, n| Net::LDAP::Filter.join(sum, n) }
}
end
+ options.merge!(size: limit) unless limit.nil?
+ ldap_search(options).map do |entry|
+ Chaltron::LDAP::Person.new(entry, uid) if entry.respond_to? uid
+ end.compact
+ end
-# if config.user_filter.present?
-# user_filter = Net::LDAP::Filter.construct(config.user_filter)
+ def find_groups_by_member(entry)
+ options = {
+ base: Chaltron.ldap_group_base || base,
+ filter: Chaltron.ldap_group_member_filter.call(entry)
+ }
+ ldap_search(options)
+ end
-# options[:filter] = if options[:filter]
-# Net::LDAP::Filter.join(options[:filter], user_filter)
-# else
-# user_filter
-# end
-# end
-
- options.merge!(size: limit) if limit.present?
-
- entries = ldap_search(options).select do |entry|
- entry.respond_to? uid
- end
-
- entries.map do |entry|
- Chaltron::LDAP::Person.new(entry, uid)
- end
+ def update_attributes(dn, args)
+ ldap.modify dn: dn, operations: args.map { |k,v| [:replace, k, v] }
end
private
def options
Devise.omniauth_configs[:ldap].options
end
+ def translate_field field
+ return uid if field.to_sym == :uid
+ return Chaltron.ldap_field_mappings[field.to_sym] unless Chaltron.ldap_field_mappings[field.to_sym].nil?
+ field
+ end
+
def adapter_options
- {
+ opts = {
host: options[:host],
port: options[:port],
- encryption: encryption,
+ encryption: encryption_options,
verbose: true
- }.tap do |options|
- options.merge!(auth_options) if has_auth?
- end
+ }
+ opts.merge!(auth_options) if has_auth?
+ opts
end
def base
options[:base]
end
def uid
options[:uid]
end
- def encryption
- case options[:method].to_s
- when 'ssl'
- :simple_tls
- when 'tls'
- :start_tls
- else
- nil
+ def encryption_options
+ method = translate_method
+ return unless method
+ {
+ method: method,
+ tls_options: tls_options
+ }
+ end
+
+ def translate_method
+ NET_LDAP_ENCRYPTION_METHOD[options[:encryption]&.to_sym]
+ end
+
+ def tls_options
+ return @tls_options if defined?(@tls_options)
+
+ method = translate_method
+ return unless method
+
+ opts = if options[:verify_certificates] && method != 'plain'
+ # Dup so we don't accidentally overwrite the constant
+ OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.dup
+ else
+ # It is important to explicitly set verify_mode for two reasons:
+ # 1. The behavior of OpenSSL is undefined when verify_mode is not set.
+ # 2. The net-ldap gem implementation verifies the certificate hostname
+ # unless verify_mode is set to VERIFY_NONE.
+ { verify_mode: OpenSSL::SSL::VERIFY_NONE }
+ end
+
+ opts.merge!(custom_tls_options)
+
+ @tls_options = opts
+ end
+
+ def custom_tls_options
+ return {} unless options['tls_options']
+
+ # Dup so we don't overwrite the original value
+ custom_options = options['tls_options'].dup.delete_if { |_, value| value.nil? || value.blank? }
+ custom_options.symbolize_keys!
+
+ if custom_options[:cert]
+ begin
+ custom_options[:cert] = OpenSSL::X509::Certificate.new(custom_options[:cert])
+ rescue OpenSSL::X509::CertificateError => e
+ Rails.logger.error "LDAP TLS Options 'cert' is invalid for provider #{provider}: #{e.message}"
+ end
end
+
+ if custom_options[:key]
+ begin
+ custom_options[:key] = OpenSSL::PKey.read(custom_options[:key])
+ rescue OpenSSL::PKey::PKeyError => e
+ Rails.logger.error "LDAP TLS Options 'key' is invalid for provider #{provider}: #{e.message}"
+ end
+ end
+ custom_options
end
def auth_options
{
auth: {