# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true module Contrast module Agent module Reporting # This is the new FindingRequest class which will include all the needed information for the new reporting system # to relay this information in the Finding/Trace messages. These requests are used by TeamServer to construct the # HTTP information for the assess feature. They represent the literal request made that resulted in the # vulnerability being triggered. class FindingRequest # @return [String] the body of this request attr_reader :body # @return [Hash>] the headers of this request attr_reader :headers # @return [String] the HTTP verb of this request attr_reader :method # @return [Hash>] the parameters of this request attr_reader :parameters # @return [Integer] the port to which this request connected attr_reader :port # @return [String] the HTTP(S) protocol of this request attr_reader :protocol # @return [String] the query string of this request attr_reader :query_string # @return [String] the url, including path and script, of this request attr_reader :uri # @return [String] the HTTP version of this request attr_reader :version class << self # @param request [Contrast::Agent::Request] # @return [Contrast::Agent::Reporting::FindingRequest] def convert request report = new report.attach_data(request) report end end # Parse the data from a Contrast::Agent::Request to attach what is required for reporting to TeamServer to this # Contrast::Agent::Reporting::FindingRequest # # @param request [Contrast::Agent::Request] def attach_data request @body = request.body @headers = {} request.headers.each_pair do |key, value| # We need to change from the uppercase _ format to capitalized - format. header = key.split('_') header.each(&:capitalize!) header = header.join('-') headers[header] = value.split end @method = request.request_method @parameters = {} request.parameters.each_pair { |key, value| @parameters[key] = Array(value) } @port = request.port || 0 @protocol = request.scheme @query_string = request.query_string @uri = request.normalized_uri @version = request.version end # Convert the instance variables on the class, and other information, into the identifiers required for # TeamServer to process the JSON form of this message. # # @return [Hash] # @raise [ArgumentError] def to_controlled_hash validate { body: body, headers: headers, method: method, # rubocop:disable Security/Object/Method parameters: parameters, port: port || 0, protocol: protocol, queryString: query_string, uri: uri, version: version } end def validate unless method && !method.empty? # rubocop:disable Security/Object/Method raise(ArgumentError, "#{ self } did not have a proper method. Unable to continue.") end raise(ArgumentError, "#{ self } did not have a proper uri. Unable to continue.") unless uri && !uri.empty? end end end end end