Class: Entitlements::Service::LDAP
- Inherits:
-
Object
- Object
- Entitlements::Service::LDAP
- Includes:
- Contracts::Core
- Defined in:
- lib/entitlements.rb,
lib/entitlements/service/ldap.rb
Defined Under Namespace
Classes: ConnectionError, DuplicateEntryError, EntryError, WTFError
Constant Summary collapse
- C =
::Contracts
Instance Attribute Summary collapse
-
#binddn ⇒ Object
readonly
We use the binddn as the owner of the group, for lack of anything better.
-
#person_dn_format ⇒ Object
readonly
We use the binddn as the owner of the group, for lack of anything better.
Class Method Summary collapse
Instance Method Summary collapse
- #delete(dn) ⇒ Object
- #exists?(dn) ⇒ Boolean
-
#initialize(addr:, binddn:, bindpw:, ca_file: , disable_ssl_verification: false, person_dn_format:) ⇒ LDAP
constructor
A new instance of LDAP.
- #modify(dn, updates) ⇒ Object
- #read(dn) ⇒ Object
- #search(base:, filter: nil, attrs: "*", index: :dn, scope: Net::LDAP::SearchScope_WholeSubtree) ⇒ Object
- #upsert(dn:, attributes:) ⇒ Object
Constructor Details
#initialize(addr:, binddn:, bindpw:, ca_file: , disable_ssl_verification: false, person_dn_format:) ⇒ LDAP
Returns a new instance of LDAP.
75 76 77 78 79 80 81 82 83 |
# File 'lib/entitlements/service/ldap.rb', line 75 def initialize(addr:, binddn:, bindpw:, ca_file: ENV["LDAP_CACERT"], disable_ssl_verification: false, person_dn_format:) # Save some parameters for the LDAP connection but don't actually bind yet. @addr = addr @binddn = binddn @bindpw = bindpw @ca_file = ca_file @disable_ssl_verification = disable_ssl_verification @person_dn_format = person_dn_format end |
Instance Attribute Details
#binddn ⇒ Object (readonly)
We use the binddn as the owner of the group, for lack of anything better. This keeps the schema happy.
18 19 20 |
# File 'lib/entitlements/service/ldap.rb', line 18 def binddn @binddn end |
#person_dn_format ⇒ Object (readonly)
We use the binddn as the owner of the group, for lack of anything better. This keeps the schema happy.
18 19 20 |
# File 'lib/entitlements/service/ldap.rb', line 18 def person_dn_format @person_dn_format end |
Class Method Details
.new_with_cache(addr:, binddn:, bindpw:, ca_file: ENV["LDAP_CACERT"], disable_ssl_verification: false, person_dn_format:) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/entitlements/service/ldap.rb', line 39 def self.new_with_cache(addr:, binddn:, bindpw:, ca_file: ENV["LDAP_CACERT"], disable_ssl_verification: false, person_dn_format:) # only look at LDAP_DISABLE_SSL_VERIFICATION in the environment if we didn't pass true to the method already if disable_ssl_verification == false # otherwise if it's set to anything at all in env, disable ssl verification disable_ssl_verification = !!ENV["LDAP_DISABLE_SSL_VERIFICATION"] end fingerprint = [addr, binddn, bindpw, ca_file, disable_ssl_verification, person_dn_format].map(&:inspect).join("|") Entitlements.cache[:ldap_connections] ||= {} Entitlements.cache[:ldap_connections][fingerprint] ||= new( addr: addr, binddn: binddn, bindpw: bindpw, ca_file: ca_file, disable_ssl_verification: disable_ssl_verification, person_dn_format: person_dn_format ) end |
Instance Method Details
#delete(dn) ⇒ Object
173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/entitlements/service/ldap.rb', line 173 def delete(dn) # See if the object exists by searching for it. If it exists we'll get its data back as a hash. If not # we'll get an empty hash. We don't need to delete something that doesn't already exist. unless exists?(dn) Entitlements.logger.debug "Not deleting #{dn} because it does not exist" return true end ldap.delete(dn: dn) operation_result = ldap.get_operation_result return true if operation_result["code"] == 0 Entitlements.logger.error "Error deleting #{dn}: #{operation_result['message']}" false end |
#exists?(dn) ⇒ Boolean
147 148 149 |
# File 'lib/entitlements/service/ldap.rb', line 147 def exists?(dn) read(dn).is_a?(Net::LDAP::Entry) end |
#modify(dn, updates) ⇒ Object
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/entitlements/service/ldap.rb', line 195 def modify(dn, updates) return false unless updates.any? updates.each do |attr_name, val| operation = "" if val.nil? next if ldap.delete_attribute(dn, attr_name) operation = "deleting" else next if ldap.replace_attribute(dn, attr_name, val) operation = "modifying" end operation_result = ldap.get_operation_result Entitlements.logger.error "Error #{operation} attribute #{attr_name} in #{dn}: #{operation_result['message']}" Entitlements.logger.error "LDAP code=#{operation_result.code}: #{operation_result.}" return false end true end |
#read(dn) ⇒ Object
92 93 94 95 96 |
# File 'lib/entitlements/service/ldap.rb', line 92 def read(dn) @dn_cache ||= {} @dn_cache[dn] ||= search(base: dn, attrs: "*", scope: Net::LDAP::SearchScope_BaseObject)[dn] || :none @dn_cache[dn] == :none ? nil : @dn_cache[dn] end |
#search(base:, filter: nil, attrs: "*", index: :dn, scope: Net::LDAP::SearchScope_WholeSubtree) ⇒ Object
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/entitlements/service/ldap.rb', line 114 def search(base:, filter: nil, attrs: "*", index: :dn, scope: Net::LDAP::SearchScope_WholeSubtree) Entitlements.logger.debug "LDAP Search: filter=#{filter.inspect} base=#{base.inspect}" # Ruby downcases these in the results anyway, so just downcase everything here so it'll # be consistent no matter what. LDAP is case insensitive after all! downcased_attrs = attrs == "*" ? "*" : attrs.map { |a| a.downcase } result = {} ldap.search(base: base, filter: filter, attributes: downcased_attrs, scope: scope, return_result: false) do |entry| result_key = index == :dn ? entry.dn : entry[index] unless result_key raise EntryError, "#{entry.dn} has no value for #{index.inspect}" end if result.key?(result_key) other_entry_dn = result[result_key].dn raise DuplicateEntryError, "#{entry.dn} and #{other_entry_dn} have the same value of #{index} = #{result_key.inspect}" end result[result_key] = entry end Entitlements.logger.debug "Completed search: #{result.keys.size} result(s)" result end |
#upsert(dn:, attributes:) ⇒ Object
161 162 163 164 165 |
# File 'lib/entitlements/service/ldap.rb', line 161 def upsert(dn:, attributes:) # See if the object exists by searching for it. If it exists we'll get its data back as a hash. If not # we'll get an empty hash. Dispatch this to the create or update methods. read(dn) ? update(dn: dn, existing: read(dn), attributes: attributes) : create(dn: dn, attributes: attributes) end |