oso-oso 0.2.2
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 +7 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.solargraph.yml +17 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +95 -0
- data/Makefile +16 -0
- data/README.md +30 -0
- data/Rakefile +9 -0
- data/bin/console +33 -0
- data/bin/setup +6 -0
- data/ext/oso-oso/lib/libpolar.dylib +0 -0
- data/ext/oso-oso/lib/libpolar.so +0 -0
- data/lib/oso.rb +14 -0
- data/lib/oso/http.rb +16 -0
- data/lib/oso/oso.rb +47 -0
- data/lib/oso/path_mapper.rb +29 -0
- data/lib/oso/polar.rb +18 -0
- data/lib/oso/polar/errors.rb +84 -0
- data/lib/oso/polar/ffi.rb +47 -0
- data/lib/oso/polar/ffi/error.rb +123 -0
- data/lib/oso/polar/ffi/polar.rb +97 -0
- data/lib/oso/polar/ffi/query.rb +55 -0
- data/lib/oso/polar/ffi/query_event.rb +23 -0
- data/lib/oso/polar/polar.rb +381 -0
- data/lib/oso/polar/predicate.rb +26 -0
- data/lib/oso/polar/query.rb +117 -0
- data/lib/oso/polar/query_event.rb +22 -0
- data/lib/oso/polar/variable.rb +20 -0
- data/lib/oso/version.rb +5 -0
- data/oso-oso.gemspec +35 -0
- metadata +157 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Oso
|
|
4
|
+
module Polar
|
|
5
|
+
# Polar predicate.
|
|
6
|
+
class Predicate
|
|
7
|
+
attr_reader :name, :args
|
|
8
|
+
|
|
9
|
+
# @param name [String]
|
|
10
|
+
# @param args [Array<Object>]
|
|
11
|
+
def initialize(name, args:)
|
|
12
|
+
@name = name
|
|
13
|
+
@args = args
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# @param other [Predicate]
|
|
17
|
+
# @return [Boolean]
|
|
18
|
+
def ==(other)
|
|
19
|
+
name == other.name && args == other.args
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @see #==
|
|
23
|
+
alias eql? ==
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Oso
|
|
4
|
+
module Polar
|
|
5
|
+
# A single Polar query.
|
|
6
|
+
class Query
|
|
7
|
+
attr_reader :results
|
|
8
|
+
|
|
9
|
+
# @param ffi_instance [FFI::Query]
|
|
10
|
+
# @param polar [Polar]
|
|
11
|
+
def initialize(ffi_instance, polar:)
|
|
12
|
+
@ffi_instance = ffi_instance
|
|
13
|
+
@polar = polar
|
|
14
|
+
@results = start
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
# @return [FFI::Query]
|
|
20
|
+
attr_reader :ffi_instance
|
|
21
|
+
# @return [Polar]
|
|
22
|
+
attr_reader :polar
|
|
23
|
+
|
|
24
|
+
# Send next result of Ruby method call across FFI boundary.
|
|
25
|
+
#
|
|
26
|
+
# @param result [String]
|
|
27
|
+
# @param call_id [Integer]
|
|
28
|
+
# @raise [Error] if the FFI call raises one.
|
|
29
|
+
def call_result(result, call_id:)
|
|
30
|
+
ffi_instance.call_result(result, call_id: call_id)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Send result of predicate check across FFI boundary.
|
|
34
|
+
#
|
|
35
|
+
# @param result [Boolean]
|
|
36
|
+
# @param call_id [Integer]
|
|
37
|
+
# @raise [Error] if the FFI call raises one.
|
|
38
|
+
def question_result(result, call_id:)
|
|
39
|
+
ffi_instance.question_result(result, call_id: call_id)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Fetch the next result from calling a Ruby method and prepare it for
|
|
43
|
+
# transmission across the FFI boundary.
|
|
44
|
+
#
|
|
45
|
+
# @param method [#to_sym]
|
|
46
|
+
# @param args [Array<Hash>]
|
|
47
|
+
# @param call_id [Integer]
|
|
48
|
+
# @param instance_id [Integer]
|
|
49
|
+
# @raise [Error] if the FFI call raises one.
|
|
50
|
+
def handle_call(method, call_id:, instance:, args:)
|
|
51
|
+
polar.register_call(method, call_id: call_id, instance: instance, args: args)
|
|
52
|
+
result = JSON.dump(polar.next_call_result(call_id))
|
|
53
|
+
call_result(result, call_id: call_id)
|
|
54
|
+
rescue InvalidCallError, StopIteration
|
|
55
|
+
call_result(nil, call_id: call_id)
|
|
56
|
+
# @TODO: polar line numbers in errors once polar errors are better.
|
|
57
|
+
# raise PolarRuntimeError(f"Error calling {attribute}")
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Create a generator that can be polled to advance the query loop.
|
|
61
|
+
#
|
|
62
|
+
# @yieldparam [Hash<String, Object>]
|
|
63
|
+
# @return [Enumerator]
|
|
64
|
+
# @raise [Error] if any of the FFI calls raise one.
|
|
65
|
+
def start # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
|
66
|
+
Enumerator.new do |yielder| # rubocop:disable Metrics/BlockLength
|
|
67
|
+
loop do # rubocop:disable Metrics/BlockLength
|
|
68
|
+
event = ffi_instance.next_event
|
|
69
|
+
case event.kind
|
|
70
|
+
when 'Done'
|
|
71
|
+
break
|
|
72
|
+
when 'Result'
|
|
73
|
+
yielder << event.data['bindings'].transform_values { |v| polar.to_ruby(v) }
|
|
74
|
+
when 'MakeExternal'
|
|
75
|
+
id = event.data['instance_id']
|
|
76
|
+
raise DuplicateInstanceRegistrationError, id if polar.instance? id
|
|
77
|
+
|
|
78
|
+
cls_name = event.data['instance']['tag']
|
|
79
|
+
fields = event.data['instance']['fields']['fields']
|
|
80
|
+
polar.make_instance(cls_name, fields: fields, id: id)
|
|
81
|
+
when 'ExternalCall'
|
|
82
|
+
call_id = event.data['call_id']
|
|
83
|
+
instance = event.data['instance']
|
|
84
|
+
method = event.data['attribute']
|
|
85
|
+
args = event.data['args']
|
|
86
|
+
handle_call(method, call_id: call_id, instance: instance, args: args)
|
|
87
|
+
when 'ExternalIsSubSpecializer'
|
|
88
|
+
instance_id = event.data['instance_id']
|
|
89
|
+
left_tag = event.data['left_class_tag']
|
|
90
|
+
right_tag = event.data['right_class_tag']
|
|
91
|
+
answer = polar.subspecializer?(instance_id, left_tag: left_tag, right_tag: right_tag)
|
|
92
|
+
question_result(answer, call_id: event.data['call_id'])
|
|
93
|
+
when 'ExternalIsa'
|
|
94
|
+
instance_id = event.data['instance_id']
|
|
95
|
+
class_tag = event.data['class_tag']
|
|
96
|
+
answer = polar.isa?(instance_id, class_tag: class_tag)
|
|
97
|
+
question_result(answer, call_id: event.data['call_id'])
|
|
98
|
+
when 'ExternalUnify'
|
|
99
|
+
left_instance_id = event.data['left_instance_id']
|
|
100
|
+
right_instance_id = event.data['right_instance_id']
|
|
101
|
+
answer = polar.unify?(left_instance_id, right_instance_id)
|
|
102
|
+
question_result(answer, call_id: event.data['call_id'])
|
|
103
|
+
when 'Debug'
|
|
104
|
+
puts event.data['message'] if event.data['message']
|
|
105
|
+
print '> '
|
|
106
|
+
input = $stdin.gets.chomp!
|
|
107
|
+
command = JSON.dump(polar.to_polar_term(input))
|
|
108
|
+
ffi_instance.debug_command(command)
|
|
109
|
+
else
|
|
110
|
+
raise "Unhandled event: #{JSON.dump(event.inspect)}"
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end.lazy
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Oso
|
|
4
|
+
module Polar
|
|
5
|
+
# A query event received across the FFI boundary.
|
|
6
|
+
class QueryEvent
|
|
7
|
+
# @return [String]
|
|
8
|
+
attr_reader :kind
|
|
9
|
+
# @return [Hash<String, Object>]
|
|
10
|
+
attr_reader :data
|
|
11
|
+
|
|
12
|
+
# @overload initialize(event_data)
|
|
13
|
+
# @param event_data [Hash<String, Object>]
|
|
14
|
+
# @overload initialize(event_data)
|
|
15
|
+
# @param event_data [String]
|
|
16
|
+
def initialize(event_data)
|
|
17
|
+
event_data = { event_data => nil } if event_data == 'Done'
|
|
18
|
+
@kind, @data = event_data.first
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Oso
|
|
4
|
+
module Polar
|
|
5
|
+
# Polar variable.
|
|
6
|
+
class Variable
|
|
7
|
+
attr_reader :name
|
|
8
|
+
|
|
9
|
+
# @param name [String]
|
|
10
|
+
def initialize(name)
|
|
11
|
+
@name = name
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @return [String]
|
|
15
|
+
def to_s
|
|
16
|
+
name
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
data/lib/oso/version.rb
ADDED
data/oso-oso.gemspec
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/oso/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'oso-oso'
|
|
7
|
+
spec.version = Oso::VERSION
|
|
8
|
+
spec.authors = ['Oso Security']
|
|
9
|
+
spec.email = ['support@osohq.com']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'Oso authorization API.'
|
|
12
|
+
spec.homepage = 'https://www.osohq.com/'
|
|
13
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.4.0')
|
|
14
|
+
|
|
15
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
16
|
+
|
|
17
|
+
# Specify which files should be added to the gem when it is released.
|
|
18
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
19
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
20
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
21
|
+
end
|
|
22
|
+
spec.bindir = 'exe'
|
|
23
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
24
|
+
spec.require_paths = ['lib']
|
|
25
|
+
|
|
26
|
+
# Runtime dependencies
|
|
27
|
+
spec.add_runtime_dependency 'ffi', '~> 1.0'
|
|
28
|
+
|
|
29
|
+
# Development dependencies
|
|
30
|
+
spec.add_development_dependency 'pry-byebug', '~> 3.9.0'
|
|
31
|
+
spec.add_development_dependency 'rake', '~> 12.0'
|
|
32
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
33
|
+
spec.add_development_dependency 'solargraph', '~> 0.39.8'
|
|
34
|
+
spec.add_development_dependency 'yard', '~> 0.9.25'
|
|
35
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: oso-oso
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.2
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Oso Security
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2020-07-17 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: ffi
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: pry-byebug
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 3.9.0
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: 3.9.0
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rake
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '12.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '12.0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rspec
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '3.0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '3.0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: solargraph
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: 0.39.8
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: 0.39.8
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: yard
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: 0.9.25
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - "~>"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: 0.9.25
|
|
97
|
+
description:
|
|
98
|
+
email:
|
|
99
|
+
- support@osohq.com
|
|
100
|
+
executables: []
|
|
101
|
+
extensions: []
|
|
102
|
+
extra_rdoc_files: []
|
|
103
|
+
files:
|
|
104
|
+
- ".gitignore"
|
|
105
|
+
- ".rspec"
|
|
106
|
+
- ".solargraph.yml"
|
|
107
|
+
- Gemfile
|
|
108
|
+
- Gemfile.lock
|
|
109
|
+
- Makefile
|
|
110
|
+
- README.md
|
|
111
|
+
- Rakefile
|
|
112
|
+
- bin/console
|
|
113
|
+
- bin/setup
|
|
114
|
+
- ext/oso-oso/lib/libpolar.dylib
|
|
115
|
+
- ext/oso-oso/lib/libpolar.so
|
|
116
|
+
- lib/oso.rb
|
|
117
|
+
- lib/oso/http.rb
|
|
118
|
+
- lib/oso/oso.rb
|
|
119
|
+
- lib/oso/path_mapper.rb
|
|
120
|
+
- lib/oso/polar.rb
|
|
121
|
+
- lib/oso/polar/errors.rb
|
|
122
|
+
- lib/oso/polar/ffi.rb
|
|
123
|
+
- lib/oso/polar/ffi/error.rb
|
|
124
|
+
- lib/oso/polar/ffi/polar.rb
|
|
125
|
+
- lib/oso/polar/ffi/query.rb
|
|
126
|
+
- lib/oso/polar/ffi/query_event.rb
|
|
127
|
+
- lib/oso/polar/polar.rb
|
|
128
|
+
- lib/oso/polar/predicate.rb
|
|
129
|
+
- lib/oso/polar/query.rb
|
|
130
|
+
- lib/oso/polar/query_event.rb
|
|
131
|
+
- lib/oso/polar/variable.rb
|
|
132
|
+
- lib/oso/version.rb
|
|
133
|
+
- oso-oso.gemspec
|
|
134
|
+
homepage: https://www.osohq.com/
|
|
135
|
+
licenses: []
|
|
136
|
+
metadata:
|
|
137
|
+
homepage_uri: https://www.osohq.com/
|
|
138
|
+
post_install_message:
|
|
139
|
+
rdoc_options: []
|
|
140
|
+
require_paths:
|
|
141
|
+
- lib
|
|
142
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
143
|
+
requirements:
|
|
144
|
+
- - ">="
|
|
145
|
+
- !ruby/object:Gem::Version
|
|
146
|
+
version: 2.4.0
|
|
147
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
|
+
requirements:
|
|
149
|
+
- - ">="
|
|
150
|
+
- !ruby/object:Gem::Version
|
|
151
|
+
version: '0'
|
|
152
|
+
requirements: []
|
|
153
|
+
rubygems_version: 3.1.4
|
|
154
|
+
signing_key:
|
|
155
|
+
specification_version: 4
|
|
156
|
+
summary: Oso authorization API.
|
|
157
|
+
test_files: []
|