Class: Entitlements::Service::LDAP
- Inherits:
-
Object
- Object
- Entitlements::Service::LDAP
show all
- 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
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
-
#modify(dn, updates) ⇒ Object
-
#read(dn) ⇒ Object
-
#search(base:, filter: nil, attrs: "*", index: :dn, scope: Net::LDAP::SearchScope_WholeSubtree) ⇒ Object
-
#upsert(dn:, attributes:) ⇒ Object
common, extended, included
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
84
85
|
# 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:)
@addr = addr
@binddn = binddn
@bindpw = bindpw
@ca_file = ca_file
@disable_ssl_verification = disable_ssl_verification
@person_dn_format = person_dn_format
@known_existing_dns = {}
@known_existing_dns_mutex = Mutex.new
end
|
Instance Attribute Details
#binddn ⇒ Object
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
|
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
.entry_to_group(entry) ⇒ Object
395
396
397
398
399
400
401
|
# File 'lib/entitlements/service/ldap.rb', line 395
def self.entry_to_group(entry)
Entitlements::Models::Group.new(
dn: entry.dn,
members: Set.new(member_array(entry)),
description: entry[:description].is_a?(Array) ? entry[:description].first.to_s : ""
)
end
|
.member_array(entry) ⇒ Object
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
|
# File 'lib/entitlements/service/ldap.rb', line 410
def self.member_array(entry)
members = if entry[:objectclass].include?("groupOfUniqueNames")
entry[:uniquemember]
elsif entry[:objectclass].include?("groupOfNames")
entry[:member]
elsif entry[:objectclass].include?("posixGroup")
entry[:memberuid]
else
raise "Do not know how to handle objectClass = #{entry[:objectclass].inspect} for dn=#{entry.dn.inspect}!"
end
members -= [entry.dn]
members.map { |dn| Entitlements::Util::Util.first_attr(dn) }
end
|
.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:)
if disable_ssl_verification == false
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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
|
# File 'lib/entitlements/service/ldap.rb', line 183
def delete(dn)
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
if operation_result["code"] == 0
forget_dn(dn)
return true
end
Entitlements.logger.error "Error deleting #{dn}: #{operation_result['message']}"
false
end
|
#exists?(dn) ⇒ Boolean
156
157
158
159
|
# File 'lib/entitlements/service/ldap.rb', line 156
def exists?(dn)
return true if known_existing_dn?(dn)
read(dn).is_a?(Net::LDAP::Entry)
end
|
#modify(dn, updates) ⇒ Object
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
|
# File 'lib/entitlements/service/ldap.rb', line 208
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.error_message}"
return false
end
true
end
|
#read(dn) ⇒ Object
94
95
96
97
98
|
# File 'lib/entitlements/service/ldap.rb', line 94
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
# File 'lib/entitlements/service/ldap.rb', line 116
def search(base:, filter: nil, attrs: "*", index: :dn, scope: Net::LDAP::SearchScope_WholeSubtree)
Entitlements.logger.debug "LDAP Search: filter=#{filter.inspect} base=#{base.inspect}"
downcased_attrs = attrs == "*" ? "*" : attrs.map { |a| a.downcase }
result = {}
search_succeeded = 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
remember_existing_dn(base) if search_succeeded
Entitlements.logger.debug "Completed search: #{result.keys.size} result(s)"
result
end
|
#upsert(dn:, attributes:) ⇒ Object
171
172
173
174
175
|
# File 'lib/entitlements/service/ldap.rb', line 171
def upsert(dn:, attributes:)
read(dn) ? update(dn: dn, existing: read(dn), attributes: attributes) : create(dn: dn, attributes: attributes)
end
|