contrast-agent 4.3.2 → 4.4.0
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.rb +5 -1
- data/lib/contrast/agent/assess.rb +0 -9
- data/lib/contrast/agent/assess/contrast_event.rb +0 -2
- data/lib/contrast/agent/assess/contrast_object.rb +5 -2
- data/lib/contrast/agent/assess/finalizers/hash.rb +7 -0
- data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +17 -3
- data/lib/contrast/agent/assess/policy/propagation_method.rb +28 -13
- data/lib/contrast/agent/assess/policy/propagator/append.rb +28 -13
- data/lib/contrast/agent/assess/policy/propagator/database_write.rb +21 -16
- data/lib/contrast/agent/assess/policy/propagator/splat.rb +23 -13
- data/lib/contrast/agent/assess/policy/propagator/split.rb +14 -7
- data/lib/contrast/agent/assess/policy/propagator/substitution.rb +30 -14
- data/lib/contrast/agent/assess/policy/trigger_method.rb +13 -8
- data/lib/contrast/agent/assess/policy/trigger_node.rb +28 -7
- data/lib/contrast/agent/assess/policy/trigger_validation/redos_validator.rb +59 -0
- data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +1 -2
- data/lib/contrast/agent/assess/policy/trigger_validation/trigger_validation.rb +6 -4
- data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +2 -4
- data/lib/contrast/agent/assess/properties.rb +0 -2
- data/lib/contrast/agent/assess/property/tagged.rb +37 -19
- data/lib/contrast/agent/assess/tracker.rb +1 -1
- data/lib/contrast/agent/middleware.rb +85 -55
- data/lib/contrast/agent/patching/policy/patch_status.rb +1 -1
- data/lib/contrast/agent/patching/policy/patcher.rb +51 -44
- data/lib/contrast/agent/patching/policy/trigger_node.rb +5 -2
- data/lib/contrast/agent/protect/rule/sqli.rb +17 -11
- data/lib/contrast/agent/request_context.rb +12 -0
- data/lib/contrast/agent/thread.rb +1 -1
- data/lib/contrast/agent/thread_watcher.rb +20 -5
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/api/communication/messaging_queue.rb +18 -21
- data/lib/contrast/api/communication/response_processor.rb +8 -1
- data/lib/contrast/api/communication/socket_client.rb +22 -14
- data/lib/contrast/api/decorators.rb +2 -0
- data/lib/contrast/api/decorators/agent_startup.rb +58 -0
- data/lib/contrast/api/decorators/application_startup.rb +51 -0
- data/lib/contrast/api/decorators/route_coverage.rb +15 -5
- data/lib/contrast/api/decorators/trace_event.rb +42 -14
- data/lib/contrast/components/agent.rb +2 -0
- data/lib/contrast/components/app_context.rb +4 -22
- data/lib/contrast/components/sampling.rb +48 -6
- data/lib/contrast/components/settings.rb +5 -4
- data/lib/contrast/framework/manager.rb +13 -12
- data/lib/contrast/framework/rails/support.rb +42 -43
- data/lib/contrast/framework/sinatra/support.rb +100 -41
- data/lib/contrast/logger/log.rb +31 -15
- data/lib/contrast/utils/class_util.rb +3 -1
- data/lib/contrast/utils/heap_dump_util.rb +103 -87
- data/lib/contrast/utils/invalid_configuration_util.rb +21 -12
- data/resources/assess/policy.json +3 -9
- data/resources/deadzone/policy.json +6 -0
- data/ruby-agent.gemspec +54 -16
- metadata +105 -136
- data/lib/contrast/agent/assess/rule.rb +0 -18
- data/lib/contrast/agent/assess/rule/base.rb +0 -52
- data/lib/contrast/agent/assess/rule/redos.rb +0 -67
- data/lib/contrast/framework/sinatra/patch/base.rb +0 -83
- data/lib/contrast/framework/sinatra/patch/support.rb +0 -27
- data/lib/contrast/utils/prevent_serialization.rb +0 -52
@@ -10,6 +10,8 @@ module Contrast
|
|
10
10
|
end
|
11
11
|
|
12
12
|
require 'contrast/api/decorators/message'
|
13
|
+
require 'contrast/api/decorators/agent_startup'
|
14
|
+
require 'contrast/api/decorators/application_startup'
|
13
15
|
require 'contrast/api/decorators/application_update'
|
14
16
|
require 'contrast/api/decorators/input_analysis'
|
15
17
|
require 'contrast/api/decorators/application_settings'
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'contrast/api/dtm.pb'
|
5
|
+
require 'contrast/components/interface'
|
6
|
+
require 'contrast/utils/string_utils'
|
7
|
+
|
8
|
+
module Contrast
|
9
|
+
module Api
|
10
|
+
module Decorators
|
11
|
+
# Used to decorate the AgentStartup protobuf model to handle reporting Agent process start
|
12
|
+
module AgentStartup
|
13
|
+
include Contrast::Components::ComponentBase
|
14
|
+
include Contrast::Components::Interface
|
15
|
+
access_component :analysis, :config
|
16
|
+
|
17
|
+
def self.included klass
|
18
|
+
klass.extend(ClassMethods)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Used to add class methods to the AgentStartup class on inclusion of the decorator
|
22
|
+
module ClassMethods
|
23
|
+
# Return a new DTM with the values from the configuration and Agent discovery
|
24
|
+
#
|
25
|
+
# @parma name [String] the Hostname of this Server, or overridden value, used to identify this process
|
26
|
+
# @parma name [String] the Hostname of this Server, or overridden value, used to identify this process
|
27
|
+
# @parma name [String] the Hostname of this Server, or overridden value, used to identify this process
|
28
|
+
# @return [Contrast::Api::Dtm::AgentStartup]
|
29
|
+
def build name, path, type
|
30
|
+
msg = new
|
31
|
+
msg.server_version = Contrast::Agent::VERSION
|
32
|
+
msg.server_name = Contrast::Utils::StringUtils.protobuf_format name
|
33
|
+
msg.server_path = Contrast::Utils::StringUtils.protobuf_format path
|
34
|
+
msg.server_type = Contrast::Utils::StringUtils.protobuf_format type
|
35
|
+
config!(msg)
|
36
|
+
msg.finding_tags = Contrast::Utils::StringUtils.protobuf_format ASSESS.tags
|
37
|
+
msg
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# set the configuration driven values for this AgentStartup msg
|
43
|
+
#
|
44
|
+
# @param msg [Contrast::Api::Dtm::AgentStartup]
|
45
|
+
def config! msg
|
46
|
+
msg.version = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.server.version
|
47
|
+
msg.environment = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.server.environment
|
48
|
+
msg.server_tags = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.server.tags
|
49
|
+
msg.application_tags = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.tags
|
50
|
+
msg.library_tags = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.inventory.tags
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
Contrast::Api::Dtm::AgentStartup.include(Contrast::Api::Decorators::AgentStartup)
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'contrast/api/dtm.pb'
|
5
|
+
require 'contrast/components/interface'
|
6
|
+
require 'contrast/utils/string_utils'
|
7
|
+
|
8
|
+
module Contrast
|
9
|
+
module Api
|
10
|
+
module Decorators
|
11
|
+
# Used to decorate the ApplicationCreate protobuf model to handle reporting Agent process start
|
12
|
+
module ApplicationStartup
|
13
|
+
include Contrast::Components::ComponentBase
|
14
|
+
include Contrast::Components::Interface
|
15
|
+
access_component :config
|
16
|
+
|
17
|
+
def self.included klass
|
18
|
+
klass.extend(ClassMethods)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Used to add class methods to the AgentStartup class on inclusion of the decorator
|
22
|
+
module ClassMethods
|
23
|
+
# Return a new DTM with the values from the configuration
|
24
|
+
#
|
25
|
+
# @return [Contrast::Api::Dtm::ApplicationCreate]
|
26
|
+
def build
|
27
|
+
msg = new
|
28
|
+
msg.group = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.group
|
29
|
+
msg.app_version = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.version.to_s
|
30
|
+
msg.code = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.code
|
31
|
+
msg.metadata = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.metadata
|
32
|
+
session!(msg)
|
33
|
+
msg
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# Set the session metadata for this ApplicationCreate msg
|
39
|
+
#
|
40
|
+
# @param msg [Contrast::Api::Dtm::ApplicationCreate]
|
41
|
+
def session! msg
|
42
|
+
msg.session_id = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.session_id, truncate: false
|
43
|
+
msg.session_metadata = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.session_metadata, truncate: false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
Contrast::Api::Dtm::ApplicationCreate.include(Contrast::Api::Decorators::ApplicationStartup)
|
@@ -26,27 +26,37 @@ module Contrast
|
|
26
26
|
end
|
27
27
|
|
28
28
|
# Convert ActionDispatch::Journey::Route to Contrast::Api::Dtm::RouteCoverage
|
29
|
+
#
|
29
30
|
# @param journey_obj [ActionDispatch::Journey::Route] a rails route
|
31
|
+
# @param url [String, nil] use url from string instead of journey object.
|
30
32
|
# @return [Contrast::Api::Dtm::RouteCoverage]
|
31
|
-
def from_action_dispatch_journey journey_obj
|
33
|
+
def from_action_dispatch_journey journey_obj, url = nil
|
32
34
|
msg = new
|
33
35
|
msg.route = "#{ journey_obj.defaults[:controller] }##{ journey_obj.defaults[:action] }"
|
34
36
|
|
35
37
|
verb = source_or_string(journey_obj.verb)
|
36
38
|
msg.verb = Contrast::Utils::StringUtils.force_utf8(verb)
|
37
39
|
|
38
|
-
url
|
40
|
+
url ||= source_or_string(journey_obj.path.spec)
|
39
41
|
msg.url = Contrast::Utils::StringUtils.force_utf8(url)
|
40
42
|
msg
|
41
43
|
end
|
42
44
|
|
43
|
-
|
45
|
+
# Convert Sinatra route data to dtm message.
|
46
|
+
#
|
47
|
+
# @param controller [::Sinatra::Base] the route's final controller.
|
48
|
+
# @param method [String] GET, PUT, POST, etc...
|
49
|
+
# @param method [::Mustermann::Sinatra] the pattern that was matched in routing.
|
50
|
+
# @param url [String, nil] use url from string instead matched pattern.
|
51
|
+
# @return [Contrast::Api::Dtm::RouteCoverage]
|
52
|
+
def from_sinatra_route controller, method, pattern, url = nil
|
44
53
|
safe_pattern = source_or_string(pattern)
|
54
|
+
safe_url = source_or_string(url || pattern)
|
45
55
|
|
46
56
|
msg = new
|
47
|
-
msg.route = "#{
|
57
|
+
msg.route = "#{ controller }##{ method } #{ safe_pattern }"
|
48
58
|
msg.verb = Contrast::Utils::StringUtils.force_utf8(method)
|
49
|
-
msg.url = Contrast::Utils::StringUtils.force_utf8(
|
59
|
+
msg.url = Contrast::Utils::StringUtils.force_utf8(safe_url)
|
50
60
|
msg
|
51
61
|
end
|
52
62
|
end
|
@@ -13,8 +13,38 @@ module Contrast
|
|
13
13
|
klass.extend(ClassMethods)
|
14
14
|
end
|
15
15
|
|
16
|
+
# The TeamServer uses the Event's type and action to render it in the Details page. These values control the
|
17
|
+
# left-hand "What happened" column and the data shown in the right-hand data
|
18
|
+
#
|
19
|
+
# @param contrast_event [Contrast::Agent::Assess::ContrastEvent]
|
20
|
+
# @return [Contrast::Api::Dtm::TraceEvent]
|
21
|
+
def build_display_params! contrast_event
|
22
|
+
self.type = contrast_event.policy_node.node_type
|
23
|
+
self.action = contrast_event.policy_node.build_action
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
# The TeamServer uses the Event's representation of the data to render the actual data used in the dataflow on
|
28
|
+
# the Details page.
|
29
|
+
#
|
30
|
+
# @param contrast_event [Contrast::Agent::Assess::ContrastEvent]
|
31
|
+
# @return [Contrast::Api::Dtm::TraceEvent]
|
32
|
+
def build_dataflow! contrast_event
|
33
|
+
# Figure out what the target of this event was. This can't be pulled into the decorator because SourceEvent
|
34
|
+
# has a custom impl :/
|
35
|
+
taint_target = contrast_event.determine_taint_target(self)
|
36
|
+
truncate_obj = Contrast::Utils::ObjectShare::OBJECT_KEY != taint_target
|
37
|
+
self.object = Contrast::Api::Dtm::TraceEventObject.build(contrast_event.object, truncate_obj)
|
38
|
+
truncate_ret = Contrast::Utils::ObjectShare::RETURN_KEY != taint_target
|
39
|
+
self.ret = Contrast::Api::Dtm::TraceEventObject.build(contrast_event.ret, truncate_ret)
|
40
|
+
build_event_args!(contrast_event, taint_target)
|
41
|
+
build_taint_ranges!(contrast_event)
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
16
45
|
# Wrapper around build_event_object for the args array. Handles
|
17
46
|
# tainting the correct argument.
|
47
|
+
# @return [Contrast::Api::Dtm::TraceEvent]
|
18
48
|
def build_event_args! contrast_event, taint_target
|
19
49
|
contrast_event.args.each_index do |idx|
|
20
50
|
truncate_arg = taint_target != idx
|
@@ -29,6 +59,7 @@ module Contrast
|
|
29
59
|
# their DTM form in order to report this.
|
30
60
|
#
|
31
61
|
# @param contrast_event [Contrast::Agent::AssessContrastEvent]
|
62
|
+
# @return [Contrast::Api::Dtm::TraceEvent]
|
32
63
|
def build_taint_ranges! contrast_event
|
33
64
|
# If there's no taint_target, this isn't a dataflow trace, but a
|
34
65
|
# trigger one
|
@@ -38,6 +69,10 @@ module Contrast
|
|
38
69
|
self
|
39
70
|
end
|
40
71
|
|
72
|
+
# For each Parent in the ContrastEvent, capture its id and report it to TeamServer.
|
73
|
+
#
|
74
|
+
# @param contrast_event [Contrast::Agent::AssessContrastEvent]
|
75
|
+
# @return [Contrast::Api::Dtm::TraceEvent]
|
41
76
|
def build_parent_ids! contrast_event
|
42
77
|
contrast_event&.parent_events&.each do |event|
|
43
78
|
next unless event
|
@@ -49,6 +84,10 @@ module Contrast
|
|
49
84
|
self
|
50
85
|
end
|
51
86
|
|
87
|
+
# Convert the caller into the Stack DTM TeamServer consumes
|
88
|
+
#
|
89
|
+
# @param contrast_event [Contrast::Agent::AssessContrastEvent]
|
90
|
+
# @return [Contrast::Api::Dtm::TraceEvent]
|
52
91
|
def build_stack! contrast_event
|
53
92
|
# We delayed doing this as long as possible b/c it's expensive
|
54
93
|
stack_dtms = Contrast::Utils::StackTraceUtils.build_assess_stack_array(contrast_event.stack_trace)
|
@@ -60,23 +99,12 @@ module Contrast
|
|
60
99
|
module ClassMethods
|
61
100
|
def build contrast_event
|
62
101
|
event_dtm = new
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
taint_target = contrast_event.determine_taint_target(event_dtm) # This can't be pulled into the decorator because SourceEvent has a custom impl :/
|
67
|
-
|
68
|
-
event_dtm.type = contrast_event.policy_node.node_type
|
69
|
-
event_dtm.action = contrast_event.policy_node.build_action
|
102
|
+
event_dtm.build_display_params!(contrast_event)
|
103
|
+
event_dtm.build_dataflow!(contrast_event)
|
104
|
+
event_dtm.build_stack!(contrast_event)
|
70
105
|
event_dtm.timestamp_ms = contrast_event.time.to_i
|
71
106
|
event_dtm.thread = Contrast::Utils::StringUtils.force_utf8(contrast_event.thread)
|
72
|
-
truncate_obj = Contrast::Utils::ObjectShare::OBJECT_KEY != taint_target
|
73
|
-
event_dtm.object = Contrast::Api::Dtm::TraceEventObject.build(contrast_event.object, truncate_obj)
|
74
|
-
truncate_ret = Contrast::Utils::ObjectShare::RETURN_KEY != taint_target
|
75
|
-
event_dtm.ret = Contrast::Api::Dtm::TraceEventObject.build(contrast_event.ret, truncate_ret)
|
76
|
-
event_dtm.build_event_args!(contrast_event, taint_target)
|
77
107
|
event_dtm.build_parent_ids!(contrast_event)
|
78
|
-
event_dtm.build_taint_ranges!(contrast_event)
|
79
|
-
event_dtm.build_stack!(contrast_event)
|
80
108
|
event_dtm.object_id = contrast_event.event_id.to_i
|
81
109
|
event_dtm.signature = Contrast::Api::Dtm::TraceEventSignature.build(contrast_event.ret, contrast_event.policy_node, contrast_event.args)
|
82
110
|
event_dtm
|
@@ -2,6 +2,8 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require 'rubygems/version'
|
5
|
+
require 'contrast/api/decorators/agent_startup'
|
6
|
+
require 'contrast/api/decorators/application_startup'
|
5
7
|
require 'contrast/utils/object_share'
|
6
8
|
|
7
9
|
module Contrast
|
@@ -77,31 +79,11 @@ module Contrast
|
|
77
79
|
end
|
78
80
|
|
79
81
|
def build_app_startup_message
|
80
|
-
|
81
|
-
|
82
|
-
msg.group = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.group
|
83
|
-
msg.app_version = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.version.to_s
|
84
|
-
msg.code = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.code
|
85
|
-
msg.metadata = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.metadata
|
86
|
-
# Other fields have limits in TeamServer, the rest don't.
|
87
|
-
msg.session_id = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.session_id, truncate: false
|
88
|
-
msg.session_metadata = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.session_metadata, truncate: false
|
89
|
-
|
90
|
-
msg
|
82
|
+
Contrast::Api::Dtm::ApplicationCreate.build
|
91
83
|
end
|
92
84
|
|
93
85
|
def build_agent_startup_message
|
94
|
-
msg = Contrast::Api::Dtm::AgentStartup.
|
95
|
-
msg.server_name = Contrast::Utils::StringUtils.protobuf_format server_name
|
96
|
-
msg.server_path = Contrast::Utils::StringUtils.protobuf_format server_path
|
97
|
-
msg.server_type = Contrast::Utils::StringUtils.protobuf_format server_type
|
98
|
-
msg.server_version = Contrast::Agent::VERSION
|
99
|
-
msg.version = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.server.version
|
100
|
-
msg.environment = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.server.environment
|
101
|
-
msg.server_tags = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.server.tags
|
102
|
-
msg.application_tags = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.tags
|
103
|
-
msg.library_tags = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.inventory.tags
|
104
|
-
msg.finding_tags = Contrast::Utils::StringUtils.protobuf_format ASSESS.tags
|
86
|
+
msg = Contrast::Api::Dtm::AgentStartup.build(server_name, server_path, server_type)
|
105
87
|
logger.info('Application context',
|
106
88
|
server_name: msg.server_name,
|
107
89
|
server_path: msg.server_path,
|
@@ -25,14 +25,14 @@ module Contrast
|
|
25
25
|
|
26
26
|
def sampling_control
|
27
27
|
@_sampling_control ||= begin
|
28
|
-
|
28
|
+
config_settings = CONFIG.root.assess&.sampling
|
29
29
|
settings = SETTINGS&.assess_state&.[](:sampling_settings)
|
30
30
|
{
|
31
|
-
enabled:
|
32
|
-
baseline:
|
33
|
-
request_frequency:
|
34
|
-
response_frequency:
|
35
|
-
window:
|
31
|
+
enabled: enabled?(config_settings, settings),
|
32
|
+
baseline: baseline(config_settings, settings),
|
33
|
+
request_frequency: request_frequency(config_settings, settings),
|
34
|
+
response_frequency: response_frequency(config_settings, settings),
|
35
|
+
window: window(config_settings, settings)
|
36
36
|
}
|
37
37
|
end
|
38
38
|
end
|
@@ -41,6 +41,48 @@ module Contrast
|
|
41
41
|
def reset_sampling_control
|
42
42
|
@_sampling_control = nil
|
43
43
|
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
# @param config_settings [Contrast::Config::SamplingConfiguration] the Sampling configuration as provided by
|
48
|
+
# local user input
|
49
|
+
# @param settings [Contrast::Api::Settings::Sampling] the Sampling settings as provided by TeamServer
|
50
|
+
# @return [Boolean] the resolution of the config_settings, settings, and default value
|
51
|
+
def enabled? config_settings, settings
|
52
|
+
true?([config_settings&.enable, settings&.enabled, DEFAULT_SAMPLING_ENABLED].reject(&:nil?)[0])
|
53
|
+
end
|
54
|
+
|
55
|
+
# @param config_settings [Contrast::Config::SamplingConfiguration] the Sampling configuration as provided by
|
56
|
+
# local user input
|
57
|
+
# @param settings [Contrast::Api::Settings::Sampling] the Sampling settings as provided by TeamServer
|
58
|
+
# @return [Integer] the resolution of the config_settings, settings, and default value
|
59
|
+
def baseline config_settings, settings
|
60
|
+
[config_settings&.baseline, settings&.baseline, DEFAULT_SAMPLING_BASELINE].map(&:to_i).find(&:positive?)
|
61
|
+
end
|
62
|
+
|
63
|
+
# @param config_settings [Contrast::Config::SamplingConfiguration] the Sampling configuration as provided by
|
64
|
+
# local user input
|
65
|
+
# @param settings [Contrast::Api::Settings::Sampling] the Sampling settings as provided by TeamServer
|
66
|
+
# @return [Integer] the resolution of the config_settings, settings, and default value
|
67
|
+
def request_frequency config_settings, settings
|
68
|
+
[config_settings&.request_frequency, settings&.request_frequency, DEFAULT_SAMPLING_REQUEST_FREQUENCY].map(&:to_i).find(&:positive?)
|
69
|
+
end
|
70
|
+
|
71
|
+
# @param config_settings [Contrast::Config::SamplingConfiguration] the Sampling configuration as provided by
|
72
|
+
# local user input
|
73
|
+
# @param settings [Contrast::Api::Settings::Sampling] the Sampling settings as provided by TeamServer
|
74
|
+
# @return [Integer] the resolution of the config_settings, settings, and default value
|
75
|
+
def response_frequency config_settings, settings
|
76
|
+
[config_settings&.response_frequency, settings&.response_frequency, DEFAULT_SAMPLING_RESPONSE_FREQUENCY].map(&:to_i).find(&:positive?)
|
77
|
+
end
|
78
|
+
|
79
|
+
# @param config_settings [Contrast::Config::SamplingConfiguration] the Sampling configuration as provided by
|
80
|
+
# local user input
|
81
|
+
# @param settings [Contrast::Api::Settings::Sampling] the Sampling settings as provided by TeamServer
|
82
|
+
# @return [Integer] the resolution of the config_settings, settings, and default value
|
83
|
+
def window config_settings, settings
|
84
|
+
[config_settings&.window_ms, settings&.window_ms, DEFAULT_SAMPLING_WINDOW_MS].map(&:to_i).find(&:positive?)
|
85
|
+
end
|
44
86
|
end
|
45
87
|
|
46
88
|
module InstanceMethods #:nodoc:
|
@@ -28,8 +28,8 @@ module Contrast
|
|
28
28
|
|
29
29
|
def assess_state
|
30
30
|
@assess_state ||= { # rubocop:disable Naming/MemoizedInstanceVariableName
|
31
|
-
enabled: false,
|
32
|
-
sampling_features: nil
|
31
|
+
enabled: false, # Boolean
|
32
|
+
sampling_features: nil # Contrast::Api::Settings::Sampling
|
33
33
|
}
|
34
34
|
end
|
35
35
|
|
@@ -95,6 +95,7 @@ module Contrast
|
|
95
95
|
exclusion_matchers.select(&:code?)
|
96
96
|
end
|
97
97
|
|
98
|
+
# @param server_features [Contrast::Api::Settings::ServerFeatures]
|
98
99
|
def update_from_server_features server_features
|
99
100
|
# protect
|
100
101
|
|
@@ -109,6 +110,7 @@ module Contrast
|
|
109
110
|
Contrast::Utils::Assess::SamplingUtil.instance.update
|
110
111
|
end
|
111
112
|
|
113
|
+
# @param application_settings [Contrast::Api::Settings::ApplicationSettings]
|
112
114
|
def update_from_application_settings application_settings
|
113
115
|
application_state.merge!(application_settings.application_state_translation)
|
114
116
|
end
|
@@ -126,9 +128,8 @@ module Contrast
|
|
126
128
|
end
|
127
129
|
|
128
130
|
def build_assess_rules
|
131
|
+
# TODO: RUBY-1120 actually build assess_rules.
|
129
132
|
@assess_rules = {}
|
130
|
-
|
131
|
-
Contrast::Agent::Assess::Rule::Redos.new
|
132
133
|
end
|
133
134
|
|
134
135
|
def build_protect_rules
|
@@ -44,11 +44,9 @@ module Contrast
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
# Return all the After Load Patches for all the Frameworks we know, even
|
48
|
-
# if that Framework hasn't been detected.
|
47
|
+
# Return all the After Load Patches for all the Frameworks we know, even if that Framework hasn't been detected.
|
49
48
|
#
|
50
|
-
# @return [Set<Contrast::Agent::Patching::Policy::AfterLoadPatch>] the
|
51
|
-
# AfterLoadPatches of each framework
|
49
|
+
# @return [Set<Contrast::Agent::Patching::Policy::AfterLoadPatch>] the AfterLoadPatches of each framework
|
52
50
|
def find_after_load_patches
|
53
51
|
patches = Set.new
|
54
52
|
SUPPORTED_FRAMEWORKS.each do |framework|
|
@@ -82,8 +80,10 @@ module Contrast
|
|
82
80
|
end
|
83
81
|
|
84
82
|
# If we have 0 or n > 1 frameworks, we need to use the default rack request
|
85
|
-
#
|
86
|
-
#
|
83
|
+
#
|
84
|
+
# @param env [Hash] the various variables stored by this and other Middlewares to know the state and values
|
85
|
+
# of this particular Request
|
86
|
+
# @return [::Rack::Request] either a rack request or subclass thereof.
|
87
87
|
def retrieve_request env
|
88
88
|
return @_frameworks[0].retrieve_request(env) if @_frameworks.length == 1
|
89
89
|
|
@@ -102,14 +102,15 @@ module Contrast
|
|
102
102
|
result
|
103
103
|
end
|
104
104
|
|
105
|
+
# Iterate through current frameworks and return the current request's route. This will be the first
|
106
|
+
# non-nil result.
|
107
|
+
#
|
108
|
+
# @param request [Contrast::Agent::Request] the current request.
|
109
|
+
# @return [Contrast::Api::Dtm::RouteCoverage] the current route as a Dtm.
|
110
|
+
# TODO: RUBY-1075 add unit test.
|
105
111
|
def get_route_dtm request
|
106
112
|
result = nil
|
107
|
-
@_frameworks.find
|
108
|
-
# TODO: RUBY-763 Sinatra::Base#call patch adds the Route report
|
109
|
-
next if framework_klass == Contrast::Framework::Sinatra::Support
|
110
|
-
|
111
|
-
result = framework_klass.current_route(request)
|
112
|
-
end
|
113
|
+
@_frameworks.find { |framework_klass| result = framework_klass.current_route(request) }
|
113
114
|
result
|
114
115
|
end
|
115
116
|
|