contrast-agent 6.1.1 → 6.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. checksums.yaml +4 -4
  2. data/ext/cs__assess_basic_object/cs__assess_basic_object.c +7 -5
  3. data/ext/cs__assess_kernel/cs__assess_kernel.c +14 -3
  4. data/ext/cs__assess_kernel/cs__assess_kernel.h +2 -0
  5. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +10 -3
  6. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.h +2 -1
  7. data/ext/cs__assess_regexp/cs__assess_regexp.c +9 -7
  8. data/ext/{cs__assess_string_interpolation26/cs__assess_string_interpolation26.c → cs__assess_string_interpolation/cs__assess_string_interpolation.c} +14 -3
  9. data/ext/{cs__assess_string_interpolation26/cs__assess_string_interpolation26.h → cs__assess_string_interpolation/cs__assess_string_interpolation.h} +1 -1
  10. data/ext/{cs__assess_string_interpolation26 → cs__assess_string_interpolation}/extconf.rb +0 -0
  11. data/ext/cs__common/cs__common.c +5 -4
  12. data/ext/cs__contrast_patch/cs__contrast_patch.c +3 -10
  13. data/lib/contrast/agent/assess/events/source_event.rb +16 -12
  14. data/lib/contrast/agent/assess/policy/policy_node.rb +6 -0
  15. data/lib/contrast/agent/assess/policy/propagation_method.rb +3 -39
  16. data/lib/contrast/agent/assess/policy/propagation_node.rb +8 -0
  17. data/lib/contrast/agent/assess/policy/propagator/base.rb +2 -0
  18. data/lib/contrast/agent/assess/policy/source_method.rb +2 -47
  19. data/lib/contrast/agent/assess/policy/source_node.rb +1 -0
  20. data/lib/contrast/agent/assess/policy/trigger_node.rb +8 -0
  21. data/lib/contrast/agent/assess/property/evented.rb +4 -18
  22. data/lib/contrast/agent/assess/tag.rb +19 -0
  23. data/lib/contrast/agent/at_exit_hook.rb +9 -8
  24. data/lib/contrast/agent/inventory/database_config.rb +18 -7
  25. data/lib/contrast/agent/inventory/dependency_analysis.rb +3 -2
  26. data/lib/contrast/agent/inventory/dependency_usage_analysis.rb +13 -9
  27. data/lib/contrast/agent/middleware.rb +4 -0
  28. data/lib/contrast/agent/patching/policy/after_load_patcher.rb +27 -2
  29. data/lib/contrast/agent/patching/policy/policy.rb +5 -0
  30. data/lib/contrast/agent/patching/policy/policy_node.rb +6 -0
  31. data/lib/contrast/agent/patching/policy/trigger_node.rb +3 -0
  32. data/lib/contrast/agent/protect/policy/applies_deserialization_rule.rb +3 -4
  33. data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +1 -0
  34. data/lib/contrast/agent/protect/policy/rule_applicator.rb +2 -2
  35. data/lib/contrast/agent/protect/rule/base.rb +1 -0
  36. data/lib/contrast/agent/protect/rule/no_sqli.rb +2 -0
  37. data/lib/contrast/agent/protect/rule/xss.rb +4 -0
  38. data/lib/contrast/agent/reporting/reporter.rb +33 -17
  39. data/lib/contrast/agent/reporting/reporter_heartbeat.rb +21 -15
  40. data/lib/contrast/agent/reporting/reporting_events/application_inventory.rb +3 -18
  41. data/lib/contrast/agent/reporting/reporting_events/application_update.rb +5 -24
  42. data/lib/contrast/agent/reporting/reporting_events/architecture_component.rb +8 -1
  43. data/lib/contrast/agent/reporting/reporting_events/discovered_route.rb +83 -16
  44. data/lib/contrast/agent/reporting/reporting_events/finding.rb +9 -3
  45. data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +10 -1
  46. data/lib/contrast/agent/reporting/reporting_events/finding_event_object.rb +11 -1
  47. data/lib/contrast/agent/reporting/reporting_events/finding_event_parent_object.rb +11 -1
  48. data/lib/contrast/agent/reporting/reporting_events/finding_event_property.rb +12 -1
  49. data/lib/contrast/agent/reporting/reporting_events/finding_event_signature.rb +10 -1
  50. data/lib/contrast/agent/reporting/reporting_events/finding_event_source.rb +11 -1
  51. data/lib/contrast/agent/reporting/reporting_events/finding_event_stack.rb +11 -1
  52. data/lib/contrast/agent/reporting/reporting_events/finding_event_taint_range.rb +11 -1
  53. data/lib/contrast/agent/reporting/reporting_events/finding_request.rb +11 -1
  54. data/lib/contrast/agent/reporting/reporting_events/library_discovery.rb +29 -32
  55. data/lib/contrast/agent/reporting/reporting_events/library_usage_observation.rb +18 -20
  56. data/lib/contrast/agent/reporting/reporting_events/observed_library_usage.rb +11 -24
  57. data/lib/contrast/agent/reporting/reporting_events/observed_route.rb +13 -6
  58. data/lib/contrast/agent/reporting/reporting_events/preflight_message.rb +10 -4
  59. data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +10 -4
  60. data/lib/contrast/agent/reporting/reporting_events/route_coverage.rb +9 -0
  61. data/lib/contrast/agent/reporting/reporting_events/route_discovery.rb +10 -1
  62. data/lib/contrast/agent/reporting/reporting_events/route_discovery_observation.rb +11 -4
  63. data/lib/contrast/agent/reporting/reporting_events/server_activity.rb +0 -8
  64. data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +2 -6
  65. data/lib/contrast/agent/reporting/reporting_utilities/dtm_message.rb +0 -32
  66. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +1 -4
  67. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +1 -11
  68. data/lib/contrast/agent/reporting/reporting_utilities/response.rb +60 -2
  69. data/lib/contrast/agent/reporting/reporting_utilities/response_extractor.rb +32 -10
  70. data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +1 -1
  71. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +58 -26
  72. data/lib/contrast/agent/reporting/settings/application_settings.rb +8 -23
  73. data/lib/contrast/agent/reporting/settings/assess_server_feature.rb +27 -33
  74. data/lib/contrast/agent/reporting/settings/bot_blocker.rb +68 -0
  75. data/lib/contrast/agent/reporting/settings/code_exclusion.rb +27 -0
  76. data/lib/contrast/agent/reporting/settings/exclusion_base.rb +33 -0
  77. data/lib/contrast/agent/reporting/settings/exclusions.rb +39 -57
  78. data/lib/contrast/agent/reporting/settings/helpers.rb +56 -0
  79. data/lib/contrast/agent/reporting/settings/input_exclusion.rb +37 -0
  80. data/lib/contrast/agent/reporting/settings/ip_filter.rb +35 -0
  81. data/lib/contrast/agent/reporting/settings/keyword.rb +74 -0
  82. data/lib/contrast/agent/reporting/settings/log_enhancer.rb +65 -0
  83. data/lib/contrast/agent/reporting/settings/protect.rb +4 -2
  84. data/lib/contrast/agent/reporting/settings/protect_server_feature.rb +62 -115
  85. data/lib/contrast/agent/reporting/settings/reaction.rb +11 -2
  86. data/lib/contrast/agent/reporting/settings/rule_definition.rb +63 -0
  87. data/lib/contrast/agent/reporting/settings/sampling.rb +10 -0
  88. data/lib/contrast/agent/reporting/settings/sanitizer.rb +38 -0
  89. data/lib/contrast/agent/reporting/settings/sensitive_data_masking.rb +9 -1
  90. data/lib/contrast/agent/reporting/settings/sensitive_data_masking_rule.rb +7 -0
  91. data/lib/contrast/agent/reporting/settings/server_features.rb +8 -0
  92. data/lib/contrast/agent/reporting/settings/syslog.rb +176 -0
  93. data/lib/contrast/agent/reporting/settings/url_exclusion.rb +42 -0
  94. data/lib/contrast/agent/reporting/settings/validator.rb +17 -0
  95. data/lib/contrast/agent/request.rb +5 -7
  96. data/lib/contrast/agent/request_context.rb +8 -13
  97. data/lib/contrast/agent/request_context_extend.rb +8 -9
  98. data/lib/contrast/agent/request_handler.rb +10 -35
  99. data/lib/contrast/agent/rule_set.rb +4 -0
  100. data/lib/contrast/agent/service_heartbeat.rb +1 -1
  101. data/lib/contrast/agent/static_analysis.rb +6 -15
  102. data/lib/contrast/agent/telemetry/base.rb +35 -35
  103. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_base.rb +2 -0
  104. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_event.rb +2 -0
  105. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_message.rb +5 -2
  106. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_message_exception.rb +3 -0
  107. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_stack_frame.rb +3 -0
  108. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exceptions.rb +0 -1
  109. data/lib/contrast/agent/thread_watcher.rb +2 -6
  110. data/lib/contrast/agent/version.rb +1 -1
  111. data/lib/contrast/agent.rb +1 -3
  112. data/lib/contrast/api/communication/socket.rb +1 -0
  113. data/lib/contrast/api/decorators/message.rb +0 -6
  114. data/lib/contrast/api/decorators.rb +0 -3
  115. data/lib/contrast/components/assess.rb +0 -6
  116. data/lib/contrast/components/config.rb +18 -2
  117. data/lib/contrast/config/base_configuration.rb +0 -13
  118. data/lib/contrast/config/root_configuration.rb +1 -0
  119. data/lib/contrast/config/ruby_configuration.rb +2 -9
  120. data/lib/contrast/configuration.rb +0 -2
  121. data/lib/contrast/extension/assess/eval_trigger.rb +0 -4
  122. data/lib/contrast/extension/assess/hash.rb +3 -2
  123. data/lib/contrast/extension/assess/kernel.rb +22 -0
  124. data/lib/contrast/extension/assess/marshal.rb +16 -0
  125. data/lib/contrast/extension/assess/string.rb +21 -20
  126. data/lib/contrast/framework/base_support.rb +13 -4
  127. data/lib/contrast/framework/grape/support.rb +6 -6
  128. data/lib/contrast/framework/manager.rb +7 -23
  129. data/lib/contrast/framework/manager_extend.rb +1 -1
  130. data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +11 -15
  131. data/lib/contrast/framework/rails/support.rb +9 -2
  132. data/lib/contrast/framework/sinatra/support.rb +3 -2
  133. data/lib/contrast/logger/aliased_logging.rb +33 -26
  134. data/lib/contrast/utils/assess/source_method_utils.rb +0 -9
  135. data/lib/contrast/utils/lru_cache.rb +3 -0
  136. data/lib/contrast/utils/middleware_utils.rb +2 -0
  137. data/lib/contrast/utils/response_utils.rb +14 -1
  138. data/lib/contrast/utils/telemetry.rb +9 -0
  139. data/lib/contrast/utils/telemetry_client.rb +7 -7
  140. data/lib/contrast/utils/telemetry_hash.rb +36 -12
  141. data/lib/contrast/utils/telemetry_identifier.rb +8 -0
  142. data/lib/contrast/utils/thread_tracker.rb +26 -9
  143. data/lib/contrast/utils/timer.rb +6 -1
  144. data/lib/contrast.rb +1 -3
  145. data/resources/assess/policy.json +2 -11
  146. data/ruby-agent.gemspec +1 -1
  147. metadata +36 -22
  148. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exceptions_report.rb +0 -30
  149. data/lib/contrast/api/decorators/application_update.rb +0 -52
  150. data/lib/contrast/api/decorators/library.rb +0 -56
  151. data/lib/contrast/api/decorators/library_usage_update.rb +0 -31
  152. data/lib/contrast/framework/platform_version.rb +0 -22
