contrast-agent 6.15.3 → 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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/ext/cs__assess_fiber_track/cs__assess_fiber_track.c +1 -1
  3. data/ext/cs__assess_fiber_track/cs__assess_fiber_track.h +1 -1
  4. data/ext/cs__assess_module/cs__assess_module.c +0 -19
  5. data/ext/cs__assess_test/cs__assess_tests.c +1 -1
  6. data/ext/cs__common/cs__common.c +17 -18
  7. data/ext/cs__common/cs__common.h +7 -11
  8. data/ext/cs__contrast_patch/cs__contrast_patch.c +16 -24
  9. data/ext/extconf_common.rb +79 -0
  10. data/lib/contrast/agent/assess/policy/policy.rb +1 -1
  11. data/lib/contrast/agent/assess/policy/source_method.rb +1 -0
  12. data/lib/contrast/agent/deadzone/policy/policy.rb +1 -1
  13. data/lib/contrast/agent/patching/policy/policy.rb +2 -2
  14. data/lib/contrast/agent/protect/input_analyzer/worth_watching_analyzer.rb +3 -0
  15. data/lib/contrast/agent/protect/rule/no_sqli/no_sqli.rb +1 -1
  16. data/lib/contrast/agent/reporting/reporter.rb +19 -4
  17. data/lib/contrast/agent/reporting/reporting_events/agent_effective_config.rb +32 -0
  18. data/lib/contrast/agent/reporting/reporting_utilities/endpoints.rb +7 -0
  19. data/lib/contrast/agent/reporting/reporting_utilities/headers.rb +3 -1
  20. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +11 -7
  21. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +15 -7
  22. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +4 -2
  23. data/lib/contrast/agent/reporting/reporting_workers/application_server_worker.rb +3 -0
  24. data/lib/contrast/agent/reporting/reporting_workers/reporter_heartbeat.rb +3 -0
  25. data/lib/contrast/agent/reporting/reporting_workers/server_settings_worker.rb +3 -0
  26. data/lib/contrast/agent/telemetry/base.rb +37 -12
  27. data/lib/contrast/agent/telemetry/client.rb +1 -3
  28. data/lib/contrast/agent/telemetry/telemetry.rb +0 -7
  29. data/lib/contrast/agent/thread/thread_watcher.rb +2 -2
  30. data/lib/contrast/agent/version.rb +1 -1
  31. data/lib/contrast/components/agent.rb +1 -1
  32. data/lib/contrast/components/api.rb +3 -3
  33. data/lib/contrast/components/app_context.rb +1 -1
  34. data/lib/contrast/components/assess.rb +1 -1
  35. data/lib/contrast/components/assess_rules.rb +2 -2
  36. data/lib/contrast/components/base.rb +3 -3
  37. data/lib/contrast/components/config/sources.rb +12 -9
  38. data/lib/contrast/components/config.rb +2 -2
  39. data/lib/contrast/components/protect.rb +2 -2
  40. data/lib/contrast/components/sampling.rb +7 -5
  41. data/lib/contrast/components/settings.rb +1 -1
  42. data/lib/contrast/config/certification_configuration.rb +1 -1
  43. data/lib/contrast/config/configuration_files.rb +47 -0
  44. data/lib/contrast/config/diagnostics/command_line.rb +24 -0
  45. data/lib/contrast/config/{config.rb → diagnostics/config.rb} +21 -6
  46. data/lib/contrast/config/diagnostics/contrast_ui.rb +24 -0
  47. data/lib/contrast/config/diagnostics/effective_config.rb +28 -0
  48. data/lib/contrast/config/diagnostics/effective_config_value.rb +14 -0
  49. data/lib/contrast/config/diagnostics/environment_variables.rb +51 -0
  50. data/lib/contrast/config/{diagnostics.rb → diagnostics/monitor.rb} +10 -10
  51. data/lib/contrast/config/diagnostics/source_config_value.rb +51 -0
  52. data/lib/contrast/config/diagnostics/tools.rb +188 -0
  53. data/lib/contrast/config/diagnostics/user_configuration_file.rb +44 -0
  54. data/lib/contrast/config/request_audit_configuration.rb +1 -1
  55. data/lib/contrast/config/server_configuration.rb +1 -1
  56. data/lib/contrast/configuration.rb +90 -57
  57. data/lib/contrast/utils/hash_utils.rb +43 -0
  58. data/lib/contrast/utils/json.rb +46 -0
  59. data/lib/contrast/utils/middleware_utils.rb +4 -4
  60. data/lib/contrast/utils/net_http_base.rb +75 -26
  61. data/lib/contrast/utils/object_share.rb +3 -3
  62. data/lib/contrast.rb +0 -16
  63. data/ruby-agent.gemspec +4 -8
  64. metadata +40 -25
  65. data/lib/contrast/config/diagnostics_tools.rb +0 -99
  66. data/lib/contrast/config/effective_config.rb +0 -131
  67. data/lib/contrast/config/effective_config_value.rb +0 -32
