contrast-agent 6.6.4 → 6.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/lib/contrast/agent/assess/policy/trigger_method.rb +21 -6
  3. data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +2 -0
  4. data/lib/contrast/agent/at_exit_hook.rb +1 -7
  5. data/lib/contrast/agent/inventory/database_config.rb +12 -13
  6. data/lib/contrast/agent/middleware.rb +0 -1
  7. data/lib/contrast/agent/protect/rule/base.rb +16 -20
  8. data/lib/contrast/agent/protect/rule/cmd_injection.rb +5 -4
  9. data/lib/contrast/agent/protect/rule/deserialization.rb +5 -4
  10. data/lib/contrast/agent/protect/rule/path_traversal.rb +9 -7
  11. data/lib/contrast/agent/protect/rule/sql_sample_builder.rb +16 -14
  12. data/lib/contrast/agent/protect/rule/sqli.rb +1 -1
  13. data/lib/contrast/agent/protect/rule/xxe.rb +9 -6
  14. data/lib/contrast/agent/reporting/attack_result/attack_result.rb +8 -0
  15. data/lib/contrast/agent/reporting/attack_result/rasp_rule_sample.rb +85 -36
  16. data/lib/contrast/agent/reporting/attack_result/user_input.rb +11 -0
  17. data/lib/contrast/agent/reporting/details/bot_blocker_details.rb +29 -0
  18. data/lib/contrast/agent/reporting/details/cmd_injection_details.rb +30 -0
  19. data/lib/contrast/agent/reporting/details/details.rb +18 -0
  20. data/lib/contrast/agent/reporting/details/http_method_tempering_details.rb +27 -0
  21. data/lib/contrast/agent/reporting/details/ip_denylist_details.rb +27 -0
  22. data/lib/contrast/agent/reporting/details/no_sqli_details.rb +36 -0
  23. data/lib/contrast/agent/reporting/details/path_traversal_details.rb +24 -0
  24. data/lib/contrast/agent/reporting/details/path_traversal_semantic_analysis_details.rb +32 -0
  25. data/lib/contrast/agent/reporting/details/protect_rule_details.rb +17 -0
  26. data/lib/contrast/agent/reporting/details/sqli_details.rb +36 -0
  27. data/lib/contrast/agent/reporting/details/untrusted_deserialization_details.rb +27 -0
  28. data/lib/contrast/agent/reporting/details/virtual_patch_details.rb +24 -0
  29. data/lib/contrast/agent/reporting/details/xss_details.rb +33 -0
  30. data/lib/contrast/agent/reporting/details/xss_match.rb +30 -0
  31. data/lib/contrast/agent/reporting/details/xxe_details.rb +36 -0
  32. data/lib/contrast/agent/reporting/details/xxe_match.rb +25 -0
  33. data/lib/contrast/agent/reporting/details/xxe_wrapper.rb +25 -0
  34. data/lib/contrast/agent/reporting/input_analysis/input_analysis_result.rb +1 -1
  35. data/lib/contrast/agent/reporting/masker/masker.rb +78 -65
  36. data/lib/contrast/agent/reporting/masker/masker_utils.rb +1 -30
  37. data/lib/contrast/agent/reporting/reporting_events/application_activity.rb +84 -15
  38. data/lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb +13 -25
  39. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_activity.rb +17 -22
  40. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample.rb +46 -125
  41. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample_activity.rb +5 -16
  42. data/lib/contrast/agent/reporting/reporting_events/application_defend_attacker_activity.rb +10 -18
  43. data/lib/contrast/agent/reporting/reporting_events/application_inventory_activity.rb +6 -14
  44. data/lib/contrast/agent/reporting/reporting_events/architecture_component.rb +29 -20
  45. data/lib/contrast/agent/reporting/reporting_events/finding_request.rb +45 -10
  46. data/lib/contrast/agent/reporting/reporting_utilities/dtm_message.rb +0 -7
  47. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +2 -1
  48. data/lib/contrast/agent/request.rb +2 -0
  49. data/lib/contrast/agent/request_context.rb +13 -4
  50. data/lib/contrast/agent/request_context_extend.rb +59 -40
  51. data/lib/contrast/agent/request_handler.rb +7 -9
  52. data/lib/contrast/agent/service_heartbeat.rb +1 -1
  53. data/lib/contrast/agent/version.rb +1 -1
  54. data/lib/contrast/components/app_context.rb +6 -6
  55. data/lib/contrast/config/assess_configuration.rb +1 -1
  56. data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +1 -6
  57. data/lib/contrast/utils/assess/event_limit_utils.rb +26 -7
  58. data/lib/contrast/utils/log_utils.rb +15 -9
  59. metadata +19 -2
