oso-cloud 1.0.0 → 1.1.0
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/.rubocop.yml +5 -0
- data/Gemfile.lock +2 -2
- data/lib/oso/api.rb +114 -97
- data/lib/oso/helpers.rb +30 -15
- data/lib/oso/oso.rb +71 -52
- data/lib/oso/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0afcafa1d502f02d19ed93b21ad4606eaf59056114c496c5a9d8b72f55994c05
|
4
|
+
data.tar.gz: e9bc9ad6450429c9d2c5a1574e4451316e1f043b666da2cfbdc3ae69e1e449cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8e837b4bd3d8c16aa1859c93453756a35c844c5371ab9cad18d2afb88748dfc413993be213da260f73bff9d9b83ef28a734e2cfd994e706220c92c4d2ce62df4
|
7
|
+
data.tar.gz: 179d6e9639dd2cf447c4c71c6f888b5474f633ad1f323f15b46a8729e8acb86419e2e5b4f628628a4c8655d874881ee6e938d379dbd794f68ea6a18b593c580d
|
data/.rubocop.yml
ADDED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
oso-cloud (1.
|
4
|
+
oso-cloud (1.1.0)
|
5
5
|
faraday (~> 2.5.2)
|
6
6
|
faraday-retry (~> 2.0.0)
|
7
7
|
|
@@ -11,7 +11,7 @@ GEM
|
|
11
11
|
faraday (2.5.2)
|
12
12
|
faraday-net_http (>= 2.0, < 3.1)
|
13
13
|
ruby2_keywords (>= 0.0.4)
|
14
|
-
faraday-net_http (3.0.
|
14
|
+
faraday-net_http (3.0.2)
|
15
15
|
faraday-retry (2.0.0)
|
16
16
|
faraday (~> 2.0)
|
17
17
|
minitest (5.15.0)
|
data/lib/oso/api.rb
CHANGED
@@ -18,18 +18,15 @@ module OsoCloud
|
|
18
18
|
end
|
19
19
|
|
20
20
|
# @!visibility private
|
21
|
-
class ApiError
|
22
|
-
attr_reader :message
|
23
|
-
|
21
|
+
class ApiError < StandardError
|
24
22
|
def initialize(message:)
|
25
|
-
|
23
|
+
super(message)
|
26
24
|
end
|
27
25
|
end
|
28
26
|
|
29
27
|
# @!visibility private
|
30
28
|
class Policy
|
31
|
-
attr_reader :filename
|
32
|
-
attr_reader :src
|
29
|
+
attr_reader :filename, :src
|
33
30
|
|
34
31
|
def initialize(filename:, src:)
|
35
32
|
@filename = filename
|
@@ -42,29 +39,27 @@ module OsoCloud
|
|
42
39
|
attr_reader :policy
|
43
40
|
|
44
41
|
def initialize(policy:)
|
45
|
-
if policy.is_a? Policy
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
42
|
+
@policy = if policy.is_a? Policy
|
43
|
+
policy
|
44
|
+
else
|
45
|
+
Policy.new(**policy)
|
46
|
+
end
|
50
47
|
end
|
51
48
|
end
|
52
49
|
|
53
50
|
# @!visibility private
|
54
51
|
class Fact
|
55
|
-
attr_reader :predicate
|
56
|
-
attr_reader :args
|
52
|
+
attr_reader :predicate, :args
|
57
53
|
|
58
54
|
def initialize(predicate:, args:)
|
59
55
|
@predicate = predicate
|
60
|
-
@args = args.map { |v|
|
56
|
+
@args = args.map { |v| (v.is_a? Value) ? v : Value.new(**v) }
|
61
57
|
end
|
62
58
|
end
|
63
59
|
|
64
60
|
# @!visibility private
|
65
61
|
class Value
|
66
|
-
attr_reader :type
|
67
|
-
attr_reader :id
|
62
|
+
attr_reader :type, :id
|
68
63
|
|
69
64
|
def initialize(type:, id:)
|
70
65
|
@type = type
|
@@ -74,12 +69,11 @@ module OsoCloud
|
|
74
69
|
|
75
70
|
# @!visibility private
|
76
71
|
class Bulk
|
77
|
-
attr_reader :delete
|
78
|
-
attr_reader :tell
|
72
|
+
attr_reader :delete, :tell
|
79
73
|
|
80
74
|
def initialize(delete:, tell:)
|
81
|
-
@delete = delete.map { |v|
|
82
|
-
@tell = tell.map { |v|
|
75
|
+
@delete = delete.map { |v| (v.is_a? Fact) ? v : Fact.new(**v) }
|
76
|
+
@tell = tell.map { |v| (v.is_a? Fact) ? v : Fact.new(**v) }
|
83
77
|
end
|
84
78
|
end
|
85
79
|
|
@@ -94,12 +88,7 @@ module OsoCloud
|
|
94
88
|
|
95
89
|
# @!visibility private
|
96
90
|
class AuthorizeQuery
|
97
|
-
attr_reader :actor_type
|
98
|
-
attr_reader :actor_id
|
99
|
-
attr_reader :action
|
100
|
-
attr_reader :resource_type
|
101
|
-
attr_reader :resource_id
|
102
|
-
attr_reader :context_facts
|
91
|
+
attr_reader :actor_type, :actor_id, :action, :resource_type, :resource_id, :context_facts
|
103
92
|
|
104
93
|
def initialize(actor_type:, actor_id:, action:, resource_type:, resource_id:, context_facts:)
|
105
94
|
@actor_type = actor_type
|
@@ -107,7 +96,7 @@ module OsoCloud
|
|
107
96
|
@action = action
|
108
97
|
@resource_type = resource_type
|
109
98
|
@resource_id = resource_id
|
110
|
-
@context_facts = context_facts.map { |v|
|
99
|
+
@context_facts = context_facts.map { |v| (v.is_a? Fact) ? v : Fact.new(**v) }
|
111
100
|
end
|
112
101
|
end
|
113
102
|
|
@@ -116,24 +105,20 @@ module OsoCloud
|
|
116
105
|
attr_reader :results
|
117
106
|
|
118
107
|
def initialize(results:)
|
119
|
-
@results = results.map { |v|
|
108
|
+
@results = results.map { |v| (v.is_a? Value) ? v : Value.new(**v) }
|
120
109
|
end
|
121
110
|
end
|
122
111
|
|
123
112
|
# @!visibility private
|
124
113
|
class AuthorizeResourcesQuery
|
125
|
-
attr_reader :actor_type
|
126
|
-
attr_reader :actor_id
|
127
|
-
attr_reader :action
|
128
|
-
attr_reader :resources
|
129
|
-
attr_reader :context_facts
|
114
|
+
attr_reader :actor_type, :actor_id, :action, :resources, :context_facts
|
130
115
|
|
131
116
|
def initialize(actor_type:, actor_id:, action:, resources:, context_facts:)
|
132
117
|
@actor_type = actor_type
|
133
118
|
@actor_id = actor_id
|
134
119
|
@action = action
|
135
|
-
@resources = resources.map { |v|
|
136
|
-
@context_facts = context_facts.map { |v|
|
120
|
+
@resources = resources.map { |v| (v.is_a? Value) ? v : Value.new(**v) }
|
121
|
+
@context_facts = context_facts.map { |v| (v.is_a? Fact) ? v : Fact.new(**v) }
|
137
122
|
end
|
138
123
|
end
|
139
124
|
|
@@ -148,18 +133,14 @@ module OsoCloud
|
|
148
133
|
|
149
134
|
# @!visibility private
|
150
135
|
class ListQuery
|
151
|
-
attr_reader :actor_type
|
152
|
-
attr_reader :actor_id
|
153
|
-
attr_reader :action
|
154
|
-
attr_reader :resource_type
|
155
|
-
attr_reader :context_facts
|
136
|
+
attr_reader :actor_type, :actor_id, :action, :resource_type, :context_facts
|
156
137
|
|
157
138
|
def initialize(actor_type:, actor_id:, action:, resource_type:, context_facts:)
|
158
139
|
@actor_type = actor_type
|
159
140
|
@actor_id = actor_id
|
160
141
|
@action = action
|
161
142
|
@resource_type = resource_type
|
162
|
-
@context_facts = context_facts.map { |v|
|
143
|
+
@context_facts = context_facts.map { |v| (v.is_a? Fact) ? v : Fact.new(**v) }
|
163
144
|
end
|
164
145
|
end
|
165
146
|
|
@@ -174,18 +155,14 @@ module OsoCloud
|
|
174
155
|
|
175
156
|
# @!visibility private
|
176
157
|
class ActionsQuery
|
177
|
-
attr_reader :actor_type
|
178
|
-
attr_reader :actor_id
|
179
|
-
attr_reader :resource_type
|
180
|
-
attr_reader :resource_id
|
181
|
-
attr_reader :context_facts
|
158
|
+
attr_reader :actor_type, :actor_id, :resource_type, :resource_id, :context_facts
|
182
159
|
|
183
160
|
def initialize(actor_type:, actor_id:, resource_type:, resource_id:, context_facts:)
|
184
161
|
@actor_type = actor_type
|
185
162
|
@actor_id = actor_id
|
186
163
|
@resource_type = resource_type
|
187
164
|
@resource_id = resource_id
|
188
|
-
@context_facts = context_facts.map { |v|
|
165
|
+
@context_facts = context_facts.map { |v| (v.is_a? Fact) ? v : Fact.new(**v) }
|
189
166
|
end
|
190
167
|
end
|
191
168
|
|
@@ -194,30 +171,27 @@ module OsoCloud
|
|
194
171
|
attr_reader :results
|
195
172
|
|
196
173
|
def initialize(results:)
|
197
|
-
@results = results.map { |v|
|
174
|
+
@results = results.map { |v| (v.is_a? Fact) ? v : Fact.new(**v) }
|
198
175
|
end
|
199
176
|
end
|
200
177
|
|
201
178
|
# @!visibility private
|
202
179
|
class Query
|
203
|
-
attr_reader :fact
|
204
|
-
attr_reader :context_facts
|
180
|
+
attr_reader :fact, :context_facts
|
205
181
|
|
206
182
|
def initialize(fact:, context_facts:)
|
207
|
-
if fact.is_a? Fact
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
@context_facts = context_facts.map { |v|
|
183
|
+
@fact = if fact.is_a? Fact
|
184
|
+
fact
|
185
|
+
else
|
186
|
+
Fact.new(**fact)
|
187
|
+
end
|
188
|
+
@context_facts = context_facts.map { |v| (v.is_a? Fact) ? v : Fact.new(**v) }
|
213
189
|
end
|
214
190
|
end
|
215
191
|
|
216
192
|
# @!visibility private
|
217
193
|
class StatsResult
|
218
|
-
attr_reader :num_roles
|
219
|
-
attr_reader :num_relations
|
220
|
-
attr_reader :num_facts
|
194
|
+
attr_reader :num_roles, :num_relations, :num_facts
|
221
195
|
|
222
196
|
def initialize(num_roles:, num_relations:, num_facts:)
|
223
197
|
@num_roles = num_roles
|
@@ -226,31 +200,61 @@ module OsoCloud
|
|
226
200
|
end
|
227
201
|
end
|
228
202
|
|
229
|
-
|
230
203
|
# @!visibility private
|
231
204
|
class Api
|
232
|
-
def initialize(url: 'https://cloud.osohq.com', api_key: nil)
|
205
|
+
def initialize(url: 'https://cloud.osohq.com', api_key: nil, options: nil)
|
233
206
|
@url = url
|
234
207
|
@connection = Faraday.new(url: url) do |faraday|
|
208
|
+
faraday.request :json
|
209
|
+
|
210
|
+
# responses are processed in reverse order; this stack implies the
|
211
|
+
# retries are attempted before an error is raised, and the json
|
212
|
+
# parser is only applied if there are no errors
|
213
|
+
faraday.response :json, preserve_raw: true
|
214
|
+
faraday.response :raise_error
|
235
215
|
faraday.request :retry, {
|
236
|
-
max:
|
237
|
-
interval: 0.
|
238
|
-
interval_randomness: 0.
|
216
|
+
max: (options && options[:max_retries]) || 10,
|
217
|
+
interval: 0.01,
|
218
|
+
interval_randomness: 0.005,
|
219
|
+
max_interval: 1,
|
239
220
|
backoff_factor: 2,
|
240
221
|
retry_statuses: [429, 500, 502, 503, 504],
|
222
|
+
# ensure authorize and related check functions are retried because
|
223
|
+
# they are POST requests, which are not retried automatically
|
224
|
+
retry_if: lambda { |env, _exc|
|
225
|
+
%w[
|
226
|
+
/api/authorize
|
227
|
+
/api/authorize_resources
|
228
|
+
/api/list
|
229
|
+
/api/actions
|
230
|
+
/api/query
|
231
|
+
].include? env.url.path
|
232
|
+
}
|
241
233
|
}
|
242
234
|
|
243
|
-
|
244
|
-
|
245
|
-
|
235
|
+
if options && options[:test_adapter]
|
236
|
+
faraday.adapter :test do |stub|
|
237
|
+
stub.post(options[:test_adapter][:path]) do |_env|
|
238
|
+
options[:test_adapter][:func].call
|
239
|
+
end
|
240
|
+
stub.get(options[:test_adapter][:path]) do |_env|
|
241
|
+
options[:test_adapter][:func].call
|
242
|
+
end
|
243
|
+
stub.delete(options[:test_adapter][:path]) do |_env|
|
244
|
+
options[:test_adapter][:func].call
|
245
|
+
end
|
246
|
+
end
|
247
|
+
else
|
248
|
+
faraday.adapter :net_http
|
249
|
+
end
|
246
250
|
end
|
247
251
|
@api_key = api_key
|
248
252
|
end
|
249
253
|
|
250
|
-
def get_policy
|
254
|
+
def get_policy
|
251
255
|
params = {}
|
252
256
|
data = nil
|
253
|
-
url =
|
257
|
+
url = '/policy'
|
254
258
|
result = GET(url, params, data)
|
255
259
|
GetPolicyResult.new(**result)
|
256
260
|
end
|
@@ -258,7 +262,7 @@ module OsoCloud
|
|
258
262
|
def post_policy(data)
|
259
263
|
params = {}
|
260
264
|
data = OsoCloud::Helpers.to_hash(data)
|
261
|
-
url =
|
265
|
+
url = '/policy'
|
262
266
|
result = POST(url, params, data)
|
263
267
|
ApiResult.new(**result)
|
264
268
|
end
|
@@ -266,7 +270,7 @@ module OsoCloud
|
|
266
270
|
def post_facts(data)
|
267
271
|
params = {}
|
268
272
|
data = OsoCloud::Helpers.to_hash(data)
|
269
|
-
url =
|
273
|
+
url = '/facts'
|
270
274
|
result = POST(url, params, data)
|
271
275
|
Fact.new(**result)
|
272
276
|
end
|
@@ -274,7 +278,7 @@ module OsoCloud
|
|
274
278
|
def delete_facts(data)
|
275
279
|
params = {}
|
276
280
|
data = OsoCloud::Helpers.to_hash(data)
|
277
|
-
url =
|
281
|
+
url = '/facts'
|
278
282
|
result = DELETE(url, params, data)
|
279
283
|
ApiResult.new(**result)
|
280
284
|
end
|
@@ -282,7 +286,7 @@ module OsoCloud
|
|
282
286
|
def post_bulk_load(data)
|
283
287
|
params = {}
|
284
288
|
data = OsoCloud::Helpers.to_hash(data)
|
285
|
-
url =
|
289
|
+
url = '/bulk_load'
|
286
290
|
result = POST(url, params, data)
|
287
291
|
ApiResult.new(**result)
|
288
292
|
end
|
@@ -290,7 +294,7 @@ module OsoCloud
|
|
290
294
|
def post_bulk_delete(data)
|
291
295
|
params = {}
|
292
296
|
data = OsoCloud::Helpers.to_hash(data)
|
293
|
-
url =
|
297
|
+
url = '/bulk_delete'
|
294
298
|
result = POST(url, params, data)
|
295
299
|
ApiResult.new(**result)
|
296
300
|
end
|
@@ -298,7 +302,7 @@ module OsoCloud
|
|
298
302
|
def post_bulk(data)
|
299
303
|
params = {}
|
300
304
|
data = OsoCloud::Helpers.to_hash(data)
|
301
|
-
url =
|
305
|
+
url = '/bulk'
|
302
306
|
result = POST(url, params, data)
|
303
307
|
ApiResult.new(**result)
|
304
308
|
end
|
@@ -306,7 +310,7 @@ module OsoCloud
|
|
306
310
|
def post_authorize(data)
|
307
311
|
params = {}
|
308
312
|
data = OsoCloud::Helpers.to_hash(data)
|
309
|
-
url =
|
313
|
+
url = '/authorize'
|
310
314
|
result = POST(url, params, data)
|
311
315
|
AuthorizeResult.new(**result)
|
312
316
|
end
|
@@ -314,7 +318,7 @@ module OsoCloud
|
|
314
318
|
def post_authorize_resources(data)
|
315
319
|
params = {}
|
316
320
|
data = OsoCloud::Helpers.to_hash(data)
|
317
|
-
url =
|
321
|
+
url = '/authorize_resources'
|
318
322
|
result = POST(url, params, data)
|
319
323
|
AuthorizeResourcesResult.new(**result)
|
320
324
|
end
|
@@ -322,7 +326,7 @@ module OsoCloud
|
|
322
326
|
def post_list(data)
|
323
327
|
params = {}
|
324
328
|
data = OsoCloud::Helpers.to_hash(data)
|
325
|
-
url =
|
329
|
+
url = '/list'
|
326
330
|
result = POST(url, params, data)
|
327
331
|
ListResult.new(**result)
|
328
332
|
end
|
@@ -330,7 +334,7 @@ module OsoCloud
|
|
330
334
|
def post_actions(data)
|
331
335
|
params = {}
|
332
336
|
data = OsoCloud::Helpers.to_hash(data)
|
333
|
-
url =
|
337
|
+
url = '/actions'
|
334
338
|
result = POST(url, params, data)
|
335
339
|
ActionsResult.new(**result)
|
336
340
|
end
|
@@ -338,33 +342,34 @@ module OsoCloud
|
|
338
342
|
def post_query(data)
|
339
343
|
params = {}
|
340
344
|
data = OsoCloud::Helpers.to_hash(data)
|
341
|
-
url =
|
345
|
+
url = '/query'
|
342
346
|
result = POST(url, params, data)
|
343
347
|
QueryResult.new(**result)
|
344
348
|
end
|
345
349
|
|
346
|
-
def get_stats
|
350
|
+
def get_stats
|
347
351
|
params = {}
|
348
352
|
data = nil
|
349
|
-
url =
|
353
|
+
url = '/stats'
|
350
354
|
result = GET(url, params, data)
|
351
355
|
StatsResult.new(**result)
|
352
356
|
end
|
353
357
|
|
354
|
-
def clear_data
|
358
|
+
def clear_data
|
355
359
|
params = {}
|
356
360
|
data = nil
|
357
|
-
url =
|
361
|
+
url = '/clear_data'
|
358
362
|
result = POST(url, params, data)
|
359
363
|
ApiResult.new(**result)
|
360
364
|
end
|
361
365
|
|
362
|
-
|
363
366
|
# hard-coded, not generated
|
364
367
|
def get_facts(predicate, args)
|
365
368
|
params = {}
|
366
|
-
params[
|
369
|
+
params['predicate'] = predicate
|
367
370
|
args.each_with_index do |arg, i|
|
371
|
+
next if arg.nil?
|
372
|
+
|
368
373
|
arg_query = OsoCloud::Helpers.extract_arg_query(arg)
|
369
374
|
if arg_query
|
370
375
|
params["args.#{i}.type"] = arg_query.type
|
@@ -372,24 +377,26 @@ module OsoCloud
|
|
372
377
|
end
|
373
378
|
end
|
374
379
|
data = nil
|
375
|
-
url =
|
380
|
+
url = '/facts'
|
376
381
|
result = GET(url, params, data)
|
377
382
|
result.map { |v| Fact.new(**v) }
|
378
383
|
end
|
379
384
|
|
380
|
-
def headers
|
385
|
+
def headers
|
381
386
|
{
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
+
'Authorization' => format('Bearer %s', @api_key),
|
388
|
+
'User-Agent' => 'Oso Cloud (ruby)',
|
389
|
+
Accept: 'application/json',
|
390
|
+
'Content-Type': 'application/json',
|
391
|
+
'X-OsoApiVersion': '0'
|
387
392
|
}
|
388
393
|
end
|
389
394
|
|
390
|
-
def GET(path, params,
|
391
|
-
response = @connection.get("api#{path}", params, headers
|
395
|
+
def GET(path, params, _body)
|
396
|
+
response = @connection.get("api#{path}", params, headers)
|
392
397
|
handle_faraday_response response
|
398
|
+
rescue Faraday::Error => e
|
399
|
+
handle_faraday_error e
|
393
400
|
end
|
394
401
|
|
395
402
|
def POST(path, params, body)
|
@@ -397,6 +404,8 @@ module OsoCloud
|
|
397
404
|
req.params = params
|
398
405
|
end
|
399
406
|
handle_faraday_response response
|
407
|
+
rescue Faraday::Error => e
|
408
|
+
handle_faraday_error e
|
400
409
|
end
|
401
410
|
|
402
411
|
def DELETE(path, params, body)
|
@@ -404,13 +413,21 @@ module OsoCloud
|
|
404
413
|
req.body = body
|
405
414
|
end
|
406
415
|
handle_faraday_response response
|
416
|
+
rescue Faraday::Error => e
|
417
|
+
handle_faraday_error e
|
407
418
|
end
|
408
419
|
|
409
420
|
def handle_faraday_response(response)
|
410
|
-
# TODO:(@patrickod) refactor duplicative JSON parsing
|
421
|
+
# TODO: (@patrickod) refactor duplicative JSON parsing
|
411
422
|
JSON.parse(response.env[:raw_body], symbolize_names: true)
|
412
423
|
end
|
413
|
-
end
|
414
424
|
|
425
|
+
def handle_faraday_error(error)
|
426
|
+
err = JSON.parse(error.response[:body], symbolize_names: true)
|
427
|
+
raise ApiError.new(**err)
|
428
|
+
rescue JSON::ParserError => e
|
429
|
+
raise ApiError.new(message: e.message)
|
430
|
+
end
|
431
|
+
end
|
415
432
|
end
|
416
433
|
end
|
data/lib/oso/helpers.rb
CHANGED
@@ -3,9 +3,9 @@ module OsoCloud
|
|
3
3
|
module Helpers
|
4
4
|
# @!visibility private
|
5
5
|
def self.extract_value(x)
|
6
|
-
return OsoCloud::Core::Value.new(type:
|
6
|
+
return OsoCloud::Core::Value.new(type: 'String', id: x) if x.is_a? String
|
7
7
|
|
8
|
-
return nil if x.nil?
|
8
|
+
return OsoCloud::Core::Value.new(type: nil, id: nil) if x.nil?
|
9
9
|
|
10
10
|
type = (x.type.nil? ? nil : x.type.to_s)
|
11
11
|
id = (x.id.nil? ? nil : x.id.to_s)
|
@@ -14,17 +14,33 @@ module OsoCloud
|
|
14
14
|
|
15
15
|
# @!visibility private
|
16
16
|
def self.extract_arg_query(x)
|
17
|
-
|
17
|
+
extract_value(x)
|
18
18
|
end
|
19
19
|
|
20
20
|
# @!visibility private
|
21
21
|
def self.param_to_fact(predicate, args)
|
22
|
-
OsoCloud::Core::Fact.new(predicate: predicate, args: args.map { |a|
|
22
|
+
OsoCloud::Core::Fact.new(predicate: predicate, args: args.map { |a| extract_value(a) })
|
23
23
|
end
|
24
24
|
|
25
25
|
# @!visibility private
|
26
26
|
def self.params_to_facts(facts)
|
27
|
-
facts.map { |predicate, *args|
|
27
|
+
facts.map { |predicate, *args| param_to_fact(predicate, args) }
|
28
|
+
end
|
29
|
+
|
30
|
+
# @!visibility private
|
31
|
+
def self.facts_to_params(facts)
|
32
|
+
facts.map do |f|
|
33
|
+
name = f.predicate
|
34
|
+
args = f.args.map do |a|
|
35
|
+
v = from_value(a)
|
36
|
+
if v.is_a? Hash
|
37
|
+
OsoCloud::Value.new(type: v[:type], id: v[:id])
|
38
|
+
else
|
39
|
+
v
|
40
|
+
end
|
41
|
+
end
|
42
|
+
[name, *args]
|
43
|
+
end
|
28
44
|
end
|
29
45
|
|
30
46
|
def self.from_value(value)
|
@@ -34,25 +50,24 @@ module OsoCloud
|
|
34
50
|
else
|
35
51
|
{ type: value.type }
|
36
52
|
end
|
53
|
+
elsif value.type == 'String'
|
54
|
+
value.id
|
37
55
|
else
|
38
|
-
|
39
|
-
value.id
|
40
|
-
else
|
41
|
-
{ id: value.id, type: value.type }
|
42
|
-
end
|
56
|
+
{ id: value.id, type: value.type }
|
43
57
|
end
|
44
58
|
end
|
45
59
|
|
46
60
|
# @!visibility private
|
47
61
|
def self.to_hash(o)
|
48
|
-
return o.map { |v|
|
62
|
+
return o.map { |v| to_hash(v) } if o.is_a? Array
|
49
63
|
return o if o.instance_variables.empty?
|
64
|
+
|
50
65
|
hash = {}
|
51
|
-
o.instance_variables.each
|
52
|
-
v = var.to_s.delete(
|
66
|
+
o.instance_variables.each do |var|
|
67
|
+
v = var.to_s.delete('@')
|
53
68
|
value = o.send(v)
|
54
|
-
hash[v] =
|
55
|
-
|
69
|
+
hash[v] = to_hash(value)
|
70
|
+
end
|
56
71
|
hash
|
57
72
|
end
|
58
73
|
end
|
data/lib/oso/oso.rb
CHANGED
@@ -10,11 +10,9 @@ require 'oso/helpers'
|
|
10
10
|
# For more detailed documentation, see
|
11
11
|
# https://www.osohq.com/docs/reference/client-apis/ruby
|
12
12
|
module OsoCloud
|
13
|
-
|
14
13
|
# Represents an object in your application, with a type and id.
|
15
14
|
# Both "type" and "id" should be strings.
|
16
|
-
Value = Struct
|
17
|
-
|
15
|
+
Value = Struct.new(:type, :id, keyword_init: true) do
|
18
16
|
def to_api_value
|
19
17
|
OsoCloud::Helpers.extract_value(self)
|
20
18
|
end
|
@@ -43,7 +41,7 @@ module OsoCloud
|
|
43
41
|
# @param policy [String]
|
44
42
|
# @return [nil]
|
45
43
|
def policy(policy)
|
46
|
-
@api.post_policy(OsoCloud::Core::Policy.new(src: policy, filename:
|
44
|
+
@api.post_policy(OsoCloud::Core::Policy.new(src: policy, filename: ''))
|
47
45
|
nil
|
48
46
|
end
|
49
47
|
|
@@ -58,18 +56,18 @@ module OsoCloud
|
|
58
56
|
# @param resource [OsoCloud::Value]
|
59
57
|
# @param context_facts [Array<fact>]
|
60
58
|
# @return [Boolean]
|
61
|
-
# @see Oso more information about facts
|
59
|
+
# @see Oso for more information about facts
|
62
60
|
def authorize(actor, action, resource, context_facts = [])
|
63
61
|
actor_typed_id = actor.to_api_value
|
64
62
|
resource_typed_id = resource.to_api_value
|
65
63
|
result = @api.post_authorize(OsoCloud::Core::AuthorizeQuery.new(
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
64
|
+
actor_type: actor_typed_id.type,
|
65
|
+
actor_id: actor_typed_id.id,
|
66
|
+
action: action,
|
67
|
+
resource_type: resource_typed_id.type,
|
68
|
+
resource_id: resource_typed_id.id,
|
69
|
+
context_facts: OsoCloud::Helpers.params_to_facts(context_facts)
|
70
|
+
))
|
73
71
|
result.allowed
|
74
72
|
end
|
75
73
|
|
@@ -84,7 +82,7 @@ module OsoCloud
|
|
84
82
|
# @param resources [Array<OsoCloud::Value>]
|
85
83
|
# @param context_facts [Array<fact>]
|
86
84
|
# @return [Array<OsoCloud::Value>]
|
87
|
-
# @see Oso more information about facts
|
85
|
+
# @see Oso for more information about facts
|
88
86
|
def authorize_resources(actor, action, resources, context_facts = [])
|
89
87
|
return [] if resources.nil?
|
90
88
|
return [] if resources.empty?
|
@@ -99,26 +97,23 @@ module OsoCloud
|
|
99
97
|
actor_type: actor_typed_id.type, actor_id: actor_typed_id.id,
|
100
98
|
action: action,
|
101
99
|
resources: resources_extracted,
|
102
|
-
context_facts: OsoCloud::Helpers
|
100
|
+
context_facts: OsoCloud::Helpers.params_to_facts(context_facts)
|
103
101
|
)
|
104
102
|
result = @api.post_authorize_resources(data)
|
105
103
|
|
106
104
|
return [] if result.results.empty?
|
107
105
|
|
108
|
-
results_lookup =
|
106
|
+
results_lookup = {}
|
109
107
|
result.results.each do |r|
|
110
108
|
k = key.call(r.type, r.id)
|
111
|
-
if results_lookup[k]
|
112
|
-
results_lookup[k] = true
|
113
|
-
end
|
109
|
+
results_lookup[k] = true if results_lookup[k].nil?
|
114
110
|
end
|
115
111
|
|
116
|
-
|
112
|
+
resources.select do |r|
|
117
113
|
e = r.to_api_value
|
118
114
|
exists = results_lookup[key.call(e.type, e.id)]
|
119
115
|
exists
|
120
116
|
end
|
121
|
-
results
|
122
117
|
end
|
123
118
|
|
124
119
|
##
|
@@ -132,16 +127,16 @@ module OsoCloud
|
|
132
127
|
# @param resource_type [String]
|
133
128
|
# @param context_facts [Array<fact>]
|
134
129
|
# @return [Array<String>]
|
135
|
-
# @see Oso more information about facts
|
130
|
+
# @see Oso for more information about facts
|
136
131
|
def list(actor, action, resource_type, context_facts = [])
|
137
132
|
actor_typed_id = actor.to_api_value
|
138
133
|
result = @api.post_list(OsoCloud::Core::ListQuery.new(
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
134
|
+
actor_type: actor_typed_id.type,
|
135
|
+
actor_id: actor_typed_id.id,
|
136
|
+
action: action,
|
137
|
+
resource_type: resource_type,
|
138
|
+
context_facts: OsoCloud::Helpers.params_to_facts(context_facts)
|
139
|
+
))
|
145
140
|
result.results
|
146
141
|
end
|
147
142
|
|
@@ -154,17 +149,17 @@ module OsoCloud
|
|
154
149
|
# @param resource [OsoCloud::Value]
|
155
150
|
# @param context_facts [Array<fact>]
|
156
151
|
# @return [Array<String>]
|
157
|
-
# @see Oso more information about facts
|
152
|
+
# @see Oso for more information about facts
|
158
153
|
def actions(actor, resource, context_facts = [])
|
159
154
|
actor_typed_id = actor.to_api_value
|
160
155
|
resource_typed_id = resource.to_api_value
|
161
156
|
result = @api.post_actions(OsoCloud::Core::ActionsQuery.new(
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
157
|
+
actor_type: actor_typed_id.type,
|
158
|
+
actor_id: actor_typed_id.id,
|
159
|
+
resource_type: resource_typed_id.type,
|
160
|
+
resource_id: resource_typed_id.id,
|
161
|
+
context_facts: OsoCloud::Helpers.params_to_facts(context_facts)
|
162
|
+
))
|
168
163
|
result.results
|
169
164
|
end
|
170
165
|
|
@@ -177,7 +172,7 @@ module OsoCloud
|
|
177
172
|
# @param args [*[String, OsoCloud::Value]]
|
178
173
|
# @return [nil]
|
179
174
|
def tell(name, *args)
|
180
|
-
typed_args = args.map { |a| OsoCloud::Helpers.extract_value(a)}
|
175
|
+
typed_args = args.map { |a| OsoCloud::Helpers.extract_value(a) }
|
181
176
|
@api.post_facts(OsoCloud::Core::Fact.new(predicate: name, args: typed_args))
|
182
177
|
nil
|
183
178
|
end
|
@@ -189,7 +184,7 @@ module OsoCloud
|
|
189
184
|
#
|
190
185
|
# @param facts [Array<fact>]
|
191
186
|
# @return [nil]
|
192
|
-
# @see Oso more information about facts
|
187
|
+
# @see Oso for more information about facts
|
193
188
|
def bulk_tell(facts)
|
194
189
|
@api.post_bulk_load(OsoCloud::Helpers.params_to_facts(facts))
|
195
190
|
nil
|
@@ -217,12 +212,32 @@ module OsoCloud
|
|
217
212
|
#
|
218
213
|
# @param facts [Array<fact>]
|
219
214
|
# @return [nil]
|
220
|
-
# @see Oso more information about facts
|
215
|
+
# @see Oso for more information about facts
|
221
216
|
def bulk_delete(facts)
|
222
217
|
@api.post_bulk_delete(OsoCloud::Helpers.params_to_facts(facts))
|
223
218
|
nil
|
224
219
|
end
|
225
220
|
|
221
|
+
##
|
222
|
+
# Transactionally delete and insert fact(s)
|
223
|
+
#
|
224
|
+
# Delete(s) are processed before insertion(s). nil arguments in facts to be
|
225
|
+
# deleted act as wildcards. Does not throw an error if facts to be deleted
|
226
|
+
# are not found or facts to be inserted already exist.
|
227
|
+
#
|
228
|
+
#
|
229
|
+
# Throws an OsoCloud::Core::Api exception if error returned from server.
|
230
|
+
#
|
231
|
+
# @param delete [Array<fact>]
|
232
|
+
# @param insert [Array<fact>]
|
233
|
+
# @return [nil]
|
234
|
+
# @see Oso for more information about facts
|
235
|
+
def bulk(delete: [], insert: [])
|
236
|
+
@api.post_bulk(OsoCloud::Core::Bulk.new(delete: OsoCloud::Helpers.params_to_facts(delete),
|
237
|
+
tell: OsoCloud::Helpers.params_to_facts(insert)))
|
238
|
+
nil
|
239
|
+
end
|
240
|
+
|
226
241
|
##
|
227
242
|
# List facts
|
228
243
|
#
|
@@ -233,23 +248,27 @@ module OsoCloud
|
|
233
248
|
# @param name [String]
|
234
249
|
# @param args [*[String, OsoCloud::Value, nil]]
|
235
250
|
# @return [Array<fact>]
|
236
|
-
# @see Oso more information about facts
|
251
|
+
# @see Oso for more information about facts
|
237
252
|
def get(name, *args)
|
238
|
-
@api.get_facts(name, args)
|
239
|
-
name = f.predicate
|
240
|
-
args = f.args.map do |a|
|
241
|
-
v = OsoCloud::Helpers.from_value(a)
|
242
|
-
if v.is_a? Hash
|
243
|
-
OsoCloud::Value.new(type: v[:type], id: v[:id])
|
244
|
-
else
|
245
|
-
v
|
246
|
-
end
|
247
|
-
end
|
248
|
-
[name, *args]
|
249
|
-
end
|
253
|
+
OsoCloud::Helpers.facts_to_params(@api.get_facts(name, args))
|
250
254
|
end
|
251
255
|
|
252
|
-
|
253
|
-
#
|
256
|
+
##
|
257
|
+
# List added and derived facts
|
258
|
+
#
|
259
|
+
# Lists facts that are stored in Oso Cloud in addition to derived facts
|
260
|
+
# from evaluating the policy. nil arguments operate as wildcards.
|
261
|
+
#
|
262
|
+
# @param name [String]
|
263
|
+
# @param args [Array<[String, OsoCloud::Value, nil]>]
|
264
|
+
# @param context_facts [Array<fact>]
|
265
|
+
# @return [Array<fact>]
|
266
|
+
# @see Oso for more information about facts
|
267
|
+
def query(name, *args, context_facts: [])
|
268
|
+
typed_args = args.map { |a| OsoCloud::Helpers.extract_value(a) }
|
269
|
+
result = @api.post_query(OsoCloud::Core::Query.new(fact: OsoCloud::Helpers.param_to_fact(name, typed_args),
|
270
|
+
context_facts: OsoCloud::Helpers.params_to_facts(context_facts)))
|
271
|
+
OsoCloud::Helpers.facts_to_params(result.results)
|
272
|
+
end
|
254
273
|
end
|
255
274
|
end
|
data/lib/oso/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oso-cloud
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oso Security, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-03-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -60,6 +60,7 @@ extensions: []
|
|
60
60
|
extra_rdoc_files: []
|
61
61
|
files:
|
62
62
|
- ".gitignore"
|
63
|
+
- ".rubocop.yml"
|
63
64
|
- Gemfile
|
64
65
|
- Gemfile.lock
|
65
66
|
- README.md
|