evervault 1.3.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2df77a79ce53a19ab616f270d0cef3fd7639e23bf4b25a2cd75bb5b70e95dbc4
4
- data.tar.gz: 71a830838eaa042e50299b827826327a7b6ed48b3a747ab395746afce754d7e6
3
+ metadata.gz: d24159a979aa8a8a684447e804ce5280bb03946ff7b81847d3ca34cdc794c488
4
+ data.tar.gz: 5b5c762a8abab38f848c506acf3674a8b39357d06f4d57c2fd4d71e8949c2886
5
5
  SHA512:
6
- metadata.gz: f1cd19d8dc2d3c09a8a10958119bb788082b809dd50aec730562116b2146f1b84d33d0e234bd86529ff982d3148749a428041c0e43ea35da733b4a32eb4f922b
7
- data.tar.gz: 17e6c1952d3af892c05a90b2165ee71a8849ae0cea637635c0914f23335a28b450ba9c326e0b9b60f325cd9ee50c5333e19892ec11195a30e35370972b19f222
6
+ metadata.gz: 3e4b9c709918dd7623c7c5209d7b0848a9eef6f1c80c016234f266eb9ecca3994229f298e5001b2a14341fe687b52b37672705971366f7d027a2e91f2639528f
7
+ data.tar.gz: f11ad2a4010f1aaf6f1c11efe6e5fb1fe9db8f4efae07e581de4eaef7af41b8f78adf3e348182c8b65cbad694fe85009786da9da6d5ea7fc4d05fe7142942cae
@@ -11,16 +11,16 @@ jobs:
11
11
  fail-fast: false
12
12
  matrix:
13
13
  os: [ubuntu, macos]
14
- ruby: [2.5, 2.6, 2.7, 3.1, truffleruby]
14
+ ruby: [2.6, 2.7, 3.1, truffleruby]
15
15
  runs-on: ${{ matrix.os }}-latest
16
16
  continue-on-error: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'debug' }}
17
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
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
24
24
 
25
25
  build:
26
26
  runs-on: ubuntu-latest
@@ -7,13 +7,13 @@ jobs:
7
7
  fail-fast: false
8
8
  matrix:
9
9
  os: [ubuntu, macos]
10
- ruby: [2.5, 2.6, 2.7, 3.1, truffleruby]
10
+ ruby: [2.6, 2.7, 3.1, truffleruby]
11
11
  runs-on: ${{ matrix.os }}-latest
12
12
  continue-on-error: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'debug' }}
13
13
  steps:
14
- - uses: actions/checkout@v2
15
- - uses: ruby/setup-ruby@v1
16
- with:
17
- ruby-version: ${{ matrix.ruby }}
18
- - run: bundle install
19
- - run: bundle exec rake
14
+ - uses: actions/checkout@v2
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: ${{ matrix.ruby }}
18
+ - run: bundle install
19
+ - run: bundle exec rake
data/README.md CHANGED
@@ -48,11 +48,15 @@ To make Evervault available for use in your app:
48
48
  ```ruby
49
49
  require "evervault"
50
50
 
51
- # Initialize the client with your team's API key
51
+ # Initialize the client with your App's ID and App's API key
52
+ Evervault.app_id = <YOUR-APP-ID>
52
53
  Evervault.api_key = <YOUR-API-KEY>
53
54
 
54
55
  # Encrypt your data
55
- encrypted_data = Evervault.encrypt({ hello: 'World!' })
56
+ encrypted_data = Evervault.encrypt('Hello World!')
57
+
58
+ # Decrypt your data
59
+ decrypted = Evervault.decrypt(encrypted_data)
56
60
 
57
61
  # Process the encrypted data using a Function
58
62
  result = Evervault.run(<FUNCTION-NAME>, encrypted_data)
@@ -65,6 +69,7 @@ req.body = encrypted_data.to_json
65
69
  http = Net::HTTP.new(uri.host, uri.port)
66
70
  http.use_ssl = true
67
71
  res = http.request(req)
72
+
68
73
  ```
69
74
 
70
75
  ## Reference