@@ -24,7 +24,6 @@ module Contrast
24
24
  protect = response_data[:settings][:defend]
25
25
  return unless protect
26
26
 
27
- # TODO: RUBY-1636 should this be `:rules` or `:protectionRules`
28
27
  res.application_settings.protect.protection_rules = protect[:protectionRules]
29
28
  res.application_settings.protect.virtual_patches = protect[:virtualPatches]
30
29
  end
@@ -40,10 +39,14 @@ module Contrast
40
39
  res.application_settings.exclusions.url_exclusions = exclusions[:urlExceptions]
41
40
  end
42
41
 
42
+ # The responses we receive for feature and settings from TS have different
43
+ # place to store these reactions: body.reactions vs body.settings.reactions.
44
+ #
43
45
  # @param response_data [Hash]
44
46
  # @param res [Contrast::Agent::Reporting::Response]
45
47
  def extract_reactions response_data, res
46
- res.application_settings.reactions = response_data[:settings][:reactions]
48
+ res.reactions = response_data[:settings][:reactions] if response_data[:settings]
49
+ res.reactions = response_data[:reactions] if response_data[:features]
47
50
  end
48
51
 
49
52
  # @param response_data [Hash]
@@ -65,10 +68,17 @@ module Contrast
65
68
  return unless protect