@@ -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
@@ -32,7 +33,8 @@ module Contrast
32
33
  FORBIDDEN_NO_ACTION_MSG = 'Report access was forbidden because the supplied credentials failed ' \
33
34
  'to authenticate the Agent'
34
35
  UNPROCESSABLE_ENTITY_MSG = 'Reporter received Unprocessable Entity response. Disabling permanently.'
35
- RETRY_AFTER_MSG = "There are too many requests of this type being sent by this Agent. #{ SUSPEND_MSG }"
36
+ RETRY_AFTER_MSG = 'There are too many requests of this type being sent by this Agent. ' \
37
+ "#{ SUSPEND_MSG }".cs__freeze
36
38
 
37
39
  def last_response_code
38
40
  @_last_response_code ||= ''
@@ -256,7 +258,7 @@ module Contrast
256
258
  response_body = response&.body
257
259
  return unless response_body
258
260
 
259
- response_data = JSON.parse(response_body, symbolize_names: true)
261
+ response_data = Contrast::Utils::Json.parse(response_body, deep_symbolize: true)
260
262
  return unless response_data.cs__is_a?(Hash)
261
263
 
262
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 = '6.15.3'
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)
@@ -18,7 +18,7 @@ module Contrast
18
18
  include Contrast::Config::BaseConfiguration
19
19
 
20
20
  CANON_NAME = 'api'
21
- PROXY_NAME = "#{ CANON_NAME }.proxy"
21
+ PROXY_NAME = "#{ CANON_NAME }.proxy".cs__freeze
22
22
  CONFIG_VALUES = %w[api_key user_name service_key url].cs__freeze
23
23
 
24
24
  # @return [String]
@@ -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)
@@ -16,7 +16,7 @@ module Contrast
16
16
 
17
17
  SPEC_KEY = :disabled_rules.cs__freeze
18
18
  CANON_NAME = 'assess.rules'
19
- NAME_PREFIX = "#{ CONTRAST }.#{ CANON_NAME }"
19
+ NAME_PREFIX = "#{ CONTRAST }.#{ CANON_NAME }".cs__freeze
20
20
 
21
21
  # @return [Array, nil] list of disabled assess rules
22
22
  attr_accessor :disabled_rules
@@ -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] ||= {}
@@ -4,7 +4,7 @@
4
4
  require 'contrast/utils/env_configuration_item'
5
5
  require 'ougai'
6
6
  require 'contrast/configuration'
7
- require 'contrast/config/diagnostics'
7
+ require 'contrast/config/diagnostics/monitor'
8
8
 
9
9
  module Contrast
10
10
  module Components
@@ -249,7 +249,7 @@ module Contrast
249
249
  return unless current_level.nil? == false && current_level.cs__respond_to?(dot_path_array[-1])
250
250
 
251
251
  current_level.send("#{ dot_path_array[-1] }=", value)
252
- sources.set(dot_path_array.join('.'), Contrast::Components::Config::Sources::ENVIRONMENT)
252
+ sources.set(dot_path_array.join('.'), Contrast::Components::Config::Sources::ENVIRONMENT_VARIABLE)
253
253
  end
254
254
  end
255
255
  end
@@ -130,7 +130,7 @@ module Contrast
130
130
  # Converts current configuration to effective config values class and appends them to
131
131
  # EffectiveConfig class.
132
132
  #
133
- # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
133
+ # @param effective_config [Contrast::Config::Diagnostics::EffectiveConfig]
134
134
  def to_effective_config effective_config
135
135
  super
136
136
  protect_rules_to_effective_config(effective_config)
@@ -138,7 +138,7 @@ module Contrast
138
138
 
139
139
  private
140
140
 
141
- # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
141
+ # @param effective_config [Contrast::Config::Diagnostics::EffectiveConfig]
142
142
  def protect_rules_to_effective_config effective_config
143
143
  return unless defend_rules
144
144
 
@@ -103,7 +103,7 @@ module Contrast
103
103
  include Contrast::Config::BaseConfiguration
104
104
 
105
105
  CANON_NAME = 'assess.sampling'
106
- NAME_PREFIX = "#{ CONTRAST }.#{ CANON_NAME }"
106
+ NAME_PREFIX = "#{ CONTRAST }.#{ CANON_NAME }".cs__freeze
107
107
  CONFIG_VALUES = %w[enable baseline request_frequency response_frequency window_ms].cs__freeze
108
108
 
109
109
  # @return [Integer, nil]
@@ -136,7 +136,7 @@ module Contrast
136
136
  # Converts current configuration to effective config values class and appends them to
137
137
  # EffectiveConfig class.
138
138
  #
139
- # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
139
+ # @param effective_config [Contrast::Config::Diagnostics::EffectiveConfig]
140
140
  def to_effective_config effective_config