@@ -79,13 +84,41 @@ The Evervault Ruby SDK exposes four methods.
79
84
  Evervault.encrypt(data = String | Number | Boolean | Hash | Array)
80
85
  ```
81
86
 
82
- | Parameter | Type | Description |
83
- | --------- | ---- | ----------- |
84
- | data | `String`, `Number`, `Boolean`, `Hash`, `Array` | Data to be encrypted |
87
+ | Parameter | Type | Description |
88
+ | --------- | ---------------------------------------------- | -------------------- |
89
+ | data | `String`, `Number`, `Boolean`, `Hash`, `Array` | Data to be encrypted |
90
+
91
+ ### Evervault.decrypt
92
+
93
+ `Evervault.decrypt` decrypts data previously encrypted with the `encrypt()` function or through Evervault's Relay (Evervault's encryption proxy).
94
+ An API Key with the `decrypt` permission must be used to perform this operation.
95
+
96
+ ```ruby
97
+ Evervault.decrypt(data = String | Array | Hash)
98
+ ```
99
+
100
+ | Parameter | Type | Description |
101
+ | --------- | ------------------------- | -------------------- |
102
+ | data | `String`, `Array`, `Hash` | Data to be decrypted |
103
+
104
+ ### Evervault.create_client_side_decrypt_token
105
+ `Evervault.create_client_side_token` is used to generate a time-bound token that can be used by front-end applications to decrypt Evervault encrypted data.
106
+
107
+ ```ruby
108
+ time_now = Time.now
109
+ time_in_five_minutes = time_now + 300
110
+ Evervault.create_client_side_decrypt_token(encrypted_data, time_in_five_minutes)
111
+ ```
112
+
113
+ | Parameter | Type | Description |
114
+ | --------- | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
115
+ | data | `String`, `Array`, `Hash` | The payload the token can be used to decrypt. |
116
+ | expiry | `Time` | Optional -- The time the token should expire. The max expiry is 10 minutes in the future. If not supplied it defaults to 5 minutes |
117
+
85
118
 
86
119
  ### Evervault.enable_outbound_relay
87
120
 
88
- `Evervault.enable_outbound_relay` configures your application to proxy HTTP requests using Outbound Relay based on the configuration created in the Evervault UI. See [Outbound Relay](https://docs.evervault.com/concepts/outbound-relay/overview) to learn more.
121
+ `Evervault.enable_outbound_relay` configures your application to proxy HTTP requests using Outbound Relay based on the configuration created in the Evervault UI. See [Outbound Relay](https://docs.evervault.com/concepts/outbound-relay/overview) to learn more.
89
122
 
90
123
  ```ruby
91
124
  Evervault.enable_outbound_relay([decryption_domains = Array])
@@ -98,6 +131,7 @@ Evervault.enable_outbound_relay([decryption_domains = Array])
98
131
  ### Evervault.run
99
132
 
100
133
  `Evervault.run` invokes a Function with a given payload.
134
+ An API Key with the `run Function` permission must be used to perform this operation.
101
135
 
102
136
  ```ruby
103
137
  Evervault.run(function_name = String, data = Hash[, options = Hash])
@@ -119,6 +153,7 @@ Evervault.run(function_name = String, data = Hash[, options = Hash])
119
153
  ### Evervault.create_run_token
120
154
 
121
155
  `Evervault.create_run_token` creates a single use, time bound token for invoking a Function.
156
+ An API Key with the `create Run Token` permission must be used to perform this operation.
122
157
 
123
158
  ```ruby
124
159
  Evervault.create_run_token(function_name = String, data = Hash)
@@ -8,23 +8,25 @@ require_relative "crypto/client"
8
8
  module Evervault
9
9
  class Client
10
10
 
11
- attr_accessor :api_key, :base_url, :cage_run_url, :request_timeout
11
+ attr_accessor :function_run_url
12
12
  def initialize(
13
+ app_uuid:,
13
14
  api_key:,
14
15
  base_url: "https://api.evervault.com/",
15
- cage_run_url: "https://run.evervault.com/",
16
+ function_run_url: "https://run.evervault.com/",
16
17
  relay_url: "https://relay.evervault.com:8443",
17
18
  ca_host: "https://ca.evervault.com",
18
19
  request_timeout: 30,
19
20
  curve: 'prime256v1'
20
21
  )
