securenative 0.1.20 → 0.1.26
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 +4 -4
- data/Gemfile +0 -1
- data/Gemfile.lock +76 -82
- data/README.md +45 -40
- data/lib/securenative/api_manager.rb +41 -0
- data/lib/securenative/config/configuration_builder.rb +29 -0
- data/lib/securenative/config/configuration_manager.rb +58 -0
- data/lib/securenative/config/securenative_options.rb +25 -0
- data/lib/securenative/context/hanami_context.rb +44 -0
- data/lib/securenative/context/rails_context.rb +46 -0
- data/lib/securenative/context/securenative_context.rb +69 -0
- data/lib/securenative/context/sinatra_context.rb +44 -0
- data/lib/securenative/enums/api_route.rb +8 -0
- data/lib/securenative/enums/event_types.rb +25 -0
- data/lib/securenative/enums/failover_strategy.rb +8 -0
- data/lib/securenative/enums/risk_level.rb +9 -0
- data/lib/securenative/errors/securenative_config_error.rb +6 -0
- data/lib/securenative/errors/securenative_http_error.rb +6 -0
- data/lib/securenative/errors/securenative_invalid_options_error.rb +6 -0
- data/lib/securenative/errors/securenative_invalid_uri_error.rb +6 -0
- data/lib/securenative/errors/securenative_parse_error.rb +6 -0
- data/lib/securenative/errors/securenative_sdk_Illegal_state_error.rb +6 -0
- data/lib/securenative/errors/securenative_sdk_error.rb +6 -0
- data/lib/securenative/event_manager.rb +159 -0
- data/lib/securenative/http/secure_native_http_response.rb +14 -0
- data/lib/securenative/http/securenative_http_client.rb +52 -0
- data/lib/securenative/models/client_token.rb +14 -0
- data/lib/securenative/models/device.rb +12 -0
- data/lib/securenative/models/event_options.rb +39 -0
- data/lib/securenative/models/request_context.rb +20 -0
- data/lib/securenative/models/request_options.rb +14 -0
- data/lib/securenative/models/sdk_event.rb +51 -0
- data/lib/securenative/models/user_traits.rb +15 -0
- data/lib/securenative/models/verify_result.rb +18 -0
- data/lib/securenative/sdk.rb +85 -0
- data/lib/securenative/utils/date_utils.rb +11 -0
- data/lib/securenative/utils/encryption_utils.rb +51 -0
- data/lib/securenative/utils/ip_utils.rb +25 -0
- data/lib/securenative/utils/request_utils.rb +71 -0
- data/lib/securenative/utils/secure_native_logger.rb +46 -0
- data/lib/securenative/utils/signature_utils.rb +18 -0
- data/lib/securenative/utils/utils.rb +11 -0
- data/lib/securenative/utils/version_utils.rb +13 -0
- data/out/production/securenative-ruby/api_manager.rb +13 -5
- data/out/production/securenative-ruby/config/configuration_builder.rb +6 -9
- data/out/production/securenative-ruby/config/configuration_manager.rb +24 -23
- data/out/production/securenative-ruby/config/securenative_options.rb +8 -5
- data/{lib → out/production/securenative-ruby}/context/hanami_context.rb +9 -2
- data/{lib → out/production/securenative-ruby}/context/rails_context.rb +4 -1
- data/out/production/securenative-ruby/context/securenative_context.rb +35 -8
- data/{lib → out/production/securenative-ruby}/context/sinatra_context.rb +11 -4
- data/out/production/securenative-ruby/event_manager.rb +15 -14
- data/{lib → out/production/securenative-ruby}/http/secure_native_http_response.rb +0 -0
- data/out/production/securenative-ruby/http/securenative_http_client.rb +23 -5
- data/out/production/securenative-ruby/models/event_options.rb +23 -1
- data/out/production/securenative-ruby/models/request_context.rb +2 -2
- data/out/production/securenative-ruby/models/sdk_event.rb +22 -6
- data/out/production/securenative-ruby/models/user_traits.rb +1 -1
- data/out/production/securenative-ruby/models/verify_result.rb +5 -1
- data/out/production/securenative-ruby/securenative.rb +2 -10
- data/out/production/securenative-ruby/utils/date_utils.rb +1 -1
- data/out/production/securenative-ruby/utils/encryption_utils.rb +38 -24
- data/out/production/securenative-ruby/utils/request_utils.rb +53 -7
- data/out/production/securenative-ruby/utils/secure_native_logger.rb +6 -6
- data/out/production/securenative-ruby/utils/version_utils.rb +5 -6
- data/out/test/securenative-ruby/spec_api_manager.rb +37 -31
- data/out/test/securenative-ruby/spec_context_builder.rb +52 -34
- data/out/test/securenative-ruby/spec_encryption_utils.rb +13 -13
- data/out/test/securenative-ruby/spec_event_manager.rb +49 -15
- data/out/test/securenative-ruby/spec_helper.rb +8 -0
- data/out/test/securenative-ruby/spec_request_utils.rb +25 -0
- data/out/test/securenative-ruby/spec_sdk_event.rb +24 -0
- data/out/test/securenative-ruby/spec_securenative.rb +35 -39
- data/out/test/securenative-ruby/spec_securenative_http_client.rb +13 -5
- data/out/test/securenative-ruby/spec_signature_utils.rb +1 -1
- data/out/test/securenative-ruby/spec_version_util.rb +10 -0
- data/securenative.gemspec +16 -14
- metadata +48 -45
- data/VERSION +0 -1
- data/lib/api_manager.rb +0 -35
- data/lib/config/configuration_builder.rb +0 -30
- data/lib/config/configuration_manager.rb +0 -55
- data/lib/config/securenative_options.rb +0 -22
- data/lib/context/securenative_context.rb +0 -67
- data/lib/enums/api_route.rb +0 -6
- data/lib/enums/event_types.rb +0 -23
- data/lib/enums/failover_strategy.rb +0 -6
- data/lib/enums/risk_level.rb +0 -7
- data/lib/errors/securenative_config_error.rb +0 -4
- data/lib/errors/securenative_http_error.rb +0 -4
- data/lib/errors/securenative_invalid_options_error.rb +0 -4
- data/lib/errors/securenative_invalid_uri_error.rb +0 -4
- data/lib/errors/securenative_parse_error.rb +0 -4
- data/lib/errors/securenative_sdk_Illegal_state_error.rb +0 -4
- data/lib/errors/securenative_sdk_error.rb +0 -4
- data/lib/event_manager.rb +0 -156
- data/lib/event_options.rb +0 -32
- data/lib/http/securenative_http_client.rb +0 -38
- data/lib/models/client_token.rb +0 -12
- data/lib/models/device.rb +0 -10
- data/lib/models/event_options.rb +0 -15
- data/lib/models/request_context.rb +0 -18
- data/lib/models/request_options.rb +0 -12
- data/lib/models/sdk_event.rb +0 -35
- data/lib/models/user_traits.rb +0 -13
- data/lib/models/verify_result.rb +0 -12
- data/lib/securenative.rb +0 -95
- data/lib/utils/date_utils.rb +0 -9
- data/lib/utils/encryption_utils.rb +0 -35
- data/lib/utils/ip_utils.rb +0 -23
- data/lib/utils/request_utils.rb +0 -54
- data/lib/utils/secure_native_logger.rb +0 -44
- data/lib/utils/signature_utils.rb +0 -16
- data/lib/utils/utils.rb +0 -9
- data/lib/utils/version_utils.rb +0 -12
- data/out/production/securenative-ruby/event_options.rb +0 -32
- data/out/production/securenative-ruby/http/http_response.rb +0 -12
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
module SecureNative
|
6
|
+
class SecureNativeLogger
|
7
|
+
@logger = Logger.new(STDOUT)
|
8
|
+
|
9
|
+
def self.init_logger(level = 'DEBUG')
|
10
|
+
@logger.level = case level
|
11
|
+
when 'WARN'
|
12
|
+
Logger::WARN
|
13
|
+
when 'DEBUG'
|
14
|
+
Logger::DEBUG
|
15
|
+
when 'ERROR'
|
16
|
+
Logger::ERROR
|
17
|
+
when 'FATAL'
|
18
|
+
Logger::FATAL
|
19
|
+
when 'INFO'
|
20
|
+
Logger::INFO
|
21
|
+
else
|
22
|
+
Logger::FATAL
|
23
|
+
end
|
24
|
+
|
25
|
+
@logger.formatter = proc do |severity, datetime, progname, msg|
|
26
|
+
"[#{datetime}] #{severity} (#{progname}): #{msg}\n"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.info(msg)
|
31
|
+
@logger.info(msg)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.debug(msg)
|
35
|
+
@logger.debug(msg)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.warning(msg)
|
39
|
+
@logger.warning(msg)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.error(msg)
|
43
|
+
@logger.error(msg)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'openssl'
|
4
|
+
|
5
|
+
module SecureNative
|
6
|
+
class SignatureUtils
|
7
|
+
SIGNATURE_HEADER = 'x-securenative'
|
8
|
+
|
9
|
+
def self.valid_signature?(api_key, payload, header_signature)
|
10
|
+
key = api_key.encode('utf-8')
|
11
|
+
body = payload.encode('utf-8')
|
12
|
+
calculated_signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha512'), key, body)
|
13
|
+
calculated_signature.eql? header_signature
|
14
|
+
rescue StandardError
|
15
|
+
false
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,5 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'models/sdk_event'
|
4
|
+
require 'enums/failover_strategy'
|
5
|
+
require 'enums/risk_level'
|
6
|
+
require 'enums/api_route'
|
7
|
+
require 'models/verify_result'
|
3
8
|
require 'json'
|
4
9
|
|
5
10
|
class ApiManager
|
@@ -19,13 +24,16 @@ class ApiManager
|
|
19
24
|
event = SDKEvent.new(event_options, @options)
|
20
25
|
|
21
26
|
begin
|
22
|
-
res =
|
23
|
-
|
27
|
+
res = @event_manager.send_sync(event, ApiRoute::VERIFY, false)
|
28
|
+
ver_result = JSON.parse(res.body)
|
29
|
+
return VerifyResult.new(risk_level: ver_result['riskLevel'], score: ver_result['score'], triggers: ver_result['triggers'])
|
24
30
|
rescue StandardError => e
|
25
|
-
SecureNativeLogger.debug(
|
31
|
+
SecureNativeLogger.debug("Failed to call verify; #{e}")
|
32
|
+
end
|
33
|
+
if @options.fail_over_strategy == FailOverStrategy::FAIL_OPEN
|
34
|
+
return VerifyResult.new(risk_level: RiskLevel::LOW, score: 0, triggers: nil)
|
26
35
|
end
|
27
|
-
return VerifyResult.new(RiskLevel::LOW, 0, nil) if @options.fail_over_strategy == FailOverStrategy::FAIL_OPEN
|
28
36
|
|
29
|
-
VerifyResult.new(RiskLevel::HIGH, 1, nil)
|
37
|
+
VerifyResult.new(risk_level: RiskLevel::HIGH, score: 1, triggers: nil)
|
30
38
|
end
|
31
39
|
end
|
@@ -3,12 +3,12 @@
|
|
3
3
|
require 'enums/failover_strategy'
|
4
4
|
|
5
5
|
class ConfigurationBuilder
|
6
|
-
attr_reader :api_key, :api_url, :interval, :max_events, :timeout, :auto_send, :disable, :log_level, :fail_over_strategy
|
7
|
-
attr_writer :api_key, :api_url, :interval, :max_events, :timeout, :auto_send, :disable, :log_level, :fail_over_strategy
|
6
|
+
attr_reader :api_key, :api_url, :interval, :max_events, :timeout, :auto_send, :disable, :log_level, :fail_over_strategy, :proxy_headers
|
7
|
+
attr_writer :api_key, :api_url, :interval, :max_events, :timeout, :auto_send, :disable, :log_level, :fail_over_strategy, :proxy_headers
|
8
8
|
|
9
|
-
def initialize(api_key
|
10
|
-
max_events
|
11
|
-
fail_over_strategy
|
9
|
+
def initialize(api_key: nil, api_url: 'https://api.securenative.com/collector/api/v1', interval: 1000,
|
10
|
+
max_events: 1000, timeout: 1500, auto_send: true, disable: false, log_level: 'FATAL',
|
11
|
+
fail_over_strategy: FailOverStrategy::FAIL_OPEN, proxy_headers: [])
|
12
12
|
@api_key = api_key
|
13
13
|
@api_url = api_url
|
14
14
|
@interval = interval
|
@@ -18,10 +18,7 @@ class ConfigurationBuilder
|
|
18
18
|
@disable = disable
|
19
19
|
@log_level = log_level
|
20
20
|
@fail_over_strategy = fail_over_strategy
|
21
|
-
|
22
|
-
|
23
|
-
def self.default_config_builder
|
24
|
-
ConfigurationBuilder.new
|
21
|
+
@proxy_headers = proxy_headers
|
25
22
|
end
|
26
23
|
|
27
24
|
def self.default_securenative_options
|
@@ -1,21 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'yaml'
|
4
|
+
require 'config/configuration_builder'
|
4
5
|
|
5
6
|
class ConfigurationManager
|
6
|
-
DEFAULT_CONFIG_FILE = 'securenative.
|
7
|
-
CUSTOM_CONFIG_FILE_ENV_NAME = '
|
7
|
+
DEFAULT_CONFIG_FILE = 'securenative.yml'
|
8
|
+
CUSTOM_CONFIG_FILE_ENV_NAME = 'SECURENATIVE_CONFIG_FILE'
|
8
9
|
@config = nil
|
9
10
|
|
10
11
|
def self.read_resource_file(resource_path)
|
11
|
-
@config = ParseConfig.new(resource_path)
|
12
|
-
|
13
12
|
properties = {}
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
begin
|
14
|
+
@config = YAML.load_file(resource_path)
|
15
|
+
properties = @config unless @config.nil?
|
16
|
+
rescue StandardError => e
|
17
|
+
SecureNativeLogger.error("Could not parse config file #{resource_path}; #{e}")
|
18
|
+
end
|
19
19
|
properties
|
20
20
|
end
|
21
21
|
|
@@ -24,32 +24,33 @@ class ConfigurationManager
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def self.config_builder
|
27
|
-
ConfigurationBuilder.
|
27
|
+
ConfigurationBuilder.new
|
28
28
|
end
|
29
29
|
|
30
30
|
def self._get_env_or_default(properties, key, default)
|
31
|
-
return
|
31
|
+
return ENV[key] if ENV[key]
|
32
32
|
return properties[key] if properties[key]
|
33
33
|
|
34
34
|
default
|
35
35
|
end
|
36
36
|
|
37
37
|
def self.load_config
|
38
|
-
options = ConfigurationBuilder
|
38
|
+
options = ConfigurationBuilder.default_securenative_options
|
39
39
|
|
40
40
|
resource_path = DEFAULT_CONFIG_FILE
|
41
|
-
resource_path =
|
41
|
+
resource_path = ENV[CUSTOM_CONFIG_FILE_ENV_NAME] unless ENV[CUSTOM_CONFIG_FILE_ENV_NAME].nil?
|
42
42
|
|
43
43
|
properties = read_resource_file(resource_path)
|
44
44
|
|
45
|
-
ConfigurationBuilder(_get_env_or_default(properties, 'SECURENATIVE_API_KEY', options.api_key),
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
45
|
+
ConfigurationBuilder.new(api_key: _get_env_or_default(properties, 'SECURENATIVE_API_KEY', options.api_key),
|
46
|
+
api_url: _get_env_or_default(properties, 'SECURENATIVE_API_URL', options.api_url),
|
47
|
+
interval: _get_env_or_default(properties, 'SECURENATIVE_INTERVAL', options.interval),
|
48
|
+
max_events: _get_env_or_default(properties, 'SECURENATIVE_MAX_EVENTS', options.max_events),
|
49
|
+
timeout: _get_env_or_default(properties, 'SECURENATIVE_TIMEOUT', options.timeout),
|
50
|
+
auto_send: _get_env_or_default(properties, 'SECURENATIVE_AUTO_SEND', options.auto_send),
|
51
|
+
disable: _get_env_or_default(properties, 'SECURENATIVE_DISABLE', options.disable),
|
52
|
+
log_level: _get_env_or_default(properties, 'SECURENATIVE_LOG_LEVEL', options.log_level),
|
53
|
+
fail_over_strategy: _get_env_or_default(properties, 'SECURENATIVE_FAILOVER_STRATEGY', options.fail_over_strategy),
|
54
|
+
proxy_headers: _get_env_or_default(properties, 'SECURENATIVE_PROXY_HEADERS', options.proxy_headers))
|
54
55
|
end
|
55
56
|
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'enums/failover_strategy'
|
4
|
+
|
3
5
|
class SecureNativeOptions
|
4
|
-
attr_reader :api_key, :api_url, :interval, :max_events, :timeout, :auto_send, :disable, :log_level, :fail_over_strategy
|
5
|
-
attr_writer :api_key, :api_url, :interval, :max_events, :timeout, :auto_send, :disable, :log_level, :fail_over_strategy
|
6
|
+
attr_reader :api_key, :api_url, :interval, :max_events, :timeout, :auto_send, :disable, :log_level, :fail_over_strategy, :proxy_headers
|
7
|
+
attr_writer :api_key, :api_url, :interval, :max_events, :timeout, :auto_send, :disable, :log_level, :fail_over_strategy, :proxy_headers
|
6
8
|
|
7
|
-
def initialize(api_key
|
8
|
-
max_events
|
9
|
-
fail_over_strategy
|
9
|
+
def initialize(api_key: nil, api_url: "https://api.securenative.com/collector/api/v1", interval: 1000,
|
10
|
+
max_events: 1000, timeout: 1500, auto_send: true, disable: false, log_level: "FATAL",
|
11
|
+
fail_over_strategy: FailOverStrategy::FAIL_OPEN, proxy_headers: [])
|
10
12
|
@api_key = api_key
|
11
13
|
@api_url = api_url
|
12
14
|
@interval = interval
|
@@ -16,5 +18,6 @@ class SecureNativeOptions
|
|
16
18
|
@disable = disable
|
17
19
|
@log_level = log_level
|
18
20
|
@fail_over_strategy = fail_over_strategy
|
21
|
+
@proxy_headers = proxy_headers
|
19
22
|
end
|
20
23
|
end
|
@@ -1,11 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class HanamiContext
|
4
|
+
SECURENATIVE_COOKIE = '_sn'
|
5
|
+
|
4
6
|
def self.get_client_token(request)
|
5
7
|
begin
|
6
8
|
request.env[SECURENATIVE_COOKIE]
|
7
9
|
rescue StandardError
|
8
|
-
|
10
|
+
begin
|
11
|
+
request.cookies[SECURENATIVE_COOKIE]
|
12
|
+
rescue StandardError
|
13
|
+
nil
|
14
|
+
end
|
9
15
|
end
|
10
16
|
end
|
11
17
|
|
@@ -27,7 +33,8 @@ class HanamiContext
|
|
27
33
|
|
28
34
|
def self.get_headers(request)
|
29
35
|
begin
|
30
|
-
|
36
|
+
# Note: At the moment we're filtering out everything but user-agent since ruby's payload is way too big
|
37
|
+
{ 'user-agent' => request.env['HTTP_USER_AGENT'] }
|
31
38
|
rescue StandardError
|
32
39
|
nil
|
33
40
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class RailsContext
|
4
|
+
SECURENATIVE_COOKIE = '_sn'
|
5
|
+
|
4
6
|
def self.get_client_token(request)
|
5
7
|
begin
|
6
8
|
request.cookies[SECURENATIVE_COOKIE]
|
@@ -33,7 +35,8 @@ class RailsContext
|
|
33
35
|
|
34
36
|
def self.get_headers(request)
|
35
37
|
begin
|
36
|
-
|
38
|
+
# Note: At the moment we're filtering out everything but user-agent since ruby's payload is way too big
|
39
|
+
{ 'user-agent' => request.env['HTTP_USER_AGENT'] }
|
37
40
|
rescue StandardError
|
38
41
|
nil
|
39
42
|
end
|
@@ -1,10 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'utils/request_utils'
|
4
|
+
require 'utils/utils'
|
5
|
+
require 'context/rails_context'
|
6
|
+
require 'context/hanami_context'
|
7
|
+
require 'context/sinatra_context'
|
8
|
+
|
3
9
|
class SecureNativeContext
|
4
10
|
attr_reader :client_token, :ip, :remote_ip, :headers, :url, :http_method, :body
|
5
11
|
attr_writer :client_token, :ip, :remote_ip, :headers, :url, :http_method, :body
|
6
12
|
|
7
|
-
|
13
|
+
SECURENATIVE_COOKIE = '_sn'
|
14
|
+
|
15
|
+
def initialize(client_token: '', ip: '', remote_ip: '', headers: nil, url: '', http_method: '', body: '')
|
8
16
|
@client_token = client_token
|
9
17
|
@ip = ip
|
10
18
|
@remote_ip = remote_ip
|
@@ -19,22 +27,41 @@ class SecureNativeContext
|
|
19
27
|
end
|
20
28
|
|
21
29
|
def self.from_http_request(request)
|
30
|
+
client_token = RailsContext.get_client_token(request)
|
31
|
+
client_token = SinatraContext.get_client_token(request) if client_token.nil?
|
32
|
+
client_token = HanamiContext.get_client_token(request) if client_token.nil?
|
33
|
+
|
22
34
|
begin
|
23
|
-
|
35
|
+
headers = RailsContext.get_headers(request)
|
36
|
+
headers = SinatraContext.get_headers(request) if headers.nil?
|
37
|
+
headers = HanamiContext.get_headers(request) if headers.nil?
|
38
|
+
|
39
|
+
# Standard Ruby request
|
40
|
+
headers = request.header.to_hash if headers.nil?
|
24
41
|
rescue StandardError
|
25
|
-
|
42
|
+
headers = []
|
26
43
|
end
|
27
44
|
|
45
|
+
url = RailsContext.get_url(request)
|
46
|
+
url = SinatraContext.get_url(request) if url.nil?
|
47
|
+
url = HanamiContext.get_url(request) if url.nil?
|
48
|
+
url = '' if url.nil?
|
49
|
+
|
50
|
+
method = RailsContext.get_method(request)
|
51
|
+
method = SinatraContext.get_method(request) if method.nil?
|
52
|
+
method = HanamiContext.get_method(request) if method.nil?
|
53
|
+
method = '' if method.nil?
|
54
|
+
|
28
55
|
begin
|
29
|
-
|
56
|
+
body = request.body.to_s
|
30
57
|
rescue StandardError
|
31
|
-
|
58
|
+
body = ''
|
32
59
|
end
|
33
60
|
|
34
61
|
client_token = RequestUtils.get_secure_header_from_request(headers) if Utils.null_or_empty?(client_token)
|
35
62
|
|
36
|
-
SecureNativeContext.new(
|
37
|
-
|
38
|
-
|
63
|
+
SecureNativeContext.new(client_token: client_token, ip: RequestUtils.get_client_ip_from_request(request),
|
64
|
+
remote_ip: RequestUtils.get_remote_ip_from_request(request),
|
65
|
+
headers: headers, url: url, http_method: method || '', body: body)
|
39
66
|
end
|
40
67
|
end
|
@@ -1,17 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class SinatraContext
|
4
|
+
SECURENATIVE_COOKIE = '_sn'
|
5
|
+
|
4
6
|
def self.get_client_token(request)
|
5
7
|
begin
|
6
8
|
request.env[SECURENATIVE_COOKIE]
|
7
9
|
rescue StandardError
|
8
|
-
|
10
|
+
begin
|
11
|
+
request.cookies[SECURENATIVE_COOKIE]
|
12
|
+
rescue StandardError
|
13
|
+
nil
|
14
|
+
end
|
9
15
|
end
|
10
16
|
end
|
11
17
|
|
12
18
|
def self.get_url(request)
|
13
19
|
begin
|
14
|
-
request.
|
20
|
+
request.env['REQUEST_URI']
|
15
21
|
rescue StandardError
|
16
22
|
nil
|
17
23
|
end
|
@@ -19,7 +25,7 @@ class SinatraContext
|
|
19
25
|
|
20
26
|
def self.get_method(request)
|
21
27
|
begin
|
22
|
-
request.
|
28
|
+
request.env['REQUEST_METHOD']
|
23
29
|
rescue StandardError
|
24
30
|
nil
|
25
31
|
end
|
@@ -27,7 +33,8 @@ class SinatraContext
|
|
27
33
|
|
28
34
|
def self.get_headers(request)
|
29
35
|
begin
|
30
|
-
|
36
|
+
# Note: At the moment we're filtering out everything but user-agent since ruby's payload is way too big
|
37
|
+
{ 'user-agent' => request.env['HTTP_USER_AGENT'] }
|
31
38
|
rescue StandardError
|
32
39
|
nil
|
33
40
|
end
|
@@ -4,6 +4,7 @@ require 'utils/secure_native_logger'
|
|
4
4
|
require 'config/securenative_options'
|
5
5
|
require 'http/securenative_http_client'
|
6
6
|
require 'errors/securenative_sdk_error'
|
7
|
+
require 'errors/securenative_http_error'
|
7
8
|
|
8
9
|
class QueueItem
|
9
10
|
attr_reader :url, :body, :retry_sending
|
@@ -36,7 +37,7 @@ class EventManager
|
|
36
37
|
@attempt = 0
|
37
38
|
@coefficients = [1, 1, 2, 3, 5, 8, 13]
|
38
39
|
|
39
|
-
@thread = Thread.new {run}
|
40
|
+
@thread = Thread.new { run }
|
40
41
|
end
|
41
42
|
|
42
43
|
def send_async(event, resource_path)
|
@@ -45,7 +46,7 @@ class EventManager
|
|
45
46
|
return
|
46
47
|
end
|
47
48
|
|
48
|
-
item = QueueItem(resource_path,
|
49
|
+
item = QueueItem.new(resource_path, EventManager.serialize(event).to_json, false)
|
49
50
|
@queue.append(item)
|
50
51
|
end
|
51
52
|
|
@@ -62,11 +63,11 @@ class EventManager
|
|
62
63
|
end
|
63
64
|
|
64
65
|
SecureNativeLogger.debug("Attempting to send event #{event}")
|
65
|
-
res = @http_client.post(resource_path,
|
66
|
+
res = @http_client.post(resource_path, EventManager.serialize(event).to_json)
|
66
67
|
|
67
|
-
if res.
|
68
|
-
SecureNativeLogger.info(
|
69
|
-
item = QueueItem(resource_path,
|
68
|
+
if res.nil? || res.code != '200'
|
69
|
+
SecureNativeLogger.info("SecureNative failed to call endpoint #{resource_path} with event #{event}. adding back to queue")
|
70
|
+
item = QueueItem.new(resource_path, EventManager.serialize(event).to_json, retry_sending)
|
70
71
|
@queue.append(item)
|
71
72
|
end
|
72
73
|
|
@@ -81,20 +82,20 @@ class EventManager
|
|
81
82
|
@queue.each do |item|
|
82
83
|
begin
|
83
84
|
res = @http_client.post(item.url, item.body)
|
84
|
-
if res.
|
85
|
+
if res.code == '401'
|
85
86
|
item.retry_sending = false
|
86
|
-
elsif res.
|
87
|
+
elsif res.code != '200'
|
87
88
|
raise SecureNativeHttpError, res.status_code
|
88
89
|
end
|
89
|
-
SecureNativeLogger.debug(
|
90
|
+
SecureNativeLogger.debug("Event successfully sent; #{item.body}")
|
90
91
|
return res
|
91
92
|
rescue StandardError => e
|
92
|
-
SecureNativeLogger.error(
|
93
|
+
SecureNativeLogger.error("Failed to send event; #{e}")
|
93
94
|
if item.retry_sending
|
94
95
|
@attempt = 0 if @coefficients.length == @attempt + 1
|
95
96
|
|
96
97
|
back_off = @coefficients[@attempt] * @options.interval
|
97
|
-
SecureNativeLogger.debug(
|
98
|
+
SecureNativeLogger.debug("Automatic back-off of #{back_off}")
|
98
99
|
@send_enabled = false
|
99
100
|
sleep back_off
|
100
101
|
@send_enabled = true
|
@@ -120,10 +121,10 @@ class EventManager
|
|
120
121
|
SecureNativeLogger.debug('Attempting to stop automatic event persistence')
|
121
122
|
begin
|
122
123
|
flush
|
123
|
-
@thread&.stop
|
124
|
+
@thread&.stop?
|
124
125
|
SecureNativeLogger.debug('Stopped event persistence')
|
125
126
|
rescue StandardError => e
|
126
|
-
SecureNativeLogger.error(
|
127
|
+
SecureNativeLogger.error("Could not stop event scheduler; #{e}")
|
127
128
|
end
|
128
129
|
end
|
129
130
|
end
|
@@ -145,7 +146,7 @@ class EventManager
|
|
145
146
|
fp: obj.request.fp,
|
146
147
|
ip: obj.request.ip,
|
147
148
|
remoteIp: obj.request.remote_ip,
|
148
|
-
|
149
|
+
method: obj.request.http_method || '',
|
149
150
|
url: obj.request.url,
|
150
151
|
headers: obj.request.headers
|
151
152
|
},
|