contrast-agent 6.1.2 → 6.2.0

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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/lib/contrast/agent/at_exit_hook.rb +2 -1
  3. data/lib/contrast/agent/inventory/dependency_usage_analysis.rb +9 -5
  4. data/lib/contrast/agent/protect/rule/xss.rb +4 -0
  5. data/lib/contrast/agent/reporting/reporter.rb +2 -11
  6. data/lib/contrast/agent/reporting/reporting_events/application_inventory.rb +3 -18
  7. data/lib/contrast/agent/reporting/reporting_events/discovered_route.rb +75 -15
  8. data/lib/contrast/agent/reporting/reporting_events/finding.rb +2 -2
  9. data/lib/contrast/agent/reporting/reporting_events/library_usage_observation.rb +5 -19
  10. data/lib/contrast/agent/reporting/reporting_events/observed_library_usage.rb +6 -22
  11. data/lib/contrast/agent/reporting/reporting_events/observed_route.rb +1 -1
  12. data/lib/contrast/agent/reporting/reporting_events/preflight_message.rb +2 -3
  13. data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +1 -3
  14. data/lib/contrast/agent/reporting/reporting_events/route_coverage.rb +9 -0
  15. data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +1 -2
  16. data/lib/contrast/agent/reporting/reporting_utilities/dtm_message.rb +0 -10
  17. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +0 -1
  18. data/lib/contrast/agent/reporting/reporting_utilities/response.rb +60 -2
  19. data/lib/contrast/agent/reporting/reporting_utilities/response_extractor.rb +32 -10
  20. data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +1 -1
  21. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +58 -26
  22. data/lib/contrast/agent/reporting/settings/application_settings.rb +8 -23
  23. data/lib/contrast/agent/reporting/settings/assess_server_feature.rb +27 -33
  24. data/lib/contrast/agent/reporting/settings/bot_blocker.rb +68 -0
  25. data/lib/contrast/agent/reporting/settings/code_exclusion.rb +27 -0
  26. data/lib/contrast/agent/reporting/settings/exclusion_base.rb +33 -0
  27. data/lib/contrast/agent/reporting/settings/exclusions.rb +39 -57
  28. data/lib/contrast/agent/reporting/settings/helpers.rb +56 -0
  29. data/lib/contrast/agent/reporting/settings/input_exclusion.rb +37 -0
  30. data/lib/contrast/agent/reporting/settings/ip_filter.rb +35 -0
  31. data/lib/contrast/agent/reporting/settings/keyword.rb +74 -0
  32. data/lib/contrast/agent/reporting/settings/log_enhancer.rb +65 -0
  33. data/lib/contrast/agent/reporting/settings/protect.rb +4 -2
  34. data/lib/contrast/agent/reporting/settings/protect_server_feature.rb +62 -115
  35. data/lib/contrast/agent/reporting/settings/reaction.rb +11 -2
  36. data/lib/contrast/agent/reporting/settings/rule_definition.rb +63 -0
  37. data/lib/contrast/agent/reporting/settings/sampling.rb +10 -0
  38. data/lib/contrast/agent/reporting/settings/sanitizer.rb +38 -0
  39. data/lib/contrast/agent/reporting/settings/sensitive_data_masking.rb +9 -1
  40. data/lib/contrast/agent/reporting/settings/sensitive_data_masking_rule.rb +7 -0
  41. data/lib/contrast/agent/reporting/settings/server_features.rb +8 -0
  42. data/lib/contrast/agent/reporting/settings/syslog.rb +176 -0
  43. data/lib/contrast/agent/reporting/settings/url_exclusion.rb +42 -0
  44. data/lib/contrast/agent/reporting/settings/validator.rb +17 -0
  45. data/lib/contrast/agent/request_context.rb +4 -0
  46. data/lib/contrast/agent/request_handler.rb +8 -4
  47. data/lib/contrast/agent/static_analysis.rb +4 -8
  48. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exceptions_report.rb +1 -1
  49. data/lib/contrast/agent/thread_watcher.rb +4 -5
  50. data/lib/contrast/agent/version.rb +1 -1
  51. data/lib/contrast/agent.rb +1 -3
  52. data/lib/contrast/api/decorators/application_update.rb +0 -8
  53. data/lib/contrast/api/decorators.rb +0 -1
  54. data/lib/contrast/framework/base_support.rb +5 -4
  55. data/lib/contrast/framework/grape/support.rb +6 -6
  56. data/lib/contrast/framework/manager.rb +2 -4
  57. data/lib/contrast/framework/manager_extend.rb +1 -0
  58. data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +2 -1
  59. data/lib/contrast/framework/rails/support.rb +9 -2
  60. data/lib/contrast/framework/sinatra/support.rb +3 -2
  61. data/lib/contrast/logger/aliased_logging.rb +31 -26
  62. data/lib/contrast/utils/response_utils.rb +14 -1
  63. data/lib/contrast/utils/telemetry.rb +9 -0
  64. data/lib/contrast/utils/telemetry_hash.rb +36 -12
  65. data/lib/contrast/utils/telemetry_identifier.rb +8 -0
  66. data/lib/contrast/utils/thread_tracker.rb +26 -9
  67. data/lib/contrast/utils/timer.rb +6 -1
  68. data/lib/contrast.rb +1 -3
  69. metadata +26 -14
  70. data/lib/contrast/api/decorators/library_usage_update.rb +0 -31