21
- @request = Evervault::Http::Request.new(timeout: request_timeout, api_key: api_key)
22
+ @function_run_url = function_run_url
23
+ @request = Evervault::Http::Request.new(timeout: request_timeout, app_uuid: app_uuid, api_key: api_key)
22
24
  @intercept = Evervault::Http::RequestIntercept.new(
23
25
  request: @request, ca_host: ca_host, api_key: api_key, base_url: base_url, relay_url: relay_url
24
26
  )
25
27
  @request_handler =
26
28
  Evervault::Http::RequestHandler.new(
27
- request: @request, base_url: base_url, cage_run_url: cage_run_url, cert: @intercept
29
+ request: @request, base_url: base_url, cert: @intercept
28
30
  )
29
31
  @crypto_client = Evervault::Crypto::Client.new(request_handler: @request_handler, curve: curve)
30
32
  @intercept.setup()
@@ -34,8 +36,37 @@ module Evervault
34
36
  @crypto_client.encrypt(data)
35
37
  end
36
38
 
37
- def run(function_name, encrypted_data, options = {})
38
- @request_handler.post(function_name, encrypted_data, options: options, cage_run: true)
39
+ def decrypt(data)
40
+ unless data.is_a?(String) || data.is_a?(Array) || data.is_a?(Hash)
41
+ raise Evervault::Errors::ArgumentError.new("data is of invalid type")
42
+ end
43
+ payload = { data: data }
44
+ response = @request_handler.post("decrypt", payload, nil, nil, true)
45
+ response["data"]
46
+ end
47
+
48
+ def create_token(action, data, expiry = nil)
49
+ payload = { payload: data, expiry: expiry, action: action }
50
+ @request_handler.post("client-side-tokens", payload, nil, nil, true)
51
+ end
52
+
53
+ def run(function_name, payload, options = {})
54
+ optional_headers = {}
55
+ if options.key?(:async)
56
+ if options[:async]
57
+ optional_headers["x-async"] = "true"
58
+ end
59
+ end
60
+ if options.key?(:version)
61
+ if options[:version].is_a? Integer
62
+ optional_headers["x-version-id"] = options[:version].to_s
63
+ end
64
+ end
65
+ @request_handler.post(function_name, payload, optional_headers, @function_run_url)
66
+ end
67
+
68
+ def create_run_token(function_name, data = {})
69
+ @request_handler.post("v2/functions/#{function_name}/run-token", data)
39
70
  end
40
71
 
41
72
  def enable_outbound_relay(decryption_domains = nil)
@@ -45,9 +76,5 @@ module Evervault
45
76
  @intercept.setup_decryption_domains(decryption_domains)
46
77
  end
47
78
  end
48
-
49
- def create_run_token(function_name, data = {})
50
- @request_handler.post("v2/functions/#{function_name}/run-token", data)
51
- end
52
79
  end
53
80
  end
@@ -6,31 +6,52 @@ require_relative "../errors/error_map"
6
6
  module Evervault
7
7
  module Http
8
8
  class Request
9
- def initialize(timeout:, api_key:)
9
+ def initialize(timeout:, app_uuid:, api_key:)
10
10
  @timeout = timeout
11
+ @app_uuid = app_uuid
11
12
  @api_key = api_key
12
13
  end
13
14
 
14
- def execute(method, url, params, optional_headers = {})
15
- resp = Faraday.send(method, url) do |req|
16
- req.body = params.nil? || params.empty? ? nil : params.to_json
17
- req.headers = build_headers(optional_headers)
15
+ def execute(method, url, body = nil, optional_headers = {}, basic_auth = false)
16
+ resp = faraday(basic_auth).public_send(method, url) do |req, url|
17
+ req.body = body.nil? || body.empty? ? nil : body.to_json
18
+ req.headers = build_headers(optional_headers, basic_auth)
18
19
  req.options.timeout = @timeout
19
20
  end
21
+
20
22
  if resp.status >= 200 && resp.status <= 300
21
23
  return resp
