contrast-agent 7.0.0 → 7.1.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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/lib/contrast/agent/assess/policy/policy.rb +1 -1
  3. data/lib/contrast/agent/deadzone/policy/policy.rb +1 -1
  4. data/lib/contrast/agent/patching/policy/policy.rb +2 -2
  5. data/lib/contrast/agent/protect/input_analyzer/worth_watching_analyzer.rb +3 -0
  6. data/lib/contrast/agent/protect/rule/no_sqli/no_sqli.rb +1 -1
  7. data/lib/contrast/agent/reporting/reporter.rb +19 -4
  8. data/lib/contrast/agent/reporting/reporting_events/agent_effective_config.rb +32 -0
  9. data/lib/contrast/agent/reporting/reporting_utilities/endpoints.rb +7 -0
  10. data/lib/contrast/agent/reporting/reporting_utilities/headers.rb +3 -1
  11. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +11 -7
  12. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +15 -7
  13. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +2 -1
  14. data/lib/contrast/agent/reporting/reporting_workers/application_server_worker.rb +3 -0
  15. data/lib/contrast/agent/reporting/reporting_workers/reporter_heartbeat.rb +3 -0
  16. data/lib/contrast/agent/reporting/reporting_workers/server_settings_worker.rb +3 -0
  17. data/lib/contrast/agent/telemetry/base.rb +37 -12
  18. data/lib/contrast/agent/telemetry/client.rb +1 -3
  19. data/lib/contrast/agent/telemetry/telemetry.rb +0 -7
  20. data/lib/contrast/agent/thread/thread_watcher.rb +2 -2
  21. data/lib/contrast/agent/version.rb +1 -1
  22. data/lib/contrast/components/agent.rb +1 -1
  23. data/lib/contrast/components/api.rb +2 -2
  24. data/lib/contrast/components/app_context.rb +1 -1
  25. data/lib/contrast/components/assess.rb +1 -1
  26. data/lib/contrast/components/assess_rules.rb +1 -1
  27. data/lib/contrast/components/base.rb +3 -3
  28. data/lib/contrast/components/config/sources.rb +12 -9
  29. data/lib/contrast/components/config.rb +2 -2
  30. data/lib/contrast/components/protect.rb +2 -2
  31. data/lib/contrast/components/sampling.rb +6 -4
  32. data/lib/contrast/components/settings.rb +1 -1
  33. data/lib/contrast/config/certification_configuration.rb +1 -1
  34. data/lib/contrast/config/configuration_files.rb +47 -0
  35. data/lib/contrast/config/diagnostics/command_line.rb +24 -0
  36. data/lib/contrast/config/{config.rb → diagnostics/config.rb} +21 -6
  37. data/lib/contrast/config/diagnostics/contrast_ui.rb +24 -0
  38. data/lib/contrast/config/diagnostics/effective_config.rb +28 -0
  39. data/lib/contrast/config/diagnostics/effective_config_value.rb +14 -0
  40. data/lib/contrast/config/diagnostics/environment_variables.rb +51 -0
  41. data/lib/contrast/config/{diagnostics.rb → diagnostics/monitor.rb} +10 -10
  42. data/lib/contrast/config/diagnostics/source_config_value.rb +51 -0
  43. data/lib/contrast/config/diagnostics/tools.rb +188 -0
  44. data/lib/contrast/config/diagnostics/user_configuration_file.rb +44 -0
  45. data/lib/contrast/config/request_audit_configuration.rb +1 -1
  46. data/lib/contrast/config/server_configuration.rb +1 -1
  47. data/lib/contrast/configuration.rb +90 -57
  48. data/lib/contrast/utils/hash_utils.rb +43 -0
  49. data/lib/contrast/utils/json.rb +46 -0
  50. data/lib/contrast/utils/net_http_base.rb +75 -26
  51. metadata +16 -7
  52. data/lib/contrast/config/diagnostics_tools.rb +0 -99
  53. data/lib/contrast/config/effective_config.rb +0 -131
  54. data/lib/contrast/config/effective_config_value.rb +0 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc98145df7f08bc47cbff0f0416a7b43852b8075c6806bd38fbbe0aa27d94adb