@@ -152,9 +152,9 @@ module Contrast
152
152
  #
153
153
  # @param response [Contrast::Agent::Reporting::Response]
154
154
  def update_reaction response
155
- return unless response.application_settings&.reactions&.any?
155
+ return unless response&.reactions&.any?
156
156
 
157
- response.application_settings.reactions.each do |reaction|
157
+ response.reactions.each do |reaction|
158
158
  # The enums are all uppercase, we need to downcase them before attempting to log.
159
159
  level = reaction.level.nil? ? :error : reaction.level.downcase
160
160
  logger.with_level(level, reaction.message) if reaction.message
@@ -198,50 +198,82 @@ module Contrast
198
198
  response_body = response&.body
199
199
  return unless response_body
200
200
 
201
- response_data = JSON.parse(response_body)
201
+ response_data = JSON.parse(response_body, symbolize_names: true)
202
202
  return unless response_data.cs__is_a?(Hash)
203
203
 
204
- response_data = response_data.deep_symbolize_keys
204
+ populate_response(response_data)
205
+ rescue StandardError => e
206
+ logger.error('Unable to convert response', e)
207
+ nil
208
+ end
209
+
210
+ # Extracts the data from the response and coverts it to
211
+ # Contrast::Agent::Reporting::Response.
212
+ #
213
+ # @param response_data[Hash]
214
+ # @return response [Contrast::Agent::Reporting::Response]
215
+ def populate_response response_data
216
+ return unless (success, messages = extract_success(response_data))
217
+
205
218
  # check if response contains application settings or Feature settings
206
219
  if response_data[:settings]
207
220
  # the response contains ApplicationSettings
208
- app_settings = build_application_settings(response_data)
221
+ response = Contrast::Agent::Reporting::Response.build_application_response
222
+ response.success = success
223
+ response.messages = messages
224
+ app_settings = build_application_settings(response_data, response)
209
225
  logger.trace('Agent: Received updated application settings', raw: response_data, processed: app_settings)
210
226
  app_settings
211
227
  else
212
228
  # the response contains FeatureSettings
213
- server_features = build_feature_settings(response_data)
229
+ response = Contrast::Agent::Reporting::Response.build_server_response
230
+ response.success = success
231
+ response.messages = messages
232
+ server_features = build_feature_settings(response_data, response)
214
233
  logger.trace('Agent: Received updated application settings', raw: response_data, processed: server_features)
215
234
  server_features
216
235
  end
217
- rescue StandardError => e
218
- logger.error('Unable to convert response', e)
219
- nil
236
+ response
220
237
  end
221
238
 
222
239
  # @param response_data [Hash]
223
240
  # @return res [Contrast::Agent::Reporting::Response]
