entitlements-app 1.2.10 → 1.2.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/entitlements/data/groups/calculated/base.rb +1 -1
- data/lib/entitlements/service/ldap.rb +96 -40
- data/lib/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6d261fd97bc7b035820a02ef58cfd54b54678ca97bba95caa68625bfdf3f09a1
|
|
4
|
+
data.tar.gz: df68e3cf38d4602047b2fcb3e853a2d31ee10e6c5a71ffdead194824ef15f8e8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0cc730a8a9eb5f0cde4c638c9228bedb52c74fd8902d7af54ddee675fda12af8246159a54bfe33ce6440dbce500c3b5d463483d60b34ca23617981eedf265f6c
|
|
7
|
+
data.tar.gz: b9237fea7006e586a638e16ffeb0b71b8325cbee3126fe2cd5102a3b8ed286d9fccd7cbc4a6e54d01e0e70761cf31d1f957e54db5e5437d8c7a2ab8f46d85505
|
|
@@ -107,7 +107,7 @@ module Entitlements
|
|
|
107
107
|
# members_in - Optionally a set of Entitlements::Models::Person with the currently calculated member set.
|
|
108
108
|
#
|
|
109
109
|
# Returns Set[Entitlements::Models::Person] of all matching members.
|
|
110
|
-
Contract C::None => C::Or[:calculating,
|
|
110
|
+
Contract C::None => C::Or[:calculating, Set]
|
|
111
111
|
def filtered_members
|
|
112
112
|
return :calculating if members == :calculating
|
|
113
113
|
|
|
@@ -84,6 +84,8 @@ module Entitlements
|
|
|
84
84
|
@person_dn_format = person_dn_format
|
|
85
85
|
@known_existing_dns = {}
|
|
86
86
|
@known_existing_dns_mutex = Mutex.new
|
|
87
|
+
@search_connections = {}
|
|
88
|
+
@search_connections_mutex = Mutex.new
|
|
87
89
|
end
|
|
88
90
|
|
|
89
91
|
# Read a single entry identified by its DN and return the value. Returns nil if
|
|
@@ -122,32 +124,32 @@ module Entitlements
|
|
|
122
124
|
# be consistent no matter what. LDAP is case insensitive after all!
|
|
123
125
|
downcased_attrs = attrs == "*" ? "*" : attrs.map { |a| a.downcase }
|
|
124
126
|
|
|
125
|
-
# Outside the retry block: `ldap` retries its own bind, and nesting would multiply attempts.
|
|
126
|
-
connection = ldap
|
|
127
127
|
result = with_ldap_connection_retries do
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
128
|
+
with_search_connection do |connection|
|
|
129
|
+
entries = {}
|
|
130
|
+
search_succeeded = connection.search(
|
|
131
|
+
base: base,
|
|
132
|
+
filter: filter,
|
|
133
|
+
attributes: downcased_attrs,
|
|
134
|
+
scope: scope,
|
|
135
|
+
return_result: false
|
|
136
|
+
) do |entry|
|
|
137
|
+
result_key = index == :dn ? entry.dn : entry[index]
|
|
138
|
+
unless result_key
|
|
139
|
+
raise EntryError, "#{entry.dn} has no value for #{index.inspect}"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
if entries.key?(result_key)
|
|
143
|
+
other_entry_dn = entries[result_key].dn
|
|
144
|
+
raise DuplicateEntryError, "#{entry.dn} and #{other_entry_dn} have the same value of #{index} = #{result_key.inspect}"
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
entries[result_key] = entry
|
|
139
148
|
end
|
|
149
|
+
remember_existing_dn(base) if search_succeeded
|
|
140
150
|
|
|
141
|
-
|
|
142
|
-
other_entry_dn = entries[result_key].dn
|
|
143
|
-
raise DuplicateEntryError, "#{entry.dn} and #{other_entry_dn} have the same value of #{index} = #{result_key.inspect}"
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
entries[result_key] = entry
|
|
151
|
+
entries
|
|
147
152
|
end
|
|
148
|
-
remember_existing_dn(base) if search_succeeded
|
|
149
|
-
|
|
150
|
-
entries
|
|
151
153
|
end
|
|
152
154
|
|
|
153
155
|
Entitlements.logger.debug "Completed search: #{result.keys.size} result(s)"
|
|
@@ -261,24 +263,6 @@ module Entitlements
|
|
|
261
263
|
|
|
262
264
|
# Construct the object
|
|
263
265
|
Entitlements.logger.debug "Creating connection to #{uri.host} port #{uri.port}"
|
|
264
|
-
ldap_options = {
|
|
265
|
-
host: uri.host,
|
|
266
|
-
port: uri.port,
|
|
267
|
-
auth: { method: :simple, username: binddn, password: bindpw }
|
|
268
|
-
}
|
|
269
|
-
if uri.scheme == "ldaps"
|
|
270
|
-
ldap_options[:encryption] = {
|
|
271
|
-
method: :simple_tls,
|
|
272
|
-
tls_options: {
|
|
273
|
-
verify_mode: @disable_ssl_verification ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
if @ca_file && ldap_options[:encryption].key?(:tls_options)
|
|
279
|
-
ldap_options[:encryption][:tls_options][:ca_file] = @ca_file
|
|
280
|
-
end
|
|
281
|
-
|
|
282
266
|
ldap_object = Net::LDAP.new(ldap_options)
|
|
283
267
|
raise WTFError, "FATAL: can't create LDAP connection object" if ldap_object.nil?
|
|
284
268
|
|
|
@@ -297,6 +281,78 @@ module Entitlements
|
|
|
297
281
|
end
|
|
298
282
|
end
|
|
299
283
|
|
|
284
|
+
def ldap_options
|
|
285
|
+
uri = URI(addr)
|
|
286
|
+
options = {
|
|
287
|
+
host: uri.host,
|
|
288
|
+
port: uri.port,
|
|
289
|
+
auth: { method: :simple, username: binddn, password: bindpw }
|
|
290
|
+
}
|
|
291
|
+
if uri.scheme == "ldaps"
|
|
292
|
+
options[:encryption] = {
|
|
293
|
+
method: :simple_tls,
|
|
294
|
+
tls_options: {
|
|
295
|
+
verify_mode: @disable_ssl_verification ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
if @ca_file && options[:encryption].key?(:tls_options)
|
|
301
|
+
options[:encryption][:tls_options][:ca_file] = @ca_file
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
options
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# Searches reuse one bound connection per thread instead of connecting and binding each time.
|
|
308
|
+
def with_search_connection
|
|
309
|
+
reused = @search_connections_mutex.synchronize { @search_connections.key?(Thread.current) }
|
|
310
|
+
yield search_connection
|
|
311
|
+
rescue SystemCallError, IOError, OpenSSL::SSL::SSLError, Net::LDAP::Error
|
|
312
|
+
close_search_connection
|
|
313
|
+
# The server may have dropped an idle connection, so retry once on a new one.
|
|
314
|
+
reused ? retry : raise
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def search_connection
|
|
318
|
+
existing = @search_connections_mutex.synchronize { @search_connections[Thread.current] }
|
|
319
|
+
return existing.first if existing
|
|
320
|
+
|
|
321
|
+
options = ldap_options
|
|
322
|
+
Entitlements.logger.debug "Creating connection to #{options[:host]} port #{options[:port]}"
|
|
323
|
+
connection = Net::LDAP::Connection.new(host: options[:host], port: options[:port], encryption: options[:encryption])
|
|
324
|
+
Entitlements.logger.debug "Binding with user #{binddn.inspect} with simple password authentication"
|
|
325
|
+
begin
|
|
326
|
+
result = connection.bind(options[:auth])
|
|
327
|
+
rescue StandardError
|
|
328
|
+
close_connection(connection)
|
|
329
|
+
raise
|
|
330
|
+
end
|
|
331
|
+
unless result.result_code == Net::LDAP::ResultCodeSuccess
|
|
332
|
+
close_connection(connection)
|
|
333
|
+
message = Net::LDAP.result2string(result.result_code)
|
|
334
|
+
Entitlements.logger.fatal message
|
|
335
|
+
raise ConnectionError, "FATAL: #{message}"
|
|
336
|
+
end
|
|
337
|
+
Entitlements.logger.debug "Successfully authenticated to #{options[:host]} port #{options[:port]}"
|
|
338
|
+
|
|
339
|
+
ldap_object = Net::LDAP.new(options)
|
|
340
|
+
ldap_object.connection = connection
|
|
341
|
+
@search_connections_mutex.synchronize { @search_connections[Thread.current] = [ldap_object, connection] }
|
|
342
|
+
ldap_object
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
def close_search_connection
|
|
346
|
+
_, connection = @search_connections_mutex.synchronize { @search_connections.delete(Thread.current) }
|
|
347
|
+
close_connection(connection)
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
def close_connection(connection)
|
|
351
|
+
connection&.close
|
|
352
|
+
rescue IOError, SystemCallError, OpenSSL::SSL::SSLError
|
|
353
|
+
nil
|
|
354
|
+
end
|
|
355
|
+
|
|
300
356
|
def with_ldap_connection_retries
|
|
301
357
|
attempts = 0
|
|
302
358
|
begin
|
data/lib/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: entitlements-app
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.2.
|
|
4
|
+
version: 1.2.12
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- GitHub, Inc. Security Ops
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-11-
|
|
11
|
+
date: 2026-11-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: concurrent-ruby
|