Class: Contrast::Agent::Reporting::ApplicationDefendActivity

Inherits:
ReportingEvent show all
Includes:
Components::Logger::InstanceMethods
Defined in:
lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb

Overview

This is the new ApplicationDefendActivity class which includes information about the defense of the application which was discovered during exercise of the application during this activity period.

Instance Attribute Summary collapse

Attributes inherited from ReportingEvent

#event_endpoint, #event_method

Instance Method Summary collapse

Methods included from Components::Logger::InstanceMethods

#cef_logger, #logger

Methods inherited from ReportingEvent

#attach_headers

Methods inherited from ReportableHash

#event_json, #valid?

Constructor Details

#initialize(ia_request: nil) ⇒ ApplicationDefendActivity

Returns a new instance of ApplicationDefendActivity.



20
21
22
23
24
25
# File 'lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb', line 20

def initialize ia_request: nil
  @attackers = []
  @event_type = :application_defend_activity
  @request = ia_request
  super()
end

Instance Attribute Details

#attackersArray<Contrast::Agent::Reporting::ApplicationDefendAttackerActivity> (readonly)



18
19
20
# File 'lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb', line 18

def attackers
  @attackers
end

Instance Method Details

#attach_data(attack_result) ⇒ Object

Parameters:



41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb', line 41

def attach_data attack_result
  return unless attack_result&.cs__is_a?(Contrast::Agent::Reporting::AttackResult)
  return if attack_result&.empty?

  attacker_activity = Contrast::Agent::Reporting::ApplicationDefendAttackerActivity.new(ia_request: @request)
  attacker_activity.attach_data(attack_result)

  @existing_attacker_activity = true
  if (existing_attacker_activity = find_existing_attacker_activity(attacker_activity))
    attach_existing(existing_attacker_activity, attacker_activity, attack_result.rule_id)
  else
    attackers << attacker_activity
  end
end

#attach_existing(existing_attacker_activity, attacker_activity, rule) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb', line 69

def attach_existing existing_attacker_activity, attacker_activity, rule
  new_violation = attacker_activity.protection_rules[rule]
  return unless new_violation

  sample_activity = Contrast::Agent::Reporting::ApplicationDefendAttackSampleActivity
  if (previously_violated = existing_attacker_activity.protection_rules[rule])
    if (new_blocked_samples = new_violation.blocked&.samples)&.any?
      previously_violated.blocked ||= sample_activity.new
      previously_violated.blocked.samples.concat(new_blocked_samples)
    end

    if (new_exploited_samples = new_violation.exploited&.samples)&.any?
      previously_violated.exploited ||= sample_activity.new
      previously_violated.exploited.samples.concat(new_exploited_samples)
    end

    if (new_ineffective_samples = new_violation.ineffective&.samples)&.any?
      previously_violated.ineffective ||= sample_activity.new
      previously_violated.ineffective.samples.concat(new_ineffective_samples)
    end

    if (new_suspicious_samples = new_violation.suspicious&.samples)&.any?
      previously_violated.suspicious ||= sample_activity.new
      previously_violated.suspicious.samples.concat(new_suspicious_samples)
    end
  else
    existing_attacker_activity.protection_rules[rule] = new_violation
  end
end

#find_existing_attacker_activity(new_attacker_activity) ⇒ Contrast::Agent::Reporting::ApplicationDefendAttackerActivity?

Find an existing attacker if it matches on source details



59
60
61
62
63
64
# File 'lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb', line 59

def find_existing_attacker_activity new_attacker_activity
  attackers.find do |existing|
    existing.source_forwarded_for == new_attacker_activity.source_forwarded_for &&
        existing.source_ip == new_attacker_activity.source_ip
  end
end

#to_controlled_hashObject



27
28
29
30
31
32
# File 'lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb', line 27

def to_controlled_hash
  validate
  {
      attackers: attackers.map(&:to_controlled_hash)
  }
end

#validateObject

Raises:

  • (ArgumentError)


34
35
36
37
38
# File 'lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb', line 34

def validate
  return unless Contrast::Utils::DuckUtils.empty_duck?(attackers)

  raise(ArgumentError, 'Attackers data must be populated')
end