4
- data.tar.gz: 60885ba415f59b893a5da6101ddc3b9d6deeac5a9d41bb2eb7c459291873b08f
3
+ metadata.gz: 81222798666699f86b31b925d531d2ee2229eb7934582d2a502cc61de3ca4e0b
4
+ data.tar.gz: 7dd4d41a58600b7d57b5f57cf95c42bd2f6d198f5f1906e93751e33c09efa3e0
5
5
  SHA512:
6
- metadata.gz: 4a6449786512d444818087fed5d880c061b1108b8e9fbe64e4fd0f3657bac3b53ffb60806a7767a50a9c7a910b5e62e223d6af84be51d8ca9b6e4e5b5ae67d07
7
- data.tar.gz: 4f2cb9c1435fbe5fdfbccbc3cc69ba3823de97f617bcff63493087a70a0551852dbe09f7699089cd22dfc509e57c39525420290813cd12ac92ee91164e2910bc
6
+ metadata.gz: 02e5d3aa6b342e8c4277ad6cefde65819aed6f6b4a1079cfe7528fcce236ec702aa8a63fc756c403c0df6e3ef38d5d25dc9f1c6e5c450d272122d699b6fd9872
7
+ data.tar.gz: 9cc83b5f69edeea949784ae766be7e02c1d589e58b2af5b5c1bd7975dcee1450d294bc7de647f60a9a3f18a1ea05a43bfe452a52d4760ed1b1cfcb0a7339a6ab
@@ -58,7 +58,7 @@ module Contrast
58
58
  # can skip policy loading.
59
59
  return if disabled_globally?
60
60
 
61
- policy_data = JSON.parse(string)
61
+ policy_data = Contrast::Utils::Json.parse(string)
62
62
 
63
63
  policy_data[SOURCES_KEY].each do |source_hash|
64
64
  source = Contrast::Agent::Assess::Policy::SourceNode.new(source_hash)
@@ -28,7 +28,7 @@ module Contrast
28
28
  end
29
29
 
30
30
  def from_hash_string string
31
- policy_data = JSON.parse(string)
31
+ policy_data = Contrast::Utils::Json.parse(string)
32
32
 
33
33
  policy_data[DEADZONES_KEY].each do |deadzone_hash|
34
34
  add_node(node_type.new(deadzone_hash))
@@ -1,7 +1,7 @@
1
1
  # Copyright (c) 2023 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'json'
4
+ require 'contrast/utils/json'
5
5
  require 'singleton'
6
6
 
7
7
  require 'contrast'
@@ -71,7 +71,7 @@ module Contrast
71
71
  # it, so in that case, we can skip policy loading.
72
72
  return if disabled_globally?
73
73
 
74
- policy_data = JSON.parse(string)
74
+ policy_data = Contrast::Utils::Json.parse(string)
75
75
 
76
76
  policy_data[RULES_KEY].each do |rule_hash|
77
77
  rule_hash[TRIGGERS_KEY].each do |trigger_hash|
@@ -26,11 +26,14 @@ module Contrast
26
26
  # Thread that will process all the InputAnalysisResults that have a score level of WORTHWATCHING and
27
27
  # sends results to TeamServer
28
28
  def start_thread!
29
+ return unless attempt_to_start?
29
30
  return if running?
30
31
 
31
32
  @_thread = Contrast::Agent::Thread.new do
32
33
  logger.info('[WorthWatchingAnalyzer] Starting thread.')
33
34
  loop do
35
+ break unless attempt_to_start?
36
+
34
37
  sleep(REPORT_INTERVAL_SECOND)
35
38
  next if queue.empty?
36
39
 
@@ -94,7 +94,7 @@ module Contrast
94
94
  #
95
95
  # @return [Boolean]
96
96
  def json? string
97
- return true if JSON.parse(string)
97
+ return true if Contrast::Utils::Json.parse(string)
98
98
  rescue StandardError
99
99
  false
100
100
  end
@@ -10,10 +10,12 @@ require 'contrast/agent/telemetry/exception'
10
10
  module Contrast
11
11
  module Agent
12
12
  # This module will hold everything essential to reporting to TeamServer
13
- class Reporter < WorkerThread
13
+ class Reporter < WorkerThread # rubocop:disable Metrics/ClassLength
14
14
  include Contrast::Components::Logger::InstanceMethods