@@ -30,21 +30,18 @@ module Contrast
30
30
 
31
31
  # Mask sensitive data according to the contrast sensitive data rules.
32
32
  #
33
- # @param [Contrast::Api::Dtm::Activity]
33
+ # @param [Contrast::Agent::Reporting::ApplicationActivity]
34
34
  def mask activity
35
- return unless Contrast::Agent::Reporter.enabled?
36
35
  return unless activity
37
36
 
38
- logger.debug('Searching for sensitive data',
39
- activity: activity.__id__,
40
- request: activity.http_request&.uuid)
37
+ logger.debug('Masker: masking sensitive data', activity: activity.__id__, request: activity.request&.__id__)
41
38
  mask_body(activity)
42
39
  mask_query_string(activity)
43
40
  mask_request_params(activity)
44
41
  mask_request_cookies(activity)
45
42
  mask_request_headers(activity)
46
43
  rescue StandardError => _e
47
- logger.debug('Could not mask activity!', activity: activity.__id__, request: activity.http_request&.uuid)
44
+ logger.debug('Could not mask activity!', activity: activity.__id__, request: activity.request&.__id__)
48
45
  end
49
46
 
50
47
  private
@@ -64,68 +61,67 @@ module Contrast
64
61
 
65
62
  # Mask request body:
66
63
  #
67
- # @param activity [Contrast::Api::Dtm::Activity]
64
+ # @param activity [Contrast::Agent::Reporting::ApplicationActivity]
68
65
  # @return masked_body [String, nil]
69
66
  def mask_body activity
70
67
  return unless mask_body?
71
68
 
72
- body = activity.http_request.request_body
69
+ body = activity.request.body
73
70
  return if body.nil? || body.empty?
74
71
 
75
- activity.http_request.request_body = BODY_MASK
76
- activity.http_request.request_body_binary = BODY_BINARY_MASK
72
+ activity.request.body = BODY_MASK
73
+ activity.request.body_binary = BODY_BINARY_MASK
77
74
  end
78
75
 
79
76
  # Mask request params.
80
77
  #
81
- # @param activity [Contrast::Api::Dtm::Activity]
78
+ # @param activity [Contrast::Agent::Reporting::ApplicationActivity]
82
79
  # @return masked_body [String, nil]
83
80
  def mask_request_params activity
84
- params = activity.http_request.normalized_request_params
81
+ params = activity.request.parameters
85
82
  return unless params
86
83
 
87
- mask_with_dictionary(activity.results, params)
84
+ mask_with_dictionary(activity.attack_results, params)
88
85
  end
89
86
 
90
87
  def mask_request_headers activity
91
- if activity.http_request.parsed_request_headers
92
- # Used normalized request_headers
93
- mask_with_dictionary(activity.results, activity.http_request.normalized_request_headers)
94
- else
95
- headers = activity.http_request.request_headers
96
- mask_field_hash(headers, activity.results)
97
- end
88
+ headers = activity.request.headers
89
+ return if headers&.empty?
90
+
91
+ # Used normalized request_headers
92
+ mask = mask_with_dictionary(activity.attack_results, headers)
93
+ activity.request.headers = mask if mask
98
94
  end
99
95
 
100
96
  # Mask Cookies.
101
97
  #
102
- # @param activity [Contrast::Api::Dtm::Activity] Activity to mask
98
+ # @param activity [Contrast::Agent::Reporting::ApplicationActivity] Activity to mask
103
99
  # @return masked_values [Hash, nil]
104
100
  def mask_request_cookies activity
105
- cookies = activity.http_request.normalized_cookies
106
- return unless cookies
101
+ cookies = activity.request.cookies
102
+ return if cookies&.empty?
107
103
 
108
- mask_with_dictionary(activity.results, cookies)
104
+ mask_with_dictionary(activity.attack_results, cookies)
109
105
  end
