contrast-agent 4.0.0 → 4.3.2

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 (107) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -0
  3. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +22 -10
  4. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.h +4 -3
  5. data/lib/contrast/agent/assess/contrast_event.rb +49 -130
  6. data/lib/contrast/agent/assess/contrast_object.rb +51 -0
  7. data/lib/contrast/agent/assess/events/source_event.rb +4 -9
  8. data/lib/contrast/agent/assess/policy/patcher.rb +4 -3
  9. data/lib/contrast/agent/assess/policy/policy_node.rb +31 -59
  10. data/lib/contrast/agent/assess/policy/preshift.rb +3 -3
  11. data/lib/contrast/agent/assess/policy/propagation_method.rb +13 -19
  12. data/lib/contrast/agent/assess/policy/propagation_node.rb +12 -24
  13. data/lib/contrast/agent/assess/policy/propagator/append.rb +1 -2
  14. data/lib/contrast/agent/assess/policy/propagator/center.rb +1 -2
  15. data/lib/contrast/agent/assess/policy/propagator/custom.rb +1 -1
  16. data/lib/contrast/agent/assess/policy/propagator/database_write.rb +1 -3
  17. data/lib/contrast/agent/assess/policy/propagator/insert.rb +1 -2
  18. data/lib/contrast/agent/assess/policy/propagator/keep.rb +1 -2
  19. data/lib/contrast/agent/assess/policy/propagator/match_data.rb +3 -2
  20. data/lib/contrast/agent/assess/policy/propagator/next.rb +1 -2
  21. data/lib/contrast/agent/assess/policy/propagator/prepend.rb +1 -2
  22. data/lib/contrast/agent/assess/policy/propagator/remove.rb +2 -4
  23. data/lib/contrast/agent/assess/policy/propagator/replace.rb +1 -2
  24. data/lib/contrast/agent/assess/policy/propagator/reverse.rb +1 -2
  25. data/lib/contrast/agent/assess/policy/propagator/select.rb +3 -4
  26. data/lib/contrast/agent/assess/policy/propagator/splat.rb +2 -4
  27. data/lib/contrast/agent/assess/policy/propagator/split.rb +73 -117
  28. data/lib/contrast/agent/assess/policy/propagator/substitution.rb +11 -11
  29. data/lib/contrast/agent/assess/policy/propagator/trim.rb +3 -7
  30. data/lib/contrast/agent/assess/policy/source_method.rb +2 -14
  31. data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +5 -8
  32. data/lib/contrast/agent/assess/policy/trigger/xpath.rb +1 -1
  33. data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +1 -1
  34. data/lib/contrast/agent/assess/property/tagged.rb +21 -15
  35. data/lib/contrast/agent/assess/rule/redos.rb +1 -1
  36. data/lib/contrast/agent/assess/tracker.rb +16 -18
  37. data/lib/contrast/agent/deadzone/policy/deadzone_node.rb +7 -0
  38. data/lib/contrast/agent/middleware.rb +50 -1
  39. data/lib/contrast/agent/patching/policy/method_policy.rb +1 -1
  40. data/lib/contrast/agent/patching/policy/patch.rb +6 -0
  41. data/lib/contrast/agent/protect/policy/applies_deserialization_rule.rb +47 -1
  42. data/lib/contrast/agent/protect/policy/rule_applicator.rb +53 -0
  43. data/lib/contrast/agent/protect/rule/base.rb +63 -14
  44. data/lib/contrast/agent/protect/rule/cmd_injection.rb +12 -28
  45. data/lib/contrast/agent/protect/rule/default_scanner.rb +1 -4
  46. data/lib/contrast/agent/protect/rule/deserialization.rb +4 -1
  47. data/lib/contrast/agent/protect/rule/no_sqli.rb +3 -3
  48. data/lib/contrast/agent/protect/rule/sqli.rb +3 -3
  49. data/lib/contrast/agent/protect/rule/xxe.rb +32 -11
  50. data/lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb +10 -6
  51. data/lib/contrast/agent/reaction_processor.rb +1 -1
  52. data/lib/contrast/agent/response.rb +5 -5
  53. data/lib/contrast/agent/rewriter.rb +3 -3
  54. data/lib/contrast/agent/scope.rb +81 -55
  55. data/lib/contrast/agent/static_analysis.rb +13 -7
  56. data/lib/contrast/agent/version.rb +1 -1
  57. data/lib/contrast/api/decorators/library.rb +1 -0
  58. data/lib/contrast/api/decorators/library_usage_update.rb +1 -0
  59. data/lib/contrast/api/decorators/trace_event.rb +19 -31
  60. data/lib/contrast/api/decorators/trace_event_object.rb +11 -3
  61. data/lib/contrast/api/decorators/trace_event_signature.rb +27 -5
  62. data/lib/contrast/api/decorators/user_input.rb +2 -1
  63. data/lib/contrast/common_agent_configuration.rb +2 -1
  64. data/lib/contrast/components/assess.rb +36 -0
  65. data/lib/contrast/components/interface.rb +5 -3
  66. data/lib/contrast/components/scope.rb +72 -6
  67. data/lib/contrast/components/settings.rb +6 -3
  68. data/lib/contrast/config/assess_configuration.rb +2 -1
  69. data/lib/contrast/extension/assess/array.rb +2 -3
  70. data/lib/contrast/extension/assess/erb.rb +1 -3
  71. data/lib/contrast/extension/assess/exec_trigger.rb +1 -4
  72. data/lib/contrast/extension/assess/fiber.rb +2 -3
  73. data/lib/contrast/extension/assess/hash.rb +4 -2
  74. data/lib/contrast/extension/assess/kernel.rb +1 -2
  75. data/lib/contrast/extension/assess/marshal.rb +34 -26
  76. data/lib/contrast/extension/assess/regexp.rb +3 -8
  77. data/lib/contrast/extension/assess/string.rb +1 -2
  78. data/lib/contrast/framework/base_support.rb +51 -53
  79. data/lib/contrast/framework/manager.rb +3 -2
  80. data/lib/contrast/framework/rack/patch/session_cookie.rb +2 -2
  81. data/lib/contrast/framework/rack/support.rb +2 -1
  82. data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +1 -1
  83. data/lib/contrast/framework/rails/patch/assess_configuration.rb +1 -1
  84. data/lib/contrast/framework/rails/patch/rails_application_configuration.rb +1 -1
  85. data/lib/contrast/framework/rails/rewrite/action_controller_railties_helper_inherited.rb +1 -1
  86. data/lib/contrast/framework/rails/rewrite/active_record_attribute_methods_read.rb +1 -1
  87. data/lib/contrast/framework/rails/rewrite/active_record_time_zone_inherited.rb +1 -1
  88. data/lib/contrast/framework/rails/support.rb +2 -1
  89. data/lib/contrast/framework/sinatra/support.rb +3 -2
  90. data/lib/contrast/logger/application.rb +0 -3
  91. data/lib/contrast/utils/duck_utils.rb +1 -1
  92. data/lib/contrast/utils/heap_dump_util.rb +1 -1
  93. data/lib/contrast/utils/object_share.rb +3 -3
  94. data/lib/contrast/utils/preflight_util.rb +1 -1
  95. data/lib/contrast/utils/prevent_serialization.rb +1 -1
  96. data/lib/contrast/utils/resource_loader.rb +1 -1
  97. data/lib/contrast/utils/sha256_builder.rb +2 -2
  98. data/lib/contrast/utils/string_utils.rb +1 -1
  99. data/lib/contrast/utils/tag_util.rb +9 -13
  100. data/resources/assess/policy.json +9 -9
  101. data/resources/deadzone/policy.json +150 -0
  102. data/resources/protect/policy.json +12 -0
  103. data/ruby-agent.gemspec +10 -6
  104. data/service_executables/VERSION +1 -1
  105. data/service_executables/linux/contrast-service +0 -0
  106. data/service_executables/mac/contrast-service +0 -0
  107. metadata +69 -25
