# 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' module Contrast module Agent module Reporting # This is the new Library Discovery class which will include all the needed information for the new # reporting system to relay this information in the Application Update messages. These libraries are used by # TeamServer to construct the dependency information for the SCA feature. They represent those gems that are # included in the GemSpec, not necessarily those that have had files in them required. # # @attr_reader class_count [Integer] the number of files in the Gem which contain code. # @attr_reader external_date [Integer] the time, in ms, when the Gem was published. Required for reporting. # @attr_reader file [String] the name of the Gem. Required for reporting. # @attr_reader hash [String] the Sha256 of the Gem, matching its hash in RubyGems. Required for reporting. # @attr_reader internal_date [Integer] the time, in ms, when the Gem was published. Required for reporting. # @attr_reader manifest [String] the YAML form of the Gem's specification. # @attr_reader tags [String] Inventory tags set by the user via configuration. # @attr_reader url [String] The homepage of the Gem. # @attr_reader version [String] The version of the Gem. class LibraryDiscovery # required attributes attr_reader :external_date, :file, :hash, :internal_date # optional attributes attr_reader :class_count, :manifest, :tags, :url, :version class << self # Convert a DTM for SpeedRacer to an Event for TeamServer. # # @param library_dtm [Contrast::Api::Dtm::Library] # @return [Contrast::Agent::Reporting::LibraryDiscovery] def convert library_dtm report = new report.attach_data(library_dtm) report end end # Attach the data from the protobuf models to this reporter so that it can be sent to TeamServer directly # # @param library_dtm [Contrast::Api::Dtm::Library] def attach_data library_dtm @class_count = library_dtm.class_count @external_date = library_dtm.external_ms @file = library_dtm.file_path @hash = library_dtm.hash_code @internal_date = library_dtm.internal_ms @manifest = library_dtm.manifest @tags = Contrast::INVENTORY.tags @url = library_dtm.url @version = library_dtm.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 msg = { classCount: class_count, externalDate: external_date, file: file, hash: hash, internalDate: internal_date, manifest: manifest, url: url, version: version } msg[:tags] = tags if tags msg end # Ensure the required fields are present. # # @raise [ArgumentError] def validate unless external_date raise(ArgumentError, "#{ self } did not have a proper external date. Unable to continue.") end unless internal_date raise(ArgumentError, "#{ self } did not have a proper internal date. Unable to continue.") end raise(ArgumentError, "#{ self } did not have a proper file. Unable to continue.") unless file raise(ArgumentError, "#{ self } did not have a proper hash. Unable to continue.") unless hash end end end end end