110
106
 
111
107
  # Mask request query string:
112
108
  # exp: password => sensitive to password => contrast-redacted-password
113
109
  #
114
- # @param activity [Contrast::Api::Dtm::Activity]
110
+ # @param activity [Contrast::Agent::Reporting::ApplicationActivity]
115
111
  # @return masked_query [String]
116
112
  def mask_query_string activity
117
- qs = activity.http_request.query_string
113
+ qs = activity.request.query_string
118
114
  return if qs.nil? || qs.empty?
119
115
 
120
- mask_field_hash(qs, activity.results) unless qs.cs__is_a?(String)
121
- mask_raw_query(qs, activity.results)
116
+ mask = mask_raw_query(qs, activity.attack_results)
117
+ activity.request.query_string = mask if mask
122
118
  end
123
119
 
124
120
  # Mask if the value in the passed hash are matched against dictionary
125
121
  # keyword. If the mask_attack_vector flag is set, this will also mask
126
122
  # any attack.
127
123
  #
128
- # @param results [Array<Contrast::Api::Dtm::AttackResults>]
124
+ # @param results [Array<Contrast::Agent::Reporting::ApplicationDefendAttackActivity>]
129
125
  # results to match against.
130
126
  # @param hash [Hash] Normalized hash representing the key/val pair from
131
127
  # the activity's http request parameters.
@@ -134,81 +130,98 @@ module Contrast
134
130
  return if hash.nil? || hash.empty?
135
131
 
136
132
  hash.each do |key, val|
137
- match = dictionary_matcher(key)
138
- next unless match
139
-
140
- # The normalized values are paired.
141
- # key => Contrast::Api::Dtm::Pair (key, val<Values>).
142
- # try one level down
143
- if val.cs__respond_to?(:values)
144
- mask_values(key, val, results)
133
+ next unless dictionary_match(key)
134
+
135
+ if val.cs__is_a?(Array)
136
+ mask_values(key, val, hash, results)
145
137
  else
146
138
  # Just assign keys.
147
139
  mask_hash(key, val, hash, results)
148
140
  end
149
141
  end
150
- hash
151
142
  end
152
143
 
153
- # Mask the values of DTM pair with attack vector condition check.
154
- # if the attack vector flag is set then mask the attack value.
144
+ # Mask the values of key value pair with array of string as input.
145
+ # If the mask_attack_vector? flag is set then the attack vector won't be
146
+ # masked.
155
147
  #
156
- # @param key [String] current iterable key from Protobuf::Field::FieldHash
157
- # pointing to Contrast::Api::Dtm::Pair<key, val>(holding the value to mask)
158
- # @param results [Array<Contrast::Api::Dtm::AttackResults>]
148
+ # @param key [String]
149
+ # @param hash [Hash] Normalized hash representing the key/val pair.
150
+ # @param results [Array<Contrast::Agent::Reporting::ApplicationDefendAttackActivity>]
159
151
  # results to match against.
160
- # @param val [Contrast::Api::Dtm::Pair<Value>]
161
- def mask_values key, val, results
162
- val.values.each.with_index do |v, idx|
152
+ # @param val [String, Array<String>]
153
+ def mask_values key, val, hash, results
154
+ val.each.with_index do |v, idx|
163
155
  # Mask the attack vector only if the flag is set.
164
- val.values[idx] = MASK + key.downcase if attack_vector?(results, v) && mask_attack_vector?
156
+ hash[key][idx] = MASK + key.downcase if attack_vector?(results, v) && mask_attack_vector?
165
157
  # It is not attack vector and we mask it as normal.
166
- val.values[idx] = MASK + key.downcase unless attack_vector?(results, v)
158
+ hash[key][idx] = MASK + key.downcase unless attack_vector?(results, v)
167
159
  end
168
- val
160
+ hash
169
161
  end
170
162
 
171
- # Handles the masking of Field hash with string values.
172
- # this case is used when called from #mask_field_hash
173
- # and #mask_raw_query helper methods. Since they dont
174
- # return values containing sub-values (key, val<Values>).
163
+ # Handles the masking of hash
175
164
  #
176
165
  # @param key [String] current iterable key from Protobuf::Field::FieldHash
177
166
  # @param val [String] normalized value to be matched against the results
