Class: OsoCloud::Oso

Inherits:
Object
  • Object
show all
Defined in:
lib/oso/oso.rb

Overview

Oso Cloud client for Ruby

About facts:

Some of these methods accept and return “fact”s. A “fact” is an array with at least one element. The first element must be a string, representing the fact’s name. Any other elements in the array, which together represent the fact’s arguments, can be “OsoCloud::Value” objects or strings.

Instance Method Summary collapse

Constructor Details

#initialize(url: 'https://cloud.osohq.com', api_key: nil, fallback_url: nil, data_bindings: nil) ⇒ Oso

Returns a new instance of Oso.



31
32
33
34
# File 'lib/oso/oso.rb', line 31

def initialize(url: 'https://cloud.osohq.com', api_key: nil, fallback_url: nil, data_bindings: nil)
  @api = OsoCloud::Core::Api.new(url: url, api_key: api_key, data_bindings: data_bindings,
                                 options: { fallback_url: fallback_url })
end

Instance Method Details

#actions(actor, resource, context_facts = []) ⇒ Array<String>

List authorized actions

Fetches a list of actions which an actor can perform on a particular resource.

Parameters:

Returns:

  • (Array<String>)

See Also:



287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/oso/oso.rb', line 287

def actions(actor, resource, context_facts = [])
  actor_typed_id = actor.to_api_value
  resource_typed_id = resource.to_api_value
  result = @api.post_actions(OsoCloud::Core::ActionsQuery.new(
                               actor_type: actor_typed_id.type,
                               actor_id: actor_typed_id.id,
                               resource_type: resource_typed_id.type,
                               resource_id: resource_typed_id.id,
                               context_facts: OsoCloud::Helpers.params_to_facts(context_facts)
                             ))
  result.results
end

#actions_local(actor, resource, context_facts = []) ⇒ String

Fetches a query that can be run against your database to fetch the actions an actor can perform on a resource.

Returns a SQL query to run against the local database

Parameters:

Returns:

  • (String)


104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/oso/oso.rb', line 104

def actions_local(actor, resource, context_facts = [])
  actor_typed_id = actor.to_api_value
  resource_typed_id = resource.to_api_value
  result = @api.post_actions_query(
    OsoCloud::Core::ActionsQuery.new(
      actor_type: actor_typed_id.type,
      actor_id: actor_typed_id.id,
      resource_type: resource_typed_id.type,
      resource_id: resource_typed_id.id,
      context_facts: OsoCloud::Helpers.params_to_facts(context_facts)
    )
  )
  result.sql
end

#authorize(actor, action, resource, context_facts = [], parity_handle: nil) ⇒ Boolean

Check a permission

Returns true if the actor can perform the action on the resource; otherwise false.

This method has an optional parameter ‘parity_handle` which is used to compare the result of your Oso authorization check with your legacy authorization system. Learn more about using the parity_handle with Oso Migrate here:

www.osohq.com/docs/app-integration/client-apis/ruby#oso-migrate

Parameters:

Returns:

  • (Boolean)

See Also:



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/oso/oso.rb', line 157

def authorize(actor, action, resource, context_facts = [], parity_handle: nil)
  actor_typed_id = actor.to_api_value
  resource_typed_id = resource.to_api_value
  result = @api.(OsoCloud::Core::AuthorizeQuery.new(
                                 actor_type: actor_typed_id.type,
                                 actor_id: actor_typed_id.id,
                                 action: action,
                                 resource_type: resource_typed_id.type,
                                 resource_id: resource_typed_id.id,
                                 context_facts: OsoCloud::Helpers.params_to_facts(context_facts)
                               ),
                               parity_handle
                               )
  result.allowed
end

#authorize_local(actor, action, resource, context_facts = [], parity_handle: nil) ⇒ String

Check a permission depending on data both in Oso Cloud and stored in a local database

Returns a SQL query to run against the local database

This method has an optional parameter ‘parity_handle` which is used to compare the result of your Oso authorization check with your legacy authorization system. Learn more about using the parity_handle with Oso Migrate here:

www.osohq.com/docs/app-integration/client-apis/ruby#oso-migrate

Parameters:

Returns:

  • (String)


53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/oso/oso.rb', line 53

def authorize_local(actor, action, resource, context_facts = [], parity_handle: nil)
  actor_typed_id = actor.to_api_value
  resource_typed_id = resource.to_api_value
  result = @api.(
    OsoCloud::Core::AuthorizeQuery.new(
      actor_type: actor_typed_id.type,
      actor_id: actor_typed_id.id,
      action: action,
      resource_type: resource_typed_id.type,
      resource_id: resource_typed_id.id,
      context_facts: OsoCloud::Helpers.params_to_facts(context_facts)
    ), parity_handle
  )
  result.sql
end

#authorize_resources(actor, action, resources, context_facts = []) ⇒ Array<OsoCloud::Value>

Check authorized resources