@@ -12,7 +12,8 @@ module Contrast
12
12
  module UserInput
13
13
  UNKNOWN_USER_INPUT = Contrast::Api::Dtm::UserInput.new.tap do |user_input|
14
14
  user_input.input_type = :UNKNOWN
15
- end.cs__freeze
15
+ end
16
+ UNKNOWN_USER_INPUT.cs__freeze
16
17
 
17
18
  def self.included klass
18
19
  klass.extend(ClassMethods)
@@ -65,7 +65,8 @@ module Contrast
65
65
  end
66
66
 
67
67
  %w[name default description required_languages display].each do |field|
68
- define_method(field) { hsh[field].dup }
68
+ # TODO: RUBY-1052
69
+ define_method(field) { hsh[field].dup } # rubocop:disable Performance/Kernel/DefineMethod
69
70
  end
70
71
  end
71
72
 
@@ -35,6 +35,42 @@ module Contrast
35
35
  disabled_rules.include?(name)
36
36
  end
37
37
 
38
+ # The value of the stacktrace should be treated as an ENUM. We upcase it for
39
+ # faster comparisons when we use it. Anything not one of the known values of
40
+ # 'NONE', 'SOME', or 'ALL' is treated as 'ALL'
41
+ #
42
+ # @return [Symbol] the normalized value of CONFIG.root.assess.stacktraces
43
+ def capture_stacktrace_value
44
+ @_capture_stacktrace_value ||= case CONFIG.root.assess.stacktraces.upcase
45
+ when 'NONE'
46
+ :NONE
47
+ when 'SOME'
48
+ :SOME
49
+ else
50
+ :ALL
51
+ end
52
+ end
53
+
54
+ # Consider capture_stacktrace_value along with the node type
55
+ # to dertmine whether stacktraces should be captured.
56
+ #
57
+ # capture_stacktrace_value -> (:ALL, :NONE, :SOME)
58
+ # node types (SourceNode, PolicyNode, TriggerNode, PropagationNode)
59
+ #
60
+ # @param policy_node [Contrast::Agent::Assess::Policy::PolicyNode] The node in question.
61
+ # @param return [Boolean] to capture or not to capture, that is the question.
62
+ def capture_stacktrace? policy_node
63
+ return true if capture_stacktrace_value == :ALL
64
+
65
+ return false if capture_stacktrace_value == :NONE
66
+
67
+ # Below here capture_stacktrace_value must be :SOME.
68
+ return true if policy_node.cs__is_a?(Contrast::Agent::Assess::Policy::SourceNode)
69
+ return true if policy_node.cs__is_a?(Contrast::Agent::Assess::Policy::TriggerNode)
70
+
71
+ false
72
+ end
73
+
38
74
  def scan_response?