178
167
  # and masked.
179
168
  # @param hash [Hash] Normalized hash representing the key/val pair.
180
- # @param results [Array<Contrast::Api::Dtm::AttackResults>]
169
+ # @param results [Array<Contrast::Agent::Reporting::ApplicationDefendAttackActivity>]
181
170
  # results to match against.
171
+ # @return [Hash]
182
172
  def mask_hash key, val, hash, results
173
+ # Mask the attack vector only if the flag is set.
183
174
  hash[key] = MASK + key.downcase if attack_vector?(results, val) && mask_attack_vector?
175
+ # It is not attack vector we mask it.
184
176
  hash[key] = MASK + key.downcase unless attack_vector?(results, val)
177
+ hash
185
178
  end
186
179
 
187
180
  # Match to see if values matches input from AttackResults array.
188
181
  # If match is found and the attack result's response is any of
189
182
  # [BAP(Block At Perimeter), BLOCKED, PROBED] the return is true.
190
183
  #
191
- # @param results [Array<Contrast::Api::Dtm::AttackResults>]
184
+ # @param results [Array<Contrast::Agent::Reporting::ApplicationDefendAttackActivity>]
192
185
  # results to match against.
193
186
  # @param value [String] Input to match.
194
- # @return true | false
187
+ # @return [Boolean]
195
188
  def attack_vector? results, value
196
189
  return false unless value && results
197
190
 
198
- results.each do |result|
199
- # Check samples Contrast::Api::Dtm::RaspRuleSample
200
- # is the value in sample and the response is valid?
201
- result.samples.any? do |sample|
202
- # Check user input Contrast::Api::Dtm::UserInput.
203
- match = sample.user_input.value == value.to_s &&
204
- result.response&.name != Contrast::Agent::Reporting::ResponseType::NO_ACTION
191
+ results.each do |attacker|
192
+ attacker.each do |activity|
193
+ blocked = iterate_attack_samples(activity.blocked, value)
194
+ return blocked if blocked
195
+
196
+ exploited = iterate_attack_samples(activity.exploited, value)
197
+ return exploited if exploited
205
198
 
206
- return match if match
199
+ ineffective = iterate_attack_samples(activity.ineffective, value)
200
+ return ineffective if ineffective
201
+
202
+ suspicious = iterate_attack_samples(activity.suspicious, value)
203
+ return suspicious if suspicious
207
204
  end
208
205
  end
209
206
  false
210
207
  end
211
208
 
209
+ # Go through activity samples and search for a matching input.
210
+ #
211
+ # @param activity [Contrast::Agent::Reporting::ApplicationDefendAttackActivity]
212
+ # @param value [String] Input to match.
213
+ # @return [Boolean]
214
+ def iterate_attack_samples activity, value
215
+ return false unless activity
216
+
217
+ activity.samples.any? do |sample|
218
+ match = sample.user_input.value == value.to_s
219
+
220
+ return true if match
221
+ end
222
+ false
223
+ end
224
+
212
225
  # Consult with our current settings state.
213
226
  #
214
227
  # @return true | false
@@ -227,7 +240,7 @@ module Contrast
227
240
  #
228
241
  # @param value [String] Value to check.
229
242
  # @return match [String, nil] from the Dictionary, or nil.
230
- def dictionary_matcher value
243
+ def dictionary_match value
231
244
  return unless @_dictionary
232
245
 
233
246
  @_dictionary.each do |rule|
@@ -9,35 +9,6 @@ module Contrast
9
9
  # helper methods used for masking
10
10
  module MaskerUtils
11
11
  include Contrast::Utils::ObjectShare
12
- # Helper to deal with Protobuf FieldHash.
13
- #
14
- # @param field_hash [Protobuf::Field::FieldHash] hash to be masked
15
- # @param results [Array<Contrast::Api::Dtm::AttackResults>]
16
- # results to match against.
17
- # @return [Hash]
18
- def mask_field_hash field_hash, results
19
- return {} unless field_hash&.any?
20
-
21
- hash = {}
22
- # Because this is the start of a built string, we have to be sure that it is not frozen.
23
- masked = +''
24
- field_hash.each do |entry|
25
- # Protobuf::Field::FieldHash produces array, with the key as first param and value as second.
26
- new_value = entry[1].delete(SEMICOLON).split(SPACE)
27
- new_value.each do |value|
28
- arr = value.split(EQUALS)
29
- # Add to new hash.
30
- hash[arr[0]] = arr[1]
31
- end
32
- # Mask the newly created hash.
33
- mask_with_dictionary(results, hash)
34
-
35
- # Restore to original form.
36
- hash.each { |k, v| masked += "#{ k }=#{ v }; " }
37
- masked.rstrip!
38
- field_hash[entry[0]] = masked
39
- end
40
- end
41
12
 