15
15
  include Contrast::Utils::ObjectShare
16
16
 
17
+ # How many tries to reconnect the Reporter should make.
18
+ RETRY_ATTEMPTS = 10
17
19
  MAX_QUEUE_SIZE = 1000
18
20
 
19
21
  class << self
@@ -35,13 +37,17 @@ module Contrast
35
37
  end
36
38
 
37
39
  def start_thread!
40
+ return unless attempt_to_start?
38
41
  return if running?
39
42
 
43
+ @connection_attempts = 0
44
+
40
45
  client.startup!(connection)
41
46
  @_thread = Contrast::Agent::Thread.new do
42
47
  logger.debug('[Reporter] Starting background Reporter thread.')
43
48
  loop do
44
49
  next unless connected?
50
+ break unless attempt_to_start?
45
51
 
46
52
  process_event(queue.pop)
47
53
  rescue StandardError => e
@@ -124,10 +130,19 @@ module Contrast
124
130
  #
125
131
  # @return [Boolean]
126
132
  def connected?
127
- return true if client && connection
133
+ if client && connection
134
+ # Try to resend startup messages now with connection:
135
+ client.startup!(connection) unless client.status.startup_messages_sent?
136
+ return true
137
+ end
128
138
 
129
- logger.debug('[Reporter] No client/connection; sleeping...', client: client, connection: connection)
130
- sleep(5)
139
+ logger.debug('[Reporter] No client/connection; sleeping...')
140
+ @connection_attempts += 1
141
+ if @connection_attempts >= RETRY_ATTEMPTS
142
+ logger.debug('[Reporter] shutting down..')
143
+ Contrast::AGENT.disable!
144
+ end
145
+ sleep(5) unless Contrast::AGENT.disabled?
131
146
  false
132
147
  end
133
148
 
@@ -0,0 +1,32 @@
1
+ # Copyright (c) 2023 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/reporting_events/reporting_event'
5
+ require 'contrast/config'
6
+
7
+ module Contrast
8
+ module Agent
9
+ module Reporting
10
+ # AgentStartup Event which sends the agent data to TeamServer on the startup of a server or process,
11
+ # used to create a new Server entity there.
12
+ class AgentEffectiveConfig < Contrast::Agent::Reporting::ReportingEvent
13
+ # @param diagnostics [Contrast::Agent::DiagnosticsConfig::Diagnostics] current diagnostics
14
+ def initialize diagnostics
15
+ @event_method = :PUT
16
+ @event_endpoint = Contrast::Agent::Reporting::Endpoints.effective_config
17
+ @event_type = :effective_config
18
+ @diagnostics = diagnostics
19
+ super()
20
+ end
21
+
22
+ def file_name
23
+ 'agent-effective-config'
24
+ end
25
+
26
+ def to_controlled_hash
27
+ @diagnostics.to_controlled_hash
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -83,6 +83,13 @@ module Contrast
83
83
  end
84
84
  end
85
85
 
86
+ # @return [String, nil]
87
+ def effective_config
88
+ with_rescue do
89
+ "#{ application_endpoint }/effective-config".cs__freeze
90
+ end
91
+ end
92
+
86
93
  private
87
94
 
88
95
  # Returns the URL needed to connect to endpoints in TeamServer required for application related information.
@@ -11,7 +11,7 @@ module Contrast
11
11
  # This class will build the required headers for agent reporting to TS
12
12
  class Headers
13
13
  attr_reader :app_name, :api_key, :agent_version, :app_language, :app_path, :app_version, :authorization,
14
- :server_name, :server_path, :server_type, :content_type, :encoding, :compression
14
+ :server_name, :server_path, :server_type, :content_type, :encoding, :compression, :session_id
15
15
 
16
16
  include Contrast::Utils::ObjectShare
17
17
  ENCODING = 'base64'
@@ -29,6 +29,7 @@ module Contrast
29
29
  @server_name = Base64.strict_encode64(Contrast::APP_CONTEXT.server_name)
30
30
  @server_path = Base64.strict_encode64(Contrast::APP_CONTEXT.server_path)
