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.
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