22
24
  end
25
+
23
26
  Evervault::Errors::ErrorMap.raise_errors_on_failure(resp.status, resp.body, resp.headers)
24
27
  end
25
28
 
26
- private def build_headers(optional_headers)
27
- optional_headers.merge({
29
+ private
30
+
31
+ def faraday(basic_auth = false)
32
+ Faraday.new do |conn|
33
+ if basic_auth
34
+ conn.request :authorization, :basic, @app_uuid, @api_key
35
+ end
36
+ end
37
+ end
38
+
39
+ def build_headers(optional_headers = {}, basic_auth = false)
40
+ headers = {
28
41
  "AcceptEncoding": "gzip, deflate",
29
42
  "Accept": "application/json",
30
43
  "Content-Type": "application/json",
31
44
  "User-Agent": "evervault-ruby/#{VERSION}",
32
- "Api-Key": @api_key,
33
- })
45
+ }
46
+ unless optional_headers.nil? || optional_headers.empty?
47
+ headers = headers.merge(optional_headers)
48
+ end
49
+ if !basic_auth
50
+ headers = headers.merge({
51
+ "Api-Key": @api_key,
52
+ })
53
+ end
54
+ headers
34
55
  end
35
56
  end
36
57
  end
@@ -6,70 +6,51 @@ require_relative "../errors/error_map"
6
6
  module Evervault
7
7
  module Http
8
8
  class RequestHandler
9
- def initialize(request:, base_url:, cage_run_url:, cert:)
9
+ def initialize(request:, base_url:, cert:)
10
10
  @request = request
11
11
  @base_url = base_url
12
- @cage_run_url = cage_run_url
13
12
  @cert = cert
14
13
  end
15
14
 
16
- def get(path, params = nil)
15
+ def get(path)
17
16
  if @cert.is_certificate_expired()
18
17
  @cert.setup()
19
18
  end
20
- resp = @request.execute(:get, build_url(path), params)
19
+ resp = @request.execute(:get, build_url(path))
21
20
  parse_json_body(resp.body)
22
21
  end
23
22
 
24
- def put(path, params)
23
+ def put(path, body)
25
24
  if @cert.is_certificate_expired()
26
25
  @cert.setup()
27
26
  end
28
- resp = @request.execute(:put, build_url(path), params)
27
+ resp = @request.execute(:put, build_url(path), body)
29
28
  parse_json_body(resp.body)
30
29
  end
31
30
 
32
- def delete(path, params)
31
+ def delete(path)
33
32
  if @cert.is_certificate_expired()
34
33
  @cert.setup()
35
34
  end
36
- resp = @request.execute(:delete, build_url(path), params)
35
+ resp = @request.execute(:delete, build_url(path))
37
36
  parse_json_body(resp.body)
38
37
  end
39
38
 
40
- def post(path, params, options: {}, cage_run: false)
39
+ def post(path, body, optional_headers = {}, alternative_base_url = nil, basic_auth = false)
41
40
  if @cert.is_certificate_expired()
42
41
  @cert.setup()
43
42
  end
44
- resp = @request.execute(:post, build_url(path, cage_run), params, build_cage_run_headers(options, cage_run))
45
- parse_json_body(resp.body)
43
+ resp = @request.execute(:post, build_url(path, alternative_base_url), body, optional_headers, basic_auth)
44
+ return parse_json_body(resp.body) unless resp.body.empty?
46
45
  end
47
46
 
48
47
  private def parse_json_body(body)
49
48
  JSON.parse(body)
50
49
  end
51
50
 
52
- private def build_url(path, cage_run = false)
53
- return "#{@base_url}#{path}" unless cage_run
54
- "#{@cage_run_url}#{path}"
55
- end
56
-
57
- private def build_cage_run_headers(options, cage_run = false)
58
- optional_headers = {}
59
- return optional_headers unless cage_run
60
- if options.key?(:async)
61
- if options[:async]
62
- optional_headers["x-async"] = "true"
63
- end
64
- options.delete(:async)
65
- end
66
- if options.key?(:version)
67
- if options[:version].is_a? Integer
68
- optional_headers["x-version-id"] = options[:version].to_s
69
- end
70
- options.delete(:version)
71
- end
72
- optional_headers.merge(options)
51
+ private def build_url(path, alternative_base_url = nil)
52
+ return "#{@base_url}#{path}" unless alternative_base_url
53
+ "#{alternative_base_url}#{path}"
73
54
  end
