Class: Contrast::Agent::RequestContext
- Includes:
- Components::Interface
- Defined in:
- lib/contrast/agent/request_context.rb
Overview
This class acts to encapsulate information about the currently executed request, making it available to the Agent for the duration of the request in a standardized and normalized format which the Agent understands.
Constant Summary collapse
- EMPTY_INPUT_ANALYSIS_PB =
Contrast::Api::Settings::InputAnalysis.new
Instance Attribute Summary collapse
-
#activity ⇒ Object
readonly
Returns the value of attribute activity.
-
#logging_hash ⇒ Object
readonly
Returns the value of attribute logging_hash.
-
#observed_route ⇒ Object
readonly
Returns the value of attribute observed_route.
-
#request ⇒ Object
readonly
Returns the value of attribute request.
-
#response ⇒ Object
readonly
Returns the value of attribute response.
-
#route ⇒ Object
readonly
Returns the value of attribute route.
-
#server_activity ⇒ Object
readonly
Returns the value of attribute server_activity.
-
#speedracer_input_analysis ⇒ Object
readonly
Returns the value of attribute speedracer_input_analysis.
-
#timer ⇒ Object
readonly
Returns the value of attribute timer.
Instance Method Summary collapse
- #add_property(key, value) ⇒ Object
- #analyze_request? ⇒ Boolean
- #analyze_response? ⇒ Boolean
- #app_loaded? ⇒ Boolean
-
#append_route_coverage(route) ⇒ Object
Convert the discovered route for this request to appropriate forms and disseminate it to those locations where it is necessary for our route coverage and finding vulnerability discovery features to function.
-
#extract_after(rack_response) ⇒ Object
append anything we’ve learned to the request seen message this is the sum-total of all inventory information that has been accumulated since the last request.
- #get_property(key) ⇒ Object
-
#handle_protect_state(agent_settings) ⇒ Object
NOTE: this method is only used as a backstop if Speedracer sends Input Evaluations when the protect state indicates a security exception should be thrown.
-
#initialize(rack_request, app_loaded = true) ⇒ RequestContext
constructor
A new instance of RequestContext.
- #reset_activity ⇒ Object
-
#results_for(rule, response_type = nil) ⇒ Array<Contrast::Api::Dtm::AttackResult>
Collect the results for the given rule with the given action.
- #service_extract_request ⇒ Object
Methods included from Components::Interface
Constructor Details
#initialize(rack_request, app_loaded = true) ⇒ RequestContext
Returns a new instance of RequestContext.
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/contrast/agent/request_context.rb', line 31 def initialize rack_request, app_loaded = true with_contrast_scope do # all requests get a timer and hash @timer = Contrast::Utils::Timer.new @logging_hash = { request_id: __id__ } # instantiate helper for request and response @request = Contrast::Agent::Request.new(rack_request) @activity = Contrast::Api::Dtm::Activity.new @activity.http_request = request.dtm @server_activity = Contrast::Api::Dtm::ServerActivity.new @observed_route = Contrast::Api::Dtm::ObservedRoute.new # build analyzer @do_not_track = false @speedracer_input_analysis = EMPTY_INPUT_ANALYSIS_PB speedracer_input_analysis.request = request # flag to indicate whether the app is fully loaded @app_loaded = !!app_loaded # generic holder for properties that can be set throughout this request @_properties = {} @sample = true @sample_request, @sample_response = Contrast::Utils::Assess::SamplingUtil.instance.sample?(@request) if ASSESS.enabled? @sample_response &&= ASSESS.scan_response? append_route_coverage(Contrast::Agent.framework_manager.get_route_dtm(@request)) end end |
Instance Attribute Details
#activity ⇒ Object (readonly)
Returns the value of attribute activity.
21 22 23 |
# File 'lib/contrast/agent/request_context.rb', line 21 def activity @activity end |
#logging_hash ⇒ Object (readonly)
Returns the value of attribute logging_hash.
21 22 23 |
# File 'lib/contrast/agent/request_context.rb', line 21 def logging_hash @logging_hash end |
#observed_route ⇒ Object (readonly)
Returns the value of attribute observed_route.
21 22 23 |
# File 'lib/contrast/agent/request_context.rb', line 21 def observed_route @observed_route end |
#request ⇒ Object (readonly)
Returns the value of attribute request.
21 22 23 |
# File 'lib/contrast/agent/request_context.rb', line 21 def request @request end |
#response ⇒ Object (readonly)
Returns the value of attribute response.
21 22 23 |
# File 'lib/contrast/agent/request_context.rb', line 21 def response @response end |
#route ⇒ Object (readonly)
Returns the value of attribute route.
21 22 23 |
# File 'lib/contrast/agent/request_context.rb', line 21 def route @route end |
#server_activity ⇒ Object (readonly)
Returns the value of attribute server_activity.
21 22 23 |
# File 'lib/contrast/agent/request_context.rb', line 21 def server_activity @server_activity end |
#speedracer_input_analysis ⇒ Object (readonly)
Returns the value of attribute speedracer_input_analysis.
21 22 23 |
# File 'lib/contrast/agent/request_context.rb', line 21 def speedracer_input_analysis @speedracer_input_analysis end |
#timer ⇒ Object (readonly)
Returns the value of attribute timer.
21 22 23 |
# File 'lib/contrast/agent/request_context.rb', line 21 def timer @timer end |
Instance Method Details
#add_property(key, value) ⇒ Object
170 171 172 |
# File 'lib/contrast/agent/request_context.rb', line 170 def add_property key, value @_properties[key] = value end |
#analyze_request? ⇒ Boolean
74 75 76 |
# File 'lib/contrast/agent/request_context.rb', line 74 def analyze_request? @sample_request end |
#analyze_response? ⇒ Boolean
78 79 80 |
# File 'lib/contrast/agent/request_context.rb', line 78 def analyze_response? @sample_response end |
#app_loaded? ⇒ Boolean
70 71 72 |
# File 'lib/contrast/agent/request_context.rb', line 70 def app_loaded? @app_loaded end |
#append_route_coverage(route) ⇒ Object
Convert the discovered route for this request to appropriate forms and disseminate it to those locations where it is necessary for our route coverage and finding vulnerability discovery features to function.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/contrast/agent/request_context.rb', line 85 def append_route_coverage route return unless route # For our findings @route = route # For SR findings @activity.routes << route # For TS routes @observed_route.signature = route.route @observed_route.verb = route.verb @observed_route.url = route.url if route.url end |
#extract_after(rack_response) ⇒ Object
append anything we’ve learned to the request seen message this is the sum-total of all inventory information that has been accumulated since the last request
163 164 165 166 167 168 |
# File 'lib/contrast/agent/request_context.rb', line 163 def extract_after rack_response @response = Contrast::Agent::Response.new(rack_response) activity.http_response = @response.dtm if @sample_response rescue StandardError => e logger.error('Unable to extract information after request', e) end |
#get_property(key) ⇒ Object
174 175 176 |
# File 'lib/contrast/agent/request_context.rb', line 174 def get_property key @_properties[key] end |
#handle_protect_state(agent_settings) ⇒ Object
NOTE: this method is only used as a backstop if Speedracer sends Input Evaluations when the protect state indicates a security exception should be thrown. This method ensures that the attack reports are generated. Normally these should be generated on Speedracer for any attacks detected during prefilter.
146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/contrast/agent/request_context.rb', line 146 def handle_protect_state agent_settings return unless agent_settings&.protect_state state = agent_settings.protect_state @uuid = state.uuid @do_not_track = true unless state.track_request return unless state.security_exception # If Contrast Service has NOT handled the input analysis, handle them here build_attack_results(agent_settings) logger.debug('Contrast Service said to block this request') raise Contrast::SecurityException.new(nil, (state. || 'Blocking suspicious behavior')) end |
#reset_activity ⇒ Object
178 179 180 181 182 |
# File 'lib/contrast/agent/request_context.rb', line 178 def reset_activity @activity = Contrast::Api::Dtm::Activity.new(http_request: request.dtm) @server_activity = Contrast::Api::Dtm::ServerActivity.new # it doesn't look like this is ever actually used? @observed_route = Contrast::Api::Dtm::ObservedRoute.new end |
#results_for(rule, response_type = nil) ⇒ Array<Contrast::Api::Dtm::AttackResult>
Collect the results for the given rule with the given action
106 107 108 109 110 111 112 |
# File 'lib/contrast/agent/request_context.rb', line 106 def results_for rule, response_type = nil if response_type.nil? activity.results.select { |r| r.rule_id == rule } else activity.results.select { |r| r.rule_id == rule && r.response == response_type } end end |
#service_extract_request ⇒ Object
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/contrast/agent/request_context.rb', line 114 def service_extract_request return false unless AGENT.enabled? return false unless PROTECT.enabled? return false if @do_not_track service_response = Contrast::Agent.messaging_queue.send_event_immediately(@activity.http_request) return false unless service_response handle_protect_state(service_response) ia = service_response.input_analysis if ia logger.trace("Analysis from Contrast Service: evaluations=#{ ia.results.length }") logger.trace('Results', input_analysis: ia.inspect) @speedracer_input_analysis = ia speedracer_input_analysis.request = request else logger.trace('Analysis from Contrast Service was empty.') false end rescue Contrast::SecurityException => e raise e rescue StandardError => e logger.warn('Unable to extract Contrast Service information from request', e) false end |