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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/lib/contrast/agent.rb +5 -1
  3. data/lib/contrast/agent/assess.rb +0 -9
  4. data/lib/contrast/agent/assess/contrast_event.rb +0 -2
  5. data/lib/contrast/agent/assess/contrast_object.rb +5 -2
  6. data/lib/contrast/agent/assess/finalizers/hash.rb +7 -0
  7. data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +17 -3
  8. data/lib/contrast/agent/assess/policy/propagation_method.rb +28 -13
  9. data/lib/contrast/agent/assess/policy/propagator/append.rb +28 -13
  10. data/lib/contrast/agent/assess/policy/propagator/database_write.rb +21 -16
  11. data/lib/contrast/agent/assess/policy/propagator/splat.rb +23 -13
  12. data/lib/contrast/agent/assess/policy/propagator/split.rb +14 -7
  13. data/lib/contrast/agent/assess/policy/propagator/substitution.rb +30 -14
  14. data/lib/contrast/agent/assess/policy/trigger_method.rb +13 -8
  15. data/lib/contrast/agent/assess/policy/trigger_node.rb +28 -7
  16. data/lib/contrast/agent/assess/policy/trigger_validation/redos_validator.rb +59 -0
  17. data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +1 -2
  18. data/lib/contrast/agent/assess/policy/trigger_validation/trigger_validation.rb +6 -4
  19. data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +2 -4
  20. data/lib/contrast/agent/assess/properties.rb +0 -2
  21. data/lib/contrast/agent/assess/property/tagged.rb +37 -19
  22. data/lib/contrast/agent/assess/tracker.rb +1 -1
  23. data/lib/contrast/agent/middleware.rb +85 -55
  24. data/lib/contrast/agent/patching/policy/patch_status.rb +1 -1
  25. data/lib/contrast/agent/patching/policy/patcher.rb +51 -44
  26. data/lib/contrast/agent/patching/policy/trigger_node.rb +5 -2
  27. data/lib/contrast/agent/protect/rule/sqli.rb +17 -11
  28. data/lib/contrast/agent/request_context.rb +12 -0
  29. data/lib/contrast/agent/thread.rb +1 -1
  30. data/lib/contrast/agent/thread_watcher.rb +20 -5
  31. data/lib/contrast/agent/version.rb +1 -1
  32. data/lib/contrast/api/communication/messaging_queue.rb +18 -21
  33. data/lib/contrast/api/communication/response_processor.rb +8 -1
  34. data/lib/contrast/api/communication/socket_client.rb +22 -14
  35. data/lib/contrast/api/decorators.rb +2 -0
  36. data/lib/contrast/api/decorators/agent_startup.rb +58 -0
  37. data/lib/contrast/api/decorators/application_startup.rb +51 -0
  38. data/lib/contrast/api/decorators/route_coverage.rb +15 -5
  39. data/lib/contrast/api/decorators/trace_event.rb +42 -14
  40. data/lib/contrast/components/agent.rb +2 -0
  41. data/lib/contrast/components/app_context.rb +4 -22
  42. data/lib/contrast/components/sampling.rb +48 -6
  43. data/lib/contrast/components/settings.rb +5 -4
  44. data/lib/contrast/framework/manager.rb +13 -12
  45. data/lib/contrast/framework/rails/support.rb +42 -43
  46. data/lib/contrast/framework/sinatra/support.rb +100 -41
  47. data/lib/contrast/logger/log.rb +31 -15
  48. data/lib/contrast/utils/class_util.rb +3 -1
  49. data/lib/contrast/utils/heap_dump_util.rb +103 -87
  50. data/lib/contrast/utils/invalid_configuration_util.rb +21 -12
  51. data/resources/assess/policy.json +3 -9
  52. data/resources/deadzone/policy.json +6 -0
  53. data/ruby-agent.gemspec +54 -16
  54. metadata +105 -136
  55. data/lib/contrast/agent/assess/rule.rb +0 -18
  56. data/lib/contrast/agent/assess/rule/base.rb +0 -52
  57. data/lib/contrast/agent/assess/rule/redos.rb +0 -67
  58. data/lib/contrast/framework/sinatra/patch/base.rb +0 -83
  59. data/lib/contrast/framework/sinatra/patch/support.rb +0 -27
  60. 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 = source_or_string(journey_obj.path.spec)
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
- def from_sinatra_route clazz, method, pattern
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 = "#{ clazz }##{ method } #{ safe_pattern }"
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(safe_pattern)
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
- # Figure out what the target of this event was. It's a little
64
- # annoying for us since P can be named (thanks, Ruby) where
65
- # as for everyone else it is idx based.
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
@@ -31,6 +31,8 @@ module Contrast
31
31
 
32
32
  def disable!
33
33
  @_enabled = false
34
+ Contrast::Agent::TracePointHook.disable
35
+ Contrast::Agent.thread_watcher&.shutdown!
34
36
  end
35
37
 
36
38
  def ruleset
@@ -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
- msg = Contrast::Api::Dtm::ApplicationCreate.new
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.new
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
- cas = CONFIG.root.assess&.sampling
28
+ config_settings = CONFIG.root.assess&.sampling
29
29
  settings = SETTINGS&.assess_state&.[](:sampling_settings)
30
30
  {
31
- enabled: true?([cas&.enable, settings&.enabled, DEFAULT_SAMPLING_ENABLED].reject(&:nil?)[0]),
32
- baseline: [cas&.baseline, settings&.baseline, DEFAULT_SAMPLING_BASELINE].map(&:to_i).find(&:positive?),
33
- request_frequency: [cas&.request_frequency, settings&.request_frequency, DEFAULT_SAMPLING_REQUEST_FREQUENCY].map(&:to_i).find(&:positive?),
34
- response_frequency: [cas&.response_frequency, settings&.response_frequency, DEFAULT_SAMPLING_RESPONSE_FREQUENCY].map(&:to_i).find(&:positive?),
35
- window: [cas&.window_ms, settings&.window_ms, DEFAULT_SAMPLING_WINDOW_MS].map(&:to_i).find(&:positive?)
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
- # @param env [Hash] the various variables stored by this and other Middlewares to know the state
86
- # and values of this particular Request
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 do |framework_klass|
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