contrast-agent 6.8.0 → 6.9.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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/lib/contrast/agent/assess/policy/trigger_method.rb +1 -1
  3. data/lib/contrast/agent/assess/property/evented.rb +11 -11
  4. data/lib/contrast/agent/assess.rb +0 -1
  5. data/lib/contrast/agent/excluder.rb +1 -1
  6. data/lib/contrast/agent/middleware.rb +8 -2
  7. data/lib/contrast/agent/protect/input_analyzer/worth_watching_analyzer.rb +116 -0
  8. data/lib/contrast/agent/protect/rule/base.rb +2 -2
  9. data/lib/contrast/agent/protect/rule/bot_blocker.rb +1 -1
  10. data/lib/contrast/agent/protect/rule/cmd_injection.rb +8 -7
  11. data/lib/contrast/agent/protect/rule/cmdi/cmdi_chained_command.rb +0 -5
  12. data/lib/contrast/agent/protect/rule/cmdi/cmdi_dangerous_path.rb +0 -5
  13. data/lib/contrast/agent/protect/rule/path_traversal.rb +4 -3
  14. data/lib/contrast/agent/protect/rule/sqli.rb +4 -3
  15. data/lib/contrast/agent/protect/rule/xss.rb +1 -0
  16. data/lib/contrast/agent/reporting/attack_result/rasp_rule_sample.rb +1 -1
  17. data/lib/contrast/agent/reporting/report.rb +1 -0
  18. data/lib/contrast/agent/reporting/reporter.rb +34 -0
  19. data/lib/contrast/agent/reporting/reporter_heartbeat.rb +3 -9
  20. data/lib/contrast/agent/reporting/reporting_events/application_activity.rb +1 -1
  21. data/lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb +12 -7
  22. data/lib/contrast/agent/reporting/reporting_events/application_inventory_activity.rb +6 -1
  23. data/lib/contrast/agent/reporting/reporting_events/finding.rb +2 -2
  24. data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +239 -93
  25. data/lib/contrast/agent/reporting/reporting_events/finding_event_signature.rb +10 -23
  26. data/lib/contrast/agent/reporting/reporting_events/finding_event_source.rb +10 -9
  27. data/lib/contrast/agent/reporting/reporting_events/observed_route.rb +12 -0
  28. data/lib/contrast/agent/reporting/reporting_events/server_reporting_event.rb +8 -0
  29. data/lib/contrast/agent/reporting/reporting_events/server_settings.rb +40 -0
  30. data/lib/contrast/agent/reporting/reporting_utilities/endpoints.rb +6 -0
  31. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +43 -1
  32. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +8 -4
  33. data/lib/contrast/agent/reporting/reporting_utilities/response_extractor.rb +58 -4
  34. data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +4 -3
  35. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +76 -16
  36. data/lib/contrast/agent/reporting/server_settings_worker.rb +44 -0
  37. data/lib/contrast/agent/reporting/settings/assess_server_feature.rb +14 -2
  38. data/lib/contrast/agent/reporting/settings/helpers.rb +7 -0
  39. data/lib/contrast/agent/reporting/settings/protect_server_feature.rb +39 -2
  40. data/lib/contrast/agent/reporting/settings/rule_definition.rb +3 -0
  41. data/lib/contrast/agent/reporting/settings/security_logger.rb +77 -0
  42. data/lib/contrast/agent/reporting/settings/server_features.rb +9 -0
  43. data/lib/contrast/agent/reporting/settings/syslog.rb +34 -5
  44. data/lib/contrast/agent/request.rb +1 -0
  45. data/lib/contrast/agent/request_handler.rb +5 -10
  46. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_event.rb +1 -1
  47. data/lib/contrast/agent/thread_watcher.rb +35 -1
  48. data/lib/contrast/agent/version.rb +1 -1
  49. data/lib/contrast/agent.rb +6 -0
  50. data/lib/contrast/api/communication/connection_status.rb +15 -0
  51. data/lib/contrast/components/agent.rb +34 -0
  52. data/lib/contrast/components/api.rb +23 -0
  53. data/lib/contrast/components/app_context.rb +23 -3
  54. data/lib/contrast/components/assess.rb +34 -4
  55. data/lib/contrast/components/assess_rules.rb +18 -0
  56. data/lib/contrast/components/base.rb +40 -0
  57. data/lib/contrast/components/config/sources.rb +95 -0
  58. data/lib/contrast/components/config.rb +18 -1
  59. data/lib/contrast/components/heap_dump.rb +10 -0
  60. data/lib/contrast/components/inventory.rb +15 -2
  61. data/lib/contrast/components/logger.rb +18 -0
  62. data/lib/contrast/components/polling.rb +36 -0
  63. data/lib/contrast/components/protect.rb +48 -1
  64. data/lib/contrast/components/ruby_component.rb +15 -0
  65. data/lib/contrast/components/sampling.rb +70 -13
  66. data/lib/contrast/components/security_logger.rb +13 -0
  67. data/lib/contrast/components/settings.rb +74 -7
  68. data/lib/contrast/config/certification_configuration.rb +14 -0
  69. data/lib/contrast/config/config.rb +46 -0
  70. data/lib/contrast/config/diagnostics.rb +114 -0
  71. data/lib/contrast/config/diagnostics_tools.rb +98 -0
  72. data/lib/contrast/config/effective_config.rb +65 -0
  73. data/lib/contrast/config/effective_config_value.rb +32 -0
  74. data/lib/contrast/config/exception_configuration.rb +12 -0
  75. data/lib/contrast/config/protect_rule_configuration.rb +1 -1
  76. data/lib/contrast/config/protect_rules_configuration.rb +8 -7
  77. data/lib/contrast/config/request_audit_configuration.rb +13 -0
  78. data/lib/contrast/config/server_configuration.rb +41 -2
  79. data/lib/contrast/configuration.rb +28 -2
  80. data/lib/contrast/extension/assess/erb.rb +1 -1
  81. data/lib/contrast/utils/assess/event_limit_utils.rb +31 -9
  82. data/lib/contrast/utils/assess/trigger_method_utils.rb +5 -4
  83. data/lib/contrast/utils/hash_digest.rb +2 -2
  84. data/lib/contrast/utils/input_classification_base.rb +1 -2
  85. data/lib/contrast/utils/reporting/application_activity_batch_utils.rb +81 -0
  86. data/lib/contrast/utils/routes_sent.rb +60 -0
  87. data/lib/contrast/utils/telemetry_client.rb +1 -2
  88. data/lib/contrast/utils/timer.rb +16 -0
  89. data/lib/contrast.rb +3 -1
  90. data/ruby-agent.gemspec +5 -1
  91. metadata +29 -20
  92. data/lib/contrast/agent/assess/contrast_event.rb +0 -157
  93. data/lib/contrast/agent/assess/events/event_factory.rb +0 -34
  94. data/lib/contrast/agent/assess/events/source_event.rb +0 -46
  95. data/lib/contrast/agent/reporting/reporting_events/server_activity.rb +0 -36
