evervault 2.0.0 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.changeset/config.json +15 -0
- data/.github/dependabot.yml +11 -0
- data/.github/workflows/e2e.yml +25 -0
- data/.github/workflows/linters.yml +23 -0
- data/.github/workflows/release.yml +51 -32
- data/.github/workflows/run-tests.yml +5 -5
- data/.gitignore +7 -1
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +43 -0
- data/Gemfile +11 -8
- data/LICENSE.txt +1 -1
- data/README.md +1 -152
- data/Rakefile +21 -4
- data/bin/console +7 -4
- data/evervault.gemspec +18 -12
- data/lib/evervault/client.rb +66 -49
- data/lib/evervault/config.rb +17 -0
- data/lib/evervault/crypto/client.rb +151 -81
- data/lib/evervault/crypto/curves/base.rb +20 -10
- data/lib/evervault/crypto/curves/koblitz.rb +26 -0
- data/lib/evervault/crypto/curves/p256.rb +12 -9
- data/lib/evervault/errors/error_map.rb +24 -36
- data/lib/evervault/errors/errors.rb +15 -22
- data/lib/evervault/errors/legacy_error_map.rb +52 -0
- data/lib/evervault/http/relay_outbound_config.rb +25 -23
- data/lib/evervault/http/request.rb +26 -31
- data/lib/evervault/http/request_handler.rb +22 -25
- data/lib/evervault/http/request_intercept.rb +39 -42
- data/lib/evervault/threading/repeated_timer.rb +12 -10
- data/lib/evervault/utils/validation_utils.rb +17 -18
- data/lib/evervault/version.rb +4 -2
- data/lib/evervault.rb +35 -19
- data/package.json +11 -0
- metadata +66 -9
@@ -1,33 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Evervault
|
2
4
|
module Errors
|
3
5
|
class EvervaultError < StandardError; end
|
4
6
|
|
5
|
-
class
|
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
|
7
|
+
class FunctionError < EvervaultError; end
|
22
8
|
|
23
|
-
class
|
9
|
+
class ForbiddenIPError < FunctionError; end
|
24
10
|
|
25
|
-
class
|
11
|
+
class FunctionTimeoutError < FunctionError; end
|
26
12
|
|
27
|
-
class
|
13
|
+
class FunctionNotReadyError < FunctionError; end
|
28
14
|
|
29
|
-
class
|
15
|
+
class FunctionRuntimeError < FunctionError
|
16
|
+
attr_reader :message, :stack, :id
|
30
17
|
|
31
|
-
|
18
|
+
def initialize(message, stack, id)
|
19
|
+
@message = message
|
20
|
+
@stack = stack
|
21
|
+
@id = id
|
22
|
+
super(message.to_s)
|
23
|
+
end
|
24
|
+
end
|
32
25
|
end
|
33
26
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'errors'
|
4
|
+
|
5
|
+
module Evervault
|
6
|
+
module Errors
|
7
|
+
class LegacyErrorMap
|
8
|
+
def self.raise_errors_on_failure(status_code, body, headers)
|
9
|
+
return if status_code < 400
|
10
|
+
|
11
|
+
case status_code
|
12
|
+
when 404
|
13
|
+
raise EvervaultError, 'Resource not found'
|
14
|
+
when 400
|
15
|
+
raise EvervaultError, 'Bad request'
|
16
|
+
when 401
|
17
|
+
raise EvervaultError, 'Unauthorized'
|
18
|
+
when 403
|
19
|
+
if (headers.include? 'x-evervault-error-code') && (headers['x-evervault-error-code'] == 'forbidden-ip-error')
|
20
|
+
raise ForbiddenIPError, 'IP is not present in Cage whitelist'
|
21
|
+
end
|
22
|
+
|
23
|
+
raise EvervaultError, 'Forbidden'
|
24
|
+
|
25
|
+
when 500
|
26
|
+
raise EvervaultError, 'Server error'
|
27
|
+
when 502
|
28
|
+
raise EvervaultError, 'Bad gateway error'
|
29
|
+
when 503
|
30
|
+
raise EvervaultError, 'Service unavailable'
|
31
|
+
else
|
32
|
+
raise EvervaultError, message_for_unexpected_error_without_type(body)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def message_for_unexpected_error_without_type(error_details)
|
39
|
+
if error_details.nil?
|
40
|
+
return(
|
41
|
+
'An unexpected error occurred without message or status code. Please contact Evervault support'
|
42
|
+
)
|
43
|
+
end
|
44
|
+
message = error_details['message']
|
45
|
+
status_code = error_details['statusCode']
|
46
|
+
"An unexpected error occured. It occurred with the message: #{
|
47
|
+
message
|
48
|
+
} and http_code: '#{status_code}'. Please contact Evervault support"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Evervault
|
2
4
|
module Http
|
3
5
|
class RelayOutboundConfig
|
4
6
|
DEFAULT_POLL_INTERVAL = 5
|
5
|
-
RELAY_OUTBOUND_CONFIG_API_ENDPOINT =
|
7
|
+
RELAY_OUTBOUND_CONFIG_API_ENDPOINT = 'v2/relay-outbound'
|
6
8
|
|
7
9
|
@@destination_domains_cache = nil
|
8
10
|
@@poll_interval = DEFAULT_POLL_INTERVAL
|
@@ -11,12 +13,10 @@ module Evervault
|
|
11
13
|
def initialize(base_url:, request:)
|
12
14
|
@base_url = base_url
|
13
15
|
@request = request
|
14
|
-
if @@destination_domains_cache.nil?
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
@@timer = Evervault::Threading::RepeatedTimer.new(@@poll_interval, -> { get_relay_outbound_config })
|
19
|
-
end
|
16
|
+
get_relay_outbound_config if @@destination_domains_cache.nil?
|
17
|
+
return unless @@timer.nil?
|
18
|
+
|
19
|
+
@@timer = Evervault::Threading::RepeatedTimer.new(@@poll_interval, -> { get_relay_outbound_config })
|
20
20
|
end
|
21
21
|
|
22
22
|
def get_destination_domains
|
@@ -24,32 +24,34 @@ module Evervault
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def self.disable_polling
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
return if @@timer.nil?
|
28
|
+
|
29
|
+
@@timer.stop
|
30
|
+
@@timer = nil
|
31
31
|
end
|
32
32
|
|
33
33
|
def self.clear_cache
|
34
34
|
@@destination_domains_cache = nil
|
35
35
|
end
|
36
36
|
|
37
|
-
private
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
37
|
+
private
|
38
|
+
|
39
|
+
def get_relay_outbound_config
|
40
|
+
resp = @request.execute(:get, "#{@base_url}#{RELAY_OUTBOUND_CONFIG_API_ENDPOINT}")
|
41
|
+
poll_interval = resp.headers['x-poll-interval']
|
42
|
+
update_poll_interval(poll_interval.to_f) unless poll_interval.nil?
|
43
43
|
resp_body = JSON.parse(resp.body)
|
44
|
-
@@destination_domains_cache = resp_body[
|
44
|
+
@@destination_domains_cache = resp_body['outboundDestinations'].values.map do |outbound_destination|
|
45
|
+
outbound_destination['destinationDomain']
|
46
|
+
end
|
45
47
|
end
|
46
48
|
|
47
|
-
|
49
|
+
def update_poll_interval(poll_interval)
|
48
50
|
@@poll_interval = poll_interval
|
49
|
-
|
50
|
-
|
51
|
-
|
51
|
+
return if @@timer.nil?
|
52
|
+
|
53
|
+
@@timer.update_interval(poll_interval)
|
52
54
|
end
|
53
55
|
end
|
54
56
|
end
|
55
|
-
end
|
57
|
+
end
|
@@ -1,55 +1,50 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
require 'json'
|
5
|
+
require_relative '../version'
|
6
|
+
require_relative '../errors/legacy_error_map'
|
5
7
|
|
6
8
|
module Evervault
|
7
9
|
module Http
|
8
10
|
class Request
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
@
|
11
|
+
attr_reader :config
|
12
|
+
|
13
|
+
def initialize(config:)
|
14
|
+
@config = config
|
13
15
|
end
|
14
16
|
|
15
|
-
def execute(method, url, body = nil,
|
16
|
-
resp = faraday(basic_auth).public_send(method, url) do |req,
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
def execute(method, url, body = nil, basic_auth = false, error_map = Evervault::Errors::LegacyErrorMap)
|
18
|
+
resp = faraday(basic_auth).public_send(method, url) do |req, _url|
|
19
|
+
req.body = body.nil? || body.empty? ? nil : body.to_json
|
20
|
+
req.headers = build_headers(basic_auth)
|
21
|
+
req.options.timeout = config.request_timeout
|
20
22
|
end
|
21
23
|
|
22
|
-
if resp.status >= 200 && resp.status <= 300
|
23
|
-
return resp
|
24
|
-
end
|
24
|
+
return resp if resp.status >= 200 && resp.status <= 300
|
25
25
|
|
26
|
-
|
26
|
+
error_map.raise_errors_on_failure(resp.status, resp.body, resp.headers)
|
27
27
|
end
|
28
28
|
|
29
29
|
private
|
30
30
|
|
31
31
|
def faraday(basic_auth = false)
|
32
32
|
Faraday.new do |conn|
|
33
|
-
if basic_auth
|
34
|
-
conn.request :authorization, :basic, @app_uuid, @api_key
|
35
|
-
end
|
33
|
+
conn.request :authorization, :basic, config.app_id, config.api_key if basic_auth
|
36
34
|
end
|
37
35
|
end
|
38
36
|
|
39
|
-
def build_headers(
|
37
|
+
def build_headers(basic_auth = false)
|
40
38
|
headers = {
|
41
|
-
"AcceptEncoding":
|
42
|
-
"Accept":
|
43
|
-
"Content-Type":
|
44
|
-
"User-Agent": "evervault-ruby/#{VERSION}"
|
39
|
+
"AcceptEncoding": 'gzip, deflate',
|
40
|
+
"Accept": 'application/json',
|
41
|
+
"Content-Type": 'application/json',
|
42
|
+
"User-Agent": "evervault-ruby/#{VERSION}"
|
45
43
|
}
|
46
|
-
unless
|
47
|
-
headers = headers.merge(optional_headers)
|
48
|
-
end
|
49
|
-
if !basic_auth
|
44
|
+
unless basic_auth
|
50
45
|
headers = headers.merge({
|
51
|
-
|
52
|
-
|
46
|
+
"Api-Key": config.api_key
|
47
|
+
})
|
53
48
|
end
|
54
49
|
headers
|
55
50
|
end
|
@@ -1,56 +1,53 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
require 'json'
|
5
|
+
require_relative '../version'
|
6
|
+
require_relative '../errors/error_map'
|
5
7
|
|
6
8
|
module Evervault
|
7
9
|
module Http
|
8
10
|
class RequestHandler
|
9
|
-
|
11
|
+
attr_reader :config
|
12
|
+
|
13
|
+
def initialize(request:, config:, cert:)
|
10
14
|
@request = request
|
11
|
-
@
|
15
|
+
@config = config
|
12
16
|
@cert = cert
|
13
17
|
end
|
14
18
|
|
15
19
|
def get(path)
|
16
|
-
if @cert.is_certificate_expired
|
17
|
-
@cert.setup()
|
18
|
-
end
|
20
|
+
@cert.setup if @cert.is_certificate_expired
|
19
21
|
resp = @request.execute(:get, build_url(path))
|
20
22
|
parse_json_body(resp.body)
|
21
23
|
end
|
22
24
|
|
23
25
|
def put(path, body)
|
24
|
-
if @cert.is_certificate_expired
|
25
|
-
@cert.setup()
|
26
|
-
end
|
26
|
+
@cert.setup if @cert.is_certificate_expired
|
27
27
|
resp = @request.execute(:put, build_url(path), body)
|
28
28
|
parse_json_body(resp.body)
|
29
29
|
end
|
30
30
|
|
31
31
|
def delete(path)
|
32
|
-
if @cert.is_certificate_expired
|
33
|
-
@cert.setup()
|
34
|
-
end
|
32
|
+
@cert.setup if @cert.is_certificate_expired
|
35
33
|
resp = @request.execute(:delete, build_url(path))
|
36
34
|
parse_json_body(resp.body)
|
37
35
|
end
|
38
36
|
|
39
|
-
def post(path, body,
|
40
|
-
if @cert.is_certificate_expired
|
41
|
-
|
42
|
-
|
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?
|
37
|
+
def post(path, body, basic_auth = false, error_map = Evervault::Errors::LegacyErrorMap)
|
38
|
+
@cert.setup if @cert.is_certificate_expired
|
39
|
+
resp = @request.execute(:post, build_url(path), body, basic_auth, error_map)
|
40
|
+
parse_json_body(resp.body) unless resp.body.empty?
|
45
41
|
end
|
46
42
|
|
47
|
-
private
|
43
|
+
private
|
44
|
+
|
45
|
+
def parse_json_body(body)
|
48
46
|
JSON.parse(body)
|
49
47
|
end
|
50
48
|
|
51
|
-
|
52
|
-
|
53
|
-
"#{alternative_base_url}#{path}"
|
49
|
+
def build_url(path)
|
50
|
+
"#{config.base_url}#{path}"
|
54
51
|
end
|
55
52
|
end
|
56
53
|
end
|
@@ -1,10 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
require 'json'
|
5
|
+
require 'tempfile'
|
6
|
+
require 'openssl'
|
5
7
|
require 'net/http'
|
6
|
-
require_relative
|
7
|
-
require_relative
|
8
|
+
require_relative '../version'
|
9
|
+
require_relative '../errors/errors'
|
8
10
|
|
9
11
|
module NetHTTPOverride
|
10
12
|
@@api_key = nil
|
@@ -18,7 +20,7 @@ module NetHTTPOverride
|
|
18
20
|
end
|
19
21
|
|
20
22
|
def self.set_relay_url(value)
|
21
|
-
relay_address_and_port = value.gsub(
|
23
|
+
relay_address_and_port = value.gsub(%r{(^\w+:|^)//}, '').split(':')
|
22
24
|
@@relay_url = relay_address_and_port[0]
|
23
25
|
@@relay_port = relay_address_and_port[1]
|
24
26
|
end
|
@@ -35,14 +37,14 @@ module NetHTTPOverride
|
|
35
37
|
if @@get_decryption_domains_func.nil?
|
36
38
|
false
|
37
39
|
else
|
38
|
-
decryption_domains = @@get_decryption_domains_func.call
|
39
|
-
decryption_domains.any?
|
40
|
-
if decryption_domain.start_with?(
|
41
|
-
domain.end_with?(decryption_domain[1
|
40
|
+
decryption_domains = @@get_decryption_domains_func.call
|
41
|
+
decryption_domains.any? do |decryption_domain|
|
42
|
+
if decryption_domain.start_with?('*')
|
43
|
+
domain.end_with?(decryption_domain[1..])
|
42
44
|
else
|
43
45
|
domain == decryption_domain
|
44
46
|
end
|
45
|
-
|
47
|
+
end
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
@@ -59,9 +61,7 @@ module NetHTTPOverride
|
|
59
61
|
|
60
62
|
def request_with_intercept(req, body = nil, &block)
|
61
63
|
should_decrypt = NetHTTPOverride.should_decrypt(@address)
|
62
|
-
if should_decrypt
|
63
|
-
req["Proxy-Authorization"] = @@api_key
|
64
|
-
end
|
64
|
+
req['Proxy-Authorization'] = @@api_key if should_decrypt
|
65
65
|
request_without_intercept(req, body, &block)
|
66
66
|
end
|
67
67
|
end
|
@@ -77,58 +77,58 @@ end
|
|
77
77
|
module Evervault
|
78
78
|
module Http
|
79
79
|
class RequestIntercept
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
80
|
+
attr_reader :config
|
81
|
+
|
82
|
+
def initialize(request:, config:)
|
83
|
+
@config = config
|
84
|
+
NetHTTPOverride.set_api_key(config.api_key)
|
85
|
+
NetHTTPOverride.set_relay_url(config.relay_url)
|
86
|
+
|
84
87
|
@request = request
|
85
|
-
@base_url = base_url
|
86
|
-
@ca_host = ca_host
|
87
88
|
@expire_date = nil
|
88
89
|
@initial_date = nil
|
89
90
|
end
|
90
91
|
|
91
|
-
def is_certificate_expired
|
92
|
+
def is_certificate_expired
|
92
93
|
if @expire_date
|
93
94
|
now = Time.now
|
94
|
-
if now > @expire_date || now < @initial_date
|
95
|
-
return true
|
96
|
-
end
|
95
|
+
return true if now > @expire_date || now < @initial_date
|
97
96
|
end
|
98
|
-
|
97
|
+
false
|
99
98
|
end
|
100
99
|
|
101
100
|
def setup_decryption_domains(decryption_domains)
|
102
|
-
NetHTTPOverride.add_get_decryption_domains_func(
|
101
|
+
NetHTTPOverride.add_get_decryption_domains_func(lambda {
|
103
102
|
decryption_domains
|
104
103
|
})
|
105
104
|
end
|
106
105
|
|
107
106
|
def setup_outbound_relay_config
|
108
|
-
@relay_outbound_config = Evervault::Http::RelayOutboundConfig.new(base_url:
|
109
|
-
NetHTTPOverride.add_get_decryption_domains_func(
|
107
|
+
@relay_outbound_config = Evervault::Http::RelayOutboundConfig.new(base_url: config.base_url, request: @request)
|
108
|
+
NetHTTPOverride.add_get_decryption_domains_func(lambda {
|
110
109
|
@relay_outbound_config.get_destination_domains
|
111
110
|
})
|
112
111
|
end
|
113
112
|
|
114
113
|
def setup
|
115
|
-
get_cert
|
114
|
+
get_cert
|
116
115
|
end
|
117
116
|
|
118
|
-
def get_cert
|
117
|
+
def get_cert
|
119
118
|
ca_content = nil
|
120
119
|
i = 0
|
121
120
|
|
122
121
|
while !ca_content && i < 1
|
123
122
|
i += 1
|
124
123
|
begin
|
125
|
-
ca_content = @request.execute(
|
126
|
-
rescue
|
124
|
+
ca_content = @request.execute('get', config.ca_host).body
|
125
|
+
rescue StandardError
|
127
126
|
end
|
128
127
|
end
|
129
128
|
|
130
|
-
if !ca_content || ca_content ==
|
131
|
-
raise Evervault::Errors::
|
129
|
+
if !ca_content || ca_content == ''
|
130
|
+
raise Evervault::Errors::EvervaultError,
|
131
|
+
"Unable to install the Evervault root certificate from #{config.ca_host}"
|
132
132
|
end
|
133
133
|
|
134
134
|
cert = OpenSSL::X509::Certificate.new ca_content
|
@@ -137,14 +137,11 @@ module Evervault
|
|
137
137
|
end
|
138
138
|
|
139
139
|
def set_cert_expire_date(cert)
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
@expire_date = nil
|
145
|
-
end
|
140
|
+
@expire_date = cert.not_after
|
141
|
+
@initial_date = cert.not_before
|
142
|
+
rescue StandardError
|
143
|
+
@expire_date = nil
|
146
144
|
end
|
147
145
|
end
|
148
146
|
end
|
149
147
|
end
|
150
|
-
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Evervault
|
2
4
|
module Threading
|
3
5
|
class RepeatedTimer
|
@@ -9,15 +11,15 @@ module Evervault
|
|
9
11
|
end
|
10
12
|
|
11
13
|
def start
|
12
|
-
if
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
14
|
+
return if running?
|
15
|
+
|
16
|
+
@thread = Thread.new do
|
17
|
+
loop do
|
18
|
+
sleep @interval
|
19
|
+
begin
|
20
|
+
@func.call
|
21
|
+
rescue StandardError
|
22
|
+
# Silently ignore exceptions
|
21
23
|
end
|
22
24
|
end
|
23
25
|
end
|
@@ -37,4 +39,4 @@ module Evervault
|
|
37
39
|
end
|
38
40
|
end
|
39
41
|
end
|
40
|
-
end
|
42
|
+
end
|
@@ -1,31 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'digest'
|
2
4
|
|
3
5
|
module Evervault
|
4
6
|
module Utils
|
5
7
|
class ValidationUtils
|
6
|
-
|
7
8
|
def self.validate_app_uuid_and_api_key(app_uuid, api_key)
|
8
9
|
if app_uuid.nil?
|
9
|
-
raise Evervault::Errors::
|
10
|
-
|
11
|
-
)
|
10
|
+
raise Evervault::Errors::EvervaultError,
|
11
|
+
'No App ID provided. The App ID can be retrieved in the Evervault dashboard (App Settings).'
|
12
12
|
end
|
13
13
|
if api_key.nil?
|
14
|
-
raise Evervault::Errors::
|
15
|
-
|
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
|
14
|
+
raise Evervault::Errors::EvervaultError,
|
15
|
+
'The provided App ID is invalid. The App ID can be retrieved in the Evervault dashboard (App Settings).'
|
27
16
|
end
|
17
|
+
return unless api_key.start_with?('ev:key')
|
18
|
+
|
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
|
+
return unless app_uuid_hash != app_uuid_hash_from_api_key
|
23
|
+
|
24
|
+
raise Evervault::Errors::EvervaultError,
|
25
|
+
"The API key is not valid for app #{app_uuid}. Make sure to use an API key belonging to the ap'\
|
26
|
+
'p #{app_uuid}."
|
28
27
|
end
|
29
28
|
end
|
30
29
|
end
|
31
|
-
end
|
30
|
+
end
|
data/lib/evervault/version.rb
CHANGED
data/lib/evervault.rb
CHANGED
@@ -1,36 +1,52 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
require_relative
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'time'
|
4
|
+
require_relative 'evervault/version'
|
5
|
+
require_relative 'evervault/client'
|
6
|
+
require_relative 'evervault/config'
|
7
|
+
require_relative 'evervault/errors/errors'
|
8
|
+
require_relative 'evervault/utils/validation_utils'
|
5
9
|
|
6
10
|
module Evervault
|
7
11
|
class << self
|
8
|
-
attr_accessor :app_id
|
9
|
-
|
12
|
+
attr_accessor :app_id, :api_key
|
13
|
+
|
14
|
+
def encrypt(...)
|
15
|
+
client.encrypt(...)
|
16
|
+
end
|
10
17
|
|
11
|
-
def
|
12
|
-
client.
|
18
|
+
def decrypt(...)
|
19
|
+
client.decrypt(...)
|
13
20
|
end
|
14
21
|
|
15
|
-
def
|
16
|
-
client.
|
22
|
+
def run(...)
|
23
|
+
client.run(...)
|
17
24
|
end
|
18
25
|
|
19
|
-
def
|
20
|
-
client.
|
26
|
+
def enable_outbound_relay(...)
|
27
|
+
client.enable_outbound_relay(...)
|
21
28
|
end
|
22
29
|
|
23
|
-
def
|
24
|
-
client.
|
30
|
+
def create_run_token(...)
|
31
|
+
client.create_run_token(...)
|
25
32
|
end
|
26
33
|
|
27
|
-
def
|
28
|
-
|
34
|
+
def create_client_side_decrypt_token(data, expiry = nil)
|
35
|
+
expiry = (expiry.to_f * 1000).to_i unless expiry.nil?
|
36
|
+
client.create_token('api:decrypt', data, expiry)
|
29
37
|
end
|
30
38
|
|
31
|
-
|
32
|
-
|
33
|
-
|
39
|
+
def configure(...)
|
40
|
+
client.configure(...)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def client
|
46
|
+
@client ||= begin
|
47
|
+
Evervault::Utils::ValidationUtils.validate_app_uuid_and_api_key(app_id, api_key)
|
48
|
+
Evervault::Client.new(app_uuid: app_id, api_key: api_key)
|
49
|
+
end
|
34
50
|
end
|
35
51
|
end
|
36
52
|
end
|