oso-cloud 0.3.0 → 0.3.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 062aa3d76c978722bbc9242d4a7c594eb0feb62146559dcc9a07b3d24f81f5c2
4
- data.tar.gz: 8f5afb67fd4e4242c35c7808df00b0bf0bbcd9fcd83257d3a34f218a33625070
3
+ metadata.gz: f782a7cb7f39a37115f0a16e229d69b09f44d91a26228c3673dcd590b2395183
4
+ data.tar.gz: 3e396a943707635a5ce4659bdb39b283e20cd1f06fb7b2bb7dc008fd2cea01ae
5
5
  SHA512:
6
- metadata.gz: bd87423b50e294bbf5ea4761a9287fd9a885b94a803ba8a51f56b428197b1bb37612828e7e58c8124e140ff6a0173d7f5614b6eb86141e6a2aeb4affa705ac83
7
- data.tar.gz: b3b1bfd172c4adcd344b2531875d1337cf0a34b3ccd12d0536a1c419a51c1a333ff2363f9d7ca9ab686f468de25bc0696ae2cae60bee2bfcc7ae59e83a956abc
6
+ metadata.gz: 8af7ceabb0bb8c434e5dc8dc378d40b3dcb08a6a4f17f464538f21f026349d9dcef3a28f79176dd893543f1be1e6e5560c0892ba8d2b73953b990c0d078a418b
7
+ data.tar.gz: 2c87cb55cceedfde35f917e78882b02da50dade1bb1565fffa1648eb276754170a6ea79716828e21b6d345ec857f6f89d785df38a7513f8173acd4900a3215aa
data/Gemfile.lock CHANGED
@@ -1,17 +1,19 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- oso-cloud (0.3.0)
4
+ oso-cloud (0.3.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
+ minitest (5.15.0)
9
10
  rake (12.3.3)
10
11
 
11
12
  PLATFORMS
12
13
  ruby
13
14
 
14
15
  DEPENDENCIES
16
+ minitest (~> 5.15)
15
17
  oso-cloud!
16
18
  rake (~> 12.0)
17
19
 
data/Rakefile CHANGED
@@ -1,2 +1,9 @@
1
- require "bundler/gem_tasks"
2
- task :default => :spec
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ end
7
+
8
+ desc "Run tests"
9
+ task :default => :test
data/lib/oso/client.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'json'
2
- require 'logger'
3
2
  require 'net/http'
4
3
  require 'uri'
5
4
 
@@ -7,73 +6,75 @@ require 'oso/version'
7
6
 
8
7
  module Oso
9
8
  class Client
10
- def initialize(url: 'https://cloud.osohq.com', api_key: nil, logger: nil)
9
+ def initialize(url: 'https://cloud.osohq.com', api_key: nil)
11
10
  @url = url
12
11
  @api_key = api_key
13
- @logger = logger || Logger.new(STDOUT)
14
- # TODO: why does this need to be configurable?
15
- # @to_type_and_id = method(default_to_type_and_id)
12
+ end
13
+
14
+ def policy(policy)
15
+ POST('policy', { src: policy })
16
16
  end
17
17
 
18
18
  def authorize(actor, action, resource)
19
- actor_type, actor_id = default_to_type_and_id actor
20
- resource_type, resource_id = default_to_type_and_id resource
21
- result = post('authorize', {
22
- actor_type: actor_type, actor_id: actor_id,
23
- action: action,
24
- resource_type: resource_type, resource_id: resource_id
25
- })
19
+ actor_typed_id = extract_typed_id actor
20
+ resource_typed_id = extract_typed_id resource
21
+ result = POST('authorize', {
22
+ actor_type: actor_typed_id.type, actor_id: actor_typed_id.id,
23
+ action: action,
24
+ resource_type: resource_typed_id.type, resource_id: resource_typed_id.id
25
+ })
26
26
  allowed = result['allowed']
27
- @logger.debug { "AUTHORIZING (#{actor}, #{action}, #{resource}) => ALLOWED? = #{allowed ? 'true' : 'false'} " }
28
-
29
27
  allowed
30
28
  end
31
29
 
32
30
  def list(actor, action, resource_type)
33
- actor_type, actor_id = default_to_type_and_id actor
34
- result = post('list',
35
- {
36
- actor_type: actor_type, actor_id: actor_id,
37
- action: action,
38
- resource_type: resource_type
39
- })
31
+ actor_typed_id = extract_typed_id actor
32
+ result = POST('list', {
33
+ actor_type: actor_typed_id.type, actor_id: actor_typed_id.id,
34
+ action: action,
35
+ resource_type: resource_type,
36
+ })
40
37
  results = result['results']
41
- @logger.debug { "AUTHORIZING (#{actor}, #{action}, #{resource_type}). RESULTS: #{results}" }
42
-
43
38
  results
44
39
  end
45
40
 
46
- def add_role(actor, role_name, resource)
47
- add_role_or_relation('role', resource, role_name, actor)
41
+ def tell(predicate, *args)
42
+ typed_args = args.map { |a| extract_typed_id a}
43
+ POST('facts', { predicate: predicate, args: typed_args })
48
44
  end
49
45
 
50
- def delete_role(actor, role_name, resource)
51
- delete_role_or_relation('role', resource, role_name, actor)
46
+ def bulk_tell(facts)
47
+ params = facts.map { |predicate, *args|
48
+ typed_args = args.map { |a| extract_typed_id a}
49
+ { predicate: predicate, args: typed_args }
50
+ }
51
+ POST('bulk_load', params)
52
52
  end
53
53
 
54
- def add_relation(subject, name, object)
55
- add_role_or_relation('relation', subject, name, object)
54
+ def delete(predicate, *args)
55
+ typed_args = args.map { |a| extract_typed_id a}
56
+ DELETE('facts', { predicate: predicate, args: typed_args })
56
57
  end
57
58
 
58
- def delete_relation(subject, name, object)
59
- delete_role_or_relation('relation', subject, name, object)
59
+ def bulk_delete(facts)
60
+ params = facts.map { |predicate, *args|
61
+ typed_args = args.map { |a| extract_typed_id a}
62
+ { predicate: predicate, args: typed_args }
63
+ }
64
+ POST('bulk_delete', params)
60
65
  end
61
66
 
62
- def get_roles(resource: nil, role: nil, actor: nil)
63
- params = {}
64
- unless actor.nil?
65
- actor_type, actor_id = default_to_type_and_id actor
66
- params[:actor_type] = actor_type
67
- params[:actor_id] = actor_id
68
- end
69
- unless resource.nil?
70
- resource_type, resource_id = default_to_type_and_id resource
71
- params[:resource_type] = resource_type
72
- params[:resource_id] = resource_id
67
+ def get(predicate, *args)
68
+ params = {predicate: predicate}
69
+ args.each_with_index do |arg, i|
70
+ typed_id = extract_arg_query(arg)
71
+ if typed_id
72
+ params["args.#{i}.type"] = typed_id.type
73
+ params["args.#{i}.id"] = typed_id.id
74
+ end
73
75
  end
74
- params[:role] = role unless role.nil?
75
76
 
76
- get('roles')
77
+ GET('facts', params)
77
78
  end
78
79
 
79
80
  private
@@ -82,65 +83,68 @@ module Oso
82
83
  {
83
84
  "Authorization" => "Basic %s" % @api_key,
84
85
  "User-Agent" => "Oso Cloud (ruby)",
85
- "Accept": "application/json"
86
+ "Accept": "application/json",
87
+ "Content-Type": "application/json"
86
88
  }
87
89
  end
88
90
 
89
- def get(path)
90
- result = Net::HTTP.get(URI("#{@url}/api/#{path}"), headers)
91
+
92
+ def GET(path, params)
93
+ uri = URI("#{@url}/api/#{path}")
94
+ uri.query = URI::encode_www_form(params)
95
+ use_ssl = (uri.scheme == 'https')
96
+
97
+ result = Net::HTTP.start(uri.hostname, uri.port, use_ssl: use_ssl ) { |http|
98
+ http.request(Net::HTTP::Get.new(uri, headers)) {|r|
99
+ r.read_body
100
+ }
101
+ }
91
102
  handle_result result
103
+
92
104
  end
93
105
 
94
- def post(path, params)
106
+ def POST(path, params)
95
107
  result = Net::HTTP.post(URI("#{@url}/api/#{path}"), params.to_json, headers)
96
108
  handle_result result
97
109
  end
98
110
 
99
- def delete(path, params)
100
- result = Net::HTTP.delete(URI("#{@url}/api/#{path}"), params.to_json, headers)
111
+ def DELETE(path, params)
112
+ uri = URI("#{@url}/api/#{path}")
113
+ use_ssl = (uri.scheme == 'https')
114
+ result = Net::HTTP.start(uri.hostname, uri.port, use_ssl: use_ssl ) { |http|
115
+ http.request(Net::HTTP::Delete.new(uri, headers), params.to_json) {|r|
116
+ r.read_body
117
+ }
118
+ }
101
119
  handle_result result
102
120
  end
103
121
 
104
- # TODO: why does this need to be configurable?
105
- def default_to_type_and_id(obj)
106
- if obj.nil?
107
- %w[null null]
108
- else
109
- [obj.class.to_s, obj.id.to_s]
110
- end
111
- end
112
-
113
122
  def handle_result(result)
114
123
  unless result.is_a?(Net::HTTPSuccess)
115
124
  raise "Got an unexpected error from Oso Service: #{result.code}\n#{result.body}"
116
125
  end
117
126
 
118
- # TODO: Always JSON?
119
127
  JSON.parse(result.body)
120
128
  end
121
129
 
122
- def to_params(role_or_relation, from, name, to)
123
- from_type, from_id = default_to_type_and_id from
124
- to_type, to_id = default_to_type_and_id to
130
+ def extract_typed_id(x)
131
+ return TypedId.new(type: "String", id: x) if x.is_a? String
125
132
 
126
- from_name = role_or_relation == 'role' ? 'resource' : 'from'
127
- to_name = role_or_relation == 'role' ? 'actor' : 'to'
133
+ raise "#{x} does not have an 'id' field" unless x.respond_to? :id
134
+ raise "Invalid 'id' field on #{x}: #{x.id}" if x.id.nil?
128
135
 
129
- {
130
- "#{from_name}_id" => from_id,
131
- "#{from_name}_type" => from_type,
132
- role_or_relation.to_s => name,
133
- "#{to_name}_id" => to_id,
134
- "#{to_name}_type" => to_type
135
- }
136
+ TypedId.new(type: x.class.name, id: x.id.to_s)
136
137
  end
137
138
 
138
- def add_role_or_relation(role_or_relation, from, name, to)
139
- post("#{role_or_relation}s", to_params(role_or_relation, from, name, to))
139
+ def extract_arg_query(x)
140
+ return nil if x.nil?
141
+ extract_typed_id(x)
140
142
  end
141
143
 
142
- def delete_role_or_relation(role_or_relation, from, name, to)
143
- delete("#{role_or_relation}s", to_params(role_or_relation, from, name, to))
144
+ TypedId = Struct.new(:type, :id, keyword_init: true) do
145
+ def to_json(*args)
146
+ to_h.to_json(*args)
147
+ end
144
148
  end
145
149
  end
146
150
  end
data/lib/oso/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Oso
2
- VERSION = '0.3.0'.freeze
2
+ VERSION = '0.3.1'.freeze
3
3
  end
data/oso-cloud.gemspec CHANGED
@@ -18,4 +18,6 @@ Gem::Specification.new do |spec|
18
18
  spec.bindir = 'exe'
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ['lib']
21
+
22
+ spec.add_development_dependency 'minitest', '~> 5.15'
21
23
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oso-cloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
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: 2022-05-13 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2022-05-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.15'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.15'
13
27
  description:
14
28
  email:
15
29
  - support@osohq.com