Returns a subset of the resource which an actor can perform a particular action. Ordering and duplicates, if any exist, are preserved.

Parameters:

Returns:

See Also:



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/oso/oso.rb', line 185

def authorize_resources(actor, action, resources, context_facts = [])
  return [] if resources.nil?
  return [] if resources.empty?

  key = lambda do |type, id|
    "#{type}:#{id}"
  end

  resources_extracted = resources.map(&:to_api_value)
  actor_typed_id = actor.to_api_value
  data = OsoCloud::Core::AuthorizeResourcesQuery.new(
    actor_type: actor_typed_id.type, actor_id: actor_typed_id.id,
    action: action,
    resources: resources_extracted,
    context_facts: OsoCloud::Helpers.params_to_facts(context_facts)
  )
  result = @api.(data)

  return [] if result.results.empty?

  results_lookup = {}
  result.results.each do |r|
    k = key.call(r.type, r.id)
    results_lookup[k] = true if results_lookup[k].nil?
  end

  resources.select do |r|
    e = r.to_api_value
    exists = results_lookup[key.call(e.type, e.id)]
    exists
  end
end

#bulk(delete: [], insert: []) ⇒ nil

Transactionally delete and insert fact(s)

Delete(s) are processed before insertion(s). nil arguments in facts to be deleted act as wildcards. Does not throw an error if facts to be deleted are not found or facts to be inserted already exist.

Throws an OsoCloud::Core::Api exception if error returned from server.

Parameters:

  • delete (Array<fact>) (defaults to: [])
  • insert (Array<fact>) (defaults to: [])

Returns:

  • (nil)

See Also:



369
370
371
372
373
# File 'lib/oso/oso.rb', line 369

def bulk(delete: [], insert: [])
  @api.post_bulk(OsoCloud::Core::Bulk.new(delete: OsoCloud::Helpers.params_to_facts(delete),
                                          tell: OsoCloud::Helpers.params_to_facts(insert)))
  nil
end

#bulk_actions(actor, queries:) ⇒ Array<Array<String>>

List authorized actions for a batch of queries

Fetches a list of actions which an actor can perform on a particular resource.

Parameters:

Returns:

  • (Array<Array<String>>)

See Also:



417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
# File 'lib/oso/oso.rb', line 417

def bulk_actions(actor, queries:)
  actor_typed_id = actor.to_api_value
  data = queries.map do |q|
    context_facts = []
    resource = nil
    if q.is_a?(Array)
      resource = q[0]
      context_facts = q[1]
    else
      resource = q
    end
    resource_typed_id = resource.to_api_value
    OsoCloud::Core::ActionsQuery.new(
      actor_type: actor_typed_id.type,
      actor_id: actor_typed_id.id,
      resource_type: resource_typed_id.type,
      resource_id: resource_typed_id.id,
      context_facts: OsoCloud::Helpers.params_to_facts(context_facts)
    )
  end
  @api.post_bulk_actions(data).map(&:results)
end

#bulk_delete(facts) ⇒ nil

Delete many facts

Deletes many facts at once. Does not throw an error when some of the facts are not found.

Parameters:

  • facts (Array<fact>)

Returns:

  • (nil)

See Also:



350
351
352
353
# File 'lib/oso/oso.rb', line 350

def bulk_delete(facts)
  @api.post_bulk_delete(OsoCloud::Helpers.params_to_facts(facts))
  nil
end

#bulk_tell(facts) ⇒ nil

Add many facts

Adds many facts at once.

Parameters:

  • facts (Array<fact>)

Returns:

  • (nil)

See Also:



322
323
324
325
# File 'lib/oso/oso.rb', line 322

def bulk_tell(facts)
  @api.post_bulk_load(OsoCloud::Helpers.params_to_facts(facts))
  nil
end

#delete(name, *args) ⇒ nil

Delete fact

Deletes a fact. Does not throw an error if the fact is not found.

Parameters:

Returns:

  • (nil)


335
336
337
338
339
# File 'lib/oso/oso.rb', line 335

def delete(name, *args)
  typed_args = args.map { |a| OsoCloud::Helpers.extract_value(a) }
  @api.delete_facts(OsoCloud::Core::Fact.new(predicate: name, args: typed_args))
  nil
end

#get(name, *args) ⇒ Array<fact>

List facts

Lists facts that are stored in Oso Cloud. Can be used to check the existence of a particular fact, or used to fetch all facts that have a particular argument. nil arguments operate as wildcards.

Parameters:

Returns:

  • (Array<fact>)

See Also:



386
387
388
# File 'lib/oso/oso.rb', line 386

def get(name, *args)
  OsoCloud::Helpers.facts_to_params(@api.get_facts(name, args))
end

#get_policy_metadataObject

Returns metadata about the currently active policy



134
135
136
# File 'lib/oso/oso.rb', line 134

def 
  @api..
end

#list(actor, action, resource_type, context_facts = []) ⇒ Array<String>