31
31
  @server_type = Base64.strict_encode64(Contrast::APP_CONTEXT.server_type)
32
+ @session_id = Contrast::CONFIG.session_id
32
33
  @content_type = CONTENT_TYPE
33
34
  @encoding = ENCODING
34
35
  @compression = COMPRESSION
@@ -46,6 +47,7 @@ module Contrast
46
47
  server_name: @server_name,
47
48
  server_path: @server_path,
48
49
  server_type: @server_type,
50
+ 'Session-ID': @session_id,
49
51
  content_type: @content_type,
50
52
  encoding: @encoding,
51
53
  compression: @compression
@@ -5,14 +5,15 @@ require 'json'
5
5
  require 'net/http'
6
6
  require 'contrast/components/logger'
7
7
  require 'contrast/utils/net_http_base'
8
+ require 'contrast/config/diagnostics/monitor'
8
9
  require 'contrast/agent/reporting/connection_status'
9
- require 'contrast/agent/reporting/reporting_utilities/response_handler'
10
- require 'contrast/agent/reporting/reporting_utilities/reporter_client_utils'
11
- require 'contrast/agent/reporting/reporting_utilities/endpoints'
12
10
  require 'contrast/agent/reporting/reporting_utilities/headers'
11
+ require 'contrast/agent/reporting/reporting_utilities/endpoints'
13
12
  require 'contrast/agent/reporting/reporting_events/server_settings'
13
+ require 'contrast/agent/reporting/reporting_utilities/response_handler'
14
14
  require 'contrast/agent/reporting/reporting_events/application_settings'
15
- require 'contrast/config/diagnostics'
15
+ require 'contrast/agent/reporting/reporting_events/agent_effective_config'
16
+ require 'contrast/agent/reporting/reporting_utilities/reporter_client_utils'
16
17
 
17
18
  module Contrast
18
19
  module Agent
@@ -57,6 +58,7 @@ module Contrast
57
58
  # @param connection [Net::HTTP] open connection
58
59
  def startup! connection
59
60
  return if status.startup_messages_sent?
61
+ return unless connection
60
62
 
61
63
  send_agent_startup(connection)
62
64
  end
@@ -76,7 +78,7 @@ module Contrast
76
78
  response = connection.request(request)
77
79
  audit&.audit_event(event, response) if ::Contrast::API.request_audit_enable
78
80
  process_settings_response(response, event)
79
- record_configuration(response, event)
81
+ report_configuration(response, event)
80
82
  process_preflight_response(event, response, connection)
81
83
  response
82
84
  rescue StandardError => e
@@ -90,7 +92,7 @@ module Contrast
90
92
  #
91
93
  # @param response [Contrast::Agent::Reporting::Response, nil]
92
94
  # @param event [Contrast::Agent::Reporting::ReportingEvent]
93
- def record_configuration response, event
95
+ def report_configuration response, event
94
96
  return unless response
95
97
 
96
98
  diagnostics.config.determine_config_status(response_handler.last_response_code || response.code)
@@ -99,6 +101,8 @@ module Contrast
99
101
 
100
102
  logger.info('[Reporter Diagnostics] last response code:', response_code: response_handler.last_response_code)
101
103
  diagnostics.write_to_file
104
+ config_event = Contrast::Agent::Reporting::AgentEffectiveConfig.new(diagnostics)
105
+ Contrast::Agent.reporter.send_event(config_event)
102
106
  end
103
107
 
104
108
  def status
@@ -110,7 +114,7 @@ module Contrast
110
114
  end
111
115
 
112
116
  def diagnostics
113
- @_diagnostics ||= Contrast::Agent::DiagnosticsConfig::Diagnostics.new(Contrast::LOGGER.path)
117
+ @_diagnostics ||= Contrast::Config::Diagnostics::Monitor.new(Contrast::LOGGER.path)
114
118
  end
115
119
 
116
120
  def sleep?
@@ -53,19 +53,15 @@ module Contrast
53
53
  # @param request [Net::HTTPRequest]
54
54
  # @return [Net::HTTPRequest]
55
55
  def build_headers request