224
- def build_application_settings response_data
225
- res = Contrast::Agent::Reporting::Response.application_response
226
- extract_assess(response_data, res)
227
- extract_protect(response_data, res)
228
- extract_exclusions(response_data, res)
229
- extract_reactions(response_data, res)
230
- extract_sensitive_data_policy(response_data, res)
231
- res
241
+ def build_application_settings response_data, response
242
+ extract_assess(response_data, response)
243
+ extract_protect(response_data, response)
244
+ extract_exclusions(response_data, response)
245
+ extract_reactions(response_data, response)
246
+ extract_sensitive_data_policy(response_data, response)
247
+ response
232
248
  end
233
249
 
234
250
  # @param response_data [Hash]
235
251
  # @return res [Contrast::Agent::Reporting::Response]
236
- def build_feature_settings response_data
237
- res = Contrast::Agent::Reporting::Response.server_response
238
- extract_assess_server_features(response_data, res)
239
- extract_protect_server_features(response_data, res)
240
- extract_protect_lists(response_data, res)
241
- res.server_features.log_level = response_data[:logLevel]
242
- res.server_features.log_file = response_data[:logFile]
243
- res.server_features.telemetry = response_data[:telemetry]
244
- res
252
+ def build_feature_settings response_data, response
253
+ extract_reactions(response_data, response)
254
+ extract_assess_server_features(response_data, response)
255
+ extract_protect_server_features(response_data, response)
256
+ extract_protect_lists(response_data, response)
257
+ extract_log_settings(response_data, response)
258
+ response.server_features.telemetry = response_data[:telemetry]
259
+ response
260
+ end
261
+
262
+ # This method with check the success and messages field of the response.
263
+ # If the success is false, then it will return nil and log the error.
264
+ #
265
+ # @param response_data [Hash]
266
+ # @return [Array, nil] Returns the success status or nil if request
267
+ # was not processed by TS.
268
+ def extract_success response_data
269
+ success = response_data[:success]
270
+ messages = response_data[:messages]
271
+ return [success, messages] if success
272
+
273
+ logger.error('Unable to connect to Contrast UI') if messages.nil?
274
+ logger.error('Failure on Contrast UI processing request', reasons: messages.join(', ')) if messages
275
+
276
+ nil
245
277
  end
246
278
  end
247
279
  end
@@ -37,13 +37,6 @@ module Contrast
37
37
  @_exclusions ||= Contrast::Agent::Reporting::Settings::Exclusions.new
38
38
  end
39
39
 
40
- # Reaction the agent should take based on a state in TS.
41
- #
42
- # @return [Array<Contrast::Agent::Reporting::Settings::Reaction>, nil]
43
- def reactions
44
- @_reactions
45
- end
46
-
47
40
  # This object will hold the masking rules send from TS.
48
41
  #
49
42
  # @return sensitive_data_masking [Contrast::Agent::Reporting::Settings::SensitiveDataMasking] this object
@@ -52,22 +45,14 @@ module Contrast
52
45
  @_sensitive_data_masking ||= Contrast::Agent::Reporting::Settings::SensitiveDataMasking.new
53
46
  end
54
47
 
55
- # Set the reaction
56
- #
57
- # @param reactions [Array<Reaction>] {
58
- # level [String] The level at which the agent should log this reaction.
59
- # [ERROR, WARN, INFO, DEBUG, TRACE]
60
- # message [String] A message to log when receiving this reaction.
61
- # operation [String] What to do in response to this reaction.[NOOP, DISABLE] }
62
- # @return [Array<Contrast::Agent::Reporting::Settings::Reaction>]
63
- def reactions= reactions
64
- return unless reactions.is_a?(Array)
65
-
66
- @_reactions = []
67
- reactions.each do |r|
68
- reaction = Contrast::Agent::Reporting::Settings::Reaction.new(r[:level], r[:operation], r[:message])
69
- @_reactions << reaction
70
- end
48
+ # Currently protect and assess are not covered with to_controlled_hash methods
49
+ def to_controlled_hash
50
+ {
51
+ defend: {},
52
+ exceptions: exclusions.to_controlled_hash,
53
+ assessment: {},
54
+ sensitive_data_masking_policy: sensitive_data_masking.to_controlled_hash
55
+ }
71
56
  end