@@ -4,6 +4,7 @@
4
4
  require 'contrast/utils/object_share'
5
5
  require 'contrast/agent/reporting/settings/assess_server_feature'
6
6
  require 'contrast/agent/reporting/settings/protect_server_feature'
7
+ require 'contrast/agent/reporting/settings/security_logger'
7
8
 
8
9
  module Contrast
9
10
  module Agent
@@ -46,6 +47,13 @@ module Contrast
46
47
  @_log_file = log_file if log_file.is_a?(String)
47
48
  end
48
49
 
50
+ # Class holding security logger settings:
51
+ #
52
+ # @return [Contrast::Agent::Reporting::Settings::SecurityLogger]
53
+ def security_logger
54
+ @_security_logger ||= Contrast::Agent::Reporting::Settings::SecurityLogger.new
55
+ end
56
+
49
57
  # Controls for the reporting of telemetry events from the agent to TeamServer.
50
58
  # This is NOT for the agent telemetry feature collecting metrics sent to other services.
51
59
  #
@@ -74,6 +82,7 @@ module Contrast
74
82
 
75
83
  def to_controlled_hash
76
84
  {
85
+ security_logger: security_logger.settings_blank? ? nil : security_logger.to_controlled_hash,
77
86
  assessment: @_assess ? assess.to_controlled_hash : {},
78
87
  defend: @_protect ? protect.to_controlled_hash : {},
79
88
  telemetry: telemetry
@@ -14,15 +14,24 @@ module Contrast
14
14
  # severity_blocked, severity_blocked_perimeter, severity_exploited, severity_probed,
15
15
  # severity_probed_perimeter
16
16
  SEVERITIES = %w[ALERT CRITICAL ERROR WARNING NOTICE INFO DEBUG].cs__freeze
17
- SYSLOG_METHODS = %i[
17
+ # Order and elements matter, the same setter must be called against same response field.
18
+ SYSLOG_METHODS_NG = %i[
18
19
  enable= ip= port= facility= protocol= connection_type= severity_exploited= severity_blocked=
19
20
  severity_probed= severity_probed_suspicious= severity_blocked_perimeter= severity_probed_perimeter=
20
21
  ].cs__freeze
21
- SYSLOG_RESPONSE_KEYS = %i[
22
+ SYSLOG_RESPONSE_KEYS_NG = %i[
22
23
  syslogEnabled syslogIpAddress syslogPortNumber syslogFacilityCode syslogProtocol
23
24
  syslogConnectionType syslogSeverityExploited syslogSeverityBlocked syslogSeverityProbed
24
25
  syslogSeveritySuspicious syslogSeverityBlockedPerimeter syslogSeverityProbedPerimeter
25
26
  ].cs__freeze
27
+ SYSLOG_METHODS = %i[
28
+ enable= ip= port= facility= connection_type= severity_blocked= severity_blocked_perimeter=
29
+ severity_exploited= severity_probed= severity_probed_perimeter=
30
+ ].cs__freeze
31
+ SYSLOG_RESPONSE_KEYS = %i[
32
+ enable ip facility connection_type severity_blocked severity_blocked_perimeter severity_exploited
33
+ severity_probed severity_probed_perimeter
34
+ ].cs__freeze
26
35
 
27
36
  # @return enable [Boolean]
28
37
  attr_accessor :enable
@@ -40,6 +49,21 @@ module Contrast
40
49
  @ip = Contrast::Utils::ObjectShare::EMPTY_STRING
41
50
  @port = 0
42
51
  @facility = 0
52
+ @blank = true
53
+ end
54
+
55
+ # check to see if object is being used
56
+ #
57
+ # @return [Boolean]
58
+ def settings_blank?
59
+ @blank
60
+ end
61
+
62
+ # Set the state of settings
63
+ #
64
+ # @return [Boolean]
65
+ def not_blank!
66
+ @blank = false
43
67
  end
44
68
 
45
69
  # @return connection_type [String] one of UNENCRYPTED, ENCRYPTED
@@ -134,10 +158,15 @@ module Contrast
134
158
  end
135
159
 
136
160
  # @param settings_array [Array] Settings retrieved from response
137
- def assign_array settings_array
138
- Contrast::Agent::Reporting::Settings::Syslog::SYSLOG_METHODS.each_with_index do |method, index|
139
- send(method, settings_array[SYSLOG_RESPONSE_KEYS[index]])
161
+ # @param ng_ [Boolean]
162
+ def assign_array settings_array, ng_: true
163
+ methods = ng_ ? SYSLOG_METHODS_NG : SYSLOG_METHODS
164
+ response_keys = ng_ ? SYSLOG_RESPONSE_KEYS_NG : SYSLOG_RESPONSE_KEYS
165
+
166
+ methods.each_with_index do |method, index|
167
+ send(method, settings_array[response_keys[index]])
140
168
  end
169
+ not_blank!
141
170
  end
142
171
 
143
172
  def to_controlled_hash
@@ -76,6 +76,7 @@ module Contrast
76
76
  @_normalized_uri ||= begin
77
77
  path = rack_request.path_info || rack_request.path.to_s
78
78
  path = '/' if path.empty?
79
+
79
80
  uri = path.split(Contrast::Utils::ObjectShare::SEMICOLON)[0] # remove ;jsessionid
80
81
  uri = uri.split(Contrast::Utils::ObjectShare::QUESTION_MARK)[0] # remove ?query_string=
81
82
  uri.gsub(INNER_REST_TOKEN, INNER_NUMBER_MARKER) # replace interior tokens
@@ -21,18 +21,13 @@ module Contrast
21
21
  @ruleset = ::Contrast::AGENT.ruleset
22
22
  end
23
23
 
24
- # reports events[Contrast::Agent::Reporting::ReporterEvent] to TS
25
- # This method is used to send our JSON messages directly to TeamServer at the end of each request. As we move
26
- # more endpoints over, this method will take the messages originally sent by #send_actiivty_messages. At the end,
27
- # that method should be removed.
28
- def report_activity
24
+ # reports events[Contrast::Agent::Reporting::ObservedRoute] to TS
25
+ # Other ReportingEvents are handled through batching in the middleware
26
+ #
27
+ def report_observed_route
29
28
  return unless (reporter = Contrast::Agent.reporter)
30
29
 
31
- reporter.send_event(context.observed_route)
32
- # Mask Sensitive Data
33
- Contrast::Agent::Reporting::Masker.mask(context.activity)
34
- event = context.activity
35
- reporter.send_event(event)
30
+ reporter.send_event(context.observed_route) if Contrast::ROUTES_SENT.sendable?(context.observed_route)
36
31
  end
37
32
 
38
33
  # If the response is streaming, we should only perform filtering on our stream safe rules
@@ -33,7 +33,7 @@ module Contrast
33
33
  end
34
34
 
35
35
  def self.path
36
- '/ruby/runtime'
36
+ '/error'
37
37
  end
38
38
 
39
39
  def to_controlled_hash
@@ -4,7 +4,10 @@
4
4
  require 'contrast/components/logger'
5
5
  require 'contrast/agent/reporting/report'
6
6
  require 'contrast/agent/reporting/reporter_heartbeat'
7
+ require 'contrast/agent/reporting/server_settings_worker'
7
8
  require 'contrast/agent/telemetry/base'
9
+ require 'contrast/agent/protect/input_analyzer/worth_watching_analyzer'
10
+ require 'contrast/config/diagnostics'
8
11
 
9
12
  module Contrast
10
13
  module Agent
@@ -18,13 +21,19 @@ module Contrast
18
21
  attr_reader :reporter
19
22
  # @return [Contrast::Agent::ReporterHeartbeat]
20
23
  attr_reader :reporter_heartbeat
24
+ # @return [Contrast::Agent::Protect::WorthWatchingInputAnalyzer]
25
+ attr_reader :worth_watching_analyzer
26
+ # @return [Contrast::Agent::ServerSettingsWorker]
27
+ attr_reader :reporter_settings_worker
21
28
 
22
29
  def initialize
23
30
  @pids = {}
24
31
  @heapdump_util = Contrast::Utils::HeapDumpUtil.new
25
32
  @reporter = Contrast::Agent::Reporter.new
26
33
  @reporter_heartbeat = Contrast::Agent::ReporterHeartbeat.new
34
+ @reporter_settings_worker = Contrast::Agent::ServerSettingsWorker.new
27
35
  @telemetry = Contrast::Agent::Telemetry::Base.new if Contrast::Agent::Telemetry::Base.enabled?
36
+ @worth_watching_analyzer = Contrast::Agent::Protect::WorthWatchingInputAnalyzer.new unless protect_disabled?
28
37
  end
29
38
 
30
39
  # @return [Hash, nil] map of process to thread startup status
@@ -34,11 +43,16 @@ module Contrast
34
43
  logger.debug('ThreadWatcher started threads')
35
44
  reporter_status = init_thread(reporter)
36
45
  reporter_heartbeat_status = init_thread(reporter_heartbeat)
37
- @pids[Process.pid] = reporter_status && reporter_heartbeat_status
46
+ reporter_settings_worker_status = init_thread(reporter_settings_worker)
47
+ @pids[Process.pid] = reporter_status && reporter_heartbeat_status && reporter_settings_worker_status
38
48
  if Contrast::Agent::Telemetry::Base.enabled?
39
49
  telemetry_status = init_thread(telemetry_queue)
40
50
  @pids[Process.pid] = @pids[Process.pid] && telemetry_status
41
51
  end
52
+ unless protect_disabled?
53
+ worth_watching_analyzer_status = init_thread(worth_watching_analyzer)
54
+ @pids[Process.pid] = @pids[Process.pid] && worth_watching_analyzer_status
55
+ end
42
56
  @pids
43
57
  end
44
58
 
@@ -49,11 +63,27 @@ module Contrast
49
63
  startup!
50
64
  end
51
65
 
66
+ # This method will check the config and if the config is invalid - it will kill the agent
67
+ def self.check_before_start
68
+ return if Contrast::CONFIG.send(:validate)
69
+
70
+ @_diagnostics = Contrast::Agent::DiagnosticsConfig::Diagnostics.new(Contrast::AGENT.logger.path ||
71
+ Contrast::Components::Config::CONTRAST_LOG)
72
+ @_diagnostics.config.populate_fail_connection
73
+ @_diagnostics.write_to_file_logic(false, reset: false)
74
+ # kill agent
75
+ Contrast::AGENT.disable_agent!
76
+ # TODO: RUBY-1822
77
+ # set the in_application_scope to 1 so we short circuit it
78
+ end
79
+
52
80
  def shutdown!
53
81
  heapdump_util&.stop!
54
82
  telemetry_queue&.stop!
55
83
  reporter&.stop!
56
84
  reporter_heartbeat&.stop!
85
+ worth_watching_analyzer&.stop!
86
+ reporter_settings_worker&.stop!
57
87
  end
58
88
 
59
89
  # @return [Contrast::Agent::Telemetry::Base]
@@ -78,6 +108,10 @@ module Contrast
78
108
  logger.debug('Thread status', type: watcher.to_s, alive: result)
79
109
  result
80
110
  end
111
+
112
+ def protect_disabled?
113
+ ::Contrast::PROTECT.forcibly_disabled?
114
+ end
81
115
  end
82
116
  end
83
117
  end
@@ -3,6 +3,6 @@
3
3
 
4
4
  module Contrast
5
5
  module Agent
6
- VERSION = '6.8.0'
6
+ VERSION = '6.9.0'
7
7
  end
8
8
  end
@@ -73,6 +73,12 @@ module Contrast
73
73
  thread_watcher.reporter
74
74
  end
75
75
 
76
+ # @return [Contrast::Agent::Protect::WorthWatchingAnalyzer]
77
+ def self.worth_watching_analyzer
78
+ thread_watcher.worth_watching_analyzer
79
+ end
80
+
81
+ # @return [Contrast::Agent::ThreadWatcher]
76
82
  def self.thread_watcher
77
83
  @_thread_watcher ||= Contrast::Agent::ThreadWatcher.new
78
84
  end
@@ -10,6 +10,7 @@ module Contrast
10
10
  @last_success = nil
11
11
  @last_failure = nil
12
12
  @startup_messages_sent = false
13
+ @_startup_server_message_sent = false
13
14
  end
14
15
 
15
16
  # Whether we have sent startup message to TeamServer. True after successfully sending startup messages to
@@ -20,6 +21,20 @@ module Contrast
20
21
  @startup_messages_sent
21
22
  end
22
23
 
24
+ # Check to see if we have sent server message and received settings from TS.
25
+ #
26
+ # @return [Boolean]
27
+ def startup_server_message_sent?
28
+ @_startup_server_message_sent
29
+ end
30
+
31
+ # Set the server message status state
32
+ #
33
+ # @return [Boolean]
34
+ def server_response_success!
35
+ @_startup_server_message_sent = true
36
+ end
37
+
23
38
  # The last message sent was successful or not
24
39
  #
25
40
  # @return [Boolean]
@@ -2,11 +2,13 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'rubygems/version'
5
+ require 'contrast/components/base'
5
6
  require 'contrast/agent/rule_set'
6
7
  require 'contrast/components/logger'
7
8
  require 'contrast/components/security_logger'
8
9
  require 'contrast/components/heap_dump'
9
10
  require 'contrast/components/ruby_component'
11
+ require 'contrast/components/polling'
10
12
 
11
13
  module Contrast
12
14
  module Components
@@ -17,11 +19,22 @@ module Contrast
17
19
  class Interface
18
20
  include Contrast::Components::ComponentBase
19
21
 
22
+ # @return [String]
23
+ attr_reader :canon_name
24
+ # @return [Array]
25
+ attr_reader :config_values
26
+
27
+ CANON_NAME = 'agent'
28
+ CONFIG_VALUES = %w[enabled? omit_body?].cs__freeze
29
+
20
30
  def initialize hsh = {}
31
+ @config_values = CONFIG_VALUES
32
+ @canon_name = CANON_NAME
21
33
  return unless hsh
22
34
 
23
35
  @_enable = hsh[:enable]
24
36
  @_omit_body = hsh[:omit_body]
37
+ @_polling = Contrast::Components::Polling::Interface.new(hsh[:polling])
25
38
  @_logger = Contrast::Components::Logger::Interface.new(hsh[:logger])
26
39
  @_security_logger = Contrast::Components::SecurityLogger::Interface.new(hsh[:security_logger])
27
40
  @_ruby = Contrast::Components::Ruby::Interface.new(hsh[:ruby])
@@ -34,6 +47,10 @@ module Contrast
34
47
  @_logger = Contrast::Components::Logger::Interface.new
35
48
  end
36
49
 
50
+ def polling
51
+ @_polling ||= Contrast::Components::Polling::Interface.new
52
+ end
53
+
37
54
  def security_logger
38
55
  return @_security_logger unless @_security_logger.nil?
39
56
 
@@ -87,6 +104,10 @@ module Contrast
87
104
  @_omit_body
88
105
  end
89
106
 
107
+ def disable_agent!
108
+ @_enable = false
109
+ end
110
+
90
111
  def exception_control
91
112
  @_exception_control ||= {
92
113
  enable: true?(ruby.exceptions.capture),
@@ -110,6 +131,19 @@ module Contrast
110
131
  Contrast::Agent::TracePointHook.enable!
111
132
  end
112
133
 
134
+ # Converts current configuration to effective config values class and appends them to
135
+ # EffectiveConfig class.
136
+ #
137
+ # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
138
+ def to_effective_config effective_config
139
+ super
140
+ logger&.to_effective_config(effective_config)
141
+ security_logger&.to_effective_config(effective_config)
142
+ ruby&.to_effective_config(effective_config)
143
+ heap_dump&.to_effective_config(effective_config)
144
+ polling&.to_effective_config(effective_config)
145
+ end
146
+
113
147
  protected
114
148
 
115
149
  def retrieve_protect_ruleset
@@ -17,6 +17,10 @@ module Contrast
17
17
  include Contrast::Components::ComponentBase
18
18
  include Contrast::Config::BaseConfiguration
19
19
 
20
+ CANON_NAME = 'api'
21
+ PROXY_NAME = "#{ CANON_NAME }.proxy"
22
+ CONFIG_VALUES = %w[api_key user_name service_key url].cs__freeze
23
+
20
24
  # @return [String]
21
25
  attr_accessor :api_key
22
26
  # @return [String]
@@ -120,8 +124,27 @@ module Contrast
120
124
  @_certification_key_file ||= ::Contrast::CONFIG.api.certificate.key_file
121
125
  end
122
126
 
127
+ # Converts current configuration to effective config values class and appends them to
128
+ # EffectiveConfig class.
129
+ #
130
+ # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
131
+ def to_effective_config effective_config
132
+ add_effective_config_values(effective_config, CONFIG_VALUES, CANON_NAME, CONTRAST)
133
+ effective_proxy(effective_config)
134
+ request_audit&.to_effective_config(effective_config)
135
+ certificate&.to_effective_config(effective_config)
136
+ end
137
+
123
138
  private
124
139
 
140
+ # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
141
+ def effective_proxy effective_config
142
+ add_single_effective_value(effective_config, ENABLE, proxy_enable.to_s, PROXY_NAME, "#{ CONTRAST }.proxy")
143
+ return unless proxy_url && proxy_enable
144
+
145
+ add_single_effective_value(effective_config, 'url', proxy_url, PROXY_NAME, "#{ CONTRAST }.proxy")
146
+ end
147
+
125
148
  def certification_truly_enabled? config_path
126
149
  return false unless true?(config_path.enable)
127
150
  return true if file_exists?(certification_ca_file) && valid_cert?(certification_ca_file)
@@ -14,7 +14,7 @@ module Contrast
14
14
  # parent_configuration_spec.yaml.
15
15
  # Specifically, this allows for querying the state of the Application,
16
16
  # including the Client, Process, and Server information.
17
- class Interface
17
+ class Interface # rubocop:disable Metrics/ClassLength
18
18
  include Contrast::Components::AppContextExtend
19
19
  include Contrast::Components::ComponentBase
20
20
  include Contrast::Config::BaseConfiguration
@@ -23,6 +23,8 @@ module Contrast
23
23
  DEFAULT_APP_PATH = '/'
24
24
  DEFAULT_SERVER_NAME = 'localhost'
25
25
  DEFAULT_SERVER_PATH = '/'
26
+ CANON_NAME = 'application'
27
+ CONFIG_VALUES = %w[name version language path group tags code metadata session_id session_metadata].cs__freeze
26
28
 
27
29
  # @return [String]
28
30
  attr_accessor :version
@@ -30,15 +32,20 @@ module Contrast
30
32
  attr_accessor :language
31
33
  # @return [String]
32
34
  attr_accessor :group
33
- # @return [String]
34
- attr_accessor :tags
35
+ attr_writer :tags
35
36
  # @return [String]
36
37
  attr_accessor :code
37
38
  # @return [String]
38
39
  attr_accessor :metadata
40
+ # @return [String]
41
+ attr_reader :canon_name
42
+ # @return [Array]
43
+ attr_reader :config_values
39
44
 
40
45
  def initialize hsh = {}
41
46
  original_pid
47
+ @config_values = CONFIG_VALUES
48
+ @canon_name = CANON_NAME
42
49
  return unless hsh
43
50
 
44
51
  @_name = hsh[:name]
@@ -135,6 +142,10 @@ module Contrast
135
142
  end
136
143
  end
137
144
 
145
+ def tags
146
+ stringify_array(@tags)
147
+ end
148
+
138
149
  # Determines if the Process we're currently in matches that of the
139
150
  # Process in which the App Context instance was created.
140
151
  # If it doesn't, that indicates the running context is in a new
@@ -147,6 +158,15 @@ module Contrast
147
158
  current_pid != original_pid
148
159
  end
149
160
 
161
+ # Converts current configuration to effective config values class and appends them to
162
+ # EffectiveConfig class.
163
+ #
164
+ # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
165
+ def to_effective_config effective_config
166
+ super
167
+ Contrast::CONFIG.server.to_effective_config(effective_config)
168
+ end
169
+
150
170
  private
151
171
 
152
172
  def original_pid
@@ -15,21 +15,36 @@ module Contrast
15
15
  class Interface # rubocop:disable Metrics/ClassLength
16
16
  include Contrast::Components::ComponentBase
17
17
 
18
- # @return [String, nil]
19
- attr_accessor :tags
20
18
  # @return [Boolean, nil]
21
19
  attr_accessor :enable
22
20
  # @return [Array, nil]
23
- attr_writer :enable_scan_response, :enable_dynamic_sources, :sampling, :rules, :stacktraces
21
+ attr_writer :enable_scan_response, :enable_dynamic_sources, :sampling, :rules, :stacktraces, :tags
22
+ # @return [String]
23
+ attr_reader :canon_name
24
+ # @return [Array]
25
+ attr_reader :config_values
24
26
 
25
27
  DEFAULT_STACKTRACES = 'ALL'
26
28
  DEFAULT_MAX_SOURCE_EVENTS = 50_000
27
29
  DEFAULT_MAX_PROPAGATION_EVENTS = 50_000
28
30
  DEFAULT_MAX_RULE_REPORTED = 100
29
31
  DEFAULT_MAX_RULE_TIME_THRESHOLD = 300_000
30
-
32
+ CANON_NAME = 'assess'
33
+ CONFIG_VALUES = %w[
34
+ enabled?
35
+ tags
36
+ enable_scan_response
37
+ enable_original_object
38
+ stacktraces
39
+ max_context_source_events
40
+ max_propagation_events
41
+ max_rule_reported
42
+ time_limit_threshold
43
+ ].cs__freeze
31
44
  # rubocop:disable Naming/MemoizedInstanceVariableName
32
45
  def initialize hsh = {}
46
+ @config_values = CONFIG_VALUES
47
+ @canon_name = CANON_NAME
33
48
  return unless hsh
34
49
 
35
50
  @enable = hsh[:enable]
@@ -91,6 +106,11 @@ module Contrast
91
106
  @max_context_source_events ||= DEFAULT_MAX_SOURCE_EVENTS
92
107
  end
93
108
 
109
+ # @return [String, nil]
110
+ def tags
111
+ stringify_array(@tags)
112
+ end
113
+
94
114
  def enabled?
95
115
  # config overrides if forcibly set
96
116
  return false if forcibly_disabled?
@@ -187,6 +207,16 @@ module Contrast
187
207
  ::Contrast::SETTINGS.assess_state.session_id
188
208
  end
189
209
 
210
+ # Converts current configuration to effective config values class and appends them to
211
+ # EffectiveConfig class.
212
+ #
213
+ # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
214
+ def to_effective_config effective_config
215
+ super
216
+ sampling&.to_effective_config(effective_config)
217
+ rules&.to_effective_config(effective_config)
218
+ end
219
+
190
220
  # rubocop:enable Naming/MemoizedInstanceVariableName
191
221
  private
192
222
 
@@ -2,6 +2,8 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'contrast/config/base_configuration'
5
+ require 'contrast/utils/object_share'
6
+ require 'contrast/components/base'
5
7
 
6
8
  module Contrast
7
9
  module Components
@@ -10,17 +12,33 @@ module Contrast
10
12
  module AssessRules
11
13
  class Interface # :nodoc:
12
14
  include Contrast::Config::BaseConfiguration
15
+ include Contrast::Components::ComponentBase
13
16
 
14
17
  SPEC_KEY = :disabled_rules.cs__freeze
18
+ CANON_NAME = 'assess.rules'
19
+ NAME_PREFIX = "#{ CONTRAST }.#{ CANON_NAME }"
20
+
15
21
  # @return [Array, nil] list of disabled assess rules
16
22
  attr_accessor :disabled_rules
23
+ # @return [String]
24
+ attr_reader :canon_name
17
25
 
18
26
  def initialize hsh = {}
27
+ @canon_name = CANON_NAME
28
+ @disabled_rules = []
19
29
  return unless hsh
20
30
 
21
31
  @disabled_rules = cast_disabled_rules(hsh)
22
32
  end
23
33
 
34
+ # Converts current configuration to effective config values class and appends them to
35
+ # EffectiveConfig class.
36
+ #
37
+ # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
38
+ def to_effective_config effective_config
39
+ add_single_effective_value(effective_config, SPEC_KEY.to_s, disabled_rules, canon_name, NAME_PREFIX)
40
+ end
41
+
24
42
  private
25
43
 
26
44
  def cast_disabled_rules hsh
@@ -1,11 +1,33 @@
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/config/diagnostics_tools'
5
+ require 'contrast/utils/object_share'
6
+
4
7
  module Contrast
5
8
  module Components
6
9
  # All components should inherit from this,
7
10
  # whether Interfaces, InstanceMethods or ClassMethods.
8
11
  module ComponentBase
12
+ include Contrast::Agent::DiagnosticsConfig::DiagnosticsTools
13
+
14
+ CONTRAST = 'contrast'
15
+ ENABLE = 'enable'
16
+
17
+ # Used for config diagnostics. Override per rule.
18
+ #
19
+ # @return [String]
20
+ def canon_name
21
+ Contrast::Utils::ObjectShare::EMPTY_STRING
22
+ end
23
+
24
+ # Used for config diagnostics. Override per rule.
25
+ #
26
+ # @return [Array]
27
+ def config_values
28
+ Contrast::Utils::ObjectShare::EMPTY_ARRAY
29
+ end
30
+
9
31
  # use this to determine if the configuration value is literally boolean
10
32
  # false or some form of the word `false`, regardless of case. It should
11
33
  # be used for those values which default to `true` as they should only
@@ -58,6 +80,24 @@ module Contrast
58
80
 
59
81
  File.exist?(path)
60
82
  end
83
+
84
+ # Converts current configuration to effective config values class and appends them to
85
+ # EffectiveConfig class.
86
+ #
87
+ # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
88
+ def to_effective_config effective_config
89
+ add_effective_config_values(effective_config, config_values, canon_name, "#{ CONTRAST }.#{ canon_name }")
90
+ end
91
+
92
+ # attempts to stringifys the config value if it is an array with the join char
93
+ # @param val[Object] val to stringify
94
+ # @param join_char[String, ','] join character defaults to ','
95
+ # @return [String, Object] the stringified val or the object as is
96
+ def stringify_array val, join_char = ','
97
+ return val.join(join_char) if val.cs__is_a?(Array)
98
+
99
+ val
100
+ end
61
101
  end
62
102
  end
63
103
  end