39
75
  @_scan_response = !false?(CONFIG.root.assess.enable_scan_response) if @_scan_response.nil?
40
76
  @_scan_response
@@ -168,9 +168,11 @@ Contrast::Components::ComponentReceiverClassInterface::COMPONENT_MAP[:settings]
168
168
  require 'contrast/components/assess'
169
169
  require 'contrast/components/protect'
170
170
  require 'contrast/components/inventory'
171
- Contrast::Components::ComponentReceiverClassInterface::COMPONENT_MAP[:analysis] = [Contrast::Components::Protect,
172
- Contrast::Components::Assess,
173
- Contrast::Components::Inventory]
171
+ Contrast::Components::ComponentReceiverClassInterface::COMPONENT_MAP[:analysis] = [
172
+ Contrast::Components::Protect,
173
+ Contrast::Components::Assess,
174
+ Contrast::Components::Inventory
175
+ ]
174
176
 
175
177
  require 'contrast/components/logger'
176
178
  Contrast::Components::ComponentReceiverClassInterface::COMPONENT_MAP[:logging] = [Contrast::Components::Logger]
@@ -42,18 +42,84 @@ module Contrast
42
42
  # For each instance method on a scope, define a forwarder
43
43
  # to the scope on the current execution context's scope.
44
44
 
45
- Contrast::Agent::Scope.public_instance_methods(false).each do |method_sym|
46
- define_method(method_sym) do |*args, &block|
47
- scope_for_current_ec.send(method_sym, *args, &block)
48
- end
49
- end
50
-
51
45
  def scope_for_current_ec
52
46
  MONITOR.synchronize do
53
47
  return EXECUTION_CONTEXT[Fiber.current] ||= Contrast::Agent::Scope.new
54
48
  end
55
49
  end
56
50
 