72
57
  end
73
58
  end
@@ -3,6 +3,9 @@
3
3
 
4
4
  require 'contrast/utils/object_share'
5
5
  require 'contrast/agent/reporting/settings/sampling'
6
+ require 'contrast/agent/reporting/settings/sanitizer'
7
+ require 'contrast/agent/reporting/settings/validator'
8
+ require 'contrast/agent/reporting/settings/helpers'
6
9
 
7
10
  module Contrast
8
11
  module Agent
@@ -52,54 +55,45 @@ module Contrast
52
55
 
53
56
  # The sanitizers defined by the user for use by the agent on this server for this organization.
54
57
  #
55
- # @return sanitizers [Array<AssessCustomRules>] AssessCustomRules
56
- # Api [String], Rules [Array[RulesID]]
57
- # tags [Array[String]]
58
- # uuid [String]
58
+ # @return sanitizers [Array<Contrast::Agent::Reporting::Settings::Sanitizer>]
59
59
  def sanitizers
60
60
  @_sanitizers ||= []
61
61
  end
62
62
 
63
63
  # set sanitizer
64
64
  #
65
- # @param sanitizers [Array<AssessCustomRules>] of AssessCustomRule: {
66
- # Api [String], Rules [Array[RulesID]]
67
- # tags [Array[String]]
68
- # uuid [String]
69
- # }
70
- # @return sanitizers [Array<AssessCustomRules>] AssessCustomRules
71
- # Api [String], Rules [Array[RulesID]]
72
- # tags [Array[String]]
73
- # uuid [String]
74
- def sanitizers= sanitizers
75
- @_sanitizers = sanitizers if sanitizers.is_a?(Array)
65
+ # @param sanitizers_array [Array<Contrast::Agent::Reporting::Settings::Sanitizer>]
66
+ # @return sanitizers [Array<Contrast::Agent::Reporting::Settings::Sanitizer>]
67
+ def sanitizers= sanitizers_array
68
+ Contrast::Agent::Reporting::Settings::Helpers.array_to_iv(Contrast::Agent::Reporting::Settings::Sanitizer,
69
+ sanitizers,
70
+ sanitizers_array)
76
71
  end
77
72
 
78
73
  # The validators defined by the user for use by the agent on this server for this organization.
79
74
  #
80
- # @return validators [Array<AssessCustomRules>] of AssessCustomRule: {
81
- # Api [String], Rules [Array[RulesID]]
82
- # tags [Array[String]]
83
- # uuid [String]
84
- # }
75
+ # @return sanitizers [Array<Contrast::Agent::Reporting::Settings::Validator>]
85
76
  def validators
86
77
  @_validators ||= []
87
78
  end
88
79
 
89
- # The validators defined by the user for use by the agent on this server for this organization.
80
+ # set validators
90
81
  #
91
- # @param validators [Array<AssessCustomRules>] of AssessCustomRule: {
92
- # Api [String], Rules [Array[RulesID]]
93
- # tags [Array[String]]
94
- # uuid [String]
95
- # }
96
- # @return validators [Array<AssessCustomRules>] of AssessCustomRule: {
97
- # Api [String], Rules [Array[RulesID]]
98
- # tags [Array[String]]
99
- # uuid [String]
100
- # }
101
- def validators= validators
102
- @_validators = validators if validators.is_a?(Array)
82
+ # @param validators_array [Array<Contrast::Agent::Reporting::Settings::Validator>]
83
+ # @return sanitizers [Array<Contrast::Agent::Reporting::Settings::Validator>]
84
+ def validators= validators_array
85
+ Contrast::Agent::Reporting::Settings::Helpers.array_to_iv(Contrast::Agent::Reporting::Settings::Validator,
86
+ validators,
87
+ validators_array)
88
+ end
89
+
90
+ def to_controlled_hash
91
+ {
92
+ enabled: enabled?,
93
+ sampling: sampling.to_controlled_hash,
94
+ sanitizers: sanitizers.map(&:to_controlled_hash),
95
+ validators: validators.map(&:to_controlled_hash)
96
+ }
103
97
  end