56
- app_version = @headers.app_version
57
- request['API-Key'] = @headers.api_key
58
- request['Application-Language'] = @headers.app_language
59
- request['Application-Name'] = @headers.app_name
60
- request['Application-Path'] = @headers.app_path
61
- request['Application-Version'] = app_version if app_version
56
+ build_application_headers(request)
57
+ build_encode_and_compress_headers(request)
62
58
  request['Authorization'] = @headers.authorization
63
59
  request['Server-Name'] = @headers.server_name
64
60
  request['Server-Path'] = @headers.server_path
65
61
  request['Server-Type'] = @headers.server_type
66
62
  request['X-Contrast-Agent'] = @headers.agent_version
67
63
  request['X-Contrast-Header-Encoding'] = @headers.encoding
68
- build_encode_and_compress_headers(request)
64
+ request['Session-ID'] = @headers.session_id
69
65
  request
70
66
  end
71
67
 
@@ -155,6 +151,18 @@ module Contrast
155
151
  request['X-Contrast-Encoding'] = @headers.compression
156
152
  request['Content-Encoding'] = @headers.compression
157
153
  end
154
+
155
+ # Adds corresponding application headers to request.
156
+ #
157
+ # @param request [Net::HTTPRequest]
158
+ def build_application_headers request
159
+ app_version = @headers.app_version
160
+ request['API-Key'] = @headers.api_key
161
+ request['Application-Language'] = @headers.app_language
162
+ request['Application-Name'] = @headers.app_name
163
+ request['Application-Path'] = @headers.app_path
164
+ request['Application-Version'] = app_version if app_version
165
+ end
158
166
  end
159
167
  end
160
168
  end
@@ -4,6 +4,7 @@
4
4
  require 'contrast/agent/reporting/reporting_utilities/ng_response_extractor'
5
5
  require 'contrast/agent/reporting/reporting_utilities/response_extractor'
6
6
  require 'contrast/agent/reactions/disable_reaction'
7
+ require 'contrast/utils/json'
7
8
 
8
9
  module Contrast
9
10
  module Agent
@@ -257,7 +258,7 @@ module Contrast
257
258
  response_body = response&.body
258
259
  return unless response_body
259
260
 
260
- response_data = JSON.parse(response_body, symbolize_names: true)
261
+ response_data = Contrast::Utils::Json.parse(response_body, deep_symbolize: true)
261
262
  return unless response_data.cs__is_a?(Hash)
262
263
 
263
264
  extract_response_last_modified(response, event)
@@ -13,11 +13,14 @@ module Contrast
13
13
  RESEND_INTERVAL_MS = 30_000.cs__freeze
14
14
 
15
15
  def start_thread!
16
+ return unless attempt_to_start?
16
17
  return if running?
17
18
 
18
19
  @_thread = Contrast::Agent::Thread.new do
19
20
  logger.info('[ApplicationSettingsWorker] Starting thread.', sending_interval: application_server_ms)
20
21
  loop do
22
+ break unless attempt_to_start?
23
+
21
24
  logger.info('[ApplicationSettingsWorker] Fetching Settings', sending_interval: application_server_ms)
22
25
  Contrast::Agent.reporter&.send_event(application_settings_message)
23
26
  sleep(application_server_ms / 1000)
@@ -19,11 +19,14 @@ module Contrast
19
19
  REFRESH_INTERVAL_SEC = 60
20
20
 
21
21
  def start_thread!
22
+ return unless attempt_to_start?
22
23
  return if running?
23
24
 
24
25
  @_thread = Contrast::Agent::Thread.new do
25
26
  logger.info('[Heartbeat] Starting thread.')
26
27
  loop do
28
+ break unless attempt_to_start?
29
+
27
30
  polling_events.each do |event|
28
31
  Contrast::Agent.reporter&.send_event(event)
29
32
  end
@@ -13,11 +13,14 @@ module Contrast
13
13
  RESEND_INTERVAL_MS = 60_000.cs__freeze
14
14
 
15
15
  def start_thread!
16
+ return unless attempt_to_start?
16
17
  return if running?
17
18
 
18
19
  @_thread = Contrast::Agent::Thread.new do
19
20
  logger.info('[ServerSettingsWorker] Starting thread.', sending_interval: server_settings_resend_ms)
20
21
  loop do
