entitlements-app 1.2.2 → 1.2.4
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 +2 -2
- data/lib/entitlements/data/groups/calculated/modifiers/expiration.rb +1 -1
- data/lib/entitlements/data/groups/calculated/text.rb +7 -5
- data/lib/entitlements/data/groups/calculated/yaml.rb +6 -4
- data/lib/entitlements/service/ldap.rb +33 -7
- data/lib/entitlements.rb +19 -0
- 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: 2ff39c49f02bf4b3dcc8ced68357e2c85084416468d8300a79dd19c5685cac35
|
|
4
|
+
data.tar.gz: c40fb54374427dda1782344df0bdeb9d5401774a755e4c89d5795438d43a6605
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0f0b5e0b20fc9a52547233b9b9f5dec204976d5a62d893a5d74b913af3222972fddadc12b2da5be4b7fb59ac8cf4722adc5f0da8a0415d8166cae3fc2066c119
|
|
7
|
+
data.tar.gz: 3585576afa5953596609cec10ca8995166e8803666cdece35003839dd365389eb46ee6e1298e8599537560083b28212f05e2d71155cd2dcc4e776f3ccbe934ec
|
|
@@ -217,7 +217,7 @@ module Entitlements
|
|
|
217
217
|
return false if expiration.nil? || expiration.strip.empty?
|
|
218
218
|
if expiration =~ /\A(\d{4})-(\d{2})-(\d{2})\z/
|
|
219
219
|
year, month, day = Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i
|
|
220
|
-
return Time.utc(year, month, day, 0, 0, 0) <=
|
|
220
|
+
return Time.utc(year, month, day, 0, 0, 0) <= Entitlements.evaluation_time.utc
|
|
221
221
|
end
|
|
222
222
|
message = "Invalid expiration date #{expiration.inspect} in #{context} (expected format: YYYY-MM-DD)"
|
|
223
223
|
raise ArgumentError, message
|
|
@@ -340,7 +340,7 @@ module Entitlements
|
|
|
340
340
|
# Returns C::SetOf[Entitlements::Models::Person] from a recursive call.
|
|
341
341
|
def handle_and(rule)
|
|
342
342
|
ensure_type!("and", rule, Array)
|
|
343
|
-
return
|
|
343
|
+
return Set.new unless rule.any?
|
|
344
344
|
|
|
345
345
|
first_rule = rule.shift
|
|
346
346
|
ensure_type!("and", first_rule, Hash)
|
|
@@ -30,7 +30,7 @@ module Entitlements
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
# If the date is in the future, leave the entitlement unchanged.
|
|
33
|
-
return false if parse_date >
|
|
33
|
+
return false if parse_date > Entitlements.evaluation_time.utc.to_date
|
|
34
34
|
|
|
35
35
|
# Empty the group. Set metadata allowing no members. Return true to indicate modification.
|
|
36
36
|
rs.metadata["no_members_ok"] = true
|
|
@@ -21,10 +21,12 @@ module Entitlements
|
|
|
21
21
|
# Returns a Set[String] with DN's of the people in the group.
|
|
22
22
|
Contract C::None => C::Or[:calculating, C::SetOf[Entitlements::Models::Person]]
|
|
23
23
|
def members
|
|
24
|
-
@members
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
return @members if @members
|
|
25
|
+
|
|
26
|
+
Entitlements.logger.debug "Calculating members from #{filename}"
|
|
27
|
+
result = members_from_rules(rules)
|
|
28
|
+
@members = result unless result == :calculating
|
|
29
|
+
result
|
|
28
30
|
end
|
|
29
31
|
|
|
30
32
|
# Standard interface: Get the description of this group.
|
|
@@ -182,7 +184,7 @@ module Entitlements
|
|
|
182
184
|
if parsed_data.key?("modifier_expiration") && affirmative.empty?
|
|
183
185
|
exp_date = parsed_data.fetch("modifier_expiration").fetch("=").first.fetch(:key)
|
|
184
186
|
date = Entitlements::Util::Util.parse_date(exp_date)
|
|
185
|
-
return {"always" => false} if date <=
|
|
187
|
+
return {"always" => false} if date <= Entitlements.evaluation_time.utc.to_date
|
|
186
188
|
end
|
|
187
189
|
|
|
188
190
|
# There has to be at least one affirmative condition, not just all negative ones.
|
|
@@ -18,10 +18,12 @@ module Entitlements
|
|
|
18
18
|
# Returns a Set[String] with DN's of the people in the group.
|
|
19
19
|
Contract C::None => C::Or[:calculating, C::SetOf[Entitlements::Models::Person]]
|
|
20
20
|
def members
|
|
21
|
-
@members
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
return @members if @members
|
|
22
|
+
|
|
23
|
+
Entitlements.logger.debug "Calculating members from #{filename}"
|
|
24
|
+
result = members_from_rules(rules)
|
|
25
|
+
@members = result unless result == :calculating
|
|
26
|
+
result
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
# Standard interface: Get the description of this group.
|
|
@@ -17,9 +17,9 @@ module Entitlements
|
|
|
17
17
|
# This keeps the schema happy.
|
|
18
18
|
attr_reader :binddn, :person_dn_format
|
|
19
19
|
|
|
20
|
-
# Constructor-like object that ensures only one LDAP object
|
|
21
|
-
#
|
|
22
|
-
#
|
|
20
|
+
# Constructor-like object that ensures only one LDAP service object is made for a
|
|
21
|
+
# given LDAP server. Takes the same parameters as the constructor and returns the
|
|
22
|
+
# same object type.
|
|
23
23
|
#
|
|
24
24
|
# addr - URL of LDAP server e.g. ldaps://ldap.example.net:636
|
|
25
25
|
# binddn - DN to bind with
|
|
@@ -80,6 +80,8 @@ module Entitlements
|
|
|
80
80
|
@ca_file = ca_file
|
|
81
81
|
@disable_ssl_verification = disable_ssl_verification
|
|
82
82
|
@person_dn_format = person_dn_format
|
|
83
|
+
@known_existing_dns = {}
|
|
84
|
+
@known_existing_dns_mutex = Mutex.new
|
|
83
85
|
end
|
|
84
86
|
|
|
85
87
|
# Read a single entry identified by its DN and return the value. Returns nil if
|
|
@@ -119,7 +121,13 @@ module Entitlements
|
|
|
119
121
|
downcased_attrs = attrs == "*" ? "*" : attrs.map { |a| a.downcase }
|
|
120
122
|
|
|
121
123
|
result = {}
|
|
122
|
-
ldap.search(
|
|
124
|
+
search_succeeded = ldap.search(
|
|
125
|
+
base: base,
|
|
126
|
+
filter: filter,
|
|
127
|
+
attributes: downcased_attrs,
|
|
128
|
+
scope: scope,
|
|
129
|
+
return_result: false
|
|
130
|
+
) do |entry|
|
|
123
131
|
result_key = index == :dn ? entry.dn : entry[index]
|
|
124
132
|
unless result_key
|
|
125
133
|
raise EntryError, "#{entry.dn} has no value for #{index.inspect}"
|
|
@@ -132,6 +140,7 @@ module Entitlements
|
|
|
132
140
|
|
|
133
141
|
result[result_key] = entry
|
|
134
142
|
end
|
|
143
|
+
remember_existing_dn(base) if search_succeeded
|
|
135
144
|
|
|
136
145
|
Entitlements.logger.debug "Completed search: #{result.keys.size} result(s)"
|
|
137
146
|
|
|
@@ -145,6 +154,7 @@ module Entitlements
|
|
|
145
154
|
# Returns true if the entry exists, false otherwise.
|
|
146
155
|
Contract String => C::Bool
|
|
147
156
|
def exists?(dn)
|
|
157
|
+
return true if known_existing_dn?(dn)
|
|
148
158
|
read(dn).is_a?(Net::LDAP::Entry)
|
|
149
159
|
end
|
|
150
160
|
|
|
@@ -180,7 +190,10 @@ module Entitlements
|
|
|
180
190
|
|
|
181
191
|
ldap.delete(dn: dn)
|
|
182
192
|
operation_result = ldap.get_operation_result
|
|
183
|
-
|
|
193
|
+
if operation_result["code"] == 0
|
|
194
|
+
forget_dn(dn)
|
|
195
|
+
return true
|
|
196
|
+
end
|
|
184
197
|
Entitlements.logger.error "Error deleting #{dn}: #{operation_result['message']}"
|
|
185
198
|
false
|
|
186
199
|
end
|
|
@@ -215,11 +228,24 @@ module Entitlements
|
|
|
215
228
|
|
|
216
229
|
attr_reader :addr, :bindpw
|
|
217
230
|
|
|
218
|
-
|
|
231
|
+
def known_existing_dn?(dn)
|
|
232
|
+
@known_existing_dns_mutex.synchronize { @known_existing_dns.key?(dn) }
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def remember_existing_dn(dn)
|
|
236
|
+
@known_existing_dns_mutex.synchronize { @known_existing_dns[dn] = true }
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def forget_dn(dn)
|
|
240
|
+
@known_existing_dns_mutex.synchronize { @known_existing_dns.delete(dn) }
|
|
241
|
+
@dn_cache&.delete(dn)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# The LDAP object is initialized and its credentials are validated on demand.
|
|
219
245
|
#
|
|
220
246
|
# Takes no arguments.
|
|
221
247
|
#
|
|
222
|
-
# Returns a Net::LDAP object
|
|
248
|
+
# Returns a Net::LDAP object configured to connect and bind for each operation.
|
|
223
249
|
Contract C::None => Net::LDAP
|
|
224
250
|
def ldap
|
|
225
251
|
@ldap ||= begin
|
data/lib/entitlements.rb
CHANGED
|
@@ -90,6 +90,7 @@ module Entitlements
|
|
|
90
90
|
@config = nil
|
|
91
91
|
@config_file = nil
|
|
92
92
|
@config_path_override = nil
|
|
93
|
+
@evaluation_time = nil
|
|
93
94
|
@person_extra_methods = {}
|
|
94
95
|
@statsd = nil
|
|
95
96
|
|
|
@@ -97,6 +98,24 @@ module Entitlements
|
|
|
97
98
|
Entitlements::Data::Groups::Calculated.reset!
|
|
98
99
|
end
|
|
99
100
|
|
|
101
|
+
# Return the fixed time used for the current date-sensitive entitlement evaluation.
|
|
102
|
+
#
|
|
103
|
+
# Returns a Time.
|
|
104
|
+
Contract C::None => Time
|
|
105
|
+
def self.evaluation_time
|
|
106
|
+
@evaluation_time ||= Time.now
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Set the time used for date-sensitive entitlement evaluation.
|
|
110
|
+
#
|
|
111
|
+
# value - A Time.
|
|
112
|
+
#
|
|
113
|
+
# Returns the supplied Time.
|
|
114
|
+
Contract Time => Time
|
|
115
|
+
def self.evaluation_time=(value)
|
|
116
|
+
@evaluation_time = value
|
|
117
|
+
end
|
|
118
|
+
|
|
100
119
|
def self.reset_extras!
|
|
101
120
|
extras_loaded = @extras_loaded
|
|
102
121
|
if extras_loaded
|
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.4
|
|
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-09-
|
|
11
|
+
date: 2026-09-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: concurrent-ruby
|