104
98
  end
105
99
  end
@@ -0,0 +1,68 @@
1
+ # Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ require 'contrast/agent/reporting/settings/helpers'
5
+
6
+ module Contrast
7
+ module Agent
8
+ module Reporting
9
+ module Settings
10
+ # Indicate if the bot protection feature set is enabled for this server or not.
11
+ class BotBlocker
12
+ # @return [Boolean]
13
+ attr_accessor :enable
14
+
15
+ def initialize
16
+ @enable = true
17
+ end
18
+
19
+ # @return bots [Hash<Contrast::Agent::Reporting::Settings::Bot>, []]
20
+ def bots
21
+ @_bots ||= []
22
+ end
23
+
24
+ def bots= bots_array
25
+ Contrast::Agent::Reporting::Settings::Helpers.array_to_iv(Contrast::Agent::Reporting::Settings::Bot,
26
+ bots,
27
+ bots_array)
28
+ end
29
+
30
+ # We should be receiving:
31
+ # bot_blockers { enable, bots[{bot, case_sensitive, start_anchor}]}
32
+ # Instead in the response there is bot_blockers[], and the enable
33
+ # which can be retrieved from bot-blocker.
34
+ def to_controlled_hash
35
+ @enable
36
+ end
37
+ end
38
+
39
+ # This class is used to represent a Bot entity inside the bots array.
40
+ class Bot
41
+ ATTRIBUTES = %i[bot case_sensitive start_anchor].cs__freeze
42
+
43
+ # @return bot [String]
44
+ attr_accessor :bot
45
+ # @return case_sensitive [Boolean] Whether the name is case-sensitive
46
+ # or not.
47
+ attr_accessor :case_sensitive
48
+ # @return start_anchor [Boolean]
49
+ attr_accessor :start_anchor
50
+
51
+ def initialize
52
+ # default values of properties:
53
+ @start_anchor = false
54
+ @case_sensitive = false
55
+ end
56
+
57
+ def to_controlled_hash
58
+ {
59
+ bot: bot,
60
+ caseSensitive: case_sensitive,
61
+ startAnchor: start_anchor
62
+ }
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,27 @@
1
+ # Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ require 'contrast/agent/reporting/settings/exclusion_base'
5
+
6
+ module Contrast
7
+ module Agent
8
+ module Reporting
9
+ module Settings
10
+ # CodeExclusions class
11
+ class CodeExclusion < ExclusionBase
12
+ ATTRIBUTES = BASE_ATTRIBUTES.dup << :denylist
13
+ ATTRIBUTES.cs__freeze
14
+
15
+ # @return denylist [Array<String>] #rubocop:disable [Naming/InclusiveLanguage]
16
+ attr_accessor :denylist
17
+
18
+ def to_controlled_hash
19
+ hash = super
20
+ hash[:denylist] = denylist
21
+ hash
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ # Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ module Contrast
5
+ module Agent
6
+ module Reporting
7
+ module Settings
8
+ # Base class to represent common exclusions fields.
9
+ class ExclusionBase
10
+ BASE_ATTRIBUTES = %i[name modes assess_rules protect_rules].cs__freeze
11
+
12
+ # @return name [String]
13
+ attr_accessor :name
14
+ # @return modes [Array<String>]
15
+ attr_accessor :modes
16
+ # @return assess_rules [Array<String>]
17
+ attr_accessor :assess_rules
18
+ # @return protect_rules [Array<String>]
19
+ attr_accessor :protect_rules
20
+
21
+ def to_controlled_hash
22
+ {
23
+ name: name, # rubocop:disable Security/Module/Name
24
+ modes: modes,
25
+ assessRules: assess_rules,
26
+ protectRules: protect_rules
27
+ }
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,6 +1,11 @@
1
1
  # Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
+ require 'contrast/agent/reporting/settings/code_exclusion'
5
+ require 'contrast/agent/reporting/settings/input_exclusion'
6
+ require 'contrast/agent/reporting/settings/url_exclusion'
7
+ require 'contrast/agent/reporting/settings/helpers'
8
+
4
9
  module Contrast