51
+ def enter_contrast_scope!
52
+ scope_for_current_ec.enter_contrast_scope!
53
+ end
54
+
55
+ def enter_deserialization_scope!
56
+ scope_for_current_ec.enter_deserialization_scope!
57
+ end
58
+
59
+ def enter_split_scope!
60
+ scope_for_current_ec.enter_split_scope!
61
+ end
62
+
63
+ def enter_scope! name
64
+ scope_for_current_ec.enter_scope! name
65
+ end
66
+
67
+ def exit_contrast_scope!
68
+ scope_for_current_ec.exit_contrast_scope!
69
+ end
70
+
71
+ def exit_deserialization_scope!
72
+ scope_for_current_ec.exit_deserialization_scope!
73
+ end
74
+
75
+ def exit_split_scope!
76
+ scope_for_current_ec.exit_split_scope!
77
+ end
78
+
79
+ def exit_scope! name
80
+ scope_for_current_ec.exit_scope! name
81
+ end
82
+
83
+ def in_contrast_scope?
84
+ scope_for_current_ec.in_contrast_scope?
85
+ end
86
+
87
+ def in_deserialization_scope?
88
+ scope_for_current_ec.in_deserialization_scope?
89
+ end
90
+
91
+ def in_split_scope?
92
+ scope_for_current_ec.in_split_scope?
93
+ end
94
+
95
+ def split_scope_depth
96
+ scope_for_current_ec.split_scope_depth
97
+ end
98
+
99
+ def in_scope? name
100
+ scope_for_current_ec.in_scope? name
101
+ end
102
+
103
+ def with_contrast_scope
104
+ scope_for_current_ec.enter_contrast_scope!
105
+ yield
106
+ ensure
107
+ scope_for_current_ec.exit_contrast_scope!
108
+ end
109
+
110
+ def with_deserialization_scope
111
+ scope_for_current_ec.enter_deserialization_scope!
112
+ ensure
113
+ scope_for_current_ec.exit_deserialization_scope!
114
+ end
115
+
116
+ def with_split_scope
117
+ scope_for_current_ec.enter_split_scope!
118
+ yield
119
+ ensure
120
+ scope_for_current_ec.exit_split_scope!
121
+ end
122
+
57
123
  # TODO: RUBY-572
58
124
  #
59
125
  # Current behavior is to no-op if we're not "in a request context".
@@ -57,19 +57,22 @@ module Contrast
57
57
  # Meta-define an accessor for each state attribute.
58
58
 
59
59
  PROTECT_STATE_ATTRS.each do |attr|
60
- define_method(attr) do
60
+ # TODO: RUBY-1052
61
+ define_method(attr) do # rubocop:disable Performance/Kernel/DefineMethod
61
62
  protect_state[attr]
62
63
  end
63
64
  end
64
65
 
65
66
  ASSESS_STATE_ATTRS.each do |attr|
66
- define_method(attr) do
67
+ # TODO: RUBY-1052
68
+ define_method(attr) do # rubocop:disable Performance/Kernel/DefineMethod
67
69
  assess_state[attr]
68
70
  end
69
71
  end
70
72
 
71
73
  APPLICATION_STATE_ATTRS.each do |attr|
72
- define_method(attr) do
74
+ # TODO: RUBY-1052
75
+ define_method(attr) do # rubocop:disable Performance/Kernel/DefineMethod
73
76
  application_state[attr]
74
77
  end
75
78
  end
@@ -11,7 +11,8 @@ module Contrast
11
11
  enable: EMPTY_VALUE,
12
12
  enable_scan_response: Contrast::Config::DefaultValue.new('true'),
13
13
  sampling: Contrast::Config::SamplingConfiguration,
14
- rules: Contrast::Config::AssessRulesConfiguration
14
+ rules: Contrast::Config::AssessRulesConfiguration,
15
+ stacktraces: Contrast::Config::DefaultValue.new('ALL')
15
16
  }.cs__freeze
16
17
 
17
18
  def initialize hsh
@@ -35,12 +35,11 @@ module Contrast
35
35
  # operation happens in C, we have to do it here rather than rely on the
36
36
  # patch of our String append or concat methods.
37
37
  def cs__track_join ary, separator, ret
38
- return ret unless ary
38
+ return ret unless ary&.any? { |element| Contrast::Agent::Assess::Tracker.tracked?(element) }
39
39
  return ret if Contrast::Agent::Patching::Policy::Patch.skip_assess_analysis?
40
40
 
41
41
  with_contrast_scope do
