# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true require 'json' require 'net/http' require 'contrast/components/logger' require 'contrast/utils/net_http_base' require 'contrast/api/communication/connection_status' require 'contrast/agent/reporting/reporting_utilities/response_handler' require 'contrast/agent/reporting/reporting_utilities/reporter_client_utils' require 'contrast/agent/reporting/reporting_utilities/endpoints' require 'contrast/agent/reporting/reporting_utilities/headers' module Contrast module Agent module Reporting # This class creates a Net::HTTP client and initiates a connection to the provided result # @attr_reader headers [Contrast::Agent::Reporting::Headers] class ReporterClient < Contrast::Utils::NetHttpBase attr_reader :headers include Contrast::Agent::Reporting::Endpoints include Contrast::Agent::Reporting::ReporterClientUtils SERVICE_NAME = 'Reporter' include Contrast::Components::Logger::InstanceMethods # This method initializes the Net::HTTP client we'll need. it will validate # the connection and make the first request. If connection is valid and response # is available then the open connection is returned. # # @return [Net::HTTP, nil] Return open connection or nil def initialize_connection # for this client we would use proxy and custom certificate file if available super(SERVICE_NAME, Contrast::API.api_url, true, true) end def initialize @headers = Contrast::Agent::Reporting::Headers.new super() end # Start the client for first time and sent startup event # # @param connection [Net::HTTP] open connection def startup! connection return if status.startup_messages_sent? return unless Contrast::Agent::Reporter.enabled? send_agent_startup(connection) end # Check event type and send it to appropriate TS endpoint # # @param event [Contrast::Api::Dtm,Contrast::Agent::Reporting::ReportingEvent] One of the DTMs valid # for the event field of Contrast::Api::Dtm::Message|Contrast::Api::Dtm::Activity # @param connection [Net::HTTP] open connection # @param send_immediately [Boolean] flag for the logger # @return response [Net::HTTP::Response, nil] response from TS if no response def send_event event, connection, send_immediately = false return unless Contrast::Agent::Reporter.enabled? response = send_events(event, connection) log_send_event event if send_immediately response rescue StandardError => e handle_error event, e end def status @_status ||= Contrast::Api::Communication::ConnectionStatus.new end def response_handler @_response_handler ||= Contrast::Agent::Reporting::ResponseHandler.new end def sleep? response_handler.sleep? end def wake_up response_handler.wake_up end end end end end