5
10
  module Agent
6
11
  module Reporting
@@ -11,52 +16,38 @@ module Contrast
11
16
  class Exclusions
12
17
  # Cases where rules should be excluded if violated in a method call
13
18
  #
14
- # @return code_exclusions [Array<CodeExclusion>] Array of CodeExclusion: {
15
- # name [String] The name of the exclusion as defined by the user in TS.
16
- # modes [String] If this exclusion applies to assess or protect. [assess, defend]
17
- # assess_rules [Array] Array of assess rules to which this exclusion applies. AssessRuleID [String]
18
- # denylist [String] The call, if in the stack, should result in the agent not taking action.
19
- # }
19
+ # @return code_exclusions [Array<Contrast::Agent::Reporting::Settings::CodeExclusion>] Array of CodeExclusion
20
20
  def code_exclusions
21
21
  @_code_exclusions ||= []
22
22
  end
23
23
 
24
24
  # set the CodeExclusions array
25
25
  #
26
- # @param code_exclusions [Array<CodeExclusion>] Array of CodeExclusion: {
26
+ # @param new_code_exclusions [Array<CodeExclusion>] Array of CodeExclusion: {
27
27
  # name [String] The name of the exclusion as defined by the user in TS.
28
28
  # modes [String] If this exclusion applies to assess or protect. [assess, defend]
29
29
  # assess_rules [Array] Array of assess rules to which this exclusion applies. AssessRuleID [String]
30
30
  # denylist [String] The call, if in the stack, should result in the agent not taking action.
31
31
  # }
32
- # @return code_exclusions [Array<CodeExclusion>] Array of CodeExclusion: {
33
- # name [String] The name of the exclusion as defined by the user in TS.
34
- # modes [String] If this exclusion applies to assess or protect. [assess, defend]
35
- # assess_rules [Array] Array of assess rules to which this exclusion applies. AssessRuleID [String]
36
- # denylist [String] The call, if in the stack, should result in the agent not taking action.
37
- # }
38
- def code_exclusions= code_exclusions
39
- @_code_exclusions = code_exclusions if code_exclusions.is_a?(Array)
32
+ # @return code_exclusions [Array<Contrast::Agent::Reporting::Settings::CodeExclusion>] Array of CodeExclusion
33
+ def code_exclusions= new_code_exclusions
34
+ @_code_exclusions = Contrast::Agent::Reporting::Settings::Helpers.array_to_iv(
35
+ Contrast::Agent::Reporting::Settings::CodeExclusion,
36
+ code_exclusions,
37
+ new_code_exclusions)
40
38
  end
41
39
 
42
40
  # Cases where rules should be excluded if violated from a given input.
43
41
  #
44
- # @return input_exclusions [Array<InputExclusions>] Array of InputExclusions: {
45
- # name [String] The name of the input.
46
- # modes [String] If this exclusion applies to assess or protect. [assess, defend]
47
- # assess_rules [Array] Array of assess rules to which this exclusion applies. AssessRuleID [String]
48
- # protect_rules [Array] Array of ProtectRuleID [String] The protect rules to which this exclusion applies.
49
- # urls [Array] Array of URLs to which the exclusions apply. URL [String]
50
- # match_strategy [String] If this exclusion applies to all URLs or only those specified. [ALL, ONLY]
51
- # type [String] The type of the input [COOKIE, PARAMETER, HEADER, BODY, QUERYSTRING]
52
- # }
42
+ # @return input_exclusions [Array<Contrast::Agent::Reporting::Settings::InputExclusions>]
43
+ # Array of InputExclusions
53
44
  def input_exclusions
54
45
  @_input_exclusions ||= []
55
46
  end
56
47
 
57
48
  # set the InputExclusions array
58
49
  #
59
- # @param input_exclusions [Array<InputExclusions>] Array of InputExclusions: {
50
+ # @param new_input_exclusions [Array<InputExclusions>] Array of InputExclusions: {
60
51
  # name [String] The name of the input.
61
52
  # modes [String] If this exclusion applies to assess or protect. [assess, defend]
62
53
  # assess_rules [Array] Array of assess rules to which this exclusion applies. AssessRuleID [String]
