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.
- checksums.yaml +4 -4
- data/lib/contrast/agent/assess/policy/policy.rb +1 -1
- data/lib/contrast/agent/deadzone/policy/policy.rb +1 -1
- data/lib/contrast/agent/patching/policy/policy.rb +2 -2
- data/lib/contrast/agent/protect/input_analyzer/worth_watching_analyzer.rb +3 -0
- data/lib/contrast/agent/protect/rule/no_sqli/no_sqli.rb +1 -1
- data/lib/contrast/agent/reporting/reporter.rb +19 -4
- data/lib/contrast/agent/reporting/reporting_events/agent_effective_config.rb +32 -0
- data/lib/contrast/agent/reporting/reporting_utilities/endpoints.rb +7 -0
- data/lib/contrast/agent/reporting/reporting_utilities/headers.rb +3 -1
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +11 -7
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +15 -7
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +2 -1
- data/lib/contrast/agent/reporting/reporting_workers/application_server_worker.rb +3 -0
- data/lib/contrast/agent/reporting/reporting_workers/reporter_heartbeat.rb +3 -0
- data/lib/contrast/agent/reporting/reporting_workers/server_settings_worker.rb +3 -0
- data/lib/contrast/agent/telemetry/base.rb +37 -12
- data/lib/contrast/agent/telemetry/client.rb +1 -3
- data/lib/contrast/agent/telemetry/telemetry.rb +0 -7
- data/lib/contrast/agent/thread/thread_watcher.rb +2 -2
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/components/agent.rb +1 -1
- data/lib/contrast/components/api.rb +2 -2
- data/lib/contrast/components/app_context.rb +1 -1
- data/lib/contrast/components/assess.rb +1 -1
- data/lib/contrast/components/assess_rules.rb +1 -1
- data/lib/contrast/components/base.rb +3 -3
- data/lib/contrast/components/config/sources.rb +12 -9
- data/lib/contrast/components/config.rb +2 -2
- data/lib/contrast/components/protect.rb +2 -2
- data/lib/contrast/components/sampling.rb +6 -4
- data/lib/contrast/components/settings.rb +1 -1
- data/lib/contrast/config/certification_configuration.rb +1 -1
- data/lib/contrast/config/configuration_files.rb +47 -0
- data/lib/contrast/config/diagnostics/command_line.rb +24 -0
- data/lib/contrast/config/{config.rb → diagnostics/config.rb} +21 -6
- data/lib/contrast/config/diagnostics/contrast_ui.rb +24 -0
- data/lib/contrast/config/diagnostics/effective_config.rb +28 -0
- data/lib/contrast/config/diagnostics/effective_config_value.rb +14 -0
- data/lib/contrast/config/diagnostics/environment_variables.rb +51 -0
- data/lib/contrast/config/{diagnostics.rb → diagnostics/monitor.rb} +10 -10
- data/lib/contrast/config/diagnostics/source_config_value.rb +51 -0
- data/lib/contrast/config/diagnostics/tools.rb +188 -0
- data/lib/contrast/config/diagnostics/user_configuration_file.rb +44 -0
- data/lib/contrast/config/request_audit_configuration.rb +1 -1
- data/lib/contrast/config/server_configuration.rb +1 -1
- data/lib/contrast/configuration.rb +90 -57
- data/lib/contrast/utils/hash_utils.rb +43 -0
- data/lib/contrast/utils/json.rb +46 -0
- data/lib/contrast/utils/net_http_base.rb +75 -26
- metadata +16 -7
- data/lib/contrast/config/diagnostics_tools.rb +0 -99
- data/lib/contrast/config/effective_config.rb +0 -131
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 81222798666699f86b31b925d531d2ee2229eb7934582d2a502cc61de3ca4e0b
|
4
|
+
data.tar.gz: 7dd4d41a58600b7d57b5f57cf95c42bd2f6d198f5f1906e93751e33c09efa3e0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 =
|
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)
|
@@ -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 =
|
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
|
|
@@ -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
|
-
|
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...'
|
130
|
-
|
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/
|
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
|
-
|
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
|
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::
|
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
|
-
|
57
|
-
request
|
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
|
-
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
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::
|
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)
|
@@ -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::
|
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::
|
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::
|
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::
|
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::
|
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::
|
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/
|
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::
|
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::
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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)) ||
|
36
|
+
data.dig(*parts_for(path)) || DEFAULT_VALUE
|
34
37
|
rescue TypeError
|
35
|
-
|
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 [
|
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] ||= {}
|