oso-oso 0.25.0 → 0.26.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/ext/oso-oso/lib/libpolar.dylib +0 -0
- data/ext/oso-oso/lib/libpolar.so +0 -0
- data/ext/oso-oso/lib/polar.dll +0 -0
- data/lib/oso/oso.rb +2 -29
- data/lib/oso/polar/data_filtering.rb +0 -190
- data/lib/oso/polar/errors.rb +1 -0
- data/lib/oso/polar/host.rb +12 -9
- data/lib/oso/polar/polar.rb +1 -8
- data/lib/oso/polar/query.rb +16 -25
- data/lib/oso/version.rb +1 -1
- data/lib/oso.rb +0 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf0c10b0c91583c11a50068bb59f33c7c44146c1
|
4
|
+
data.tar.gz: c115ab372e3b70dc4dfa36ad7c2466fe4129aaf7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3baf118cf112eb427e2b369bbd064eca8e239a4f6c5a864ec13b81615160845d68c7db7d4bb40df4e35e771b4a30022e3fe34681263e6c53972eedebb95a6c7e
|
7
|
+
data.tar.gz: 16ea938c4230e2c6942831d263ebf9b0016fba9265a8a098aec557c2d2ba052aa5133c3eb3bc084d27f3375bc6777ba1cd5e7f0b788f9874bc11c671e3caf6e7
|
data/Gemfile.lock
CHANGED
Binary file
|
data/ext/oso-oso/lib/libpolar.so
CHANGED
Binary file
|
data/ext/oso-oso/lib/polar.dll
CHANGED
Binary file
|
data/lib/oso/oso.rb
CHANGED
@@ -182,16 +182,7 @@ module Oso
|
|
182
182
|
#
|
183
183
|
# @return A query for resources accessible to the actor.
|
184
184
|
def authorized_query(actor, action, resource_cls)
|
185
|
-
|
186
|
-
|
187
|
-
unless host.types[resource_cls].build_query == ::Oso::Polar::Host::DEFAULT_BUILD_QUERY
|
188
|
-
warn 'Warning: redundant data filtering configuration detected'
|
189
|
-
end
|
190
|
-
|
191
|
-
new_authorized_query(actor, action, resource_cls)
|
192
|
-
else
|
193
|
-
old_authorized_query(actor, action, resource_cls)
|
194
|
-
end
|
185
|
+
new_authorized_query(actor, action, resource_cls)
|
195
186
|
end
|
196
187
|
|
197
188
|
# Determine the resources of type +resource_cls+ that +actor+
|
@@ -203,25 +194,7 @@ module Oso
|
|
203
194
|
#
|
204
195
|
# @return A list of resources accessible to the actor.
|
205
196
|
def authorized_resources(actor, action, resource_cls)
|
206
|
-
|
207
|
-
|
208
|
-
if host.use_new_data_filtering?
|
209
|
-
host.adapter.execute_query q
|
210
|
-
elsif q.nil?
|
211
|
-
[]
|
212
|
-
else
|
213
|
-
host.types[resource_cls].exec_query[q]
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
# Register default values for data filtering query functions.
|
218
|
-
# These can be overridden by passing specific implementations to
|
219
|
-
# `register_class` or by defining `build_query`, `exec_query` and
|
220
|
-
# `combine_query` methods on the class object.
|
221
|
-
def set_data_filtering_query_defaults(build_query: nil, exec_query: nil, combine_query: nil)
|
222
|
-
host.build_query = build_query if build_query
|
223
|
-
host.exec_query = exec_query if exec_query
|
224
|
-
host.combine_query = combine_query if combine_query
|
197
|
+
host.adapter.execute_query authorized_query(actor, action, resource_cls)
|
225
198
|
end
|
226
199
|
|
227
200
|
def data_filtering_adapter=(adapter)
|
@@ -4,110 +4,6 @@ module Oso
|
|
4
4
|
module Polar
|
5
5
|
# Data filtering interface for Ruby
|
6
6
|
module DataFiltering
|
7
|
-
GETATTR = ->(x, attr) { attr.nil? ? x : x.send(attr) }
|
8
|
-
# Represents a set of filter sequences that should allow the host
|
9
|
-
# to obtain the records satisfying a query.
|
10
|
-
class FilterPlan
|
11
|
-
attr_reader :result_sets
|
12
|
-
|
13
|
-
def self.parse(polar, partials, class_name)
|
14
|
-
types = polar.host.serialize_types
|
15
|
-
parsed_json = polar.ffi.build_filter_plan(types, partials, 'resource', class_name)
|
16
|
-
result_sets = parsed_json['result_sets'].map do |rset|
|
17
|
-
ResultSet.parse polar, rset
|
18
|
-
end
|
19
|
-
|
20
|
-
new polar: polar, result_sets: result_sets
|
21
|
-
end
|
22
|
-
|
23
|
-
def initialize(polar:, result_sets:)
|
24
|
-
@polar = polar
|
25
|
-
@result_sets = result_sets
|
26
|
-
end
|
27
|
-
|
28
|
-
def build_query # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
29
|
-
combine = nil
|
30
|
-
result_sets.each_with_object([]) do |rs, qb|
|
31
|
-
rs.resolve_order.each_with_object({}) do |i, set_results|
|
32
|
-
req = rs.requests[i]
|
33
|
-
cs = req.ground(set_results)
|
34
|
-
typ = @polar.host.types[req.class_tag]
|
35
|
-
q = typ.build_query[cs]
|
36
|
-
if i != rs.result_id
|
37
|
-
set_results[i] = typ.exec_query[q]
|
38
|
-
else
|
39
|
-
combine = typ.combine_query
|
40
|
-
qb.push q
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end.reduce(&combine)
|
44
|
-
end
|
45
|
-
|
46
|
-
# Represents a sequence of filters for one set of results
|
47
|
-
class ResultSet
|
48
|
-
attr_reader :requests, :resolve_order, :result_id
|
49
|
-
|
50
|
-
def self.parse(polar, parsed_json)
|
51
|
-
resolve_order = parsed_json['resolve_order']
|
52
|
-
result_id = parsed_json['result_id']
|
53
|
-
requests = parsed_json['requests'].each_with_object({}) do |req, reqs|
|
54
|
-
reqs[req[0].to_i] = Request.parse(polar, req[1])
|
55
|
-
end
|
56
|
-
|
57
|
-
new resolve_order: resolve_order, result_id: result_id, requests: requests
|
58
|
-
end
|
59
|
-
|
60
|
-
def initialize(requests:, resolve_order:, result_id:)
|
61
|
-
@resolve_order = resolve_order
|
62
|
-
@requests = requests
|
63
|
-
@result_id = result_id
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
# Represents a filter for a result set
|
68
|
-
class Request
|
69
|
-
attr_reader :constraints, :class_tag
|
70
|
-
|
71
|
-
def self.parse(polar, parsed_json)
|
72
|
-
@polar = polar
|
73
|
-
constraints = parsed_json['constraints'].map do |con|
|
74
|
-
Filter.parse polar, con
|
75
|
-
end
|
76
|
-
class_tag = parsed_json['class_tag']
|
77
|
-
|
78
|
-
new(constraints: constraints, class_tag: class_tag)
|
79
|
-
end
|
80
|
-
|
81
|
-
def ground(results) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/PerceivedComplexity
|
82
|
-
xrefs, rest = constraints.partition do |c|
|
83
|
-
c.value.is_a?(Ref) and !c.value.result_id.nil?
|
84
|
-
end
|
85
|
-
|
86
|
-
yrefs, nrefs = xrefs.partition { |r| %w[In Eq].include? r.kind }
|
87
|
-
[[yrefs, 'In'], [nrefs, 'Nin']].each do |refs, kind|
|
88
|
-
refs.group_by { |f| f.value.result_id }.each do |rid, fils|
|
89
|
-
if fils.length > 1
|
90
|
-
value = results[rid].map { |r| fils.map { |f| GETATTR[r, f.value.field] } }
|
91
|
-
field = fils.map(&:field)
|
92
|
-
rest.push(Filter.new(kind: kind, value: value, field: field))
|
93
|
-
else
|
94
|
-
fil = fils[0]
|
95
|
-
field = fil.value.field
|
96
|
-
value = results[rid].map { |r| field.nil? ? r : r.send(field) }
|
97
|
-
rest.push(Filter.new(kind: kind, field: fil.field, value: value))
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
rest
|
102
|
-
end
|
103
|
-
|
104
|
-
def initialize(constraints:, class_tag:)
|
105
|
-
@constraints = constraints
|
106
|
-
@class_tag = class_tag
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
7
|
# Represents relationships between resources, eg. one-one or one-many
|
112
8
|
class Relation
|
113
9
|
attr_reader :kind, :other_type, :my_field, :other_field
|
@@ -124,92 +20,6 @@ module Oso
|
|
124
20
|
@other_field = other_field
|
125
21
|
end
|
126
22
|
end
|
127
|
-
|
128
|
-
# Represents field-field relationships on one resource.
|
129
|
-
class Field
|
130
|
-
attr_reader :field
|
131
|
-
|
132
|
-
def initialize(field:)
|
133
|
-
@field = field
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
# Represents field-field relationships on different resources.
|
138
|
-
class Ref
|
139
|
-
attr_reader :field, :result_id
|
140
|
-
|
141
|
-
def initialize(field:, result_id:)
|
142
|
-
@field = field
|
143
|
-
@result_id = result_id
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
# Represents a condition that must hold on a resource.
|
148
|
-
class Filter
|
149
|
-
attr_reader :kind, :field, :value
|
150
|
-
|
151
|
-
CHECKS = {
|
152
|
-
'Eq' => ->(a, b) { a == b },
|
153
|
-
'In' => ->(a, b) { b.include? a },
|
154
|
-
'Neq' => ->(a, b) { a != b },
|
155
|
-
'Nin' => ->(a, b) { !b.include?(a) },
|
156
|
-
'Contains' => ->(a, b) { a.include? b }
|
157
|
-
}.freeze
|
158
|
-
|
159
|
-
# Create a new predicate for data filtering.
|
160
|
-
# @param kind [String] Represents a condition. One of "Eq", "Neq", "In", "Contains".
|
161
|
-
# @param field The field the condition applies to.
|
162
|
-
# @param value The value with which to compare the field according to the condition.
|
163
|
-
def initialize(kind:, field:, value:)
|
164
|
-
@kind = kind
|
165
|
-
@field = field
|
166
|
-
@value = value
|
167
|
-
end
|
168
|
-
|
169
|
-
def ground(results)
|
170
|
-
return unless value.is_a? Ref
|
171
|
-
|
172
|
-
ref = value
|
173
|
-
@value = results[ref.result_id]
|
174
|
-
@value = value.map { |v| v.send ref.field } unless ref.field.nil?
|
175
|
-
end
|
176
|
-
|
177
|
-
def check(item) # rubocop:disable Metrics/AbcSize
|
178
|
-
val = value.is_a?(Field) ? item.send(value.field) : value
|
179
|
-
item = if field.nil?
|
180
|
-
item
|
181
|
-
elsif field.is_a? Array
|
182
|
-
field.map { |f| GETATTR[item, f] }
|
183
|
-
else
|
184
|
-
item.send field
|
185
|
-
end
|
186
|
-
CHECKS[@kind][item, val]
|
187
|
-
end
|
188
|
-
|
189
|
-
def self.parse(polar, constraint) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
190
|
-
kind = constraint['kind']
|
191
|
-
field = constraint['field']
|
192
|
-
value = constraint['value']
|
193
|
-
|
194
|
-
value_kind = value.keys.first
|
195
|
-
value = value[value_kind]
|
196
|
-
|
197
|
-
case value_kind
|
198
|
-
when 'Term'
|
199
|
-
value = polar.host.to_ruby value
|
200
|
-
when 'Ref'
|
201
|
-
child_field = value['field']
|
202
|
-
result_id = value['result_id']
|
203
|
-
value = Ref.new field: child_field, result_id: result_id
|
204
|
-
when 'Field'
|
205
|
-
value = Field.new field: value
|
206
|
-
else
|
207
|
-
raise "Unknown value kind `#{value_kind}`"
|
208
|
-
end
|
209
|
-
|
210
|
-
new kind: kind, field: field, value: value
|
211
|
-
end
|
212
|
-
end
|
213
23
|
end
|
214
24
|
end
|
215
25
|
end
|
data/lib/oso/polar/errors.rb
CHANGED
data/lib/oso/polar/host.rb
CHANGED
@@ -319,17 +319,24 @@ module Oso
|
|
319
319
|
end
|
320
320
|
else
|
321
321
|
instance_id = nil
|
322
|
-
|
323
|
-
|
324
|
-
# only pass class_repr for registered types
|
322
|
+
class_id = nil
|
325
323
|
class_repr = nil
|
326
|
-
|
324
|
+
# id=class_id,
|
325
|
+
|
326
|
+
# pass `class_id` & `class_repr` for registered types
|
327
|
+
if value.is_a?(Class) && types.key?(value)
|
328
|
+
instance_id = class_id = types[value].id
|
329
|
+
elsif types.key?(value.class)
|
330
|
+
class_id = types[value.class].id
|
331
|
+
class_repr = types[value.class].name
|
332
|
+
end
|
327
333
|
|
328
334
|
{
|
329
335
|
'ExternalInstance' => {
|
330
336
|
'instance_id' => cache_instance(value, id: instance_id),
|
331
337
|
'repr' => nil,
|
332
|
-
'class_repr' => class_repr
|
338
|
+
'class_repr' => class_repr,
|
339
|
+
'class_id' => class_id
|
333
340
|
}
|
334
341
|
}
|
335
342
|
end
|
@@ -407,10 +414,6 @@ module Oso
|
|
407
414
|
get_instance(Regexp.last_match[1].to_i).to_s
|
408
415
|
end
|
409
416
|
end
|
410
|
-
|
411
|
-
def use_new_data_filtering?
|
412
|
-
!adapter.nil?
|
413
|
-
end
|
414
417
|
end
|
415
418
|
end
|
416
419
|
end
|
data/lib/oso/polar/polar.rb
CHANGED
@@ -217,6 +217,7 @@ module Oso
|
|
217
217
|
exec_query: exec_query || maybe_mtd(cls, :exec_query)
|
218
218
|
)
|
219
219
|
register_constant(cls, name: name)
|
220
|
+
host.register_mros
|
220
221
|
end
|
221
222
|
|
222
223
|
# Register a Ruby object with Polar.
|
@@ -277,13 +278,6 @@ module Oso
|
|
277
278
|
host.adapter.build_query filter
|
278
279
|
end
|
279
280
|
|
280
|
-
def old_authorized_query(actor, action, resource_cls)
|
281
|
-
results = partial_query(actor, action, resource_cls)
|
282
|
-
::Oso::Polar::DataFiltering::FilterPlan
|
283
|
-
.parse(self, results, class_to_name(resource_cls))
|
284
|
-
.build_query
|
285
|
-
end
|
286
|
-
|
287
281
|
# handle Isa constraints in a partial query
|
288
282
|
def prefilter_isas(key, val) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
289
283
|
# this will usually be the case! sometimes not, if it's an instance.
|
@@ -343,7 +337,6 @@ module Oso
|
|
343
337
|
# Register MROs, load Polar code, and check inline queries.
|
344
338
|
# @param sources [Array<Source>] Polar sources to load.
|
345
339
|
def load_sources(sources)
|
346
|
-
host.register_mros
|
347
340
|
ffi_polar.load(sources)
|
348
341
|
check_inline_queries
|
349
342
|
end
|
data/lib/oso/polar/query.rb
CHANGED
@@ -245,31 +245,22 @@ module Oso
|
|
245
245
|
def handle_relationship(call_id, instance, rel) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
246
246
|
typ = host.types[rel.other_type]
|
247
247
|
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
res = host.adapter.execute_query host.adapter.build_query(filter)
|
265
|
-
else
|
266
|
-
constraint = ::Oso::Polar::DataFiltering::Filter.new(
|
267
|
-
kind: 'Eq',
|
268
|
-
field: rel.other_field,
|
269
|
-
value: instance.send(rel.my_field)
|
270
|
-
)
|
271
|
-
res = typ.exec_query[typ.build_query[[constraint]]]
|
272
|
-
end
|
248
|
+
cls = typ.klass.get
|
249
|
+
|
250
|
+
condition = ::Oso::Polar::Data::Filter::Condition.new(
|
251
|
+
::Oso::Polar::Data::Filter::Projection.new(cls, rel.other_field),
|
252
|
+
'Eq',
|
253
|
+
instance.send(rel.my_field)
|
254
|
+
)
|
255
|
+
|
256
|
+
filter = ::Oso::Polar::Data::Filter.new(
|
257
|
+
model: cls,
|
258
|
+
relations: [],
|
259
|
+
conditions: [[condition]],
|
260
|
+
types: host.types
|
261
|
+
)
|
262
|
+
|
263
|
+
res = host.adapter.execute_query host.adapter.build_query(filter)
|
273
264
|
|
274
265
|
if rel.kind == 'one'
|
275
266
|
raise "multiple parents: #{res}" unless res.length == 1
|
data/lib/oso/version.rb
CHANGED
data/lib/oso.rb
CHANGED
@@ -8,7 +8,6 @@ require 'oso/version'
|
|
8
8
|
# Top-level namespace for Oso authorization library.
|
9
9
|
module Oso
|
10
10
|
Relation = ::Oso::Polar::DataFiltering::Relation
|
11
|
-
Filter = ::Oso::Polar::DataFiltering::Filter
|
12
11
|
|
13
12
|
def self.new(not_found_error: NotFoundError, forbidden_error: ForbiddenError, read_action: 'read')
|
14
13
|
::Oso::Oso.new(not_found_error: not_found_error, forbidden_error: forbidden_error, read_action: read_action)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oso-oso
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.26.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oso Security, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|