List authorized resources

Fetches a list of resource ids on which an actor can perform a particular action.

Parameters:

  • actor (OsoCloud::Value)
  • action (String)
  • resource_type (String)
  • context_facts (Array<fact>) (defaults to: [])

Returns:

  • (Array<String>)

See Also:



230
231
232
233
234
235
236
237
238
239
240
# File 'lib/oso/oso.rb', line 230

def list(actor, action, resource_type, context_facts = [])
  all_results = []
  page_token = nil
  loop do
    page = list_paginated(actor, action, resource_type, 10000, page_token: page_token, context_facts: context_facts)
    all_results.concat(page.results)
    break if page.next_page_token.nil?
    page_token = page.next_page_token
  end
  all_results
end

#list_local(actor, action, resource_type, column, context_facts = []) ⇒ String

List authorized resources depending on data both in Oso Cloud and stored in a local database

Returns a SQL query to run against the local database

Parameters:

  • actor (OsoCloud::Value)
  • action (String)
  • resource_type (String)
  • column (String)
  • context_facts (Array<fact>) (defaults to: [])

Returns:

  • (String)


80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/oso/oso.rb', line 80

def list_local(actor, action, resource_type, column, context_facts = [])
  actor_typed_id = actor.to_api_value
  result = @api.post_list_query(
    query: OsoCloud::Core::ListQuery.new(
      actor_type: actor_typed_id.type,
      actor_id: actor_typed_id.id,
      action: action,
      resource_type: resource_type,
      context_facts: OsoCloud::Helpers.params_to_facts(context_facts)
    ),
    column: column
  )
  result.sql
end

#list_paginated(actor, action, resource_type, page_size, page_token: nil, context_facts: []) ⇒ OsoCloud::Core::ListResult

List authorized resources with pagination

Fetches a page of resource ids on which an actor can perform a particular action. Returns a ListResult with ‘results` and `next_page_token`. Pass `next_page_token` to fetch subsequent pages.

Parameters:

  • actor (OsoCloud::Value)
  • action (String)
  • resource_type (String)
  • page_size (Integer)
  • page_token (String, nil) (defaults to: nil)
  • context_facts (Array<fact>) (defaults to: [])

Returns:

  • (OsoCloud::Core::ListResult)

Raises:

  • (OsoCloud::Core::ApiError)


256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/oso/oso.rb', line 256

def list_paginated(actor, action, resource_type, page_size, page_token: nil, context_facts: [])
  actor_typed_id = actor.to_api_value
  10.times do |attempt|
    begin
      return @api.post_list(OsoCloud::Core::ListQuery.new(
                              actor_type: actor_typed_id.type,
                              actor_id: actor_typed_id.id,
                              action: action,
                              resource_type: resource_type,
                              context_facts: OsoCloud::Helpers.params_to_facts(context_facts),
                              page_size: page_size,
                              page_token: page_token
                            ))
    rescue OsoCloud::Core::ApiError => e
      raise unless e.status_code == 409 && e.retry_after && attempt < 9
      sleep(e.retry_after)
    end
  end
  raise OsoCloud::Core::ApiError.new(message: 'Page not available after retries', status_code: 409)
end

#policy(policy) ⇒ nil

Update the active policy

Updates the active policy in Oso Cloud, The string passed into this method should be written in Polar.

Parameters:

  • policy (String)

Returns:

  • (nil)


127
128
129
130
# File 'lib/oso/oso.rb', line 127

def policy(policy)
  @api.post_policy(OsoCloud::Core::Policy.new(src: policy, filename: ''))
  nil
end

#query(name, *args, context_facts: []) ⇒ Array<fact>

List added and derived facts

Lists facts that are stored in Oso Cloud in addition to derived facts from evaluating the policy. nil arguments operate as wildcards.

Parameters:

  • name (String)
  • args (Array<[String, OsoCloud::Value, nil]>)
  • context_facts (Array<fact>) (defaults to: [])

Returns:

  • (Array<fact>)

See Also:



401
402
403
404
405
406
# File 'lib/oso/oso.rb', line 401

def query(name, *args, context_facts: [])
  typed_args = args.map { |a| OsoCloud::Helpers.extract_value(a) }
  result = @api.post_query(OsoCloud::Core::Query.new(fact: OsoCloud::Helpers.param_to_fact(name, typed_args),
                                                     context_facts: OsoCloud::Helpers.params_to_facts(context_facts)))
  OsoCloud::Helpers.facts_to_params(result.results)
end

#tell(name, *args) ⇒ nil

Add a fact

Adds a fact with the given name and arguments.

Parameters:

Returns:

  • (nil)


308
309
310
311
312
# File 'lib/oso/oso.rb', line 308

def tell(name, *args)
  typed_args = args.map { |a| OsoCloud::Helpers.extract_value(a) }
  @api.post_facts(OsoCloud::Core::Fact.new(predicate: name, args: typed_args))
  nil
end