@@ -65,37 +56,25 @@ module Contrast
65
56
  # match_strategy [String] If this exclusion applies to all URLs or only those specified. [ALL, ONLY]
66
57
  # type [String] The type of the input [COOKIE, PARAMETER, HEADER, BODY, QUERYSTRING]
67
58
  # }
68
- # @return input_exclusions [Array<InputExclusions>] Array of InputExclusions: {
69
- # name [String] The name of the input.
70
- # modes [String] If this exclusion applies to assess or protect. [assess, defend]
71
- # assess_rules [Array] Array of assess rules to which this exclusion applies. AssessRuleID [String]
72
- # protect_rules [Array] Array of ProtectRuleID [String] The protect rules to which this exclusion applies.
73
- # urls [Array] Array of URLs to which the exclusions apply. URL [String]
74
- # match_strategy [String] If this exclusion applies to all URLs or only those specified. [ALL, ONLY]
75
- # type [String] The type of the input [COOKIE, PARAMETER, HEADER, BODY, QUERYSTRING]
76
- # }
77
- def input_exclusions= input_exclusions
78
- @_input_exclusions = input_exclusions if input_exclusions.is_a?(Array)
59
+ # @return input_exclusions [Array<Contrast::Agent::Reporting::Settings::InputExclusions>]
60
+ # Array of InputExclusions
61
+ def input_exclusions= new_input_exclusions
62
+ @_input_exclusions = Contrast::Agent::Reporting::Settings::Helpers.array_to_iv(
63
+ Contrast::Agent::Reporting::Settings::InputExclusion,
64
+ input_exclusions,
65
+ new_input_exclusions)
79
66
  end
80
67
 
81
68
  # A case where rules should be excluded if violated during a call to a given URL.
82
69
  #
83
- # @return url_exclusions [Array<UrlExclusions>] Array of UrlExclusions: {
84
- # name [String] The name of the input.
85
- # modes [String] If this exclusion applies to assess or protect. [assess, defend]
86
- # assess_rules [Array] Array of assess rules to which this exclusion applies. AssessRuleID [String]
87
- # protect_rules [Array] Array of ProtectRuleID [String] The protect rules to which this exclusion applies.
88
- # urls [Array] Array of URLs to which the exclusions apply. URL [String]
89
- # match_strategy [String] If this exclusion applies to all URLs or only those specified. [ALL, ONLY]
90
- # type [String] The type of the input [COOKIE, PARAMETER, HEADER, BODY, QUERYSTRING]
91
- # }
70
+ # @return url_exclusions [Array<Contrast::Agent::Reporting::Settings::UrlExclusion>] Array of UrlExclusions
92
71
  def url_exclusions
93
72
  @_url_exclusions ||= []
94
73
  end
95
74
 
96
75
  # set the UrlExclusions array
97
76
  #
98
- # @param url_exclusions [Array] Array of UrlExclusions: {
77
+ # @param new_url_exclusions [Array] Array of UrlExclusions: {
99
78
  # name [String] The name of the input.
100
79
  # modes [String] If this exclusion applies to assess or protect. [assess, defend]
101
80
  # assess_rules [Array] Array of assess rules to which this exclusion applies. AssessRuleID [String]
@@ -104,17 +83,20 @@ module Contrast
104
83
  # match_strategy [String] If this exclusion applies to all URLs or only those specified. [ALL, ONLY]
105
84
  # type [String] The type of the input [COOKIE, PARAMETER, HEADER, BODY, QUERYSTRING]
106
85
  # }
