# Copyright (c) 2023 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_defend_attack_sample_activity' require 'contrast/agent/reporting/reporting_events/reportable_hash' module Contrast module Agent module Reporting # This is the new ApplicationDefendAttackActivity class which will include the attacks sent by the source. class ApplicationDefendAttackActivity < Contrast::Agent::Reporting::ReportableHash # @return [Contrast::Agent::Reporting::ApplicationDefendAttackSampleActivity] attr_accessor :blocked # @return [Contrast::Agent::Reporting::ApplicationDefendAttackSampleActivity] attr_accessor :exploited # @return [Contrast::Agent::Reporting::ApplicationDefendAttackSampleActivity] attr_accessor :ineffective # @return [Contrast::Agent::Reporting::ApplicationDefendAttackSampleActivity] attr_accessor :suspicious # Helper method to determine before hand the response type and iv needed for access # # @return [Contrast::Agent::Reporting::ResponseType] attr_reader :response_type def initialize @start_time = start_time super() end def to_controlled_hash blocked_hash = blocked&.to_controlled_hash || Contrast::Utils::ObjectShare::EMPTY_HASH exploited_hash = exploited&.to_controlled_hash || Contrast::Utils::ObjectShare::EMPTY_HASH ineffective_hash = ineffective&.to_controlled_hash || Contrast::Utils::ObjectShare::EMPTY_HASH suspicious_hash = suspicious&.to_controlled_hash || Contrast::Utils::ObjectShare::EMPTY_HASH validate(blocked_hash, exploited_hash, ineffective_hash, suspicious_hash) { startTime: @start_time, blocked: blocked_hash, exploited: exploited_hash, ineffective: ineffective_hash, suspicious: suspicious_hash } end def validate blocked_hash, exploited_hash, ineffective_hash, suspicious_hash raise(ArgumentError, 'Start Time for is not presented') unless @start_time return unless [blocked_hash, exploited_hash, ineffective_hash, suspicious_hash].all?(&:empty?) raise(ArgumentError, 'At least one of the samples must be populated') end # @param attack_result [Contrast::Agent::Reporting::AttackResult] # @return [Contrast::Agent::Reporting::Defend::AttackSampleActivity] def attach_data attack_result attack_sample_activity = Contrast::Agent::Reporting::ApplicationDefendAttackSampleActivity.new attack_sample_activity.attach_data(attack_result) @response_type = attack_result.response case response_type when ::Contrast::Agent::Reporting::ResponseType::BLOCKED, ::Contrast::Agent::Reporting::ResponseType::BLOCKED_AT_PERIMETER @blocked = attack_sample_activity when ::Contrast::Agent::Reporting::ResponseType::MONITORED @exploited = attack_sample_activity when ::Contrast::Agent::Reporting::ResponseType::PROBED @ineffective = attack_sample_activity when ::Contrast::Agent::Reporting::ResponseType::SUSPICIOUS @suspicious = attack_sample_activity end end def start_time Contrast::Agent::REQUEST_TRACKER.current&.timer&.start_ms || 0 end end end end end