42
13
  # Mask raw query as it comes from the env.
43
14
  # exp:
@@ -45,7 +16,7 @@ module Contrast
45
16
  # 'ssn=contrast-redacted-ssn&id=contrast-redacted-id'
46
17
  #
47
18
  # @param query [String]
48
- # @param results [Array<Contrast::Api::Dtm::AttackResults>]
19
+ # @param results [Array<Contrast::Agent::Reporting::ApplicationDefendAttackActivitys>]
49
20
  # results to match against.
50
21
  def mask_raw_query query, results
51
22
  masked = EMPTY_STRING
@@ -5,6 +5,7 @@ require 'contrast/components/logger'
5
5
  require 'contrast/agent/reporting/reporting_events/application_reporting_event'
6
6
  require 'contrast/agent/reporting/reporting_events/application_defend_activity'
7
7
  require 'contrast/agent/reporting/reporting_events/application_inventory_activity'
8
+ require 'contrast/agent/reporting/attack_result/response_type'
8
9
 
9
10
  module Contrast
10
11
  module Agent
@@ -12,38 +13,106 @@ module Contrast
12
13
  # This is the new ApplicationActivity class which will include all the needed information for the new reporting
13
14
  # system to report
14
15
  class ApplicationActivity < Contrast::Agent::Reporting::ApplicationReportingEvent
15
- class << self
16
- # @param app_activity_dtm [Contrast::Api::Dtm::Activity]
17
- # @return [Contrast::Agent::Reporting::ApplicationActivity]
18
- def convert app_activity_dtm
19
- app_activity = new
20
- app_activity.attach_data(app_activity_dtm)
21
- app_activity
22
- end
23
- end
16
+ include Contrast::Agent::Reporting::ResponseType
17
+
18
+ # @return [Integer]
19
+ attr_accessor :query_count
20
+ # @return [Array]
21
+ attr_accessor :routes
22
+ # @return [Array]
23
+ attr_accessor :dynamic_sources
24
+ # @return [Contrast::Agent::Response]
25
+ attr_accessor :response
24
26
 
25
27
  def initialize
28
+ @routes = []
29
+ @dynamic_sources = {}
30
+ @query_count = 0
26
31
  @event_method = :PUT
27
32
  @event_type = :application_activity
28
33
  @event_endpoint = Contrast::Agent::Reporting::Endpoints.application_activity
29
34
  super
30
35
  end
31
36
 
37
+ # @return [Contrast::Agent::Reporting::FindingRequest] Current context's request
38
+ def request
39
+ @_request ||= FindingRequest.convert(Contrast::Agent::REQUEST_TRACKER.current&.request)
40
+ end
41
+
42
+ # @return [Contrast::Agent::Reporting::ApplicationDefendActivity] main
43
+ # activity for all protect rules.
44
+ def defend
45
+ @_defend ||= Contrast::Agent::Reporting::ApplicationDefendActivity.new
46
+ end
47
+
48
+ # @return [Contrast::Agent::Reporting::ApplicationInventoryActivity] main
49
+ # activity for all inventory activity reporting.
50
+ def inventory
51
+ @_inventory ||= Contrast::Agent::Reporting::ApplicationInventoryActivity.new
52
+ end
53
+
54
+ # @return file_name [String] used for audit
32
55
  def file_name
33
56
  'activity-application'
34
57
  end
35
58
 
36
59
  def to_controlled_hash
37
60
  hsh = { lastUpdate: since_last_update }
38
- hsh[:defend] = @defend&.to_controlled_hash if @defend
39
- hsh[:inventory] = @inventory&.to_controlled_hash if @inventory
61
+ hsh[:defend] = @_defend&.to_controlled_hash if @_defend
62
+ hsh[:inventory] = @_inventory&.to_controlled_hash if @_inventory
40
63
  hsh