22
+ break unless attempt_to_start?
23
+
21
24
  logger.info('[ServerSettingsWorker] Fetching Settings', sending_interval: server_settings_resend_ms)
22
25
  Contrast::Agent.reporter&.send_event(settings_message)
23
26
  sleep(server_settings_resend_ms / 1000)
@@ -46,6 +46,39 @@ module Contrast
46
46
  @enabled
47
47
  end
48
48
 
49
+ # In case of connection error, do not create the background thread or queue,
50
+ # as if the opt-out env var was set.
51
+ #
52
+ # @return [Boolean]
53
+ def ip_opt_out?
54
+ @_ip_opt_out ||= begin
55
+ test_conn = Contrast::Agent::Telemetry::Client.new.initialize_connection(URL)
56
+
57
+ if test_conn.nil? || Contrast::Utils::NetHttpBase.last_error
58
+ # log if error:
59
+ if defined?(Contrast) && defined?(Contrast::CONFIG) && defined?(Contrast::CONFIG)
60
+ Contrast::CONFIG.proto_logger.warn('[Telemetry] connection error disabling...',
61
+ error: Contrast::Utils::NetHttpBase.last_error)
62
+
63
+ end
64
+ # Disable telemetry:
65
+ @enabled = false
66
+ true
67
+ else
68
+ # Close the connection
69
+ test_conn.finish if test_conn.started?
70
+ false
71
+ end
72
+ end
73
+ rescue StandardError
74
+ @enabled = false
75
+ true
76
+ end
77
+
78
+ def disable!
79
+ @enabled = false
80
+ end
81
+
49
82
  private
50
83
 
51
84
  def telemetry_enabled?
@@ -56,15 +89,7 @@ module Contrast
56
89
 
57
90
  # In case of connection error, do not create the background thread or queue,
58
91
  # as if the opt-out env var was set
