contrast-agent 6.6.0 → 6.6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/contrast/agent/assess/policy/source_method.rb +10 -9
- data/lib/contrast/agent/inventory/database_config.rb +6 -1
- data/lib/contrast/agent/inventory/policy/datastores.rb +1 -2
- data/lib/contrast/agent/middleware.rb +6 -5
- data/lib/contrast/agent/protect/rule/default_scanner.rb +64 -5
- data/lib/contrast/agent/protect/rule/sql_sample_builder.rb +3 -5
- data/lib/contrast/agent/reporting/reporting_events/preflight_message.rb +2 -2
- data/lib/contrast/agent/reporting/reporting_utilities/endpoints.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_utilities/headers.rb +2 -2
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +1 -1
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/api/decorators/message.rb +1 -1
- data/lib/contrast/components/app_context.rb +62 -8
- data/lib/contrast/components/app_context_extend.rb +8 -8
- data/lib/contrast/components/logger.rb +0 -10
- data/lib/contrast/config/root_configuration.rb +6 -4
- data/lib/contrast/config.rb +0 -1
- data/lib/contrast/logger/application.rb +2 -1
- data/lib/contrast/logger/log.rb +0 -69
- data/lib/contrast/logger/time.rb +19 -12
- data/lib/contrast/utils/log_utils.rb +1 -1
- data/lib/contrast/utils/string_utils.rb +2 -6
- data/lib/contrast.rb +1 -1
- metadata +13 -14
- data/lib/contrast/config/application_configuration.rb +0 -57
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 38657595e182ad9ef1a26180b273061522dcea43e441e1750d9883d2d1d2d9f6
|
4
|
+
data.tar.gz: 37fe627c2fec00f17c6a2cd6b42aa96149bc4b01871fddd6bb929c5a2baabb63
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a2a85843ec7ba80d84a84f21defd2333a1b1130165113777c324176597231ca17b6c861f1f44ff6024f71e01e7d3508f0d57e767381e3d7580e82c7e10bee4a
|
7
|
+
data.tar.gz: b7b98e93f5b8e3bfd826f730e3981bb6006aa69a71dbd24ecec6eeef373b0b147ce542f0e0416f42d9da33dbbe4a76945bb1341bde91ea9b7134a4ddee80b2fb
|
@@ -38,19 +38,20 @@ module Contrast
|
|
38
38
|
# @param ret [Object] the Return of the invoked method
|
39
39
|
# @param args [Array<Object>] the Arguments with which the method was invoked
|
40
40
|
def apply_source method_policy, object, ret, args
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
logger.trace_with_time('Elapsed time for Contrast::Agent::Assess::Policy::SourceMethod#apply_source') do
|
42
|
+
return unless analyze?(method_policy, object, ret, args)
|
43
|
+
return if event_limit?(method_policy)
|
44
|
+
return unless (source_node = method_policy.source_node)
|
44
45
|
|
45
|
-
|
46
|
-
|
46
|
+
# used to hold the object and ret
|
47
|
+
source_data = Contrast::Agent::Assess::Events::EventData.new(nil, nil, object, ret, nil)
|
47
48
|
|
48
|
-
|
49
|
-
|
49
|
+
return unless (target = determine_target(source_node, source_data, args))
|
50
|
+
return if target.cs__frozen? && !Contrast::Agent::Assess::Tracker.trackable?(target)
|
50
51
|
|
51
|
-
|
52
|
+
process_source(source_node, target, source_data, source_node.type, nil, *args)
|
53
|
+
end
|
52
54
|
end
|
53
|
-
Contrast::Components::Logger.add_trace_log_timing_for(SourceMethod, :apply_source)
|
54
55
|
|
55
56
|
private
|
56
57
|
|
@@ -31,7 +31,7 @@ module Contrast
|
|
31
31
|
# Contrast::Api::Dtm::ArchitectureComponent, but have different names for their fields.
|
32
32
|
#
|
33
33
|
# @param activity_or_update [Contrast::Api::Dtm::Activity, Contrast::Agent::Reporting::ApplicationUpdate]
|
34
|
-
# @param hash_or_str [Hash, String] the database connection information
|
34
|
+
# @param hash_or_str [Hash, String, #configuration_hash] the database connection information
|
35
35
|
def append_db_config activity_or_update, hash_or_str = active_record_config
|
36
36
|
arr = build_from_db_config(hash_or_str)
|
37
37
|
return unless arr&.any?
|
@@ -82,6 +82,11 @@ module Contrast
|
|
82
82
|
def build_from_db_config hash_or_str
|
83
83
|
return unless hash_or_str
|
84
84
|
|
85
|
+
# we need to handle types of HashConfig, which != Hash
|
86
|
+
# for example ActiveRecord::DatabaseConfigurations::HashConfig is type of active_record config
|
87
|
+
# but the method is not handling it properly
|
88
|
+
# so we need to handle it here and extract the hash
|
89
|
+
hash_or_str = hash_or_str.configuration_hash if hash_or_str.cs__respond_to?(:configuration_hash)
|
85
90
|
if hash_or_str.is_a?(Hash)
|
86
91
|
build_from_db_hash(hash_or_str)
|
87
92
|
else
|
@@ -13,9 +13,8 @@ module Contrast
|
|
13
13
|
# in which database operations occur. It is responsible for deciding if
|
14
14
|
# the given invocation is worth reporting or not.
|
15
15
|
module DataStores
|
16
|
+
extend Contrast::Components::Logger::InstanceMethods
|
16
17
|
class << self
|
17
|
-
extend Contrast::Components::Logger::InstanceMethods
|
18
|
-
|
19
18
|
# The key used in policy.json to indicate the database type to
|
20
19
|
# report.
|
21
20
|
DATA_STORE_MARKER = 'data_store'
|
@@ -61,13 +61,14 @@ module Contrast
|
|
61
61
|
# @return [Array,Rack::Response] the Response of this and subsequent Middlewares to be passed back to the user up
|
62
62
|
# the Rack framework.
|
63
63
|
def call env
|
64
|
-
|
64
|
+
logger.trace_with_time('Elapsed time for Contrast::Agent::Middleware#call') do
|
65
|
+
return app.call(env) unless ::Contrast::AGENT.enabled?
|
65
66
|
|
66
|
-
|
67
|
-
|
68
|
-
|
67
|
+
Contrast::Agent.heapdump_util.start_thread!
|
68
|
+
handle_first_request
|
69
|
+
call_with_agent(env)
|
70
|
+
end
|
69
71
|
end
|
70
|
-
::Contrast::Components::Logger.add_trace_log_timing_for(::Contrast::Agent::Middleware, :call)
|
71
72
|
|
72
73
|
private
|
73
74
|
|
@@ -20,11 +20,16 @@ class Contrast::Agent::Protect::Rule::DefaultScanner # rubocop:disable Style/Cla
|
|
20
20
|
# :STATE_INSIDE_BLOCK_COMMENT # inside a commend that will end with a closing tag
|
21
21
|
# :STATE_SKIP_NEXT_CHARACTER
|
22
22
|
|
23
|
+
# @param query [String] the query being executed
|
24
|
+
# @param index [Integer] the index of the input in the query
|
25
|
+
# @param input [String] the input value provided by the user
|
26
|
+
# @return [Array<Integer>, nil] the boundary overrun by the input or nil if no overrun
|
23
27
|
def crosses_boundary query, index, input
|
24
28
|
last_boundary = 0
|
25
|
-
|
29
|
+
scan_token_boundaries(query).each do |boundary|
|
26
30
|
if boundary > index
|
27
|
-
|
31
|
+
# We should report the previous and overrun boundary if the input crosses one.
|
32
|
+
return last_boundary, boundary if boundary < (index + input.length)
|
28
33
|
|
29
34
|
break
|
30
35
|
end
|
@@ -33,10 +38,10 @@ class Contrast::Agent::Protect::Rule::DefaultScanner # rubocop:disable Style/Cla
|
|
33
38
|
nil
|
34
39
|
end
|
35
40
|
|
36
|
-
|
37
|
-
@_token_boundaries ||= scan_token_boundaries(query)
|
38
|
-
end
|
41
|
+
private
|
39
42
|
|
43
|
+
# @param query [String] the query being executed
|
44
|
+
# @return [Array<Integer>] the boundaries of the query
|
40
45
|
def scan_token_boundaries query
|
41
46
|
boundaries = []
|
42
47
|
return boundaries unless query && !query.empty?
|
@@ -73,6 +78,11 @@ class Contrast::Agent::Protect::Rule::DefaultScanner # rubocop:disable Style/Cla
|
|
73
78
|
boundaries
|
74
79
|
end
|
75
80
|
|
81
|
+
# @param boundaries [Array<Integer>] the indexes of the state changes in the query
|
82
|
+
# @param current_state [Symbol] the state of the query
|
83
|
+
# @param char [String] the character being evaluated
|
84
|
+
# @param index [Integer] the location of the character in the query
|
85
|
+
# @param query [String] the query being executed
|
76
86
|
def process_state boundaries, current_state, char, index, query
|
77
87
|
case current_state
|
78
88
|
when :STATE_EXPECTING_TOKEN
|
@@ -88,6 +98,10 @@ class Contrast::Agent::Protect::Rule::DefaultScanner # rubocop:disable Style/Cla
|
|
88
98
|
end
|
89
99
|
end
|
90
100
|
|
101
|
+
# @param boundaries [Array<Integer>] the indexes of the state changes in the query
|
102
|
+
# @param char [String] the character being evaluated
|
103
|
+
# @param index [Integer] the location of the character in the query
|
104
|
+
# @param query [String] the query being executed
|
91
105
|
def process_expecting_token boundaries, char, index, query
|
92
106
|
if char == Contrast::Utils::ObjectShare::SINGLE_QUOTE
|
93
107
|
boundaries << index
|
@@ -112,6 +126,10 @@ class Contrast::Agent::Protect::Rule::DefaultScanner # rubocop:disable Style/Cla
|
|
112
126
|
end
|
113
127
|
end
|
114
128
|
|
129
|
+
# @param boundaries [Array<Integer>] the indexes of the state changes in the query
|
130
|
+
# @param char [String] the character being evaluated
|
131
|
+
# @param index [Integer] the location of the character in the query
|
132
|
+
# @param query [String] the query being executed
|
115
133
|
def process_inside_token boundaries, char, index, query
|
116
134
|
if char == Contrast::Utils::ObjectShare::SINGLE_QUOTE
|
117
135
|
boundaries << index
|
@@ -133,6 +151,10 @@ class Contrast::Agent::Protect::Rule::DefaultScanner # rubocop:disable Style/Cla
|
|
133
151
|
end
|
134
152
|
end
|
135
153
|
|
154
|
+
# @param boundaries [Array<Integer>] the indexes of the state changes in the query
|
155
|
+
# @param char [String] the character being evaluated
|
156
|
+
# @param index [Integer] the location of the character in the query
|
157
|
+
# @param _query [String] the query being executed
|
136
158
|
def process_number boundaries, char, index, _query
|
137
159
|
if char.match?(Contrast::Utils::ObjectShare::DIGIT_REGEXP) || char == Contrast::Utils::ObjectShare::PERIOD
|
138
160
|
:STATE_INSIDE_NUMBER
|
@@ -142,6 +164,10 @@ class Contrast::Agent::Protect::Rule::DefaultScanner # rubocop:disable Style/Cla
|
|
142
164
|
end
|
143
165
|
end
|
144
166
|
|
167
|
+
# @param boundaries [Array<Integer>] the indexes of the state changes in the query
|
168
|
+
# @param char [String] the character being evaluated
|
169
|
+
# @param index [Integer] the location of the character in the query
|
170
|
+
# @param query [String] the query being executed
|
145
171
|
def process_double_quote boundaries, char, index, query
|
146
172
|
if escape_char?(char)
|
147
173
|
:STATE_SKIP_NEXT_CHARACTER
|
@@ -159,6 +185,10 @@ class Contrast::Agent::Protect::Rule::DefaultScanner # rubocop:disable Style/Cla
|
|
159
185
|
end
|
160
186
|
end
|
161
187
|
|
188
|
+
# @param boundaries [Array<Integer>] the indexes of the state changes in the query
|
189
|
+
# @param char [String] the character being evaluated
|
190
|
+
# @param index [Integer] the location of the character in the query
|
191
|
+
# @param query [String] the query being executed
|
162
192
|
def process_single_quote boundaries, char, index, query
|
163
193
|
if escape_char?(char)
|
164
194
|
:STATE_SKIP_NEXT_CHARACTER
|
@@ -176,18 +206,24 @@ class Contrast::Agent::Protect::Rule::DefaultScanner # rubocop:disable Style/Cla
|
|
176
206
|
end
|
177
207
|
end
|
178
208
|
|
209
|
+
# @param query [String] the query being executed
|
210
|
+
# @param index [Integer] the location of the character in the query
|
179
211
|
def double_quote? query, index
|
180
212
|
return false unless index >= 0 && index < query.length
|
181
213
|
|
182
214
|
query[index] == Contrast::Utils::ObjectShare::DOUBLE_QUOTE
|
183
215
|
end
|
184
216
|
|
217
|
+
# @param query [String] the query being executed
|
218
|
+
# @param index [Integer] the location of the character in the query
|
185
219
|
def single_quote? query, index
|
186
220
|
return false unless index >= 0 && index < query.length
|
187
221
|
|
188
222
|
query[index] == Contrast::Utils::ObjectShare::SINGLE_QUOTE
|
189
223
|
end
|
190
224
|
|
225
|
+
# @param query [String] the query being executed
|
226
|
+
# @param index [Integer] the location of the character in the query
|
191
227
|
def find_escape_sequence_boundary query, index
|
192
228
|
idx = index
|
193
229
|
while idx < query.length
|
@@ -199,6 +235,8 @@ class Contrast::Agent::Protect::Rule::DefaultScanner # rubocop:disable Style/Cla
|
|
199
235
|
idx
|
200
236
|
end
|
201
237
|
|
238
|
+
# @param query [String] the query being executed
|
239
|
+
# @param index [Integer] the location of the character in the query
|
202
240
|
def find_block_comment_boundary query, index
|
203
241
|
idx = index
|
204
242
|
while idx < query.length
|
@@ -210,6 +248,8 @@ class Contrast::Agent::Protect::Rule::DefaultScanner # rubocop:disable Style/Cla
|
|
210
248
|
idx
|
211
249
|
end
|
212
250
|
|
251
|
+
# @param query [String] the query being executed
|
252
|
+
# @param index [Integer] the location of the character in the query
|
213
253
|
def find_new_line_boundary query, index
|
214
254
|
idx = index
|
215
255
|
while idx < query.length
|
@@ -222,12 +262,17 @@ class Contrast::Agent::Protect::Rule::DefaultScanner # rubocop:disable Style/Cla
|
|
222
262
|
idx
|
223
263
|
end
|
224
264
|
|
265
|
+
# @param char [String] the character being evaluated
|
225
266
|
def operator? char
|
226
267
|
char.match?(OPERATOR_PATTERN)
|
227
268
|
end
|
228
269
|
|
229
270
|
# @note: Any class extending this module should override these methods as needed
|
230
271
|
# Are the current and subsequent characters both '-' ?
|
272
|
+
#
|
273
|
+
# @param char [String] the character being evaluated
|
274
|
+
# @param index [Integer] the location of the character in the query
|
275
|
+
# @param query [String] the query being executed
|
231
276
|
def start_line_comment? char, index, query
|
232
277
|
return false unless char == Contrast::Utils::ObjectShare::DASH
|
233
278
|
return false unless (query.length - 2) >= index
|
@@ -237,6 +282,10 @@ class Contrast::Agent::Protect::Rule::DefaultScanner # rubocop:disable Style/Cla
|
|
237
282
|
|
238
283
|
# Is the current character / sequence of characters the start of a block comment
|
239
284
|
# We assume '/*' starts the comment by default
|
285
|
+
#
|
286
|
+
# @param char [String] the character being evaluated
|
287
|
+
# @param index [Integer] the location of the character in the query
|
288
|
+
# @param query [String] the query being executed
|
240
289
|
def start_block_comment? char, index, query
|
241
290
|
return false unless char == Contrast::Utils::ObjectShare::SLASH
|
242
291
|
return false unless (query.length - 2) >= index
|
@@ -246,6 +295,10 @@ class Contrast::Agent::Protect::Rule::DefaultScanner # rubocop:disable Style/Cla
|
|
246
295
|
|
247
296
|
# Is the current character / sequence of characters the end of a block comment
|
248
297
|
# We assume '*/' ends the comment by default
|
298
|
+
#
|
299
|
+
# @param char [String] the character being evaluated
|
300
|
+
# @param index [Integer] the location of the character in the query
|
301
|
+
# @param query [String] the query being executed
|
249
302
|
def end_block_comment? char, index, query
|
250
303
|
return false unless char == Contrast::Utils::ObjectShare::ASTERISK
|
251
304
|
return false unless (query.length - 2) >= index
|
@@ -267,18 +320,24 @@ class Contrast::Agent::Protect::Rule::DefaultScanner # rubocop:disable Style/Cla
|
|
267
320
|
|
268
321
|
# Is the character provided an escape character?
|
269
322
|
# By default, we'll assume
|
323
|
+
#
|
324
|
+
# @param char [String] the character being evaluated
|
270
325
|
def escape_char? char
|
271
326
|
char == Contrast::Utils::ObjectShare::BACK_SLASH
|
272
327
|
end
|
273
328
|
|
274
329
|
# Is this the start of a string escape sequence?
|
275
330
|
# Since escape sequences aren't supported, the answer is always false
|
331
|
+
#
|
332
|
+
# @param _char [String] the character being evaluated
|
276
333
|
def escape_sequence_start? _char
|
277
334
|
false
|
278
335
|
end
|
279
336
|
|
280
337
|
# Is this the end of a string escape sequence?
|
281
338
|
# Since escape sequences aren't supported, the answer is always false
|
339
|
+
#
|
340
|
+
# @param _char [String] the character being evaluated
|
282
341
|
def escape_sequence_end? _char
|
283
342
|
false
|
284
343
|
end
|
@@ -65,8 +65,8 @@ module Contrast
|
|
65
65
|
# if one exists, in the case of multiple inputs being found to violate the protection criteria
|
66
66
|
# @param result [Contrast::Api::Dtm::AttackResult, nil] previous attack result for this rule, if one exists,
|
67
67
|
# in the case of multiple inputs being found to violate the protection criteria
|
68
|
-
# @query_string [
|
69
|
-
# @kwargs [Hash] key - value pairs of context individual rules need to build out details to send
|
68
|
+
# @param query_string [String] the value of the input which may be an attack
|
69
|
+
# @param kwargs [Hash] key - value pairs of context individual rules need to build out details to send
|
70
70
|
# to the Service to tell the story of the attack
|
71
71
|
# @return [Contrast::Api::Dtm::AttackResult] the result from this attack
|
72
72
|
def build_attack_with_match context, input_analysis_result, result, query_string, **kwargs
|
@@ -86,14 +86,12 @@ module Contrast
|
|
86
86
|
ss = StringScanner.new(query_string)
|
87
87
|
length = attack_string.length
|
88
88
|
while ss.scan_until(regexp)
|
89
|
-
# the pos of StringScanner is at the end of the regexp (input string),
|
90
|
-
# we need the beginning
|
89
|
+
# the pos of StringScanner is at the end of the regexp (input string), we need the beginning
|
91
90
|
idx = ss.pos - attack_string.length
|
92
91
|
last_boundary, boundary = scanner.crosses_boundary(query_string, idx, input_analysis_result.value)
|
93
92
|
next unless last_boundary && boundary
|
94
93
|
|
95
94
|
result ||= build_attack_result(context)
|
96
|
-
|
97
95
|
record_match(idx, length, boundary, last_boundary, kwargs)
|
98
96
|
append_match(context, input_analysis_result, result, query_string, **kwargs)
|
99
97
|
end
|
@@ -27,8 +27,8 @@ module Contrast
|
|
27
27
|
|
28
28
|
def initialize
|
29
29
|
@app_language = Contrast::Utils::ObjectShare::RUBY
|
30
|
-
@app_name = ::Contrast::APP_CONTEXT.
|
31
|
-
@app_version = ::Contrast::APP_CONTEXT.
|
30
|
+
@app_name = ::Contrast::APP_CONTEXT.name # rubocop:disable Security/Module/Name
|
31
|
+
@app_version = ::Contrast::APP_CONTEXT.version
|
32
32
|
@routes = []
|
33
33
|
end
|
34
34
|
|
@@ -153,7 +153,7 @@ module Contrast
|
|
153
153
|
def app_name
|
154
154
|
return @_app_name unless @_app_name.nil?
|
155
155
|
|
156
|
-
@_app_name = ::Contrast::APP_CONTEXT.
|
156
|
+
@_app_name = ::Contrast::APP_CONTEXT.name # rubocop:disable Security/Module/Name
|
157
157
|
end
|
158
158
|
|
159
159
|
# @return [String,nil]
|
@@ -18,12 +18,12 @@ module Contrast
|
|
18
18
|
CONTENT_TYPE = 'application/json'
|
19
19
|
|
20
20
|
def initialize
|
21
|
-
@app_name = Base64.strict_encode64(Contrast::APP_CONTEXT.
|
21
|
+
@app_name = Base64.strict_encode64(Contrast::APP_CONTEXT.name) # rubocop:disable Security/Module/Name
|
22
22
|
@api_key = Contrast::API.api_key
|
23
23
|
@agent_version = [RUBY, Contrast::Agent::VERSION].join(SPACE)
|
24
24
|
@app_language = RUBY
|
25
25
|
@app_path = Base64.strict_encode64(Contrast::APP_CONTEXT.path)
|
26
|
-
@app_version = Contrast::APP_CONTEXT.
|
26
|
+
@app_version = Contrast::APP_CONTEXT.version
|
27
27
|
@authorization = Base64.strict_encode64("#{ Contrast::API.user_name }:#{ Contrast::API.service_key }")
|
28
28
|
@server_name = Base64.strict_encode64(Contrast::APP_CONTEXT.server_name)
|
29
29
|
@server_path = Base64.strict_encode64(Contrast::APP_CONTEXT.server_path)
|
@@ -107,7 +107,7 @@ module Contrast
|
|
107
107
|
suspend_reporting(message, ready_after, error_message) if mode == @_mode.resending
|
108
108
|
return unless mode == @_mode.disabled
|
109
109
|
|
110
|
-
stop_reporting(message, application: Contrast::APP_CONTEXT.
|
110
|
+
stop_reporting(message, application: Contrast::APP_CONTEXT.name, error_message: error_message) # rubocop:disable Security/Module/Name
|
111
111
|
rescue StandardError => e
|
112
112
|
logger.debug('Could not handle Response error information', error: e)
|
113
113
|
end
|
@@ -52,7 +52,7 @@ module Contrast
|
|
52
52
|
|
53
53
|
def build event
|
54
54
|
msg = new
|
55
|
-
msg.app_name = ::Contrast::APP_CONTEXT.
|
55
|
+
msg.app_name = ::Contrast::APP_CONTEXT.name # rubocop:disable Security/Module/Name
|
56
56
|
msg.app_path = ::Contrast::APP_CONTEXT.path
|
57
57
|
msg.app_language = Contrast::Utils::ObjectShare::RUBY
|
58
58
|
msg.client_id = ::Contrast::APP_CONTEXT.client_id
|
@@ -6,6 +6,7 @@ require 'contrast/api/decorators/agent_startup'
|
|
6
6
|
require 'contrast/api/decorators/application_startup'
|
7
7
|
require 'contrast/utils/object_share'
|
8
8
|
require 'contrast/components/app_context_extend'
|
9
|
+
require 'contrast/config/base_configuration'
|
9
10
|
|
10
11
|
module Contrast
|
11
12
|
module Components
|
@@ -18,15 +19,66 @@ module Contrast
|
|
18
19
|
class Interface
|
19
20
|
include Contrast::Components::AppContextExtend
|
20
21
|
include Contrast::Components::ComponentBase
|
21
|
-
include Contrast::
|
22
|
+
include Contrast::Config::BaseConfiguration
|
22
23
|
|
23
24
|
DEFAULT_APP_NAME = 'rails'
|
24
25
|
DEFAULT_APP_PATH = '/'
|
25
26
|
DEFAULT_SERVER_NAME = 'localhost'
|
26
27
|
DEFAULT_SERVER_PATH = '/'
|
27
28
|
|
28
|
-
|
29
|
+
# @return [String]
|
30
|
+
attr_reader :version
|
31
|
+
# @return [String]
|
32
|
+
attr_reader :language
|
33
|
+
# @return [String]
|
34
|
+
attr_reader :group
|
35
|
+
# @return [String]
|
36
|
+
attr_reader :tags
|
37
|
+
# @return [String]
|
38
|
+
attr_reader :code
|
39
|
+
# @return [String]
|
40
|
+
attr_reader :metadata
|
41
|
+
|
42
|
+
def initialize hsh = {}
|
29
43
|
original_pid
|
44
|
+
return unless hsh
|
45
|
+
|
46
|
+
@_name = hsh[:name]
|
47
|
+
@version = hsh[:version]
|
48
|
+
@language = hsh[:language]
|
49
|
+
@_path = hsh[:path]
|
50
|
+
@group = hsh[:group]
|
51
|
+
@tags = hsh[:tags]
|
52
|
+
@code = hsh[:code]
|
53
|
+
@metadata = hsh[:metadata]
|
54
|
+
@_session_id = hsh[:session_id]
|
55
|
+
@_session_metadata = hsh[:session_metadata]
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [String, Contrast::Utils::ObjectShare::EMPTY_STRING]
|
59
|
+
def session_id
|
60
|
+
@_session_id ||= Contrast::Utils::ObjectShare::EMPTY_STRING
|
61
|
+
end
|
62
|
+
|
63
|
+
# Set session_id
|
64
|
+
#
|
65
|
+
# @param id [String]
|
66
|
+
# @return [String]
|
67
|
+
def session_id= id
|
68
|
+
@_session_id = id
|
69
|
+
end
|
70
|
+
|
71
|
+
# @return [String, Contrast::Utils::ObjectShare::EMPTY_STRING]
|
72
|
+
def session_metadata
|
73
|
+
@_session_metadata ||= Contrast::Utils::ObjectShare::EMPTY_STRING
|
74
|
+
end
|
75
|
+
|
76
|
+
# Set session_metadata
|
77
|
+
#
|
78
|
+
# @param meta [String]
|
79
|
+
# @return [String]
|
80
|
+
def session_metadata= meta
|
81
|
+
@_session_metadata = meta
|
30
82
|
end
|
31
83
|
|
32
84
|
def server_type
|
@@ -37,9 +89,8 @@ module Contrast
|
|
37
89
|
end
|
38
90
|
end
|
39
91
|
|
40
|
-
def
|
41
|
-
@
|
42
|
-
tmp = ::Contrast::CONFIG.root.application.name # rubocop:disable Security/Module/Name
|
92
|
+
def name
|
93
|
+
@_name ||= begin
|
43
94
|
tmp = Contrast::Agent.framework_manager.app_name unless Contrast::Utils::StringUtils.present?(tmp)
|
44
95
|
tmp = File.basename(Dir.pwd) unless Contrast::Utils::StringUtils.present?(tmp)
|
45
96
|
Contrast::Utils::StringUtils.truncate(tmp, DEFAULT_APP_NAME)
|
@@ -48,13 +99,16 @@ module Contrast
|
|
48
99
|
end
|
49
100
|
end
|
50
101
|
|
51
|
-
|
52
|
-
|
102
|
+
# Set application name
|
103
|
+
#
|
104
|
+
# @param app_name [String] application name
|
105
|
+
# @return [String]
|
106
|
+
def name= app_name
|
107
|
+
@_name = app_name
|
53
108
|
end
|
54
109
|
|
55
110
|
def path
|
56
111
|
@_path ||= begin
|
57
|
-
tmp = ::Contrast::CONFIG.root.application.path
|
58
112
|
tmp = Contrast::Agent.framework_manager.application_root unless Contrast::Utils::StringUtils.present?(tmp)
|
59
113
|
Contrast::Utils::StringUtils.truncate(tmp, DEFAULT_APP_PATH)
|
60
114
|
rescue StandardError
|
@@ -18,13 +18,13 @@ module Contrast
|
|
18
18
|
|
19
19
|
def build_agent_startup_message
|
20
20
|
msg = Contrast::Api::Dtm::AgentStartup.build(server_name, server_path, server_type)
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
21
|
+
Contrast::CONFIG.proto_logger.info('Application context',
|
22
|
+
server_name: msg.server_name,
|
23
|
+
server_path: msg.server_path,
|
24
|
+
server_type: msg.server_type,
|
25
|
+
application_name: name, # rubocop:disable Security/Module/Name
|
26
|
+
application_path: path,
|
27
|
+
application_language: Contrast::Utils::ObjectShare::RUBY)
|
28
28
|
|
29
29
|
msg
|
30
30
|
end
|
@@ -42,7 +42,7 @@ module Contrast
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def client_id
|
45
|
-
@_client_id ||= [
|
45
|
+
@_client_id ||= [name, pgid].join('-') # rubocop:disable Security/Module/Name
|
46
46
|
end
|
47
47
|
|
48
48
|
def app_and_server_information
|
@@ -16,16 +16,6 @@ module Contrast
|
|
16
16
|
def cef_logger
|
17
17
|
@_cef_logger ||= Contrast::Logger::CEFLog.instance.tap(&:build_logger)
|
18
18
|
end
|
19
|
-
|
20
|
-
def add_trace_perf_logging_for sym, custom_message = nil
|
21
|
-
logger.add_trace_perf_logging(self, sym, custom_message)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
class << self
|
26
|
-
def add_trace_log_timing_for clazz, method_name, custom_message = nil
|
27
|
-
Contrast::Logger::Log.instance.add_method_to_trace_timing(clazz, method_name, custom_message)
|
28
|
-
end
|
29
19
|
end
|
30
20
|
|
31
21
|
# So This class here follows the update for the configuration
|
@@ -4,6 +4,8 @@
|
|
4
4
|
require 'contrast/components/agent'
|
5
5
|
require 'contrast/components/inventory'
|
6
6
|
require 'contrast/components/protect'
|
7
|
+
require 'contrast/components/app_context'
|
8
|
+
|
7
9
|
module Contrast
|
8
10
|
module Config
|
9
11
|
# The base of the Common Configuration settings.
|
@@ -14,7 +16,7 @@ module Contrast
|
|
14
16
|
attr_writer :api
|
15
17
|
# @return [Contrast::Components::Agent::Interface]
|
16
18
|
attr_writer :agent
|
17
|
-
# @return [Contrast::
|
19
|
+
# @return [Contrast::Components::AppContext::Interface]
|
18
20
|
attr_writer :application
|
19
21
|
# @return [Contrast::Config::ServerConfiguration]
|
20
22
|
attr_writer :server
|
@@ -36,7 +38,7 @@ module Contrast
|
|
36
38
|
@api = Contrast::Components::Api::Interface.new(hsh[:api])
|
37
39
|
@enable = hsh[:enable]
|
38
40
|
@agent = Contrast::Components::Agent::Interface.new(hsh[:agent])
|
39
|
-
@application = Contrast::
|
41
|
+
@application = Contrast::Components::AppContext::Interface.new(hsh[:application])
|
40
42
|
@server = Contrast::Config::ServerConfiguration.new(hsh[:server])
|
41
43
|
@assess = Contrast::Config::AssessConfiguration.new(hsh[:assess])
|
42
44
|
@inventory = Contrast::Components::Inventory::Interface.new(hsh[:inventory])
|
@@ -54,9 +56,9 @@ module Contrast
|
|
54
56
|
@agent ||= Contrast::Components::Agent::Interface.new
|
55
57
|
end
|
56
58
|
|
57
|
-
# @return [Contrast::
|
59
|
+
# @return [Contrast::Components::AppContext::Interface]
|
58
60
|
def application
|
59
|
-
@application ||= Contrast::
|
61
|
+
@application ||= Contrast::Components::AppContext::Interface.new
|
60
62
|
end
|
61
63
|
|
62
64
|
# @return [Contrast::Config::ServerConfiguration]
|
data/lib/contrast/config.rb
CHANGED
@@ -18,7 +18,6 @@ require 'contrast/config/protect_rule_configuration'
|
|
18
18
|
require 'contrast/config/protect_rules_configuration'
|
19
19
|
|
20
20
|
require 'contrast/config/ruby_configuration'
|
21
|
-
require 'contrast/config/application_configuration'
|
22
21
|
require 'contrast/config/server_configuration'
|
23
22
|
require 'contrast/config/assess_configuration'
|
24
23
|
require 'contrast/config/root_configuration'
|
@@ -12,7 +12,8 @@ module Contrast
|
|
12
12
|
return unless info?
|
13
13
|
|
14
14
|
info('Process environment information', p_id: Process.pid, pp_id: Process.ppid,
|
15
|
-
agent_version: Contrast::Agent::VERSION
|
15
|
+
agent_version: Contrast::Agent::VERSION,
|
16
|
+
ruby_version: RUBY_VERSION)
|
16
17
|
ENV.each do |env_key, env_value|
|
17
18
|
env_key = env_key.to_s
|
18
19
|
next unless ENV_KEYS.include?(env_key) ||
|
data/lib/contrast/logger/log.rb
CHANGED
@@ -13,72 +13,6 @@ require 'contrast/logger/time'
|
|
13
13
|
require 'contrast/components/config'
|
14
14
|
require 'contrast/utils/log_utils'
|
15
15
|
|
16
|
-
module Contrast
|
17
|
-
# This module allows us to dynamically weave timing into our code, so that only when the time is actually needed do
|
18
|
-
# we pay the penalty for that timing block
|
19
|
-
module TraceTiming
|
20
|
-
def methods_to_time
|
21
|
-
@_methods_to_time ||= []
|
22
|
-
end
|
23
|
-
|
24
|
-
# Store info about methods for later patching.
|
25
|
-
METHOD_INFO = Struct.new(:clazz, :method_name, :custom_msg, :aliased)
|
26
|
-
|
27
|
-
# Add a method to the list of methods to be trace timed if logger set to TRACE. Enables trace timing after if
|
28
|
-
# logger set to TRACE.
|
29
|
-
#
|
30
|
-
# @param: clazz [Class] the class of the method to time.
|
31
|
-
# @param: method [Symbol] the method to time.
|
32
|
-
# @param: method [String] optional custom logging message.
|
33
|
-
def add_method_to_trace_timing clazz, method, msg = nil
|
34
|
-
methods_to_time.append(METHOD_INFO.new(clazz, method, msg, false))
|
35
|
-
enable_trace_timing if logger.level == ::Ougai::Logging::TRACE
|
36
|
-
end
|
37
|
-
|
38
|
-
# Add a method to the list of methods to be trace timed if logger set to TRACE. Enables trace timing after if
|
39
|
-
# logger set to TRACE.
|
40
|
-
#
|
41
|
-
# @param: meth_spec [METHOD_INFO] specs about the method to be timed.
|
42
|
-
# @param: class_method [Boolean] whether this is or isn't a class/module method.
|
43
|
-
def trace_time_class_method meth_spec, class_method # rubocop:disable Metrics/AbcSize
|
44
|
-
untimed_func_symbol = "untimed_#{ meth_spec.method_name }".to_sym
|
45
|
-
send_to = class_method ? meth_spec.clazz.cs__singleton_class : meth_spec.clazz
|
46
|
-
meth_spec.clazz.class_eval do
|
47
|
-
include(Contrast::Components::Logger::InstanceMethods)
|
48
|
-
extend(Contrast::Components::Logger::InstanceMethods)
|
49
|
-
|
50
|
-
send_to.send(:alias_method, untimed_func_symbol, meth_spec.method_name)
|
51
|
-
meth_spec.aliased = true
|
52
|
-
|
53
|
-
log_message = "Elapsed time for #{ meth_spec.method_name }."
|
54
|
-
log_message = meth_spec.custom_message if meth_spec.custom_msg
|
55
|
-
|
56
|
-
send_to.send(:define_method, meth_spec.method_name) do |*args, **kwargs, &block| # rubocop:disable Performance/Kernel/DefineMethod
|
57
|
-
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
58
|
-
rv = if kwargs.empty?
|
59
|
-
send(untimed_func_symbol, *args, &block)
|
60
|
-
else
|
61
|
-
send(untimed_func_symbol, *args, **kwargs, &block)
|
62
|
-
end
|
63
|
-
delta = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
|
64
|
-
logger.trace(log_message, elapsed: delta * 1000)
|
65
|
-
rv
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
# Enable trace timing of methods specified in @_methods_to_time via aliasing.
|
71
|
-
def enable_trace_timing
|
72
|
-
methods_to_time.each do |meth_spec|
|
73
|
-
next if meth_spec.aliased
|
74
|
-
|
75
|
-
is_class_method = meth_spec.clazz.singleton_methods(false).include?(meth_spec.method_name)
|
76
|
-
trace_time_class_method(meth_spec, is_class_method)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
16
|
module Contrast
|
83
17
|
# Used as a wrapper around our logging. The module option specifically adds in a new method for error that raises the
|
84
18
|
# logged exception, used in testing so that we can see if anything unexpected happens without it being swallowed
|
@@ -105,7 +39,6 @@ module Contrast
|
|
105
39
|
# level based on updates to TeamServer.
|
106
40
|
class Log
|
107
41
|
include Singleton
|
108
|
-
include ::Contrast::TraceTiming
|
109
42
|
include Contrast::Utils::LogUtils
|
110
43
|
|
111
44
|
attr_reader :previous_path, :previous_level
|
@@ -132,8 +65,6 @@ module Contrast
|
|
132
65
|
@previous_path = current_path
|
133
66
|
@previous_level = current_level_const
|
134
67
|
|
135
|
-
enable_trace_timing if current_level_const == ::Ougai::Logging::TRACE
|
136
|
-
|
137
68
|
progname = Contrast::CONFIG.root.agent.logger.progname
|
138
69
|
@_logger = build(path: current_path, level_const: current_level_const, progname: progname)
|
139
70
|
# If we're logging to a new path, then let's start it w/ our helpful
|
data/lib/contrast/logger/time.rb
CHANGED
@@ -8,31 +8,38 @@ module Contrast
|
|
8
8
|
module Time
|
9
9
|
# Log the message at the given level.
|
10
10
|
#
|
11
|
-
# @param level [String] the name of the method to use. Should be one of
|
12
|
-
# trace, debug, info, warn, error
|
11
|
+
# @param level [String] the name of the method to use. Should be one of trace, debug, info, warn, error
|
13
12
|
# @param message [String] the message to log
|
14
13
|
def with_level level, message
|
15
14
|
send(level.to_sym, message)
|
16
15
|
end
|
17
16
|
|
18
|
-
# Log, at the debug level, the action with a message including the time
|
19
|
-
#
|
17
|
+
# Log, at the debug level, the action with a message including the time it took for the wrapped function to
|
18
|
+
# complete. If not logging to debug, simply yield the given block.
|
20
19
|
#
|
21
|
-
# @param msgs [Array<Object>] the arguments to pass to the logger.
|
22
|
-
#
|
20
|
+
# @param msgs [Array<Object>] the arguments to pass to the logger. msgs[0] will be modified to include the elapsed
|
21
|
+
# time.
|
23
22
|
# @param block [Block, Proc] the block to execute
|
24
23
|
def debug_with_time *msgs, &block
|
25
|
-
|
24
|
+
if debug?
|
25
|
+
log_with_time(:debug, *msgs, &block)
|
26
|
+
elsif block
|
27
|
+
yield
|
28
|
+
end
|
26
29
|
end
|
27
30
|
|
28
|
-
# Log, at the trace level, the action with a message including the time
|
29
|
-
#
|
31
|
+
# Log, at the trace level, the action with a message including the time it took for the wrapped function to
|
32
|
+
# complete. If not logging to debug, simply yield the given block.
|
30
33
|
#
|
31
|
-
# @param msgs [Array<Object>] the arguments to pass to the logger.
|
32
|
-
#
|
34
|
+
# @param msgs [Array<Object>] the arguments to pass to the logger. msgs[0] will be modified to include the elapsed
|
35
|
+
# time.
|
33
36
|
# @param block [Block, Proc] the block to execute
|
34
37
|
def trace_with_time *msgs, &block
|
35
|
-
|
38
|
+
if trace?
|
39
|
+
log_with_time(:trace, *msgs, &block)
|
40
|
+
elsif block
|
41
|
+
yield
|
42
|
+
end
|
36
43
|
end
|
37
44
|
|
38
45
|
private
|
@@ -182,7 +182,7 @@ module Contrast
|
|
182
182
|
else
|
183
183
|
DEFAULT_METADATA
|
184
184
|
end
|
185
|
-
app_name = ::Contrast::APP_CONTEXT.
|
185
|
+
app_name = ::Contrast::APP_CONTEXT.name # rubocop:disable Security/Module/Name
|
186
186
|
attach_request_and_sender_info(message, sender_info)
|
187
187
|
message << "request=#{ context.request.url } "
|
188
188
|
message << "requestMethod=#{ request_method } "
|
@@ -1,15 +1,11 @@
|
|
1
1
|
# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require 'contrast/components/logger'
|
5
|
-
|
6
4
|
module Contrast
|
7
5
|
module Utils
|
8
6
|
# Utilities for encoding and normalizing strings
|
9
|
-
|
7
|
+
module StringUtils
|
10
8
|
class << self
|
11
|
-
include Contrast::Components::Logger::InstanceMethods
|
12
|
-
|
13
9
|
UTF8 = 'utf-8'
|
14
10
|
HTTP_PREFIX = 'HTTP_'
|
15
11
|
|
@@ -61,7 +57,7 @@ module Contrast
|
|
61
57
|
# We were unable to switch the String to a UTF-8 format.
|
62
58
|
# Return non-nil so as not to throw an exception later when trying
|
63
59
|
# to do regexp or other compares on the String
|
64
|
-
|
60
|
+
Contrast::CONFIG.proto_logger.trace('Unable to cast String to UTF-8 format', e, value: str)
|
65
61
|
|
66
62
|
Contrast::Utils::ObjectShare::EMPTY_STRING
|
67
63
|
end
|
data/lib/contrast.rb
CHANGED
@@ -81,7 +81,7 @@ module Contrast
|
|
81
81
|
AGENT = CONFIG.root.agent
|
82
82
|
LOGGER = AGENT.logger
|
83
83
|
CONTRAST_SERVICE = Contrast::Components::ContrastService::Interface.new
|
84
|
-
APP_CONTEXT =
|
84
|
+
APP_CONTEXT = CONFIG.root.application
|
85
85
|
end
|
86
86
|
|
87
87
|
module Contrast
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: contrast-agent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.6.
|
4
|
+
version: 6.6.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- galen.palmer@contrastsecurity.com
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: exe
|
15
15
|
cert_chain: []
|
16
|
-
date: 2022-07-
|
16
|
+
date: 2022-07-19 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: bundler
|
@@ -665,22 +665,22 @@ executables:
|
|
665
665
|
- contrast_service
|
666
666
|
extensions:
|
667
667
|
- ext/cs__common/extconf.rb
|
668
|
-
- ext/
|
669
|
-
- ext/cs__assess_string/extconf.rb
|
668
|
+
- ext/cs__tests/extconf.rb
|
670
669
|
- ext/cs__assess_module/extconf.rb
|
671
|
-
- ext/
|
672
|
-
- ext/cs__assess_kernel/extconf.rb
|
673
|
-
- ext/cs__assess_yield_track/extconf.rb
|
670
|
+
- ext/cs__assess_array/extconf.rb
|
674
671
|
- ext/cs__assess_hash/extconf.rb
|
672
|
+
- ext/cs__assess_basic_object/extconf.rb
|
673
|
+
- ext/cs__assess_regexp/extconf.rb
|
675
674
|
- ext/cs__os_information/extconf.rb
|
675
|
+
- ext/cs__assess_test/extconf.rb
|
676
|
+
- ext/cs__assess_string/extconf.rb
|
676
677
|
- ext/cs__contrast_patch/extconf.rb
|
677
|
-
- ext/cs__assess_marshal_module/extconf.rb
|
678
|
-
- ext/cs__assess_regexp/extconf.rb
|
679
|
-
- ext/cs__assess_array/extconf.rb
|
680
|
-
- ext/cs__scope/extconf.rb
|
681
|
-
- ext/cs__assess_basic_object/extconf.rb
|
682
|
-
- ext/cs__tests/extconf.rb
|
683
678
|
- ext/cs__assess_string_interpolation/extconf.rb
|
679
|
+
- ext/cs__scope/extconf.rb
|
680
|
+
- ext/cs__assess_marshal_module/extconf.rb
|
681
|
+
- ext/cs__assess_fiber_track/extconf.rb
|
682
|
+
- ext/cs__assess_yield_track/extconf.rb
|
683
|
+
- ext/cs__assess_kernel/extconf.rb
|
684
684
|
extra_rdoc_files: []
|
685
685
|
files:
|
686
686
|
- ".clang-format"
|
@@ -1193,7 +1193,6 @@ files:
|
|
1193
1193
|
- lib/contrast/components/settings.rb
|
1194
1194
|
- lib/contrast/config.rb
|
1195
1195
|
- lib/contrast/config/api_proxy_configuration.rb
|
1196
|
-
- lib/contrast/config/application_configuration.rb
|
1197
1196
|
- lib/contrast/config/assess_configuration.rb
|
1198
1197
|
- lib/contrast/config/assess_rules_configuration.rb
|
1199
1198
|
- lib/contrast/config/base_configuration.rb
|
@@ -1,57 +0,0 @@
|
|
1
|
-
# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require 'contrast/utils/object_share'
|
5
|
-
|
6
|
-
module Contrast
|
7
|
-
module Config
|
8
|
-
# Common Configuration settings. Those in this section pertain to the
|
9
|
-
# application identification functionality of the Agent.
|
10
|
-
class ApplicationConfiguration
|
11
|
-
include Contrast::Config::BaseConfiguration
|
12
|
-
|
13
|
-
# @return [String]
|
14
|
-
attr_accessor :name
|
15
|
-
# @return [String]
|
16
|
-
attr_accessor :version
|
17
|
-
# @return [String]
|
18
|
-
attr_accessor :language
|
19
|
-
# @return [String]
|
20
|
-
attr_accessor :path
|
21
|
-
# @return [String]
|
22
|
-
attr_accessor :group
|
23
|
-
# @return [String]
|
24
|
-
attr_accessor :tags
|
25
|
-
# @return [String]
|
26
|
-
attr_accessor :code
|
27
|
-
# @return [String]
|
28
|
-
attr_accessor :metadata
|
29
|
-
attr_writer :session_id, :session_metadata
|
30
|
-
|
31
|
-
def initialize hsh = {}
|
32
|
-
return unless hsh
|
33
|
-
|
34
|
-
@name = hsh[:name]
|
35
|
-
@version = hsh[:version]
|
36
|
-
@language = hsh[:language]
|
37
|
-
@path = hsh[:path]
|
38
|
-
@group = hsh[:group]
|
39
|
-
@tags = hsh[:tags]
|
40
|
-
@code = hsh[:code]
|
41
|
-
@metadata = hsh[:metadata]
|
42
|
-
@session_id = hsh[:session_id]
|
43
|
-
@session_metadata = hsh[:session_metadata]
|
44
|
-
end
|
45
|
-
|
46
|
-
# @return [String, Contrast::Utils::ObjectShare::EMPTY_STRING]
|
47
|
-
def session_id
|
48
|
-
@session_id ||= Contrast::Utils::ObjectShare::EMPTY_STRING
|
49
|
-
end
|
50
|
-
|
51
|
-
# @return [String, Contrast::Utils::ObjectShare::EMPTY_STRING]
|
52
|
-
def session_metadata
|
53
|
-
@session_metadata ||= Contrast::Utils::ObjectShare::EMPTY_STRING
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|