74
55
  end
75
56
  end
@@ -0,0 +1,31 @@
1
+ require 'digest'
2
+
3
+ module Evervault
4
+ module Utils
5
+ class ValidationUtils
6
+
7
+ def self.validate_app_uuid_and_api_key(app_uuid, api_key)
8
+ if app_uuid.nil?
9
+ raise Evervault::Errors::AuthenticationError.new(
10
+ "No App ID provided. The App ID can be retrieved in the Evervault dashboard (App Settings)."
11
+ )
12
+ end
13
+ if api_key.nil?
14
+ raise Evervault::Errors::AuthenticationError.new(
15
+ "The provided App ID is invalid. The App ID can be retrieved in the Evervault dashboard (App Settings)."
16
+ )
17
+ end
18
+ if api_key.start_with?('ev:key')
19
+ # Scoped API key
20
+ app_uuid_hash = Digest::SHA512.base64digest(app_uuid)[0, 6]
21
+ app_uuid_hash_from_api_key = api_key.split(':')[4]
22
+ if app_uuid_hash != app_uuid_hash_from_api_key
23
+ raise Evervault::Errors::AuthenticationError.new(
24
+ "The API key is not valid for app #{app_uuid}. Make sure to use an API key belonging to the app #{app_uuid}."
25
+ )
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,4 +1,4 @@
1
1
  module Evervault
2
- VERSION = "1.3.2"
2
+ VERSION = "2.1.0"
3
3
  EV_VERSION = {"prime256v1" => "NOC", "secp256k1" => "DUB"}
4
4
  end
data/lib/evervault.rb CHANGED
@@ -1,15 +1,22 @@
1
+ require "time"
1
2
  require_relative "evervault/version"
2
3
  require_relative "evervault/client"
3
4
  require_relative "evervault/errors/errors"
5
+ require_relative "evervault/utils/validation_utils"
4
6
 
5
7
  module Evervault
6
8
  class << self
9
+ attr_accessor :app_id
7
10
  attr_accessor :api_key
8
11
 
9
12
  def encrypt(data)
10
13
  client.encrypt(data)
11
14
  end
12
15
 
16
+ def decrypt(data)
17
+ client.decrypt(data)
18
+ end
19
+
13
20
  def run(function_name, encrypted_data, options = {})
14
21
  client.run(function_name, encrypted_data, options)
15
22
  end
@@ -22,13 +29,16 @@ module Evervault
22
29
  client.create_run_token(function_name, data)
23
30
  end
24
31
 
25
- private def client
26
- if api_key.nil?
27
- raise Evervault::Errors::AuthenticationError.new(
28
- "Please enter your team's API Key"
29
- )
32
+ def create_client_side_decrypt_token(data, expiry = nil)
33
+ if expiry != nil
34
+ expiry = (expiry.to_f * 1000).to_i
30
35
  end
31
- @client ||= Evervault::Client.new(api_key: api_key)
36
+ client.create_token("api:decrypt", data, expiry)
37
+ end
38
+
39
+ private def client
40
+ Evervault::Utils::ValidationUtils.validate_app_uuid_and_api_key(app_id, api_key)
41
+ @client ||= Evervault::Client.new(app_uuid: app_id, api_key: api_key)
32
42
  end
33
43
  end
34
44
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: evervault
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonny O'Mahony
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-04-22 00:00:00.000000000 Z
11
+ date: 2023-08-23 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -42,6 +42,7 @@ files:
42
42
  - lib/evervault/http/request_handler.rb
43
43
  - lib/evervault/http/request_intercept.rb
44
44
  - lib/evervault/threading/repeated_timer.rb
45
+ - lib/evervault/utils/validation_utils.rb
45
46
  - lib/evervault/version.rb
46
47
  - res/logo.svg
47
48
  - res/logo512.png