59
- @_client = Contrast::Agent::Telemetry::Client.new
60
- ip_opt_out_telemetry = @_client.initialize_connection(URL)
61
- if ip_opt_out_telemetry.nil?
62
- # TODO: RUBY-2033 we cannot log the error above debug level here b/c it results in
63
- # an infinite loop w/ telemetry
64
- logger.debug("[Telemetry] Connection was not established properly!!! \n
65
- Telemetry reporting will be disabled!")
66
- return false
67
- end
92
+ return false if ip_opt_out?
68
93
 
69
94
  true
70
95
  end
@@ -91,6 +116,7 @@ module Contrast
91
116
  end
92
117
 
93
118
  def start_thread!
119
+ return unless attempt_to_start?
94
120
  return if running?
95
121
 
96
122
  logger.debug('[Telemetry] Starting background telemetry thread.')
@@ -140,6 +166,7 @@ module Contrast
140
166
  Contrast::Agent::Thread.new do
141
167
  loop do
142
168
  next unless client && connection
169
+ break unless attempt_to_start?
143
170
 
144
171
  # Start pushing exceptions to queue for reporting.
145
172
  Contrast::TELEMETRY_EXCEPTIONS.each_value { |value| queue << value }
@@ -155,9 +182,7 @@ module Contrast
155
182
  sleep(retry_sleep_time) unless retry_sleep_time.nil?
156
183
  end
157
184
  rescue StandardError => e
158
- # TODO: RUBY-2033 we cannot log the error above debug level here b/c it results in
159
- # an infinite loop w/ telemetry
160
- logger.debug('[Telemetry] Could not send message to service from telemetry queue.', e)
185
+ logger.error('[Telemetry] Could not send message to service from telemetry queue.', e)
161
186
  stop!
162
187
  end
163
188
  end
@@ -100,9 +100,7 @@ module Contrast
100
100
  def get_event_json event
101
101
  Array(event.to_controlled_hash).to_json
102
102
  rescue Exception => e # rubocop:disable Lint/RescueException
103
- # TODO: RUBY-2033 we cannot log the error above debug level here b/c it results in
104
- # an infinite loop w/ telemetry
105
- logger.debug('[Telemetry] Unable to convert TelemetryEvent to JSON string', e, hsh)
103
+ logger.error('[Telemetry] Unable to convert TelemetryEvent to JSON string', e, hsh)
106
104
  raise(e)
107
105
  end
108
106
  end
@@ -92,13 +92,6 @@ module Contrast
92
92
  #
93
93
  # @return [Boolean]
94
94
  def telemetry_exceptions_enabled?
95
- opts_out_telemetry = return_value(:telemetry_opt_outs).to_s
96
- return false if opts_out_telemetry.casecmp?('true') || opts_out_telemetry == '1'
97
- # Double check if telemetry is enabled, this includes a check for Agent enable setting in the
98
- # config. In case of disabled Agent the queue won't be created and the Telemetry would not
99
- # be enabled. This check is here to prevent a loop of error creations that could no be added
100
- # to a queue ( because the client cannot be initialized if the Agent is disabled or settings are
101
- # missing).
102
95
  return false unless Contrast::Agent::Telemetry::Base.enabled?
103
96
 
104
97
  true
@@ -6,7 +6,7 @@ require 'contrast/agent/reporting/report'
6
6
  require 'contrast/agent/reporting/reporting_workers/reporting_workers'
7
7
  require 'contrast/agent/telemetry/base'
8
8
  require 'contrast/agent/protect/input_analyzer/worth_watching_analyzer'
9
- require 'contrast/config/diagnostics'
9
+ require 'contrast/config/diagnostics/monitor'
10
10
  require 'contrast/utils/job_servers_running'
11
11
 
12
12
  module Contrast
@@ -114,7 +114,7 @@ module Contrast
114
114
  def check_before_start
115
115
  return if Contrast::CONFIG.send(:validate)
116
116
 
117
- @_diagnostics = Contrast::Agent::DiagnosticsConfig::Diagnostics.new(Contrast::AGENT.logger.path ||
117
+ @_diagnostics = Contrast::Config::Diagnostics::Monitor.new(Contrast::AGENT.logger.path ||
118
118
  Contrast::Components::Config::CONTRAST_LOG)
119
119
  @_diagnostics.config.populate_fail_connection
120
120
  @_diagnostics.write_to_file_logic(false, reset: false)
@@ -3,6 +3,6 @@
3
3
 
4
4
  module Contrast
5
5
  module Agent
6
- VERSION = '7.0.0'
6
+ VERSION = '7.1.0'
7
7
  end
8
8
  end
@@ -137,7 +137,7 @@ module Contrast
137
137
  # Converts current configuration to effective config values class and appends them to
138
138
  # EffectiveConfig class.
139
139
  #
140
- # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
140
+ # @param effective_config [Contrast::Config::Diagnostics::EffectiveConfig]
141
141
  def to_effective_config effective_config
142
142
  super
143
143
  logger&.to_effective_config(effective_config)
@@ -127,7 +127,7 @@ module Contrast
127
127
  # Converts current configuration to effective config values class and appends them to
128
128
  # EffectiveConfig class.
129
129
  #
130
- # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
130
+ # @param effective_config [Contrast::Config::Diagnostics::EffectiveConfig]
131
131
  def to_effective_config effective_config
132
132
  add_effective_config_values(effective_config, CONFIG_VALUES, CANON_NAME, CONTRAST)
133
133
  effective_proxy(effective_config)
@@ -137,7 +137,7 @@ module Contrast
137
137
 
138
138
  private
139
139
 
140
- # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
140
+ # @param effective_config [Contrast::Config::Diagnostics::EffectiveConfig]
141
141
  def effective_proxy effective_config
142
142
  add_single_effective_value(effective_config, ENABLE, proxy_enable.to_s, PROXY_NAME, "#{ CONTRAST }.proxy")
143
143
  return unless proxy_url && proxy_enable
@@ -161,7 +161,7 @@ module Contrast
161
161
  # Converts current configuration to effective config values class and appends them to
162
162
  # EffectiveConfig class.
163
163
  #
164
- # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
164
+ # @param effective_config [Contrast::Config::Diagnostics::EffectiveConfig]
165
165
  def to_effective_config effective_config
166
166
  super
167
167
  Contrast::CONFIG.server.to_effective_config(effective_config)
@@ -218,7 +218,7 @@ module Contrast
218
218
  # Converts current configuration to effective config values class and appends them to
219
219
  # EffectiveConfig class.
220
220
  #
221
- # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
221
+ # @param effective_config [Contrast::Config::Diagnostics::EffectiveConfig]
222
222
  def to_effective_config effective_config
223
223
  super
224
224
  sampling&.to_effective_config(effective_config)
@@ -34,7 +34,7 @@ module Contrast
34
34
  # Converts current configuration to effective config values class and appends them to
35
35
  # EffectiveConfig class.
36
36
  #
37
- # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
37
+ # @param effective_config [Contrast::Config::Diagnostics::EffectiveConfig]
38
38
  def to_effective_config effective_config
39
39
  add_single_effective_value(effective_config, SPEC_KEY.to_s, disabled_rules, canon_name, NAME_PREFIX)
40
40
  end
@@ -1,7 +1,7 @@
1
1
  # Copyright (c) 2023 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'
4
+ require 'contrast/config/diagnostics/tools'
5
5
  require 'contrast/utils/object_share'
6
6
 
7
7
  module Contrast
@@ -9,7 +9,7 @@ module Contrast
9
9
  # All components should inherit from this,
10
10
  # whether Interfaces, InstanceMethods or ClassMethods.
11
11
  module ComponentBase
12
- include Contrast::Agent::DiagnosticsConfig::DiagnosticsTools
12
+ include Contrast::Config::Diagnostics::Tools
13
13
 
14
14
  CONTRAST = 'contrast'
15
15
  ENABLE = 'enable'
@@ -84,7 +84,7 @@ module Contrast
84
84
  # Converts current configuration to effective config values class and appends them to
85
85
  # EffectiveConfig class.
86
86
  #
87
- # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
87
+ # @param effective_config [Contrast::Config::Diagnostics::EffectiveConfig]
88
88
  def to_effective_config effective_config
89
89
  add_effective_config_values(effective_config, config_values, canon_name, "#{ CONTRAST }.#{ canon_name }")
90
90
  end
@@ -11,11 +11,14 @@ module Contrast
11
11
  # This component encapsulates storing the source for each entry in the config,
12
12
  # so that we can report on where the value was set from.
13
13
  class Sources
14
- ENVIRONMENT = 'ENV'
15
- CLI = 'CLI'
16
- CONTRASTUI = 'ContrastUI'
17
- DEFAULT = 'Default'
18
- YAML = 'YAML'
14
+ ENVIRONMENT_VARIABLE = 'ENV'
15
+ COMMAND_LINE = 'CLI'
16
+ CONTRAST_UI = 'ContrastUI'
17
+ DEFAULT_VALUE = 'Default'
18
+ # Order matters for the Configurations files. This is read when Agent starts up and will always go
19
+ # through the YAML as priority.
20
+ # Do not change the order!
21
+ APP_CONFIGURATION_FILE = %w[YAML YML].cs__freeze
19
22
 
20
23
  # @return [Hash]
21
24
  attr_reader :data
@@ -30,15 +33,15 @@ module Contrast
30
33
  # @param path [String] the canonical name for the config entry (such as api.proxy.enable)
31
34
  # @return [String] the source for the entry
32
35
  def get path
33
- data.dig(*parts_for(path)) || DEFAULT
36
+ data.dig(*parts_for(path)) || DEFAULT_VALUE
34
37
  rescue TypeError
35
- DEFAULT
38
+ DEFAULT_VALUE
36
39
  end
37
40
 
38
41
  # Assigns the config source for a specified config path.
39
42
  #
40
43
  # @param path [String] the canonical name for the config entry (such as api.proxy.enable)
41
- # @param [String] the source for the entry
44
+ # @param source[String] the source for the entry
42
45
  # @return [String] the source type for the entry
43
46
  def set path, source
44
47
  assign_value(data, parts_for(path), source)
@@ -64,7 +67,7 @@ module Contrast
64
67
  # @param current_level [Hash] all, or some of, the config source information
65
68
  # @param parts [Array] the parts for canonical name of the config entry
66
69
  # @param source [String] the source to be set for the specified entry
67
- # @return [Array] the path split on periods, and converted to symbols
70
+ # @return [String] the path split on periods, and converted to symbols
68
71
  def assign_value current_level, parts, source
69
72
  parts[0...-1].each do |segment|
70
73
  current_level[segment] ||= {}