66
69
 
67
70
  res.server_features.protect.enabled = protect[:enabled]
68
- res.server_features.protect.bot_blocker = protect[:'bot-blocker']
69
- # TODO: RUBY-1636 should this be `:rules` or `:protectionRules`
70
- # process the botBlockers field
71
- res.server_features.protect.syslog = protect[:syslog]
71
+ res.server_features.protect.bot_blocker.enable = protect[:'bot-blocker']
72
+ res.server_features.protect.bot_blocker.bots = protect[:botBlockers]
73
+ extract_syslog(response_data, res)
74
+ end
75
+
76
+ # @param response_data [Hash]
77
+ # @param res [Contrast::Agent::Reporting::Response]
78
+ def extract_syslog response_data, res
79
+ return unless (syslog = response_data[:features][:defend][:syslog])
80
+
81
+ res.server_features.protect.syslog.assign_array(syslog)
72
82
  end
73
83
 
74
84
  # @param response_data [Hash]
@@ -78,22 +88,34 @@ module Contrast
78
88
  return unless protect
79
89
 
80
90
  res.server_features.protect.ip_allowlist = protect[:ipAllowlist]
81
- res.server_features.protect.ip_denylist = protect[:ipDenyList]
82
- res.server_features.protect.log_enchancers = protect[:logEnhancers]
91
+ res.server_features.protect.ip_denylist = protect[:ipDenylist]
92
+ res.server_features.protect.log_enhancers = protect[:logEnhancers]
83
93
  res.server_features.protect.rule_definition_list = protect[:ruleDefinitionList]
