contrast-agent 4.3.2 → 4.4.0
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/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
|
|