# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true require 'contrast/components/logger' require 'contrast/agent/reporting/reporting_events/application_reporting_event' require 'contrast/agent/reporting/reporting_events/application_defend_activity' require 'contrast/agent/reporting/reporting_events/application_inventory_activity' require 'contrast/agent/reporting/attack_result/response_type' module Contrast module Agent module Reporting # This is the new ApplicationActivity class which will include all the needed information for the new reporting # system to report class ApplicationActivity < Contrast::Agent::Reporting::ApplicationReportingEvent include Contrast::Agent::Reporting::ResponseType include Contrast::Components::Logger::InstanceMethods # @return [Integer] attr_accessor :query_count # @return [Array] attr_accessor :routes # @return [Contrast::Agent::Response] attr_accessor :response def initialize @routes = [] @query_count = 0 @event_method = :PUT @event_type = :application_activity @event_endpoint = Contrast::Agent::Reporting::Endpoints.application_activity super end # @return [Contrast::Agent::Reporting::FindingRequest] Current context's request def request @_request ||= FindingRequest.convert(Contrast::Agent::REQUEST_TRACKER.current&.request) end # @return [Contrast::Agent::Reporting::ApplicationDefendActivity] main # activity for all protect rules. def defend @_defend ||= Contrast::Agent::Reporting::ApplicationDefendActivity.new end # @return [Contrast::Agent::Reporting::ApplicationInventoryActivity] main # activity for all inventory activity reporting. def inventory @_inventory ||= Contrast::Agent::Reporting::ApplicationInventoryActivity.new end # @return file_name [String] used for audit def file_name 'activity-application' end def to_controlled_hash hsh = { lastUpdate: since_last_update } hsh[:defend] = defend&.to_controlled_hash hsh[:inventory] = inventory&.to_controlled_hash hsh end # Look for attack results and access to samples by # searching with rule_id and response_type # # @param rule_id [String] name of the protect rule # @param response_type[Symbol, nil] # return any matches. def attack_results_for rule_id, response_type = nil results = [] defend.attackers.each do |attacker| next unless attacker.protection_rules[rule_id] result = case response_type when BLOCKED, BLOCKED_AT_PERIMETER attacker.protection_rules[rule_id].blocked when EXPLOITED attacker.protection_rules[rule_id].exploited when PROBED attacker.protection_rules[rule_id].ineffective when SUSPICIOUS attacker.protection_rules[rule_id].suspicious else attacker.protection_rules[rule_id] end results << result if result end results end # By reference. List of all results only by values, no rule_ids. # # @return [Array<[Contrast::Agent::Reporting::ApplicationDefendAttackerActivity]>] def attack_results defend.attackers.map { |a| a.protection_rules.values } end # This is primary used for attaching new data and merging existing # samples per rule entry in attackers, and to make sure the attack # time_map is updated correctly. # # @param attack_result [Contrast::Agent::Reporting::AttackResult] def attach_defend attack_result defend.attach_data(attack_result) end # This is primary used for attaching new inventory reporting # # @param architecture [Contrast::Agent::Reporting::ArchitectureComponent] def attach_inventory architecture inventory.attach_data(architecture) end end end end end