# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true require 'contrast/api/dtm.pb' require 'contrast/components/logger' module Contrast module Agent module Reporting # This is the new Architecture Component class which will include all the needed information for the new # reporting system to relay this information in the Application Update and Application Activity messages. These # components are used by TeamServer to construct the backend/ outbound connection section of the Flow Map # feature. # # @attr_reader remote_host [String] the host section of the connection to the component. # @attr_reader remote_port [Integer] the port section of the connection to the component. # @attr_reader type [String] the type of the component. Only ::VALID_TYPES can be used. Required for reporting. # @attr_reader url [String] the url used to connect to the component. Required for reporting. # @attr_reader vendor [String] the publisher of the component, like MySQL. class ArchitectureComponent include Contrast::Components::Logger::InstanceMethods # required attributes attr_reader :type, :url # optional attributes attr_reader :remote_host, :remote_port, :vendor # TeamServer only treats these specific values as valid for Architecture Components. It does not know how to # process a message with a different type. VALID_TYPES = %w[db ldap ws].cs__freeze class << self # Convert a DTM for SpeedRacer to an Event for TeamServer. # # @param component_dtm [Contrast::Api::Dtm::ArchitectureComponent] # @return [Contrast::Agent::Reporting::ArchitectureComponent] def convert component_dtm report = new report.attach_data(component_dtm) report end end # Attach the data from the protobuf models to this reporter so that it can be sent to TeamServer directly. # # @param component_dtm [Contrast::Api::Dtm::ArchitectureComponent] def attach_data component_dtm @remote_host = component_dtm.remote_host @remote_port = component_dtm.remote_port @type = component_dtm.type @url = component_dtm.url @vendor = component_dtm.vendor 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('ArchitectureComponent validation failed with: ', e) return end { remoteHost: remote_host, remotePort: remote_port, type: type, url: url, vendor: vendor } end # Ensure the required fields are present. # # @raise [ArgumentError] def validate unless VALID_TYPES.include?(type) raise(ArgumentError, "#{ self } did not have a proper type - '#{ type }'. Unable to continue.") end raise(ArgumentError, "#{ self } did not have a proper URL. Unable to continue.") unless url end end end end end