# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true require 'json' require 'contrast/components/logger' require 'contrast/agent/reporting/reporting_events/application_reporting_event' require 'contrast/utils/object_share' module Contrast module Agent module Reporting # This is the new Route Observation class which will include all the needed information for the new reporting # system to relay this information in the Route Observation messages. These observations are used by TeamServer # to construct the route coverage information for the assess feature. They represent those methods which map to # externally accessible endpoints within the application, as registered to the application framework. This also # includes the literal URL and HTTP Verb used to invoke them, as they must have been called at this point to be # recorded. class ObservedRoute < Contrast::Agent::Reporting::ApplicationReportingEvent include Contrast::Components::Logger::InstanceMethods # @param [String] the method signature used to uniquely identify the coverage report. attr_accessor :signature # @param [String] the normalized URL used to access the method in the route. attr_accessor :url # @param [String] the HTTP Verb used to access the method in the route. attr_accessor :verb # @param [Array] the sources of user input accessed during this # request. Used for remediation determinations in TeamServer. attr_reader :sources def initialize @event_endpoint = Contrast::Agent::Reporting::Endpoints.observed_route @sources = [] @signature = Contrast::Utils::ObjectShare::EMPTY_STRING @verb = Contrast::Utils::ObjectShare::EMPTY_STRING @url = Contrast::Utils::ObjectShare::EMPTY_STRING super() end def file_name 'routes-observed' 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 begin validate rescue ArgumentError => e logger.error('ObservedRoute validation failed with: ', e) return end { session_id: ::Contrast::ASSESS.session_id, sources: @sources.map(&:to_controlled_hash), signature: @signature, verb: @verb, url: @url }.compact end # @raise [ArgumentError] def validate raise(ArgumentError, "#{ self } did not have a proper sources. Unable to continue.") if @sources.nil? raise(ArgumentError, "#{ self } did not have a proper signature. Unable to continue.") unless signature raise(ArgumentError, "#{ self } did not have a proper url. Unable to continue.") unless url nil end end end end end