41
64
  end
42
65
 
43
- # @param activity_dtm [Contrast::Api::Dtm::ApplicationActivity]
44
- def attach_data activity_dtm
45
- @defend = Contrast::Agent::Reporting::ApplicationDefendActivity.convert(activity_dtm)
46
- @inventory = Contrast::Agent::Reporting::ApplicationInventoryActivity.convert(activity_dtm)
66
+ # Look for attack results and access to samples by
67
+ # searching with rule_id and response_type
68
+ #
69
+ # @param rule_id [String] name of the protect rule
70
+ # @param response_type[Symbol<Contrast::Agent::Reporting::ResponseType]
71
+ # filter by response type
72
+ # @return [Array<Contrast::Agent::Reporting::ApplicationDefendAttackSampleActivity>, nil]
73
+ # return any matches.
74
+ def attack_results_for rule_id, response_type = nil
75
+ results = []
76
+ defend.attackers.each do |attacker|
77
+ results << case response_type
78
+ when BLOCKED, BLOCK_AT_PERIMETER
79
+ attacker.protection_rules[rule_id].blocked
80
+ when EXPLOITED
81
+ attacker.protection_rules[rule_id].exploited
82
+ when PROBED
83
+ attacker.protection_rules[rule_id].ineffective
84
+ when SUSPICIOUS
85
+ attacker.protection_rules[rule_id].suspicious
86
+ else
87
+ attacker.protection_rules[rule_id]
88
+ end
89
+ end
90
+ results
91
+ end
92
+
93
+ # By reference. List of all results only by values, no rule_ids.
94
+ #
95
+ # @return [Array<[Contrast::Agent::Reporting::ApplicationDefendAttackerActivity]>]
96
+ def attack_results
97
+ results = []
98
+ defend.attackers.each { |a| results << a.protection_rules.values }
99
+ results
100
+ end
101
+
102
+ # This is primary used for attaching new data and merging existing
103
+ # samples per rule entry in attackers, and to make sure the attack
104
+ # time_map is updated correctly.
105
+ #
106
+ # @param attack_result [Contrast::Agent::Reporting::AttackResult]
107
+ def attach_defend attack_result
108
+ defend.attach_data(attack_result)
109
+ end
110
+
111
+ # This is primary used for attaching new inventory reporting
112
+ #
113
+ # @param architecture [Contrast::Agent::Reporting::AttackResult]
114
+ def attach_inventory architecture
115
+ inventory.attach_data(architecture)
47
116
  end
48
117
  end
49
118
  end
@@ -13,20 +13,9 @@ module Contrast
13
13
  # @return [Array<Contrast::Agent::Reporting::ApplicationDefendAttackerActivity>]
14
14
  attr_reader :attackers
15
15
 
16
- class << self
17
- # @param activity_dtm [Contrast::Api::Dtm::ApplicationActivity]
18
- # @return [Contrast::Agent::Reporting::ApplicationDefendActivity]
19
- def convert activity_dtm
20
- activity = new
21
- activity.attach_data(activity_dtm.results)
22
- activity
23
- end
24
- end
25
-
26
16
  def initialize
27
17
  @attackers = []
28
18
  @event_type = :application_defend_activity
29
- super
30
19
  end
31
20
 
32
21
  def to_controlled_hash
@@ -35,20 +24,19 @@ module Contrast
35
24
  }
36
25
  end
37
26
 
38
- # @param attack_dtms [Array<Contrast::Api::Dtm::AttackResult>]
39
- def attach_data attack_dtms
40
- attack_dtms.each do |attack_result|
41
- attacker_activity = Contrast::Agent::Reporting::ApplicationDefendAttackerActivity.convert(attack_result)
42
- existing_attacker_activity = attackers.find do |existing|
43
- existing.source_forwarded_for == attacker_activity.source_forwarded_for &&
44
- existing.source_ip == attacker_activity.source_ip
45
- end
46
- rule = attack_result.rule_id
47
- if existing_attacker_activity
48
- attach_existing(existing_attacker_activity, attacker_activity, rule)
49
- else
50
- attackers << attacker_activity
51
- end
27
+ # @param attack_result [Contrast::Agent::Reporting::AttackResult]
28
+ def attach_data attack_result
29
+ attacker_activity = Contrast::Agent::Reporting::ApplicationDefendAttackerActivity.new
30
+ attacker_activity.attach_data(attack_result)
31
+ existing_attacker_activity = attackers.find do |existing|
32
+ existing.source_forwarded_for == attacker_activity.source_forwarded_for &&
33
+ existing.source_ip == attacker_activity.source_ip
34
+ end
35
+ rule = attack_result.rule_id
36
+ if existing_attacker_activity
37
+ attach_existing(existing_attacker_activity, attacker_activity, rule)
38
+ else
39
+ attackers << attacker_activity
52
40
  end