42
- properties = Contrast::Agent::Assess::Tracker.properties(ret)
43
- return ret unless properties
42
+ return ret unless (properties = Contrast::Agent::Assess::Tracker.properties!(ret))
44
43
 
45
44
  shift = 0
46
45
  separator_length = separator.nil? ? 0 : separator.to_s.length
@@ -6,9 +6,7 @@ module ERBPropagator
6
6
  class << self
7
7
  def result_tagger patcher, preshift, ret, _block
8
8
  return unless preshift.args.length >= 1
9
-
10
- properties = Contrast::Agent::Assess::Tracker.properties(ret)
11
- return unless properties
9
+ return unless (properties = Contrast::Agent::Assess::Tracker.properties!(ret))
12
10
 
13
11
  used_binding = preshift.args[0]
14
12
  binding_variable_set = used_binding.local_variables
@@ -27,10 +27,7 @@ module Contrast
27
27
  source,
28
28
  Kernel,
29
29
  nil,
30
- [source])
31
- # Exec replaces the current process, if we occur in a forked process
32
- # our appendage of this finding will not make it to TS
33
- Contrast::Agent::AtExitHook.on_exit
30
+ source)
34
31
  end
35
32
 
36
33
  private
@@ -61,8 +61,7 @@ module Contrast
61
61
 
62
62
  with_contrast_scope do
63
63
  results.each do |result|
64
- result_properties = Contrast::Agent::Assess::Tracker.properties(result)
65
- next unless result_properties
64
+ next unless (result_properties = Contrast::Agent::Assess::Tracker.properties!(result))
66
65
 
67
66
  result_properties.splat_from(fiber, result)