107
- # @return url_exclusions [Array<UrlExclusions>] Array of UrlExclusions: {
108
- # name [String] The name of the input.
109
- # modes [String] If this exclusion applies to assess or protect. [assess, defend]
110
- # assess_rules [Array] Array of assess rules to which this exclusion applies. AssessRuleID [String]
111
- # protect_rules [Array] Array of ProtectRuleID [String] The protect rules to which this exclusion applies.
112
- # urls [Array] Array of URLs to which the exclusions apply. URL [String]
113
- # match_strategy [String] If this exclusion applies to all URLs or only those specified. [ALL, ONLY]
114
- # type [String] The type of the input [COOKIE, PARAMETER, HEADER, BODY, QUERYSTRING]
115
- # }
116
- def url_exclusions= url_exclusions
117
- @_url_exclusions = url_exclusions if url_exclusions.is_a?(Array)
86
+ # @return url_exclusions [Array<Contrast::Agent::Reporting::Settings::UrlExclusion>] Array of UrlExclusions
87
+ def url_exclusions= new_url_exclusions
88
+ @_url_exclusions = Contrast::Agent::Reporting::Settings::Helpers.array_to_iv(
89
+ Contrast::Agent::Reporting::Settings::UrlExclusion,
90
+ url_exclusions,
91
+ new_url_exclusions)
92
+ end
93
+
94
+ def to_controlled_hash
95
+ {
96
+ codeExceptions: code_exclusions.map(&:to_controlled_hash),
97
+ inputExceptions: input_exclusions.map(&:to_controlled_hash),
98
+ urlExceptions: url_exclusions.map(&:to_controlled_hash)
99
+ }
118
100
  end
119
101
  end
120
102
  end
@@ -0,0 +1,56 @@
1
+ # Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ module Contrast
5
+ module Agent
6
+ module Reporting
7
+ module Settings
8
+ # Helper methods used across the settings.
9
+ module Helpers
10
+ class << self
11
+ # Fills instance variable [Array] with new settings as new instance type
12
+ # for each entry.
13
+ #
14
+ # @param instance_type [Class] a class to create new instance from to
15
+ # @param instance_variable [Array] instance variable accessor method
16
+ # return an array to fill.
17
+ # @param array [Array] array to be used to fill the iv.
18
+ # fill the iv with the new type containing data from the provided array
19
+ # param.
20
+ # @return instance_variable [Class]
21
+ def array_to_iv instance_type, instance_variable, array
22
+ return unless array.is_a?(Array)
23
+
24
+ array.each_with_index do |entry, index|
25
+ new_instance = instance_type.new
26
+ instance_type::ATTRIBUTES.each do |attr|
27
+ new_instance.send("#{ attr }=".to_sym, entry[no_more_underscore(attr)])
28
+ end
29
+ instance_variable[index] = new_instance
30
+ end
31
+
32
+ instance_variable
33
+ end
34
+
35
+ # :attr_name => :attrName
36
+ # return original if no '_'
37
+ #
38
+ # @param attr_name [Symbol]
39
+ # @return normalized_name [Symbol]
40
+ def no_more_underscore attr_name
41
+ name = attr_name.to_s
42
+ idx = name.index('_')
43
+ return attr_name if idx.nil? || (idx.zero? && idx >= name.length)
44
+
45
+ result = name
46
+ result.slice!(idx)
47
+ result.insert(idx, name[idx]&.upcase)
48
+ result.slice!(idx + 1)
49
+ result.index('_') ? no_more_underscore(result).to_sym : result.to_sym
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,37 @@
1
+ # Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ require 'contrast/agent/reporting/settings/exclusion_base'
5
+ require 'contrast/utils/object_share'
6
+
7
+ module Contrast
8
+ module Agent
9
+ module Reporting
10
+ module Settings
11
+ # InputExclusions class
12
+ class InputExclusion < ExclusionBase
13
+ ATTRIBUTES = BASE_ATTRIBUTES.dup << :type
14
+ ATTRIBUTES.cs__freeze
15
+ VALID_INPUT_TYPES = %w[COOKIE PARAMETER HEADER BODY QUERYSTRING].cs__freeze
16
+
17
+ # @return type [String] The type of the input
18
+ def type
19
+ @_type ||= Contrast::Utils::ObjectShare::EMPTY_STRING
20
+ end
21
+
22
+ # @param new_type [String] Set new input type.
23
+ # @return type [String] The type of the input.
24
+ def type= new_type
25
+ @_type = new_type if VALID_INPUT_TYPES.include?(new_type)
26
+ end
27
+
28
+ def to_controlled_hash
29
+ hash = super
30
+ hash[:type] = type
31
+ hash
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end