evervault 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0e83fca85d13b65463d59ce895338341fc504f961f148bb674df43412896f621
4
+ data.tar.gz: 7737c63198b95422dde627271577ec1b16428604b680751b016062cd6cee8b7c
5
+ SHA512:
6
+ metadata.gz: e3d1977f9f8350c320ec115311f42671c00b360dd9623a3a2e8f3e769ed7b1b6576eeb5db5b0b7140557a627927e542a3cb6c3375ecad813a1515dd2b4ec2646
7
+ data.tar.gz: c5b31592a06d3dacb5cc1225cfc69fba44d88757e8c28f0209787a9641a0c0b6b99f6bf5b45b01031bbe91e823ae8bebda340f871b476ad498094f0229dab11d
@@ -0,0 +1,23 @@
1
+ name: Run test matrix
2
+ on:
3
+ push:
4
+ branches:
5
+ - "**"
6
+ - "!master"
7
+
8
+ jobs:
9
+ test:
10
+ strategy:
11
+ fail-fast: false
12
+ matrix:
13
+ os: [ubuntu, macos]
14
+ ruby: [2.5, 2.6, 2.7, jruby, jruby-head, truffleruby]
15
+ runs-on: ${{ matrix.os }}-latest
16
+ continue-on-error: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'debug' }}
17
+ steps:
18
+ - uses: actions/checkout@v2
19
+ - uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: ${{ matrix.ruby }}
22
+ - run: bundle install
23
+ - run: bundle exec rake
@@ -0,0 +1,17 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
12
+
13
+ # JetBrains
14
+ .idea/
15
+
16
+ # VSCode
17
+ .vscode/
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in evervault.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 12.0"
7
+ gem "rspec", "~> 3.0"
8
+ gem "pry"
9
+ gem "typhoeus"
10
+ gem "webmock"
@@ -0,0 +1,56 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ evervault (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ addressable (2.7.0)
10
+ public_suffix (>= 2.0.2, < 5.0)
11
+ coderay (1.1.3)
12
+ crack (0.4.4)
13
+ diff-lcs (1.4.4)
14
+ ethon (0.12.0)
15
+ ffi (>= 1.3.0)
16
+ ffi (1.13.1)
17
+ hashdiff (1.0.1)
18
+ method_source (1.0.0)
19
+ pry (0.13.1)
20
+ coderay (~> 1.1)
21
+ method_source (~> 1.0)
22
+ public_suffix (4.0.6)
23
+ rake (12.3.3)
24
+ rspec (3.9.0)
25
+ rspec-core (~> 3.9.0)
26
+ rspec-expectations (~> 3.9.0)
27
+ rspec-mocks (~> 3.9.0)
28
+ rspec-core (3.9.3)
29
+ rspec-support (~> 3.9.3)
30
+ rspec-expectations (3.9.2)
31
+ diff-lcs (>= 1.2.0, < 2.0)
32
+ rspec-support (~> 3.9.0)
33
+ rspec-mocks (3.9.1)
34
+ diff-lcs (>= 1.2.0, < 2.0)
35
+ rspec-support (~> 3.9.0)
36
+ rspec-support (3.9.3)
37
+ typhoeus (1.4.0)
38
+ ethon (>= 0.9.0)
39
+ webmock (3.9.3)
40
+ addressable (>= 2.3.6)
41
+ crack (>= 0.3.2)
42
+ hashdiff (>= 0.4.0, < 2.0.0)
43
+
44
+ PLATFORMS
45
+ ruby
46
+
47
+ DEPENDENCIES
48
+ evervault!
49
+ pry
50
+ rake (~> 12.0)
51
+ rspec (~> 3.0)
52
+ typhoeus
53
+ webmock
54
+
55
+ BUNDLED WITH
56
+ 2.1.4
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Jonny
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,233 @@
1
+ # Evervault
2
+
3
+ Ruby SDK for [Evervault](https://evervault.com)
4
+
5
+ ## Getting Started
6
+
7
+ ### Prerequisites
8
+
9
+ To get started with the Evervault Python SDK, you will need to have created a team on the evervault dashboard.
10
+
11
+ We are currently in invite-only early access. You can apply for early access [here](https://evervault.com).
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'evervault'
19
+ ```
20
+
21
+ And then execute:
22
+ ```sh
23
+ bundle install
24
+ ```
25
+ Or install it yourself as:
26
+ ```sh
27
+ gem install evervault
28
+ ```
29
+
30
+ ## Setup
31
+
32
+ Evervault can be initialized as a singleton throughout the lifecycle of your application.
33
+ ```ruby
34
+ require "evervault"
35
+
36
+ # Initialize the client with your team's api key
37
+ Evervault.api_key = <YOUR-API-KEY>
38
+
39
+ # Encrypt your data and run a cage
40
+ result = Evervault.encrypt_and_run(<CAGE-NAME>, { hello: 'World!' })
41
+ ```
42
+
43
+ It's recommended to re-use your Evervault client, to prevent additional overhead of loading keys at runtime, so the singleton pattern should be the go-to pattern for most use-cases.
44
+
45
+ However, if you'd prefer to initialize different clients at different times, for example, if you have multiple teams and need to switch context, you can simply create a client:
46
+ ```ruby
47
+ require "evervault"
48
+
49
+ # Initialize the client with your team's api key
50
+ evervault = Evervault::Client.new(api_key: <YOUR-API-KEY>)
51
+
52
+ # Encrypt your data and run a cage
53
+ result = evervault.encrypt_and_run(<CAGE-NAME>, { hello: 'World!' })
54
+ ```
55
+
56
+ ## API Reference
57
+
58
+ ### evervault.encrypt
59
+
60
+ Encrypt lets you encrypt data for use in any of your evervault cages. You can use it to store encrypted data to be used in a cage at another time.
61
+
62
+ ```ruby
63
+ Evervault.encrypt(data = Hash | String)
64
+ ```
65
+
66
+ | Parameter | Type | Description |
67
+ | --------- | ---- | ----------- |
68
+ | data | Hash or String | Data to be encrypted |
69
+
70
+ ### evervault.run
71
+
72
+ Run lets you invoke your evervault cages with a given payload.
73
+
74
+ ```ruby
75
+ Evervault.run(cage_name = String, data = Hash)
76
+ ```
77
+
78
+ | Parameter | Type | Description |
79
+ | --------- | ---- | ----------- |
80
+ | cageName | String | Name of the cage to be run |
81
+ | data | Hash | Payload for the cage |
82
+
83
+ ### evervault.encryptAndRun
84
+
85
+ Encrypt your data and use it as the payload to invoke the cage.
86
+
87
+ ```ruby
88
+ Evervault.encrypt_and_run(cage_name = String, data = Hash)
89
+ ```
90
+
91
+ | Parameter | Type | Description |
92
+ | --------- | ---- | ----------- |
93
+ | cageName | String | Name of the cage to be run |
94
+ | data | dict | Data to be encrypted |
95
+
96
+ ### evervault.cages
97
+
98
+ Return a hash of your team's Cage objects in hash format, with cage-name as keys
99
+
100
+ ```ruby
101
+ Evervault.cages
102
+ => {"hello-cage-chilly-plum"=>
103
+ #<Evervault::Models::Cage:0x00007f8b900b4438
104
+ @name="hello-cage-chilly-plum",
105
+ @request=#<Evervault::Http::Request:0x00007f8b900b7d40 @api_key="API-KEY", @base_url="https://api.evervault.com/", @cage_run_url="https://cage.run/", @timeout=30>,
106
+ @uuid="c8a7ed58-4858-4510-a542-43125ccd1183">,
107
+ "hello-cage-filthy-fuchsia"=>
108
+ #<Evervault::Models::Cage:0x00007f8b900b43e8
109
+ @name="hello-cage-filthy-fuchsia",
110
+ @request=#<Evervault::Http::Request:0x00007f8b900b7d40 @api_key="API-KEY", @base_url="https://api.evervault.com/", @cage_run_url="https://cage.run/", @timeout=30>,
111
+ @uuid="9af32d2b-53fa-406a-9abf-6a240648b45b">,
112
+ "hello-cage-extra-amaranth"=>
113
+ #<Evervault::Models::Cage:0x00007f8b900b4398
114
+ @name="hello-cage-extra-amaranth",
115
+ @request=#<Evervault::Http::Request:0x00007f8b900b7d40 @api_key="API-KEY", @base_url="https://api.evervault.com/", @cage_run_url="https://cage.run/", @timeout=30>,
116
+ @uuid="5b99011e-a64d-4af7-bf81-619c8cb8c67f">,
117
+ "twilio-cage-explicit-salmon"=>
118
+ #<Evervault::Models::Cage:0x00007f8b900b4348
119
+ @name="twilio-cage-explicit-salmon",
120
+ @request=#<Evervault::Http::Request:0x00007f8b900b7d40 @api_key="API-KEY", @base_url="https://api.evervault.com/", @cage_run_url="https://cage.run/", @timeout=30>,
121
+ @uuid="55986772-4db7-4695-ba44-1b807290ddea">}
122
+ ```
123
+
124
+ ### evervault.cage_list
125
+
126
+ Return a `CageList` object, containing a list of your team's cages
127
+
128
+ ```ruby
129
+ Evervault.cage_list
130
+ => #<Evervault::Models::CageList:0x00007f8b900b44b0
131
+ @cages=
132
+ [#<Evervault::Models::Cage:0x00007f8b900b4438
133
+ @name="hello-cage-chilly-plum",
134
+ @request=#<Evervault::Http::Request:0x00007f8b900b7d40 @api_key="API-KEY", @base_url="https://api.evervault.com/", @cage_run_url="https://cage.run/", @timeout=30>,
135
+ @uuid="c8a7ed58-4858-4510-a542-43125ccd1183">,
136
+ #<Evervault::Models::Cage:0x00007f8b900b43e8
137
+ @name="hello-cage-filthy-fuchsia",
138
+ @request=#<Evervault::Http::Request:0x00007f8b900b7d40 @api_key="API-KEY", @base_url="https://api.evervault.com/", @cage_run_url="https://cage.run/", @timeout=30>,
139
+ @uuid="9af32d2b-53fa-406a-9abf-6a240648b45b">,
140
+ #<Evervault::Models::Cage:0x00007f8b900b4398
141
+ @name="hello-cage-extra-amaranth",
142
+ @request=#<Evervault::Http::Request:0x00007f8b900b7d40 @api_key="API-KEY", @base_url="https://api.evervault.com/", @cage_run_url="https://cage.run/", @timeout=30>,
143
+ @uuid="5b99011e-a64d-4af7-bf81-619c8cb8c67f">,
144
+ #<Evervault::Models::Cage:0x00007f8b900b4348
145
+ @name="twilio-cage-explicit-salmon",
146
+ @request=#<Evervault::Http::Request:0x00007f8b900b7d40 @api_key="API-KEY", @base_url="https://api.evervault.com/", @cage_run_url="https://cage.run/", @timeout=30>,
147
+ @uuid="55986772-4db7-4695-ba44-1b807290ddea">,
148
+ #<Evervault::Models::Cage:0x00007f8b900b42f8
149
+ @name="hello-cage-collective-aquamarine",
150
+ @request=#<Evervault::Http::Request:0x00007f8b900b7d40 @api_key="API-KEY", @base_url="https://api.evervault.com/", @cage_run_url="https://cage.run/", @timeout=30>,
151
+ @uuid="01691e76-691b-473e-aad5-44bf813ef146">,
152
+ #<Evervault::Models::Cage:0x00007f8b900b42a8
153
+ @name="twilio-cage-bored-scarlet",
154
+ @request=#<Evervault::Http::Request:0x00007f8b900b7d40 @api_key="API-KEY", @base_url="https://api.evervault.com/", @cage_run_url="https://cage.run/", @timeout=30>,
155
+ @uuid="dc056e8b-faf3-445b-9c95-0885b983c302">,
156
+ #<Evervault::Models::Cage:0x00007f8b900b4258
157
+ @name="hello-cage-front-emerald",
158
+ @request=#<Evervault::Http::Request:0x00007f8b900b7d40 @api_key="API-KEY", @base_url="https://api.evervault.com/", @cage_run_url="https://cage.run/", @timeout=30>,
159
+ @uuid="a30295e6-91fc-4d1d-837c-ac4c9b87d02d">]>
160
+ ```
161
+
162
+ #### CageList.to_hash
163
+
164
+ Converts a list of cages to a hash with keys of CageName => Cage Model
165
+
166
+ ```ruby
167
+ Evervault.cage_list.to_hash
168
+ => {"hello-cage-chilly-plum"=>
169
+ #<Evervault::Models::Cage:0x00007f8b900b4438
170
+ @name="hello-cage-chilly-plum",
171
+ @request=#<Evervault::Http::Request:0x00007f8b900b7d40 @api_key="API-KEY", @base_url="https://api.evervault.com/", @cage_run_url="https://cage.run/", @timeout=30>,
172
+ @uuid="c8a7ed58-4858-4510-a542-43125ccd1183">,
173
+ "hello-cage-filthy-fuchsia"=>
174
+ #<Evervault::Models::Cage:0x00007f8b900b43e8
175
+ @name="hello-cage-filthy-fuchsia",
176
+ @request=#<Evervault::Http::Request:0x00007f8b900b7d40 @api_key="API-KEY", @base_url="https://api.evervault.com/", @cage_run_url="https://cage.run/", @timeout=30>,
177
+ @uuid="9af32d2b-53fa-406a-9abf-6a240648b45b">,
178
+ "hello-cage-extra-amaranth"=>
179
+ #<Evervault::Models::Cage:0x00007f8b900b4398
180
+ @name="hello-cage-extra-amaranth",
181
+ @request=#<Evervault::Http::Request:0x00007f8b900b7d40 @api_key="API-KEY", @base_url="https://api.evervault.com/", @cage_run_url="https://cage.run/", @timeout=30>,
182
+ @uuid="5b99011e-a64d-4af7-bf81-619c8cb8c67f">,
183
+ "twilio-cage-explicit-salmon"=>
184
+ #<Evervault::Models::Cage:0x00007f8b900b4348
185
+ @name="twilio-cage-explicit-salmon",
186
+ @request=#<Evervault::Http::Request:0x00007f8b900b7d40 @api_key="API-KEY", @base_url="https://api.evervault.com/", @cage_run_url="https://cage.run/", @timeout=30>,
187
+ @uuid="55986772-4db7-4695-ba44-1b807290ddea">,
188
+ "hello-cage-collective-aquamarine"=>
189
+ #<Evervault::Models::Cage:0x00007f8b900b42f8
190
+ @name="hello-cage-collective-aquamarine",
191
+ @request=#<Evervault::Http::Request:0x00007f8b900b7d40 @api_key="API-KEY", @base_url="https://api.evervault.com/", @cage_run_url="https://cage.run/", @timeout=30>,
192
+ @uuid="01691e76-691b-473e-aad5-44bf813ef146">,
193
+ "twilio-cage-bored-scarlet"=>
194
+ #<Evervault::Models::Cage:0x00007f8b900b42a8
195
+ @name="twilio-cage-bored-scarlet",
196
+ @request=#<Evervault::Http::Request:0x00007f8b900b7d40 @api_key="API-KEY", @base_url="https://api.evervault.com/", @cage_run_url="https://cage.run/", @timeout=30>,
197
+ @uuid="dc056e8b-faf3-445b-9c95-0885b983c302">,
198
+ "hello-cage-front-emerald"=>
199
+ #<Evervault::Models::Cage:0x00007f8b900b4258
200
+ @name="hello-cage-front-emerald",
201
+ @request=#<Evervault::Http::Request:0x00007f8b900b7d40 @api_key="API-KEY", @base_url="https://api.evervault.com/", @cage_run_url="https://cage.run/", @timeout=30>,
202
+ @uuid="a30295e6-91fc-4d1d-837c-ac4c9b87d02d">}
203
+ ```
204
+
205
+ ### Evervault::Models::Cage.run
206
+
207
+ Each Cage model exposes a `run` method, which allows you to run that particular cage.
208
+
209
+ *Note*: this does not encrypt data before running the cage
210
+ ```ruby
211
+ cage = Evervault.cage_list.cages[0]
212
+ cage.run({'name': 'testing'})
213
+ => {"result"=>{"message"=>"Hello, world!", "details"=>"Please send an encrypted `name` parameter to show cage decryption in action"}, "runId"=>"5428800061ff"}
214
+ ```
215
+
216
+ | Parameter | Type | Description |
217
+ | --------- | ---- | ----------- |
218
+ | data | Hash | Payload for the cage |
219
+
220
+ ## Development
221
+
222
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
223
+
224
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
225
+
226
+ ## Contributing
227
+
228
+ Bug reports and pull requests are welcome on GitHub at https://github.com/evervault/evervault-ruby.
229
+
230
+
231
+ ## License
232
+
233
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "evervault"
5
+ require "pry"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "pry"
15
+ Pry.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,25 @@
1
+ require_relative 'lib/evervault/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "evervault"
5
+ spec.version = Evervault::VERSION
6
+ spec.authors = ["Jonny O'Mahony"]
7
+ spec.email = ["jonny@evervault.com"]
8
+
9
+ spec.summary = %q{Ruby SDK to run Evervault Cages}
10
+ spec.homepage = "https://evervault.com"
11
+ spec.license = "MIT"
12
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
13
+
14
+ spec.metadata["homepage_uri"] = spec.homepage
15
+ spec.metadata["source_code_uri"] = "https://github.com/evervault/evervault-ruby"
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('..', __FILE__)) 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
+ end
@@ -0,0 +1,38 @@
1
+ require_relative "evervault/version"
2
+ require_relative "evervault/client"
3
+ require_relative "evervault/errors/errors"
4
+
5
+ module Evervault
6
+ class << self
7
+ attr_accessor :api_key
8
+
9
+ def run(cage_name, encrypted_data)
10
+ client.run(cage_name, encrypted_data)
11
+ end
12
+
13
+ def encrypt_and_run(cage_name, data)
14
+ client.encrypt_and_run(cage_name, data)
15
+ end
16
+
17
+ def encrypt(data)
18
+ client.encrypt(data)
19
+ end
20
+
21
+ def cages
22
+ client.cages
23
+ end
24
+
25
+ def cage_list
26
+ client.cage_list
27
+ end
28
+
29
+ private def client
30
+ if api_key.nil?
31
+ raise Evervault::Errors::AuthenticationError.new(
32
+ "Please enter your team's API Key"
33
+ )
34
+ end
35
+ @client ||= Evervault::Client.new(api_key: api_key)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,50 @@
1
+ require_relative "http/request"
2
+ require_relative "crypto/client"
3
+ require_relative "models/cage_list"
4
+
5
+ module Evervault
6
+ class Client
7
+
8
+ attr_accessor :api_key, :base_url, :cage_run_url, :request_timeout
9
+ def initialize(
10
+ api_key:,
11
+ base_url: "https://api.evervault.com/",
12
+ cage_run_url: "https://cage.run/",
13
+ request_timeout: 30
14
+ )
15
+ @api_key = api_key
16
+ @base_url = base_url
17
+ @cage_run_url = cage_run_url
18
+ @request =
19
+ Evervault::Http::Request.new(
20
+ api_key: api_key,
21
+ timeout: request_timeout,
22
+ base_url: base_url,
23
+ cage_run_url: cage_run_url
24
+ )
25
+ @crypto_client = Evervault::Crypto::Client.new(request: @request)
26
+ end
27
+
28
+ def encrypt(data)
29
+ @crypto_client.encrypt(data)
30
+ end
31
+
32
+ def run(cage_name, encrypted_data)
33
+ @request.post(cage_name, encrypted_data, cage_run: true)
34
+ end
35
+
36
+ def encrypt_and_run(cage_name, data)
37
+ encrypted_data = encrypt(data)
38
+ run(cage_name, encrypted_data)
39
+ end
40
+
41
+ def cages
42
+ cage_list.to_hash
43
+ end
44
+
45
+ def cage_list
46
+ cages = @request.get("cages")
47
+ @cage_list ||= Evervault::Models::CageList.new(cages: cages["cages"], request: @request)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,102 @@
1
+ require_relative "../errors/errors"
2
+ require_relative "key"
3
+ require "openssl"
4
+ require "base64"
5
+ require "json"
6
+ require "securerandom"
7
+
8
+ module Evervault
9
+ module Crypto
10
+ class Client
11
+ attr_reader :request
12
+ def initialize(request:)
13
+ @request = request
14
+ end
15
+
16
+ def encrypt(data)
17
+ raise Evervault::Errors::UndefinedDataError.new(
18
+ "Data is required for encryption"
19
+ ) if data.nil? || data.empty?
20
+
21
+ if data.instance_of? Hash
22
+ encrypt_hash(data)
23
+ elsif encryptable_data?(data)
24
+ encrypt_string(data)
25
+ end
26
+ end
27
+
28
+ private def encrypt_string(data)
29
+ cipher = OpenSSL::Cipher::AES256.new(:GCM).encrypt
30
+ iv = cipher.random_iv
31
+ root_key = cipher.random_key
32
+ cipher.key = root_key
33
+ cipher.iv = iv
34
+ encrypted_data = cipher.update(data) + cipher.final
35
+ encrypted_buffer = encrypted_data + cipher.auth_tag
36
+ encrypted_key =
37
+ team_key.public_key.public_encrypt(
38
+ root_key,
39
+ OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING
40
+ )
41
+ data = [encrypted_key, encrypted_buffer, iv].map { |val| Base64.strict_encode64(val) }
42
+ format(header_type(data), *data)
43
+ end
44
+
45
+ private def encrypt_hash(data)
46
+ if encryptable_data?(data)
47
+ return encrypt_string(data)
48
+ elsif data.instance_of?(Hash)
49
+ encrypted_data = {}
50
+ data.each { |key, value| encrypted_data[key] = encrypt_hash(value) }
51
+ return encrypted_data
52
+ end
53
+ data
54
+ end
55
+
56
+ private def encryptable_data?(data)
57
+ data.instance_of?(String) || data.instance_of?(Array) ||
58
+ [true, false].include?(data) || data.instance_of?(Integer) ||
59
+ data.instance_of?(Float)
60
+ end
61
+
62
+ private def team_key
63
+ @team_key ||= Key.new(public_key: @request.get("cages/key")["key"])
64
+ end
65
+
66
+ private def format(header, encrypted_key, encrypted_data, iv)
67
+ header =
68
+ utf8_to_base_64_url(
69
+ { iss: "evervault", version: 1, datatype: header }.to_json
70
+ )
71
+ payload =
72
+ utf8_to_base_64_url(
73
+ {
74
+ cageData: encrypted_key,
75
+ keyIv: iv,
76
+ sharedEncryptedData: encrypted_data
77
+ }.to_json
78
+ )
79
+ "#{header}.#{payload}.#{SecureRandom.uuid}"
80
+ end
81
+
82
+ private def utf8_to_base_64_url(data)
83
+ b64_string = Base64.strict_encode64(data)
84
+ b64_string.gsub("+", "-").gsub("/", "_")
85
+ end
86
+
87
+ private def header_type(data)
88
+ if data.instance_of?(Array)
89
+ return "Array"
90
+ elsif [true, false].include?(data)
91
+ return "boolean"
92
+ elsif data.instance_of?(Hash)
93
+ return "object"
94
+ elsif data.instance_of?(Float) || data.instance_of?(Integer)
95
+ return "number"
96
+ elsif data.instance_of?(String)
97
+ return "string"
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,19 @@
1
+ require "openssl"
2
+
3
+ module Evervault
4
+ module Crypto
5
+ class Key
6
+ attr_reader :public_key
7
+ def initialize(public_key:)
8
+ @public_key = OpenSSL::PKey::RSA.new(format_key(public_key))
9
+ end
10
+
11
+ private def format_key(key)
12
+ key_header = "-----BEGIN PUBLIC KEY-----\n"
13
+ key_footer = "-----END PUBLIC KEY-----"
14
+ return key if key.include?(key_header) && key.include?(key_footer)
15
+ "#{key_header}#{key.scan(/.{0,64}/).join("\n")}#{key_footer}"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,44 @@
1
+ require_relative "errors"
2
+
3
+ module Evervault
4
+ module Errors
5
+ class ErrorMap
6
+ def self.raise_errors_on_failure(status_code, body)
7
+ return if status_code < 400
8
+ case status_code
9
+ when 404
10
+ raise ResourceNotFoundError.new("Resource Not Found")
11
+ when 400
12
+ raise BadRequestError.new("Bad request")
13
+ when 401
14
+ raise AuthenticationError.new("Unauthorized")
15
+ when 403
16
+ raise AuthenticationError.new("Forbidden")
17
+ when 500
18
+ raise ServerError.new("Server Error")
19
+ when 502
20
+ raise BadGatewayError.new("Bad Gateway Error")
21
+ when 503
22
+ raise ServiceUnavailableError.new("Service Unavailable")
23
+ else
24
+ raise UnexpectedError.new(
25
+ self.message_for_unexpected_error_without_type(body)
26
+ )
27
+ end
28
+ end
29
+
30
+ private def message_for_unexpected_error_without_type(error_details)
31
+ if error_details.nil?
32
+ return(
33
+ "An unexpected error occurred without message or status code. Please contact Evervault support"
34
+ )
35
+ end
36
+ message = error_details["message"]
37
+ status_code = error_details["statusCode"]
38
+ "An unexpected error occured. It occurred with the message: #{
39
+ message
40
+ } and http_code: '#{status_code}'. Please contact Evervault support"
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,27 @@
1
+ module Evervault
2
+ module Errors
3
+ class EvervaultError < StandardError; end
4
+
5
+ class ArgumentError < EvervaultError; end
6
+
7
+ class HttpError < EvervaultError; end
8
+
9
+ class ResourceNotFoundError < EvervaultError; end
10
+
11
+ class AuthenticationError < EvervaultError; end
12
+
13
+ class ServerError < EvervaultError; end
14
+
15
+ class BadGatewayError < EvervaultError; end
16
+
17
+ class ServiceUnavailableError < EvervaultError; end
18
+
19
+ class BadRequestError < EvervaultError; end
20
+
21
+ class UndefinedDataError < EvervaultError; end
22
+
23
+ class InvalidPublicKeyError < EvervaultError; end
24
+
25
+ class UnexpectedError < EvervaultError; end
26
+ end
27
+ end
@@ -0,0 +1,69 @@
1
+ require "typhoeus"
2
+ require "json"
3
+ require_relative "../version"
4
+ require_relative "../errors/error_map"
5
+
6
+ module Evervault
7
+ module Http
8
+ class Request
9
+ def initialize(api_key:, base_url:, cage_run_url:, timeout:)
10
+ @api_key = api_key
11
+ @timeout = timeout
12
+ @base_url = base_url
13
+ @cage_run_url = cage_run_url
14
+ end
15
+
16
+ def get(path, params = nil)
17
+ execute(:get, build_url(path), params)
18
+ end
19
+
20
+ def put(path, params)
21
+ execute(:put, build_url(path), params)
22
+ end
23
+
24
+ def delete(path, params)
25
+ execute(:delete, build_url(path), params)
26
+ end
27
+
28
+ def post(path, params, cage_run: false)
29
+ execute(:post, build_url(path, cage_run), params)
30
+ end
31
+
32
+ private def build_url(path, cage_run = false)
33
+ return "#{@base_url}#{path}" unless cage_run
34
+ "#{@cage_run_url}#{path}"
35
+ end
36
+
37
+ def execute(method, url, params)
38
+ req =
39
+ Typhoeus::Request.new(
40
+ url,
41
+ method: method,
42
+ params: params,
43
+ headers: build_headers
44
+ )
45
+ req.on_complete do |response|
46
+ if response.success?
47
+ return JSON.parse(response.body)
48
+ else
49
+ Evervault::Errors::ErrorMap.raise_errors_on_failure(
50
+ response.code,
51
+ response.body
52
+ )
53
+ end
54
+ end
55
+ resp = req.run
56
+ end
57
+
58
+ private def build_headers
59
+ {
60
+ "User-Agent": "evervault-ruby/#{VERSION}",
61
+ "AcceptEncoding": "gzip, deflate",
62
+ "Accept": "application/json",
63
+ "Content-Type": "application/json",
64
+ "Api-Key": @api_key
65
+ }
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,18 @@
1
+ module Evervault
2
+ module Models
3
+ class Cage
4
+
5
+ attr_reader :name, :uuid
6
+ def initialize(name:, uuid:, request:)
7
+ @name = name
8
+ @uuid = uuid
9
+ @request = request
10
+ end
11
+
12
+ def run(params)
13
+ @request.post(self.name, params, cage_run: true)
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ require_relative "cage"
2
+
3
+ module Evervault
4
+ module Models
5
+ class CageList
6
+ attr_reader :cages
7
+ def initialize(cages:, request:)
8
+ @cages = build_cage_list(cages, request)
9
+ end
10
+
11
+ def to_hash
12
+ cage_hash = {}
13
+ cages.each { |cage| cage_hash[cage.name] = cage }
14
+ cage_hash
15
+ end
16
+
17
+ private def build_cage_list(cages, request)
18
+ cages.map { |cage| Cage.new(name: cage["name"], uuid: cage["uuid"], request: request) }
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module Evervault
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: evervault
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jonny O'Mahony
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-10-22 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ - jonny@evervault.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".github/workflows/run-tests.yml"
21
+ - ".gitignore"
22
+ - ".rspec"
23
+ - Gemfile
24
+ - Gemfile.lock
25
+ - LICENSE.txt
26
+ - README.md
27
+ - Rakefile
28
+ - bin/console
29
+ - bin/setup
30
+ - evervault.gemspec
31
+ - lib/evervault.rb
32
+ - lib/evervault/client.rb
33
+ - lib/evervault/crypto/client.rb
34
+ - lib/evervault/crypto/key.rb
35
+ - lib/evervault/errors/error_map.rb
36
+ - lib/evervault/errors/errors.rb
37
+ - lib/evervault/http/request.rb
38
+ - lib/evervault/models/cage.rb
39
+ - lib/evervault/models/cage_list.rb
40
+ - lib/evervault/version.rb
41
+ homepage: https://evervault.com
42
+ licenses:
43
+ - MIT
44
+ metadata:
45
+ homepage_uri: https://evervault.com
46
+ source_code_uri: https://github.com/evervault/evervault-ruby
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: 2.3.0
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ requirements: []
62
+ rubygems_version: 3.1.2
63
+ signing_key:
64
+ specification_version: 4
65
+ summary: Ruby SDK to run Evervault Cages
66
+ test_files: []