68
67
  result_properties.build_event(
@@ -82,7 +81,7 @@ module Contrast
82
81
  return unless underlying.is_a?(String) && !underlying.empty?
83
82
 
84
83
  with_contrast_scope do
85
- properties = Contrast::Agent::Assess::Tracker.properties(fiber)
84
+ properties = Contrast::Agent::Assess::Tracker.properties!(fiber)
86
85
  return unless properties
87
86
 
88
87
  properties.splat_from(underlying, fiber)
@@ -17,11 +17,13 @@ module Contrast
17
17
  return object unless object.is_a?(String) && !object.cs__frozen?
18
18
  return object unless Contrast::Agent::Assess::Tracker.tracked?(object)
19
19
 
20
- ret = Contrast::Agent::Assess::Tracker.duplicate(object)
21
- ret.cs__freeze
20
+ # Copy the object, then freeze it, so that it looks the same
21
+ # externally, but will have our finalizer on it.
22
+ object.dup&.cs__freeze
22
23
  rescue StandardError
23
24
  # we'll rescue this error, but we can't log it here as that will
24
25
  # result in a seg fault
26
+ object
25
27
  end
26
28
 
27
29
  def instrument_hash_track
@@ -39,8 +39,7 @@ module Contrast
39
39
  # oh, and there's also %<name>type and %{name}... b/c of course there is
40
40
  # -HM
41
41
  def sprintf_tagger patcher, preshift, ret, _block
42
- properties = Contrast::Agent::Assess::Tracker.properties(ret)
43
- return unless properties
42
+ return unless (properties = Contrast::Agent::Assess::Tracker.properties!(ret))
44
43
 
45
44
  format_string = preshift.args[0]
46
45
  args = preshift.args[1]
@@ -6,42 +6,50 @@ require 'contrast/components/interface'
6
6
  module Contrast
7
7
  module Extension
8
8
  module Assess
9
- # This is our patch of the Array class required to handle propagation
9
+ # This is our patch of the Marshal class
10
10
  # Disclaimer: there may be a better way, but we're in a 'get it work' state.
11
11
  # Hopefully, we'll be in a 'get it right' state soon.
12
- # This module is used for our Marshal#load patches
12
+ # This module is used for our Marshal.load patches
13
13
  class MarshalPropagator
14
14
  include Contrast::Components::Interface
15
15
 
16
- access_component :logging
16
+ access_component :logging, :scope
17
17
 
18
18
  class << self
19
- def cs__load_trigger_check source, ret
20
- current_context = Contrast::Agent::REQUEST_TRACKER.current
21
- return unless current_context
19
+ def cs__load_protect arg
20
+ return if in_contrast_scope?
22
21
 
23
- # Since we know this is the source of the trigger, we can do some
24
- # optimization here and return when it is not tracked
25
- return unless Contrast::Agent::Assess::Tracker.tracked?(source)
22
+ with_contrast_scope do
23
+ Contrast::Agent::Protect::Policy::AppliesDeserializationRule.prepended_invoke(arg)
24
+ end
25
+ nil
26
+ end
27
+
28
+ def cs__load_assess source, ret
29
+ with_contrast_scope do
30
+ current_context = Contrast::Agent::REQUEST_TRACKER.current
31
+ return unless current_context
26
32
 
27
- args = [source]
28
- # source might not be all the args passed in, but it is the one we care
29
- # about. we could pass in all the args in the last param here if it
30
- # becomes an issue in rendering on TS
31
- Contrast::Agent::Assess::Policy::TriggerMethod.build_finding(
32
- current_context,
33
- trigger_node('Marshal', :load),
34
- source,
35
- self,
36
- ret,
37
- args)
38
- properties = Contrast::Agent::Assess::Tracker.properties(ret)
39
- properties.copy_from(source, ret)
33
+ args = [source]
34
+ # source might not be all the args passed in, but it is the one we care
35
+ # about. we could pass in all the args in the last param here if it
36
+ # becomes an issue in rendering on TS
37
+ Contrast::Agent::Assess::Policy::TriggerMethod.build_finding(
38
+ current_context,
39
+ trigger_node('Marshal', :load),
40
+ source,
41
+ self,
42
+ ret,
43
+ *args)
44
+ return unless (properties = Contrast::Agent::Assess::Tracker.properties!(ret))
40
45
 
41
- node = Contrast::Agent::Assess::Policy::Policy.instance.find_propagator_node('Marshal', :load, false)
42
- properties.build_event(node, ret, self, ret, args)
43
- rescue StandardError => e
44
- logger.error('Unable to determine if a trigger occurred in Marshal.load', e)
46
+ properties.copy_from(source, ret)
47
+
48
+ node = Contrast::Agent::Assess::Policy::Policy.instance.find_propagator_node('Marshal', :load, false)
49
+ properties.build_event(node, ret, self, ret, args)
50
+ rescue StandardError => e
51
+ logger.error('Unable to run Assess for Marshal.load', e)
52
+ end
45
53
  end
46
54
 
47
55
  def instrument_marshal_load
@@ -48,14 +48,9 @@ module Contrast
48
48
 
49
49
  target = info_hash[:back_ref]
50
50
  with_contrast_scope do
51
- result = info_hash[:result]
52
- return unless result
53
-
54
- string = info_hash[:string]
55
- return unless string
56
-
57
- properties = Contrast::Agent::Assess::Tracker.properties(target)
58
- return unless properties
51
+ return unless (result = info_hash[:result])
52
+ return unless (string = info_hash[:string])
53
+ return unless (properties = Contrast::Agent::Assess::Tracker.properties!(target))
59
54
 
60
55
  properties.splat_from(string, target)
61
56
  properties.build_event(
@@ -36,8 +36,7 @@ module Contrast
36
36
  return unless inputs.any? { |input| Contrast::Agent::Assess::Tracker.tracked?(input) }
37
37
 
38
38
  with_contrast_scope do
39
- properties = Contrast::Agent::Assess::Tracker.properties(result)
40
- return unless properties
39
+ return unless (properties = Contrast::Agent::Assess::Tracker.properties!(result))
41
40
 
42
41
  parent_events = []
43
42
  offset = 0
@@ -4,68 +4,66 @@
4
4
  module Contrast
5
5
  module Framework
6
6
  # The API for all subclasses to implement to correctly support a given framework
7
- class BaseSupport
8
- class << self
9
- # The top level module name used by the framework
10
- def detection_class
11
- raise NoMethodError('Subclasses of BaseSupport should implement this method')
12
- end
7
+ module BaseSupport
8
+ # The top level module name used by the framework
9
+ def detection_class
10
+ raise NoMethodError('Subclasses of BaseSupport should implement this method')
11
+ end
13
12
 
14
- def version
15
- raise NoMethodError('Subclasses of BaseSupport should implement this method')
16
- end
13
+ def version
14
+ raise NoMethodError('Subclasses of BaseSupport should implement this method')
15
+ end
17
16
 
18
- def application_name
19
- raise NoMethodError, 'Subclasses of BaseSupport should implement this method'
20
- end
17
+ def application_name
18
+ raise NoMethodError, 'Subclasses of BaseSupport should implement this method'
19
+ end
21
20
 
22
- def server_type
23
- raise NoMethodError, 'Subclasses of BaseSupport should implement this method'
24
- end
21
+ def server_type
22
+ raise NoMethodError, 'Subclasses of BaseSupport should implement this method'
23
+ end
25
24
 
26
- # Find all the predefined routes for this application and append them to the
27
- # provided inventory message
28
- # msg should be a Contrast::Api::Dtm::ApplicationUpdate or some other msg
29
- # that has a routes array consisting of Contrast::Api::Dtm::RouteCoverage
30
- def collect_routes
31
- raise NoMethodError, 'Subclasses of BaseSupport should implement this method'
32
- end
25
+ # Find all the predefined routes for this application and append them to the
26
+ # provided inventory message
27
+ # msg should be a Contrast::Api::Dtm::ApplicationUpdate or some other msg
28
+ # that has a routes array consisting of Contrast::Api::Dtm::RouteCoverage
29
+ def collect_routes
30
+ raise NoMethodError, 'Subclasses of BaseSupport should implement this method'
31
+ end
33
32
 
34
- def current_route
35
- raise NoMethodError, 'Subclasses of BaseSupport should implement this method'
36
- end
33
+ def current_route
34
+ raise NoMethodError, 'Subclasses of BaseSupport should implement this method'
35
+ end
37
36
 
38
- def retrieve_request _env
39
- raise NoMethodError, 'Subclasses of BaseSupport should implement this method'
40
- end
37
+ def retrieve_request _env
38
+ raise NoMethodError, 'Subclasses of BaseSupport should implement this method'
39
+ end
41
40
 
42
- # Some Frameworks require specific patching for their classes to handle
43
- # functionality like configuration scanning. To accommodate this, this
44
- # method provides a place to register those patches for invocation on
45
- # Agent load.
46
- #
47
- # By default, and hopefully in all cases, we won't need these patches,
48
- # so we're allowing nil here rather than raising an exception.
49
- def before_load_patches!; end
41
+ # Some Frameworks require specific patching for their classes to handle
42
+ # functionality like configuration scanning. To accommodate this, this
43
+ # method provides a place to register those patches for invocation on
44
+ # Agent load.
45
+ #
46
+ # By default, and hopefully in all cases, we won't need these patches,
47
+ # so we're allowing nil here rather than raising an exception.
48
+ def before_load_patches!; end
50
49
 
51
- # Some Frameworks require specific patching for their classes to handle
52
- # functionality like routing. To accommodate this, this method provides
53
- # a place to register those patches for invocation in our
54
- # AfterLoadPatcher flow.
55
- #
56
- # By default, and hopefully in all cases, we won't need these patches,
57
- # so we're allowing nil here rather than raising an exception.
58
- #
59
- # @return [Set<Contrast::Agent::Patching::Policy::AfterLoadPatch>,nil]
60
- # those patches required for a Framework which can only be installed
61
- # once a specific module has been loaded.
62
- def after_load_patches; end
50
+ # Some Frameworks require specific patching for their classes to handle
51
+ # functionality like routing. To accommodate this, this method provides
52
+ # a place to register those patches for invocation in our
53
+ # AfterLoadPatcher flow.
54
+ #
55
+ # By default, and hopefully in all cases, we won't need these patches,
56
+ # so we're allowing nil here rather than raising an exception.
57
+ #
58
+ # @return [Set<Contrast::Agent::Patching::Policy::AfterLoadPatch>,nil]
59
+ # those patches required for a Framework which can only be installed
60
+ # once a specific module has been loaded.
61
+ def after_load_patches; end
63
62
 
64
- # We only support websockets in rails right now, so we won't detect streaming in
65
- # any other framework
66
- def streaming? _env
67
- false
68
- end
63
+ # We only support websockets in rails right now, so we won't detect streaming in
64
+ # any other framework
65
+ def streaming? _env
66
+ false
69
67
  end
70
68
  end
71
69
  end