securenative 0.1.20 → 0.1.21
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 +13 -15
- data/README.md +37 -32
- data/lib/api_manager.rb +6 -2
- data/lib/config/configuration_builder.rb +0 -4
- data/lib/config/configuration_manager.rb +21 -21
- data/lib/context/hanami_context.rb +9 -2
- data/lib/context/rails_context.rb +4 -1
- data/lib/context/securenative_context.rb +1 -1
- data/lib/context/sinatra_context.rb +11 -4
- data/lib/event_manager.rb +5 -4
- data/lib/http/securenative_http_client.rb +14 -2
- data/lib/models/event_options.rb +23 -1
- data/lib/models/sdk_event.rb +8 -3
- data/lib/models/verify_result.rb +4 -0
- data/lib/securenative.rb +1 -13
- data/lib/utils/date_utils.rb +1 -1
- data/lib/utils/encryption_utils.rb +38 -24
- data/lib/utils/version_utils.rb +5 -6
- data/securenative.gemspec +1 -1
- metadata +2 -4
- data/VERSION +0 -1
- data/lib/event_options.rb +0 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8aa7eb317d253da74f5b3f78ef8ca0739074e23c0c06396b4a4fb23d40e44320
|
4
|
+
data.tar.gz: '0975ccad317a881c689bc6b5d80d9c38b677d2d65907f275548471e4cc4c5f9d'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d032dcb9eead67fd2cda1e40e3d402853fc250134d3a325bfb37edf5545440307dd53def5ea79d40e737b2afc2a472110c6a7e9a5092f37d540f7a205637a1b
|
7
|
+
data.tar.gz: f8093a2e2c272d911f5a0ae9f6039e229f1598b1a428efdcdf6752f2f20b7b98acf5aa4553c820e8868b36d218937b7e26c85ab13ce4682ffa4054a729518cdd
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
securenative (0.1.
|
4
|
+
securenative (0.1.21)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -73,7 +73,7 @@ GEM
|
|
73
73
|
crack (0.4.3)
|
74
74
|
safe_yaml (~> 1.0.0)
|
75
75
|
crass (1.0.6)
|
76
|
-
diff-lcs (1.
|
76
|
+
diff-lcs (1.4.4)
|
77
77
|
docile (1.3.2)
|
78
78
|
dry-configurable (0.11.6)
|
79
79
|
concurrent-ruby (~> 1.0)
|
@@ -174,7 +174,6 @@ GEM
|
|
174
174
|
nio4r (2.5.2)
|
175
175
|
nokogiri (1.10.10)
|
176
176
|
mini_portile2 (~> 2.4.0)
|
177
|
-
parseconfig (1.0.8)
|
178
177
|
public_suffix (4.0.5)
|
179
178
|
rack (2.2.3)
|
180
179
|
rack-protection (2.0.8.1)
|
@@ -208,19 +207,19 @@ GEM
|
|
208
207
|
rake (>= 0.8.7)
|
209
208
|
thor (>= 0.20.3, < 2.0)
|
210
209
|
rake (13.0.1)
|
211
|
-
rspec (3.
|
212
|
-
rspec-core (~> 3.
|
213
|
-
rspec-expectations (~> 3.
|
214
|
-
rspec-mocks (~> 3.
|
215
|
-
rspec-core (3.
|
216
|
-
rspec-support (~> 3.
|
217
|
-
rspec-expectations (3.
|
210
|
+
rspec (3.9.0)
|
211
|
+
rspec-core (~> 3.9.0)
|
212
|
+
rspec-expectations (~> 3.9.0)
|
213
|
+
rspec-mocks (~> 3.9.0)
|
214
|
+
rspec-core (3.9.2)
|
215
|
+
rspec-support (~> 3.9.3)
|
216
|
+
rspec-expectations (3.9.2)
|
218
217
|
diff-lcs (>= 1.2.0, < 2.0)
|
219
|
-
rspec-support (~> 3.
|
220
|
-
rspec-mocks (3.
|
218
|
+
rspec-support (~> 3.9.0)
|
219
|
+
rspec-mocks (3.9.1)
|
221
220
|
diff-lcs (>= 1.2.0, < 2.0)
|
222
|
-
rspec-support (~> 3.
|
223
|
-
rspec-support (3.
|
221
|
+
rspec-support (~> 3.9.0)
|
222
|
+
rspec-support (3.9.3)
|
224
223
|
ruby2_keywords (0.0.2)
|
225
224
|
safe_yaml (1.0.5)
|
226
225
|
simplecov (0.19.0)
|
@@ -263,7 +262,6 @@ DEPENDENCIES
|
|
263
262
|
bundler (~> 2.0)
|
264
263
|
codecov
|
265
264
|
hanami
|
266
|
-
parseconfig
|
267
265
|
rails
|
268
266
|
rake
|
269
267
|
rspec
|
data/README.md
CHANGED
@@ -47,7 +47,7 @@ Or install it yourself as:
|
|
47
47
|
To get your *API KEY*, login to your SecureNative account and go to project settings page:
|
48
48
|
|
49
49
|
### Option 1: Initialize via Config file
|
50
|
-
SecureNative can automatically load your config from *securenative.
|
50
|
+
SecureNative can automatically load your config from *securenative.yml* file or from the file that is specified in your *SECURENATIVE_CONFIG_FILE* env variable:
|
51
51
|
|
52
52
|
```ruby
|
53
53
|
require 'securenative'
|
@@ -69,7 +69,8 @@ securenative = SecureNative.init_with_api_key('YOUR_API_KEY')
|
|
69
69
|
require 'securenative'
|
70
70
|
|
71
71
|
|
72
|
-
|
72
|
+
options = ConfigurationBuilder.new(api_key: 'API_KEY', max_events: 10, log_level: 'ERROR')
|
73
|
+
SecureNative.init_with_options(options)
|
73
74
|
```
|
74
75
|
|
75
76
|
## Getting SecureNative instance
|
@@ -88,42 +89,46 @@ instance. Make sure you build event with the EventBuilder:
|
|
88
89
|
|
89
90
|
```ruby
|
90
91
|
require 'securenative'
|
91
|
-
require '
|
92
|
-
require '
|
93
|
-
require '
|
94
|
-
require 'securenative/context/context_builder'
|
92
|
+
require 'models/event_options'
|
93
|
+
require 'enums/event_types'
|
94
|
+
require 'models/user_traits'
|
95
95
|
|
96
96
|
|
97
|
-
|
98
|
-
|
99
|
-
context =
|
100
|
-
|
101
|
-
|
102
|
-
event_options = EventOptions(
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
securenative.track(event_options)
|
97
|
+
def track
|
98
|
+
securenative = SecureNative.instance
|
99
|
+
context = SecureNativeContext.new(client_token: '2a980d872b939c7e4f4378aa111a5eeffb22808b58b5372f658d34904ebd5b05fff0daab91921243ac08b72442a5b3992e402dc21df16aa7cc0e19f8bffa9d6cc59996d480d70aa22b857189403675d37fd144ebaf9dc697fed149b907678f2b1f964d73b332dc8ea7df63fcfc3c11f7bbb51ba2672652ca7d5d43f36a62e15db8b13dfd794a5eccfc5968ca514dd7cce59f2df2b9d8184d076eba808c81b311', ip: '127.0.0.1',
|
100
|
+
headers: { 'user-agent' => 'Mozilla: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.3 Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/43.4' })
|
101
|
+
|
102
|
+
event_options = EventOptions.new(event: EventTypes::LOG_IN, user_id: '1234', context: context,
|
103
|
+
user_traits: UserTraits.new(name: 'Your Name', email: 'name@gmail.com', phone: '+1234567890'),
|
104
|
+
properties: { custom_param1: 'CUSTOM_PARAM_VALUE', custom_param2: true, custom_param3: 3 })
|
105
|
+
|
106
|
+
securenative.track(event_options)
|
107
|
+
|
108
|
+
@message = 'tracked'
|
109
|
+
end
|
107
110
|
```
|
108
111
|
|
109
112
|
You can also create request context from requests:
|
110
113
|
|
111
114
|
```ruby
|
112
115
|
require 'securenative'
|
113
|
-
require '
|
114
|
-
require '
|
115
|
-
require '
|
116
|
+
require 'models/event_options'
|
117
|
+
require 'enums/event_types'
|
118
|
+
require 'models/user_traits'
|
116
119
|
|
117
120
|
|
118
|
-
def track
|
121
|
+
def track
|
119
122
|
securenative = SecureNative.instance
|
120
|
-
context =
|
121
|
-
|
122
|
-
event_options = EventOptions(
|
123
|
-
|
124
|
-
|
123
|
+
context = SecureNativeContext.from_http_request(request)
|
124
|
+
|
125
|
+
event_options = EventOptions.new(event: EventTypes::LOG_IN, user_id: '1234', context: context,
|
126
|
+
user_traits: UserTraits.new(name: 'Your Name', email: 'name@gmail.com', phone: '+1234567890'),
|
127
|
+
properties: { custom_param1: 'CUSTOM_PARAM_VALUE', custom_param2: true, custom_param3: 3 })
|
125
128
|
|
126
129
|
securenative.track(event_options)
|
130
|
+
|
131
|
+
@message = 'tracked'
|
127
132
|
end
|
128
133
|
```
|
129
134
|
|
@@ -133,18 +138,18 @@ end
|
|
133
138
|
|
134
139
|
```ruby
|
135
140
|
require 'securenative'
|
136
|
-
require '
|
137
|
-
require '
|
138
|
-
require '
|
141
|
+
require 'models/event_options'
|
142
|
+
require 'enums/event_types'
|
143
|
+
require 'models/user_traits'
|
139
144
|
|
140
145
|
|
141
146
|
def verify(request)
|
142
147
|
securenative = SecureNative.instance
|
143
|
-
context =
|
148
|
+
context = SecureNativeContext.from_http_request(request)
|
144
149
|
|
145
|
-
event_options = EventOptions(
|
146
|
-
|
147
|
-
|
150
|
+
event_options = EventOptions.new(event: EventTypes::LOG_IN, user_id: '1234', context: context,
|
151
|
+
user_traits: UserTraits.new(name: 'Your Name', email: 'name@gmail.com', phone: '+1234567890'),
|
152
|
+
properties: { custom_param1: 'CUSTOM_PARAM_VALUE', custom_param2: true, custom_param3: 3 })
|
148
153
|
|
149
154
|
verify_result = securenative.verify(event_options)
|
150
155
|
verify_result.risk_level # Low, Medium, High
|
data/lib/api_manager.rb
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'models/sdk_event'
|
4
4
|
require 'enums/failover_strategy'
|
5
|
+
require 'enums/risk_level'
|
6
|
+
require 'enums/api_route'
|
7
|
+
require 'models/verify_result'
|
5
8
|
require 'json'
|
6
9
|
|
7
10
|
class ApiManager
|
@@ -21,8 +24,9 @@ class ApiManager
|
|
21
24
|
event = SDKEvent.new(event_options, @options)
|
22
25
|
|
23
26
|
begin
|
24
|
-
res =
|
25
|
-
|
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'])
|
26
30
|
rescue StandardError => e
|
27
31
|
SecureNativeLogger.debug("Failed to call verify; #{e}")
|
28
32
|
end
|
@@ -1,20 +1,20 @@
|
|
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
|
+
DEFAULT_CONFIG_FILE = 'securenative.yml'
|
7
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
|
-
|
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
18
|
end
|
19
19
|
properties
|
20
20
|
end
|
@@ -24,32 +24,32 @@ 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
54
|
end
|
55
55
|
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
|
@@ -12,7 +12,7 @@ class SecureNativeContext
|
|
12
12
|
|
13
13
|
SECURENATIVE_COOKIE = '_sn'
|
14
14
|
|
15
|
-
def initialize(client_token:
|
15
|
+
def initialize(client_token: '', ip: '', remote_ip: '', headers: nil, url: '', http_method: '', body: '')
|
16
16
|
@client_token = client_token
|
17
17
|
@ip = ip
|
18
18
|
@remote_ip = remote_ip
|
@@ -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
|
data/lib/event_manager.rb
CHANGED
@@ -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
|
@@ -64,7 +65,7 @@ class EventManager
|
|
64
65
|
SecureNativeLogger.debug("Attempting to send event #{event}")
|
65
66
|
res = @http_client.post(resource_path, EventManager.serialize(event).to_json)
|
66
67
|
|
67
|
-
if res.code != 200
|
68
|
+
if res.nil? || res.code != '200'
|
68
69
|
SecureNativeLogger.info("SecureNative failed to call endpoint #{resource_path} with event #{event}. adding back to queue")
|
69
70
|
item = QueueItem.new(resource_path, EventManager.serialize(event).to_json, retry_sending)
|
70
71
|
@queue.append(item)
|
@@ -81,9 +82,9 @@ 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
90
|
SecureNativeLogger.debug("Event successfully sent; #{item.body}")
|
@@ -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
|
},
|
@@ -3,6 +3,8 @@
|
|
3
3
|
require 'net/http'
|
4
4
|
require 'uri'
|
5
5
|
require 'json'
|
6
|
+
require 'utils/version_utils'
|
7
|
+
require 'utils/secure_native_logger'
|
6
8
|
|
7
9
|
class SecureNativeHttpClient
|
8
10
|
AUTHORIZATION_HEADER = 'Authorization'
|
@@ -30,9 +32,19 @@ class SecureNativeHttpClient
|
|
30
32
|
headers = _headers
|
31
33
|
|
32
34
|
client = Net::HTTP.new(uri.host, uri.port)
|
35
|
+
client.use_ssl = true
|
36
|
+
client.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
37
|
+
|
33
38
|
request = Net::HTTP::Post.new(uri.request_uri, headers)
|
34
|
-
request.body = body
|
39
|
+
request.body = body
|
35
40
|
|
36
|
-
|
41
|
+
res = nil
|
42
|
+
begin
|
43
|
+
res = client.request(request)
|
44
|
+
rescue StandardError => e
|
45
|
+
SecureNativeLogger.error("Failed to send request; #{e}")
|
46
|
+
return res
|
47
|
+
end
|
48
|
+
res
|
37
49
|
end
|
38
50
|
end
|
data/lib/models/event_options.rb
CHANGED
@@ -1,10 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'models/event_options'
|
4
|
+
require 'models/user_traits'
|
5
|
+
require 'errors/securenative_invalid_options_error'
|
6
|
+
|
3
7
|
class EventOptions
|
4
8
|
attr_reader :event, :user_id, :user_traits, :context, :properties, :timestamp
|
5
9
|
attr_writer :event, :user_id, :user_traits, :context, :properties, :timestamp
|
6
10
|
|
7
|
-
|
11
|
+
MAX_PROPERTIES_SIZE = 10
|
12
|
+
|
13
|
+
def initialize(event: nil, user_id: nil, user_traits: nil, user_name: nil, email: nil, phone: nil, created_at: nil, context: nil, properties: nil, timestamp: nil)
|
14
|
+
if !properties.nil? && properties.length > MAX_PROPERTIES_SIZE
|
15
|
+
raise SecureNativeInvalidOptionsError, "You can have only up to #{MAX_PROPERTIES_SIZE} custom properties"
|
16
|
+
end
|
17
|
+
|
18
|
+
if user_traits.nil?
|
19
|
+
if user_name && email && phone && created_at
|
20
|
+
user_traits = UserTraits(user_name, email, phone, created_at)
|
21
|
+
elsif user_name && email && phone
|
22
|
+
user_traits = UserTraits(user_name, email, phone)
|
23
|
+
elsif user_name && email
|
24
|
+
user_traits = UserTraits(user_name, email)
|
25
|
+
else
|
26
|
+
user_traits = UserTraits.new
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
8
30
|
@event = event
|
9
31
|
@user_id = user_id
|
10
32
|
@user_traits = user_traits
|
data/lib/models/sdk_event.rb
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'context/securenative_context'
|
4
4
|
require 'utils/encryption_utils'
|
5
|
+
require 'utils/date_utils'
|
6
|
+
require 'models/request_context'
|
7
|
+
require 'securerandom'
|
5
8
|
|
6
9
|
class SDKEvent
|
7
10
|
attr_reader :context, :rid, :event_type, :user_id, :user_traits, :request, :timestamp, :properties
|
@@ -20,9 +23,11 @@ class SDKEvent
|
|
20
23
|
@event_type = event_options.event
|
21
24
|
@user_id = event_options.user_id
|
22
25
|
@user_traits = event_options.user_traits
|
23
|
-
@request = RequestContext(client_token ? client_token.cid : '', client_token ? client_token.vid : '',
|
24
|
-
|
25
|
-
|
26
|
+
@request = RequestContext.new(cid: client_token ? client_token.cid : '', vid: client_token ? client_token.vid : '',
|
27
|
+
fp: client_token ? client_token.fp : '', ip: @context.ip,
|
28
|
+
remote_ip: @context.remote_ip, headers: @context.headers,
|
29
|
+
url: @context.url, http_method: @context.http_method)
|
30
|
+
|
26
31
|
|
27
32
|
@timestamp = DateUtils.to_timestamp(event_options.timestamp)
|
28
33
|
@properties = event_options.properties
|
data/lib/models/verify_result.rb
CHANGED
data/lib/securenative.rb
CHANGED
@@ -8,6 +8,7 @@ require 'errors/securenative_sdk_Illegal_state_error'
|
|
8
8
|
require 'errors/securenative_config_error'
|
9
9
|
require 'enums/failover_strategy'
|
10
10
|
require 'config/configuration_builder'
|
11
|
+
require 'config/configuration_manager'
|
11
12
|
require 'event_manager'
|
12
13
|
require 'api_manager'
|
13
14
|
|
@@ -61,19 +62,6 @@ class SecureNative
|
|
61
62
|
@securenative
|
62
63
|
end
|
63
64
|
|
64
|
-
def self.config_builder(api_key: nil, api_url: 'https://api.securenative.com/collector/api/v1', interval: 1000,
|
65
|
-
max_events: 1000, timeout: 1500, auto_send: true, disable: false, log_level: 'FATAL',
|
66
|
-
fail_over_strategy: FailOverStrategy::FAIL_OPEN)
|
67
|
-
ConfigurationBuilder.new(api_key: api_key, api_url: api_url, interval: interval, max_events: max_events,
|
68
|
-
timeout: timeout, auto_send: auto_send, disable: disable, log_level: log_level,
|
69
|
-
fail_over_strategy: fail_over_strategy)
|
70
|
-
end
|
71
|
-
|
72
|
-
def self.context_builder(client_token: nil, ip: nil, remote_ip: nil, headers: nil, url: nil, http_method: nil, body: nil)
|
73
|
-
SecureNativeContext.new(client_token: client_token, ip: ip, remote_ip: remote_ip, headers: headers,
|
74
|
-
url: url, http_method: http_method, body: body)
|
75
|
-
end
|
76
|
-
|
77
65
|
def track(event_options)
|
78
66
|
@api_manager.track(event_options)
|
79
67
|
end
|
data/lib/utils/date_utils.rb
CHANGED
@@ -1,35 +1,49 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'openssl'
|
4
|
+
require 'digest'
|
5
|
+
require 'base64'
|
6
|
+
require 'models/client_token'
|
4
7
|
|
5
8
|
class EncryptionUtils
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
def self.padding_key(key, length)
|
10
|
+
if key.length == length
|
11
|
+
key
|
12
|
+
else
|
13
|
+
if key.length > length
|
14
|
+
key.slice(0, length)
|
15
|
+
else
|
16
|
+
(length - key.length).times { key << '0' }
|
17
|
+
key
|
18
|
+
end
|
15
19
|
end
|
16
|
-
|
17
|
-
cipher_key = Digest::SHA1.hexdigest cipher_key
|
18
|
-
cipher.key = cipher_key.slice(0, BLOCK_SIZE)
|
19
|
-
s = cipher.update(text) + cipher.final
|
20
|
-
|
21
|
-
s.unpack('H*')[0].upcase
|
22
20
|
end
|
23
21
|
|
24
|
-
def self.
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
22
|
+
def self.encrypt(plain_text, secret_key)
|
23
|
+
begin
|
24
|
+
cipher = OpenSSL::Cipher.new('aes-256-cbc')
|
25
|
+
cipher.encrypt
|
26
|
+
iv = cipher.random_iv
|
27
|
+
cipher.key = padding_key(secret_key, 32)
|
28
|
+
encrypted = cipher.update(plain_text) + cipher.final
|
29
|
+
(iv + encrypted).unpack1('H*')
|
30
|
+
rescue StandardError
|
31
|
+
''
|
32
|
+
end
|
33
|
+
end
|
31
34
|
|
32
|
-
|
33
|
-
|
35
|
+
def self.decrypt(cipher_text, secret_key)
|
36
|
+
begin
|
37
|
+
cipher = OpenSSL::Cipher.new('aes-256-cbc')
|
38
|
+
cipher.decrypt
|
39
|
+
raw_data = [cipher_text].pack('H*')
|
40
|
+
cipher.iv = raw_data.slice(0, 16)
|
41
|
+
cipher.key = padding_key(secret_key, 32)
|
42
|
+
decrypted = JSON.parse(cipher.update(raw_data.slice(16, raw_data.length)) + cipher.final)
|
43
|
+
|
44
|
+
return ClientToken.new(decrypted['cid'], decrypted['vid'], decrypted['fp'])
|
45
|
+
rescue StandardError
|
46
|
+
ClientToken.new('', '','')
|
47
|
+
end
|
34
48
|
end
|
35
49
|
end
|
data/lib/utils/version_utils.rb
CHANGED
data/securenative.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: securenative
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.21
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- SecureNative
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-08-
|
11
|
+
date: 2020-08-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -56,7 +56,6 @@ files:
|
|
56
56
|
- LICENSE
|
57
57
|
- README.md
|
58
58
|
- Rakefile
|
59
|
-
- VERSION
|
60
59
|
- bin/console
|
61
60
|
- bin/setup
|
62
61
|
- lib/api_manager.rb
|
@@ -79,7 +78,6 @@ files:
|
|
79
78
|
- lib/errors/securenative_sdk_Illegal_state_error.rb
|
80
79
|
- lib/errors/securenative_sdk_error.rb
|
81
80
|
- lib/event_manager.rb
|
82
|
-
- lib/event_options.rb
|
83
81
|
- lib/http/secure_native_http_response.rb
|
84
82
|
- lib/http/securenative_http_client.rb
|
85
83
|
- lib/models/client_token.rb
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.1.20
|
data/lib/event_options.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class EventOptions
|
4
|
-
MAX_PROPERTIES_SIZE = 10
|
5
|
-
|
6
|
-
def initialize(event_type, user_id, user_traits, user_name, email, phone, created_at, context, properties, timestamp)
|
7
|
-
traits = UserTraits(user_name)
|
8
|
-
if user_name && email && phone && created_at
|
9
|
-
traits = UserTraits(user_name, email, phone, created_at)
|
10
|
-
elsif user_name && email && phone
|
11
|
-
traits = UserTraits(user_name, email, phone)
|
12
|
-
elsif user_name && email
|
13
|
-
traits = UserTraits(user_name, email)
|
14
|
-
end
|
15
|
-
|
16
|
-
@event_options = EventOptions(event_type)
|
17
|
-
@event_options.user_id = user_id
|
18
|
-
@event_options.user_traits = user_traits if user_traits
|
19
|
-
@event_options.user_traits = traits
|
20
|
-
@event_options.context = context
|
21
|
-
@event_options.properties = properties
|
22
|
-
@event_options.timestamp = timestamp
|
23
|
-
end
|
24
|
-
|
25
|
-
def build
|
26
|
-
if !@event_options.properties.nil? && @event_options.properties.length > MAX_PROPERTIES_SIZE
|
27
|
-
raise SecureNativeInvalidOptionsError('You can have only up to {} custom properties', MAX_PROPERTIES_SIZE)
|
28
|
-
end
|
29
|
-
|
30
|
-
@event_options
|
31
|
-
end
|
32
|
-
end
|