84
94
  end
85
95
 
86
96
  # Here we extract the rules and state for the sensitive data masking policy
87
- # Received from TS.
97
+ # received from TS.
88
98
  #
89
99
  # @param response_data [Hash]
90
100
  # @param res [Contrast::Agent::Reporting::Response]
91
101
  def extract_sensitive_data_policy response_data, res
92
- sensitive_data = response_data[:settings][:sensitive_data_masking_policy]
102
+ return unless (sensitive_data = response_data[:settings][:sensitive_data_masking_policy])
103
+
93
104
  res.application_settings.sensitive_data_masking.mask_http_body = sensitive_data[:mask_http_body]
94
105
  res.application_settings.sensitive_data_masking.mask_attack_vector = sensitive_data[:mask_attack_vector]
95
106
  res.application_settings.sensitive_data_masking.build_rules_form_settings(sensitive_data[:rules])
96
107
  end
108
+
109
+ # Here we extract the log settings received from TS.
110
+ #
111
+ # @param response_data [Hash]
112
+ # @param res [Contrast::Agent::Reporting::Response]
113
+ def extract_log_settings response_data, res
114
+ return unless (log_level = response_data[:logLevel])
115
+
116
+ res.server_features.log_level = log_level
117
+ res.server_features.log_file = response_data[:logFile] if response_data[:logFile]
118
+ end
97
119
  end
98
120
  end
99
121
  end
@@ -90,7 +90,7 @@ module Contrast
90
90
  when ERROR_CODES[:too_many_requests]
91
91
  handle_response_errors(response, RETRY_AFTER_MSG, mode.resending)
92
92
  else
93
- logger.debug('Response Error code could not be processed')
93
+ logger.error('Response Error code could not be processed')
94
94
  end
95
95
  end
96
96
 
@@ -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