contrast-agent 6.15.3 → 7.1.0

Sign up to get free protection for your applications and to get access to all the features.
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