141
141
  confirm_sources
142
142
 
@@ -161,10 +161,11 @@ module Contrast
161
161
  # back to the default values.
162
162
  def confirm_sources
163
163
  if sampling_control[:enabled] == DEFAULT_SAMPLING_ENABLED
164
- Contrast::CONFIG.sources.set('assess.sampling.enable', Contrast::Components::Config::Sources::DEFAULT)
164
+ Contrast::CONFIG.sources.set('assess.sampling.enable', Contrast::Components::Config::Sources::DEFAULT_VALUE)
165
165
  end
166
166
  if sampling_control[:window] == DEFAULT_SAMPLING_WINDOW_MS
167
- Contrast::CONFIG.sources.set('assess.sampling.window_ms', Contrast::Components::Config::Sources::DEFAULT)
167
+ Contrast::CONFIG.sources.set('assess.sampling.window_ms',
168
+ Contrast::Components::Config::Sources::DEFAULT_VALUE)
168
169
  end
169
170
  {
170
171
  'baseline' => :baseline,
@@ -172,7 +173,8 @@ module Contrast
172
173
  'response_frequency' => :response_frequency
173
174
  }.each do |k, v|
174
175
  if sampling_control[v] == cs__class.cs__const_get("DEFAULT_SAMPLING_#{ v.upcase }")
175
- Contrast::CONFIG.sources.set("assess.sampling.#{ k }", Contrast::Components::Config::Sources::DEFAULT)
176
+ Contrast::CONFIG.sources.set("assess.sampling.#{ k }",
177
+ Contrast::Components::Config::Sources::DEFAULT_VALUE)
176
178
  end
177
179
  end
178
180
  end
@@ -283,7 +283,7 @@ module Contrast
283
283
  return unless level.cs__is_a?(Hash)
284
284
 
285
285
  level[parts[-1]] = value
286
- Contrast::CONFIG.sources.set(parts.join('.'), Contrast::Components::Config::Sources::CONTRASTUI)
286
+ Contrast::CONFIG.sources.set(parts.join('.'), Contrast::Components::Config::Sources::CONTRAST_UI)
287
287
  end
288
288
  end
289
289
  end
@@ -38,7 +38,7 @@ module Contrast
38
38
  # Converts current configuration to effective config values class and appends them to
39
39
  # EffectiveConfig class.
40
40
  #
41
- # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
41
+ # @param effective_config [Contrast::Config::Diagnostics::EffectiveConfig]
42
42
  def to_effective_config effective_config
43
43
  add_effective_config_values(effective_config, CONFIG_VALUES, CANON_NAME, CONTRAST)
44
44
  end
@@ -0,0 +1,47 @@
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/utils/duck_utils'
5
+ require 'contrast/utils/object_share'
6
+ require 'contrast/components/config/sources'
7
+ require 'contrast/config/diagnostics/tools'
8
+
9
+ module Contrast
10
+ module Config
11
+ # This class will hold all the references for the configuration files. It will safe read values used to
12
+ # identify the source of configuration in Configuration Diagnostics reported to TS.
13
+ class ConfigurationFiles
14
+ # @return [String] path of the main configuration file.
15
+ attr_accessor :main_file
16
+
17
+ # @return [Array<Contrast::Config::LocalSourceValue>]
18
+ def source_files
19
+ @_source_files ||= []
20
+ end
21
+
22
+ # @param path [String]
23
+ # @param values [Hash]
24
+ def add_source_file path, values
25
+ source_files << Contrast::Config::LocalSourceValue.new(path, values)
26
+ @main_file = path if source_files.length == 1
27
+ end
28
+ end
29
+
30
+ # This class will hold all the info about the read file.
31
+ class LocalSourceValue
32
+ YML_EXT = '.yml'
33
+ YAML_EXT = '.yaml'
34
+ # @return [String]
35
+ attr_reader :path
36
+ # @return [Hash]
37
+ attr_reader :values
38
+
39
+ # @param path [String]
40
+ # @param values [Hash]
41
+ def initialize path = '', values = {}
42
+ @path = path unless Contrast::Utils::DuckUtils.empty_duck?(path)
43
+ @values = values
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,24 @@
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/config/diagnostics/effective_config_value'
5
+ require 'contrast/config/diagnostics/tools'
6
+ require 'contrast/utils/object_share'
7
+
8
+ module Contrast
9
+ module Config
10
+ module Diagnostics
11
+ # Reads All ENV variables.
12
+ module CommandLine
13
+ class << self
14
+ def command_line_settings
15
+ cli = Contrast::Config::Diagnostics::Tools.flatten_settings(Contrast::CONFIG.sources.
16
+ for(Contrast::Components::Config::Sources::COMMAND_LINE))
17
+
18
+ Contrast::Config::Diagnostics::Tools.to_config_values(cli, source: true)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end