53
41
  end
54
42
 
@@ -19,44 +19,39 @@ module Contrast
19
19
  attr_accessor :ineffective
20
20
  # @return [Contrast::Agent::Reporting::ApplicationDefendAttackSampleActivity]
21
21
  attr_accessor :suspicious
22
-
23
- class << self
24
- # @param attack_result [Contrast::Api::Dtm::AttackResult]
25
- def convert attack_result
26
- activity = new
27
- activity.attach_data(attack_result)
28
- activity
29
- end
30
- end
22
+ # Helper method to determine before hand the response type and iv needed for access
23
+ #
24
+ # @return [Contrast::Agent::Reporting::ResponseType]
25
+ attr_reader :response_type
31
26
 
32
27
  def initialize
33
28
  @start_time = start_time
34
- super
35
29
  end
36
30
 
37
31
  def to_controlled_hash
38
32
  {
39
33
  startTime: @start_time,
40
- blocked: blocked&.to_controlled_hash || Contrast::Utils::ObjectShare::EMPTY_HASH,
41
- exploited: exploited&.to_controlled_hash || Contrast::Utils::ObjectShare::EMPTY_HASH,
42
- ineffective: ineffective&.to_controlled_hash || Contrast::Utils::ObjectShare::EMPTY_HASH,
43
- suspicious: suspicious&.to_controlled_hash || Contrast::Utils::ObjectShare::EMPTY_HASH
34
+ blocked: @blocked&.to_controlled_hash || Contrast::Utils::ObjectShare::EMPTY_HASH,
35
+ exploited: @exploited&.to_controlled_hash || Contrast::Utils::ObjectShare::EMPTY_HASH,
36
+ ineffective: @ineffective&.to_controlled_hash || Contrast::Utils::ObjectShare::EMPTY_HASH,
37
+ suspicious: @suspicious&.to_controlled_hash || Contrast::Utils::ObjectShare::EMPTY_HASH
44
38
  }
45
39
  end
46
40
 
47
- # @param attack_result [Contrast::Api::Dtm::AttackResult]
41
+ # @param attack_result [Contrast::Agent::Reporting::AttackResult]
48
42
  # @return [Contrast::Agent::Reporting::Defend::AttackSampleActivity]
49
43
  def attach_data attack_result
50
- attack_sample_activity =
51
- Contrast::Agent::Reporting::ApplicationDefendAttackSampleActivity.convert(attack_result)
52
- case attack_result.response
53
- when ::Contrast::Api::Dtm::AttackResult::ResponseType::BLOCKED
44
+ attack_sample_activity = Contrast::Agent::Reporting::ApplicationDefendAttackSampleActivity.new
45
+ attack_sample_activity.attach_data(attack_result)
46
+ @response_type = attack_result.response
47
+ case response_type
48
+ when ::Contrast::Agent::Reporting::ResponseType::BLOCKED
54
49
  @blocked = attack_sample_activity
55
- when ::Contrast::Api::Dtm::AttackResult::ResponseType::MONITORED
50
+ when ::Contrast::Agent::Reporting::ResponseType::MONITORED
56
51
  @exploited = attack_sample_activity
57
- when ::Contrast::Api::Dtm::AttackResult::ResponseType::PROBED
52
+ when ::Contrast::Agent::Reporting::ResponseType::PROBED
58
53
  @ineffective = attack_sample_activity
59
- when ::Contrast::Api::Dtm::AttackResult::ResponseType::SUSPICIOUS
54
+ when ::Contrast::Agent::Reporting::ResponseType::SUSPICIOUS
60
55
  @suspicious = attack_sample_activity
61
56
  end
62
57
  end