contrast-agent 5.2.0 → 6.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/cs__assess_array/cs__assess_array.c +7 -0
- data/ext/cs__assess_basic_object/cs__assess_basic_object.c +19 -5
- data/ext/cs__assess_fiber_track/cs__assess_fiber_track.c +1 -1
- data/ext/cs__assess_hash/cs__assess_hash.c +3 -4
- data/ext/cs__assess_kernel/cs__assess_kernel.c +1 -2
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +26 -12
- data/ext/cs__assess_module/cs__assess_module.c +1 -1
- data/ext/cs__assess_regexp/cs__assess_regexp.c +15 -2
- data/ext/cs__assess_regexp/cs__assess_regexp.h +2 -0
- data/ext/cs__assess_string/cs__assess_string.c +21 -1
- data/ext/cs__assess_test/cs__assess_test.h +9 -0
- data/ext/cs__assess_test/cs__assess_tests.c +22 -0
- data/ext/cs__assess_test/extconf.rb +5 -0
- data/ext/cs__common/cs__common.c +113 -11
- data/ext/cs__common/cs__common.h +29 -5
- data/ext/cs__contrast_patch/cs__contrast_patch.c +55 -44
- data/ext/cs__os_information/cs__os_information.c +13 -10
- data/ext/cs__scope/cs__scope.c +146 -97
- data/ext/cs__tests/cs__tests.c +12 -0
- data/ext/cs__tests/cs__tests.h +3 -0
- data/ext/cs__tests/extconf.rb +5 -0
- data/lib/contrast/agent/assess/contrast_object.rb +16 -16
- data/lib/contrast/agent/assess/events/source_event.rb +17 -19
- data/lib/contrast/agent/assess/finalizers/hash.rb +2 -0
- data/lib/contrast/agent/assess/policy/policy_node.rb +50 -27
- data/lib/contrast/agent/assess/policy/policy_node_utils.rb +51 -0
- data/lib/contrast/agent/assess/policy/policy_scanner.rb +2 -16
- data/lib/contrast/agent/assess/policy/preshift.rb +8 -2
- data/lib/contrast/agent/assess/policy/propagation_method.rb +47 -13
- data/lib/contrast/agent/assess/policy/propagator/buffer.rb +118 -0
- data/lib/contrast/agent/assess/policy/propagator/keep.rb +19 -4
- data/lib/contrast/agent/assess/policy/propagator/remove.rb +18 -2
- data/lib/contrast/agent/assess/policy/propagator/splat.rb +17 -3
- data/lib/contrast/agent/assess/policy/propagator/split.rb +15 -19
- data/lib/contrast/agent/assess/policy/propagator/substitution.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/substitution_utils.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/trim.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator.rb +1 -0
- data/lib/contrast/agent/assess/policy/source_method.rb +7 -7
- data/lib/contrast/agent/assess/policy/trigger_method.rb +4 -10
- data/lib/contrast/agent/assess/property/tagged.rb +1 -1
- data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +7 -2
- data/lib/contrast/agent/assess/rule/response/auto_complete_rule.rb +1 -1
- data/lib/contrast/agent/assess/rule/response/base_rule.rb +11 -3
- data/lib/contrast/agent/assess/rule/response/body_rule.rb +3 -3
- data/lib/contrast/agent/assess/rule/response/cache_control_header_rule.rb +60 -36
- data/lib/contrast/agent/assess/rule/response/framework/rails_support.rb +3 -3
- data/lib/contrast/agent/assess/rule/response/parameters_pollution_rule.rb +1 -1
- data/lib/contrast/agent/assess/rule/response/x_xss_protection_header_rule.rb +1 -2
- data/lib/contrast/agent/at_exit_hook.rb +1 -1
- data/lib/contrast/agent/deadzone/policy/deadzone_node.rb +0 -7
- data/lib/contrast/agent/deadzone/policy/policy.rb +0 -6
- data/lib/contrast/agent/exclusion_matcher.rb +3 -3
- data/lib/contrast/agent/inventory/database_config.rb +10 -3
- data/lib/contrast/agent/middleware.rb +5 -3
- data/lib/contrast/agent/patching/policy/after_load_patch.rb +0 -2
- data/lib/contrast/agent/patching/policy/patch.rb +13 -12
- data/lib/contrast/agent/patching/policy/patcher.rb +4 -4
- data/lib/contrast/agent/patching/policy/policy_node.rb +15 -2
- data/lib/contrast/agent/protect/exploitable_collection.rb +38 -0
- data/lib/contrast/agent/protect/input_analyzer/input_analyzer.rb +66 -9
- data/lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb +2 -1
- data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +2 -2
- data/lib/contrast/agent/protect/rule/base.rb +37 -5
- data/lib/contrast/agent/protect/rule/base_service.rb +3 -1
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +13 -0
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_input_classification.rb +83 -0
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_worth_watching.rb +64 -0
- data/lib/contrast/agent/protect/rule/http_method_tampering/http_method_tampering_input_classification.rb +96 -0
- data/lib/contrast/agent/protect/rule/http_method_tampering.rb +8 -0
- data/lib/contrast/agent/protect/rule/no_sqli/no_sqli_input_classification.rb +231 -0
- data/lib/contrast/agent/protect/rule/no_sqli.rb +27 -0
- data/lib/contrast/agent/protect/rule/sqli/sqli_input_classification.rb +18 -54
- data/lib/contrast/agent/protect/rule/sqli/sqli_worth_watching.rb +1 -4
- data/lib/contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_input_classification.rb +82 -0
- data/lib/contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_matcher.rb +45 -0
- data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +42 -0
- data/lib/contrast/agent/reporting/attack_result/attack_result.rb +63 -0
- data/lib/contrast/agent/reporting/attack_result/rasp_rule_sample.rb +52 -0
- data/lib/contrast/agent/reporting/attack_result/response_type.rb +29 -0
- data/lib/contrast/agent/reporting/attack_result/user_input.rb +87 -0
- data/lib/contrast/agent/reporting/masker/masker.rb +243 -0
- data/lib/contrast/agent/reporting/masker/masker_utils.rb +62 -0
- data/lib/contrast/agent/reporting/report.rb +2 -0
- data/lib/contrast/agent/reporting/reporter.rb +29 -22
- data/lib/contrast/agent/reporting/reporter_heartbeat.rb +49 -0
- data/lib/contrast/agent/reporting/reporting_events/agent_startup.rb +34 -0
- data/lib/contrast/agent/reporting/reporting_events/application_activity.rb +53 -0
- data/lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb +48 -0
- data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_activity.rb +64 -0
- data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample.rb +70 -0
- data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample_activity.rb +57 -0
- data/lib/contrast/agent/reporting/reporting_events/application_defend_attacker_activity.rb +56 -0
- data/lib/contrast/agent/reporting/reporting_events/application_inventory.rb +12 -4
- data/lib/contrast/agent/reporting/reporting_events/application_inventory_activity.rb +58 -0
- data/lib/contrast/agent/reporting/reporting_events/application_reporting_event.rb +27 -0
- data/lib/contrast/agent/reporting/reporting_events/application_startup.rb +50 -0
- data/lib/contrast/agent/reporting/reporting_events/application_startup_instrumentation.rb +27 -0
- data/lib/contrast/agent/reporting/reporting_events/application_update.rb +7 -12
- data/lib/contrast/agent/reporting/reporting_events/finding.rb +10 -4
- data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +2 -4
- data/lib/contrast/agent/reporting/reporting_events/finding_event_object.rb +3 -3
- data/lib/contrast/agent/reporting/reporting_events/library_usage_observation.rb +5 -5
- data/lib/contrast/agent/reporting/reporting_events/observed_library_usage.rb +6 -2
- data/lib/contrast/agent/reporting/reporting_events/observed_route.rb +16 -12
- data/lib/contrast/agent/reporting/reporting_events/poll.rb +6 -2
- data/lib/contrast/agent/reporting/reporting_events/preflight.rb +10 -8
- data/lib/contrast/agent/reporting/reporting_events/preflight_message.rb +8 -11
- data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +2 -1
- data/lib/contrast/agent/reporting/reporting_events/route_coverage.rb +8 -6
- data/lib/contrast/agent/reporting/reporting_events/server_activity.rb +12 -20
- data/lib/contrast/agent/reporting/reporting_events/server_reporting_event.rb +27 -0
- data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +17 -27
- data/lib/contrast/agent/reporting/reporting_utilities/build_preflight.rb +38 -0
- data/lib/contrast/agent/reporting/reporting_utilities/dtm_message.rb +8 -0
- data/lib/contrast/agent/reporting/reporting_utilities/endpoints.rb +6 -0
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +23 -7
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +64 -76
- data/lib/contrast/agent/reporting/reporting_utilities/reporting_storage.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_utilities/response.rb +17 -7
- data/lib/contrast/agent/reporting/reporting_utilities/response_extractor.rb +100 -0
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +75 -13
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_mode.rb +63 -0
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +154 -113
- data/lib/contrast/agent/reporting/settings/application_settings.rb +9 -0
- data/lib/contrast/agent/reporting/settings/assess_server_feature.rb +5 -33
- data/lib/contrast/agent/reporting/settings/protect.rb +1 -1
- data/lib/contrast/agent/reporting/settings/protect_server_feature.rb +2 -2
- data/lib/contrast/agent/reporting/settings/sampling.rb +36 -0
- data/lib/contrast/agent/reporting/settings/sensitive_data_masking.rb +110 -0
- data/lib/contrast/agent/reporting/settings/sensitive_data_masking_rule.rb +58 -0
- data/lib/contrast/agent/request.rb +3 -3
- data/lib/contrast/agent/request_context.rb +1 -1
- data/lib/contrast/agent/request_context_extend.rb +2 -2
- data/lib/contrast/agent/request_handler.rb +7 -3
- data/lib/contrast/agent/response.rb +2 -0
- data/lib/contrast/agent/service_heartbeat.rb +6 -48
- data/lib/contrast/agent/static_analysis.rb +1 -1
- data/lib/contrast/agent/telemetry/base.rb +151 -0
- data/lib/contrast/agent/telemetry/events/event.rb +35 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_base.rb +59 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_event.rb +44 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_message.rb +115 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_message_exception.rb +83 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_stack_frame.rb +64 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exceptions.rb +20 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exceptions_report.rb +32 -0
- data/lib/contrast/agent/telemetry/events/metric_event.rb +28 -0
- data/lib/contrast/agent/telemetry/events/startup_metrics_event.rb +123 -0
- data/lib/contrast/agent/thread_watcher.rb +52 -68
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/agent/worker_thread.rb +8 -0
- data/lib/contrast/agent.rb +4 -3
- data/lib/contrast/api/communication/messaging_queue.rb +28 -11
- data/lib/contrast/api/communication/response_processor.rb +7 -10
- data/lib/contrast/api/communication/speedracer.rb +1 -1
- data/lib/contrast/api/decorators/activity.rb +33 -0
- data/lib/contrast/api/decorators/address.rb +1 -1
- data/lib/contrast/api/decorators/http_request.rb +1 -1
- data/lib/contrast/api/decorators/response_type.rb +30 -0
- data/lib/contrast/api/decorators.rb +1 -0
- data/lib/contrast/components/app_context.rb +0 -4
- data/lib/contrast/components/assess.rb +14 -0
- data/lib/contrast/components/config.rb +13 -22
- data/lib/contrast/components/contrast_service.rb +9 -0
- data/lib/contrast/components/protect.rb +2 -2
- data/lib/contrast/components/sampling.rb +7 -11
- data/lib/contrast/components/settings.rb +116 -8
- data/lib/contrast/config/agent_configuration.rb +34 -41
- data/lib/contrast/config/api_configuration.rb +16 -75
- data/lib/contrast/config/api_proxy_configuration.rb +9 -48
- data/lib/contrast/config/application_configuration.rb +24 -95
- data/lib/contrast/config/assess_configuration.rb +21 -76
- data/lib/contrast/config/assess_rules_configuration.rb +13 -38
- data/lib/contrast/config/base_configuration.rb +11 -76
- data/lib/contrast/config/certification_configuration.rb +15 -68
- data/lib/contrast/config/exception_configuration.rb +15 -59
- data/lib/contrast/config/heap_dump_configuration.rb +19 -73
- data/lib/contrast/config/inventory_configuration.rb +11 -55
- data/lib/contrast/config/logger_configuration.rb +8 -41
- data/lib/contrast/config/protect_configuration.rb +23 -10
- data/lib/contrast/config/protect_rule_configuration.rb +23 -37
- data/lib/contrast/config/protect_rules_configuration.rb +39 -43
- data/lib/contrast/config/request_audit_configuration.rb +16 -55
- data/lib/contrast/config/root_configuration.rb +70 -13
- data/lib/contrast/config/ruby_configuration.rb +14 -47
- data/lib/contrast/config/sampling_configuration.rb +12 -65
- data/lib/contrast/config/server_configuration.rb +13 -45
- data/lib/contrast/config/service_configuration.rb +36 -17
- data/lib/contrast/configuration.rb +21 -13
- data/lib/contrast/extension/assess/string.rb +20 -1
- data/lib/contrast/extension/module.rb +0 -1
- data/lib/contrast/framework/manager.rb +2 -2
- data/lib/contrast/framework/rails/patch/support.rb +13 -45
- data/lib/contrast/logger/aliased_logging.rb +87 -0
- data/lib/contrast/logger/application.rb +1 -5
- data/lib/contrast/logger/cef_log.rb +1 -1
- data/lib/contrast/tasks/config.rb +100 -4
- data/lib/contrast/utils/assess/object_store.rb +36 -0
- data/lib/contrast/utils/assess/propagation_method_utils.rb +6 -0
- data/lib/contrast/utils/class_util.rb +5 -18
- data/lib/contrast/utils/input_classification.rb +73 -0
- data/lib/contrast/utils/invalid_configuration_util.rb +1 -1
- data/lib/contrast/utils/log_utils.rb +3 -1
- data/lib/contrast/utils/middleware_utils.rb +10 -9
- data/lib/contrast/utils/net_http_base.rb +1 -1
- data/lib/contrast/utils/object_share.rb +2 -1
- data/lib/contrast/utils/os.rb +0 -5
- data/lib/contrast/utils/patching/policy/patch_utils.rb +4 -5
- data/lib/contrast/utils/response_utils.rb +18 -33
- data/lib/contrast/utils/telemetry.rb +20 -2
- data/lib/contrast/utils/telemetry_client.rb +23 -11
- data/lib/contrast/utils/telemetry_hash.rb +41 -0
- data/lib/contrast/utils/telemetry_identifier.rb +16 -1
- data/lib/contrast.rb +9 -0
- data/resources/assess/policy.json +98 -0
- data/resources/deadzone/policy.json +0 -86
- data/ruby-agent.gemspec +10 -9
- data/service_executables/VERSION +1 -1
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
- metadata +98 -30
- data/lib/contrast/agent/metric_telemetry_event.rb +0 -26
- data/lib/contrast/agent/startup_metrics_telemetry_event.rb +0 -121
- data/lib/contrast/agent/telemetry.rb +0 -137
- data/lib/contrast/agent/telemetry_event.rb +0 -33
- data/lib/contrast/utils/exclude_key.rb +0 -20
@@ -0,0 +1,64 @@
|
|
1
|
+
# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative 'telemetry_exception_base'
|
5
|
+
|
6
|
+
module Contrast
|
7
|
+
module Agent
|
8
|
+
module Telemetry
|
9
|
+
module TelemetryException
|
10
|
+
# This class will hold the all the information for the specific exception
|
11
|
+
# and will be passed in the Exception message itself
|
12
|
+
class StackFrame < Contrast::Agent::Telemetry::TelemetryException::Base
|
13
|
+
VALIDATIONS = {
|
14
|
+
function: { required: true, range: 1..256 },
|
15
|
+
type: { required: true, range: 1..256 },
|
16
|
+
module_name: { required: false, range: 1..256 }
|
17
|
+
}.cs__freeze
|
18
|
+
|
19
|
+
# @return [String] The type of the exception itself
|
20
|
+
attr_reader :type
|
21
|
+
|
22
|
+
# @return [String] the function of the stack trace
|
23
|
+
attr_reader :function
|
24
|
+
|
25
|
+
# @return [Boolean] Is it in contrast
|
26
|
+
attr_accessor :in_contrast
|
27
|
+
|
28
|
+
# @return [String]
|
29
|
+
attr_reader :module_name
|
30
|
+
|
31
|
+
def initialize function, type
|
32
|
+
super()
|
33
|
+
@function = function
|
34
|
+
@type = type
|
35
|
+
@in_contrast = false
|
36
|
+
validate VALIDATIONS
|
37
|
+
end
|
38
|
+
|
39
|
+
def module_name= module_name
|
40
|
+
@module_name = module_name
|
41
|
+
validate_field(VALIDATIONS[:module_name], 'module_name')
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_controlled_hash
|
45
|
+
super
|
46
|
+
{ function: function, type: type, module: module_name, inContrast: in_contrast }.compact
|
47
|
+
end
|
48
|
+
|
49
|
+
class << self
|
50
|
+
# @param method [String] method, triggered the logger on warn/error/fatal
|
51
|
+
# @param type [String] the type ( where it occurred )
|
52
|
+
# @param module_name [String, nil] Name of the module if any.
|
53
|
+
def build method, type, module_name = nil
|
54
|
+
inst = new(method, type)
|
55
|
+
inst.module_name = module_name if module_name
|
56
|
+
inst.in_contrast = type.include?('lib/contrast')
|
57
|
+
inst
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Contrast
|
5
|
+
module Agent
|
6
|
+
module Telemetry
|
7
|
+
# This is the module that will include every information created and stored for the
|
8
|
+
# Telemetry Exceptions
|
9
|
+
module TelemetryException
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'contrast/agent/telemetry/events/exceptions/telemetry_exception_base'
|
16
|
+
require 'contrast/agent/telemetry/events/exceptions/telemetry_exception_stack_frame'
|
17
|
+
require 'contrast/agent/telemetry/events/exceptions/telemetry_exception_message_exception'
|
18
|
+
require 'contrast/agent/telemetry/events/exceptions/telemetry_exception_message'
|
19
|
+
require 'contrast/agent/telemetry/events/exceptions/telemetry_exception_event'
|
20
|
+
require 'contrast/agent/telemetry/events/exceptions/telemetry_exceptions_report'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Contrast
|
5
|
+
module Agent
|
6
|
+
module Telemetry
|
7
|
+
# This module will handle the reporting of the TelemetryExceptionHash
|
8
|
+
module TelemetryExceptionReport
|
9
|
+
class << self
|
10
|
+
# Here we will send any exceptions gathered. The telemetry_hash is split into batches of 256
|
11
|
+
# and then added to the telemetry queue. Since this method is called before entering the
|
12
|
+
# until queue loop any updates after clearing the Contrast::TELEMETRY_EXCEPTIONS would have
|
13
|
+
# to wait for the sending process to be completed, so accumulating new batches.
|
14
|
+
# This methods expects queue and error_messages methods from Contrast::Agent::Telemetry::Base
|
15
|
+
def push_exceptions
|
16
|
+
return unless Contrast::TELEMETRY_EXCEPTIONS&.any?
|
17
|
+
|
18
|
+
Contrast::TELEMETRY_EXCEPTIONS.values.each_slice(256) { |tuple| error_messages.push tuple }
|
19
|
+
# Clear the hash. All exceptions now live in @_error_messages instance variable. and we will
|
20
|
+
# add them to the queue. Clearing would make the hash available to be populated again while the
|
21
|
+
# sending is proceeding.
|
22
|
+
Contrast::TELEMETRY_EXCEPTIONS.clear
|
23
|
+
# Add batch to queue. We need to shift here, because we want to report from the oldest batch to
|
24
|
+
# the newest. And even if somehow the array is filled during sending the new messages would stay
|
25
|
+
# and wait their turn.
|
26
|
+
queue << error_messages.shift until error_messages.empty?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'contrast/utils/metrics_hash'
|
5
|
+
require 'contrast/agent/telemetry/events/event'
|
6
|
+
|
7
|
+
module Contrast
|
8
|
+
module Agent
|
9
|
+
module Telemetry
|
10
|
+
# This class will hold the basic information for a Telemetry Event
|
11
|
+
class MetricEvent < Contrast::Agent::Telemetry::Event
|
12
|
+
include Contrast::Utils
|
13
|
+
|
14
|
+
attr_reader :fields
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
super
|
18
|
+
@fields = MetricsHash.new(Numeric)
|
19
|
+
@fields['_filler'] = 0
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_hash **_args
|
23
|
+
super.merge!({ fields: @fields })
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'contrast/utils/metrics_hash'
|
5
|
+
require 'contrast/agent/telemetry/events/metric_event'
|
6
|
+
require 'contrast/agent/version'
|
7
|
+
require 'contrast/utils/os'
|
8
|
+
|
9
|
+
module Contrast
|
10
|
+
module Agent
|
11
|
+
module Telemetry
|
12
|
+
# This class will hold the Startup Metrics Telemetry Event
|
13
|
+
# The class will include initialization of the agent version, language version
|
14
|
+
# os type, arch and version
|
15
|
+
# application framework and version and server framework
|
16
|
+
# It will be initialized and send in Middleware#agent_startup_routine
|
17
|
+
class StartupMetricsEvent < Contrast::Agent::Telemetry::MetricEvent
|
18
|
+
include Contrast::Utils::OS
|
19
|
+
|
20
|
+
APP_AND_SERVER_DATA = ::Contrast::APP_CONTEXT.app_and_server_information.cs__freeze
|
21
|
+
# Multi-tenant Production Environments
|
22
|
+
SAAS_DEFAULT = { addr: 'app.contrastsecurity.com', type: 'SAAS_DEFAULT' }.cs__freeze
|
23
|
+
SAAS_CS = { addr: /cs[[:digit:]]+\.contrastsecurity\.com/, type: 'SAAS_DEFAULT' }.cs__freeze
|
24
|
+
SAAS_JP = { addr: 'app.contrastsecurity.jp', type: 'SAAS_DEFAULT' }.cs__freeze
|
25
|
+
SAAS_CE = { addr: 'ce.contrastsecurity.com', type: 'SAAS_CE' }.cs__freeze
|
26
|
+
# Multi-tenant Demo Environments
|
27
|
+
SAAS_DEMO = { addr: 'apptwo.contrastsecurity.com', type: 'SAAS_DEMO' }.cs__freeze
|
28
|
+
SAAS_POV = { addr: 'eval.contrastsecurity.com', type: 'SAAS_POV' }.cs__freeze
|
29
|
+
# Multi-tenant Testing Environment
|
30
|
+
SAAS_RESEARCH = { addr: 'security-research.contrastsecurity.com', type: 'SAAS_RESEARCH' }.cs__freeze
|
31
|
+
SAAS_ALPHA = { addr: 'alpha.contrastsecurity.com', type: 'SAAS_ALPHA' }.cs__freeze
|
32
|
+
SAAS_STAGING = { addr: 'teamserver-staging.contsec.com', type: 'SAAS_TESTING' }.cs__freeze
|
33
|
+
SAAS_STAGING_TOKYO = { addr: 'teamserver-staging.contsec.jp', type: 'SAAS_TESTING' }.cs__freeze
|
34
|
+
SAAS_TESTING = { addr: 'teamserver-darpa.contsec.com', type: 'SAAS_TESTING' }.cs__freeze
|
35
|
+
SAAS_OPS_TESTING = { addr: 'teamserver-ops.contsec.com', type: 'SAAS_TESTING' }.cs__freeze
|
36
|
+
# Fallback for Single-tenant Production Environments
|
37
|
+
SAAS_CUSTOM = { addr: 'contrastsecurity.com', type: 'SAAS_CUSTOM' }.cs__freeze
|
38
|
+
SAAS_CUSTOM_JP = { addr: 'contrastsecurity.jp', type: 'SAAS_CUSTOM' }.cs__freeze
|
39
|
+
|
40
|
+
SINGLE_MAP_TENANTS = [
|
41
|
+
SAAS_DEFAULT, SAAS_JP, SAAS_CE, SAAS_DEMO, SAAS_POV, SAAS_RESEARCH, SAAS_ALPHA,
|
42
|
+
SAAS_STAGING, SAAS_STAGING_TOKYO, SAAS_TESTING, SAAS_OPS_TESTING
|
43
|
+
].cs__freeze
|
44
|
+
REGEXP_MAP_TENANTS = [SAAS_CS].cs__freeze
|
45
|
+
FALLBACK_TENANTS = [SAAS_CUSTOM, SAAS_CUSTOM_JP].cs__freeze
|
46
|
+
# Fallback for Custom, most likely self-hosted, Environments
|
47
|
+
EOP = 'EOP'
|
48
|
+
REJECTED_VALUES = [nil, 'NEEDS_TO_BE_SET', Contrast::Utils::ObjectShare::EMPTY_STRING].cs__freeze
|
49
|
+
|
50
|
+
def initialize
|
51
|
+
super
|
52
|
+
@settings = []
|
53
|
+
add_config_keys ::Contrast::CONFIG.root, 'root'
|
54
|
+
@settings << ENV.keys.select { |v| v.starts_with?('CONTRAST') }
|
55
|
+
@settings.flatten
|
56
|
+
add_tags
|
57
|
+
end
|
58
|
+
|
59
|
+
def path
|
60
|
+
'/startup'
|
61
|
+
end
|
62
|
+
|
63
|
+
def add_tags
|
64
|
+
add_system_tags
|
65
|
+
@tags['app_framework_and_version'] = APP_AND_SERVER_DATA[:application_info].to_s
|
66
|
+
@tags['server_framework_and_version'] = APP_AND_SERVER_DATA[:server_info].to_s
|
67
|
+
@tags['ASSESS'] = Contrast::ASSESS.enabled?.to_s
|
68
|
+
@tags['PROTECT'] = Contrast::PROTECT.enabled?.to_s
|
69
|
+
@tags['settings'] = @settings.join(',')
|
70
|
+
end
|
71
|
+
|
72
|
+
def add_config_keys config, nested_key
|
73
|
+
config.to_hash.reject! { |_k, v| REJECTED_VALUES.include?(v) }
|
74
|
+
|
75
|
+
config.to_hash.each do |k, v|
|
76
|
+
unless v.cs__class <= Contrast::Config::BaseConfiguration
|
77
|
+
@settings << "#{ nested_key }.#{ k }"
|
78
|
+
next
|
79
|
+
end
|
80
|
+
|
81
|
+
add_config_keys v, "#{ nested_key }.#{ k }"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def sys_info
|
86
|
+
@sys_info ||= get_system_information if @sys_info.nil?
|
87
|
+
@sys_info
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
# Here we extract the TeamServer url type
|
93
|
+
#
|
94
|
+
# @return [String] the type of TeamServer environment to which we're connecting
|
95
|
+
def teamserver_type
|
96
|
+
@_teamserver_type ||= begin
|
97
|
+
url = Contrast::API.api_url
|
98
|
+
if (single = SINGLE_MAP_TENANTS.find { |tenant| url.include?(tenant[:addr]) })
|
99
|
+
single[:type]
|
100
|
+
elsif (regexp = REGEXP_MAP_TENANTS.find { |tenant| tenant[:addr].match?(url) })
|
101
|
+
regexp[:type]
|
102
|
+
elsif (fallback = FALLBACK_TENANTS.find { |tenant| url.include?(tenant[:addr]) })
|
103
|
+
fallback[:type]
|
104
|
+
else
|
105
|
+
EOP
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Here we attach the key-value pairs of the system
|
111
|
+
#
|
112
|
+
def add_system_tags
|
113
|
+
@tags['teamserver'] = teamserver_type
|
114
|
+
@tags['agent_version'] = VERSION
|
115
|
+
@tags['ruby_version'] = RUBY_VERSION
|
116
|
+
@tags['os_type'] = sys_info['os_type'] == 'Darwin' ? 'MacOS' : 'Linux'
|
117
|
+
@tags['os_arch'] = sys_info['os_arch']
|
118
|
+
@tags['os_version'] = sys_info['os_version']
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -5,46 +5,58 @@ require 'contrast/components/logger'
|
|
5
5
|
require 'contrast/agent/service_heartbeat'
|
6
6
|
require 'contrast/api/communication/messaging_queue'
|
7
7
|
require 'contrast/agent/reporting/report'
|
8
|
-
require 'contrast/agent/
|
8
|
+
require 'contrast/agent/reporting/reporter_heartbeat'
|
9
|
+
require 'contrast/agent/telemetry/base'
|
9
10
|
|
10
11
|
module Contrast
|
11
12
|
module Agent
|
12
13
|
# This class used to ensure that our worker threads are running in multi-process environments
|
13
|
-
#
|
14
|
-
# @attr_reader heapdump_util [Contrast::Utils::HeapDumpUtil]
|
15
|
-
# @attr_reader heartbeat [Contrast::Agent::ServiceHeartbeat]
|
16
|
-
# @attr_reader messaging_queue [Contrast::Api::Communication::MessagingQueue]
|
17
14
|
class ThreadWatcher
|
18
15
|
include Contrast::Components::Logger::InstanceMethods
|
19
16
|
|
20
|
-
|
17
|
+
# @return [Contrast::Utils::HeapDumpUtil]
|
18
|
+
attr_reader :heapdump_util
|
19
|
+
# @return [Contrast::Agent::ServiceHeartbeat, nil]
|
20
|
+
attr_reader :heartbeat
|
21
|
+
# @return [Contrast::Api::Communication::MessagingQueue, nil]
|
22
|
+
attr_reader :messaging_queue
|
23
|
+
# @return [Contrast::Agent::Reporter]
|
24
|
+
attr_reader :reporter
|
25
|
+
# @return [Contrast::Agent::ReporterHeartbeat]
|
26
|
+
attr_reader :reporter_heartbeat
|
21
27
|
|
22
28
|
def initialize
|
23
29
|
@pids = {}
|
24
30
|
@heapdump_util = Contrast::Utils::HeapDumpUtil.new
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
31
|
+
unless ::Contrast::CONTRAST_SERVICE.unnecessary?
|
32
|
+
@heartbeat = Contrast::Agent::ServiceHeartbeat.new
|
33
|
+
@messaging_queue = Contrast::Api::Communication::MessagingQueue.new
|
34
|
+
end
|
35
|
+
if Contrast::Agent::Reporter.enabled?
|
36
|
+
@reporter = Contrast::Agent::Reporter.new
|
37
|
+
@reporter_heartbeat = Contrast::Agent::ReporterHeartbeat.new
|
38
|
+
end
|
39
|
+
@telemetry = Contrast::Agent::Telemetry::Base.new if Contrast::Agent::Telemetry::Base.enabled?
|
29
40
|
end
|
30
41
|
|
42
|
+
# @return [Hash, nil] map of process to thread startup status
|
31
43
|
def startup!
|
32
44
|
return unless ::Contrast::AGENT.enabled?
|
33
45
|
|
34
|
-
telemetry_status = telemetry_thread_init
|
35
|
-
heartbeat_status = heartbeat_thread_init
|
36
|
-
messaging_status = messaging_thread_init
|
37
|
-
reporter_status = reporter_thread_init
|
38
|
-
|
39
46
|
logger.debug('ThreadWatcher started threads')
|
40
|
-
|
47
|
+
heartbeat_status = init_thread(heartbeat)
|
48
|
+
messaging_status = init_thread(messaging_queue)
|
41
49
|
@pids[Process.pid] = messaging_status && heartbeat_status
|
42
|
-
|
43
|
-
|
44
|
-
|
50
|
+
if Contrast::Agent::Telemetry::Base.enabled?
|
51
|
+
telemetry_status = init_thread(telemetry_queue)
|
52
|
+
@pids[Process.pid] = @pids[Process.pid] && telemetry_status
|
53
|
+
end
|
45
54
|
return @pids unless Contrast::Agent::Reporter.enabled?
|
46
55
|
|
47
|
-
|
56
|
+
reporter_status = init_thread(reporter)
|
57
|
+
reporter_heartbeat_status = init_thread(reporter_heartbeat)
|
58
|
+
@pids[Process.pid] = @pids[Process.pid] && reporter_status && reporter_heartbeat_status
|
59
|
+
@pids
|
48
60
|
end
|
49
61
|
|
50
62
|
def ensure_running?
|
@@ -55,63 +67,35 @@ module Contrast
|
|
55
67
|
end
|
56
68
|
|
57
69
|
def shutdown!
|
58
|
-
heartbeat
|
59
|
-
messaging_queue
|
60
|
-
heapdump_util
|
70
|
+
heartbeat&.stop!
|
71
|
+
messaging_queue&.stop!
|
72
|
+
heapdump_util&.stop!
|
61
73
|
telemetry_queue&.stop!
|
62
74
|
reporter&.stop!
|
75
|
+
reporter_heartbeat&.stop!
|
63
76
|
end
|
64
77
|
|
65
|
-
|
66
|
-
unless heartbeat.running?
|
67
|
-
logger.debug('Attempting to start heartbeat thread')
|
68
|
-
heartbeat.start_thread!
|
69
|
-
end
|
70
|
-
heartbeat_result = heartbeat.running?
|
71
|
-
logger.debug('Heartbeat thread status', alive: heartbeat_result)
|
72
|
-
heartbeat_result
|
73
|
-
end
|
74
|
-
|
75
|
-
def telemetry_thread_init
|
76
|
-
@telemetry.start_thread! if @telemetry&.attempt_to_start?
|
77
|
-
telemetry_result = @telemetry&.running?
|
78
|
-
logger.debug('Telemetry thread status', alive: telemetry_result)
|
79
|
-
telemetry_result
|
80
|
-
end
|
81
|
-
|
82
|
-
def messaging_thread_init
|
83
|
-
unless messaging_queue.running?
|
84
|
-
logger.debug('Attempting to start messaging queue thread')
|
85
|
-
messaging_queue.start_thread!
|
86
|
-
end
|
87
|
-
messaging_result = messaging_queue.running?
|
88
|
-
logger.debug('Messaging thread status', alive: messaging_result)
|
89
|
-
messaging_result
|
90
|
-
end
|
91
|
-
|
92
|
-
def reporter_thread_init
|
93
|
-
@reporter.start_thread! if @reporter&.attempt_to_start?
|
94
|
-
unless @reporter&.running?
|
95
|
-
logger.debug('Attempting to start reporter thread')
|
96
|
-
@reporter&.start_thread!
|
97
|
-
end
|
98
|
-
reporter_result = @reporter&.running?
|
99
|
-
logger.debug('Reporter thread status', alive: reporter_result)
|
100
|
-
reporter_result
|
101
|
-
end
|
102
|
-
|
103
|
-
# @return [Contrast::Agent::Telemetry]
|
78
|
+
# @return [Contrast::Agent::Telemetry::Base]
|
104
79
|
def telemetry_queue
|
105
|
-
return if @telemetry.nil?
|
106
|
-
|
107
80
|
@telemetry
|
108
81
|
end
|
109
82
|
|
110
|
-
|
111
|
-
def reporter
|
112
|
-
return if @reporter.nil?
|
83
|
+
private
|
113
84
|
|
114
|
-
|
85
|
+
# Start the thread governed by the given watcher
|
86
|
+
#
|
87
|
+
# @param watcher [Contrast::Agent::ThreadWatcher]
|
88
|
+
# @return [Boolean] if the watched thread started successfully
|
89
|
+
def init_thread watcher
|
90
|
+
return unless watcher&.attempt_to_start?
|
91
|
+
|
92
|
+
unless watcher.running?
|
93
|
+
logger.debug('Attempting to start thread', type: watcher.to_s)
|
94
|
+
watcher.start_thread!
|
95
|
+
end
|
96
|
+
result = watcher.running?
|
97
|
+
logger.debug('Thread status', type: watcher.to_s, alive: result)
|
98
|
+
result
|
115
99
|
end
|
116
100
|
end
|
117
101
|
end
|
@@ -15,10 +15,18 @@ module Contrast
|
|
15
15
|
|
16
16
|
def stop!
|
17
17
|
return unless running?
|
18
|
+
return unless @_thread
|
18
19
|
|
19
20
|
Thread.kill(@_thread)
|
20
21
|
@_thread = nil
|
21
22
|
end
|
23
|
+
|
24
|
+
# Most threads, we always want to start. Some may be controlled by feature guards though, so we need to check.
|
25
|
+
#
|
26
|
+
# @return [Boolean]
|
27
|
+
def attempt_to_start?
|
28
|
+
true
|
29
|
+
end
|
22
30
|
end
|
23
31
|
end
|
24
32
|
end
|
data/lib/contrast/agent.rb
CHANGED
@@ -32,6 +32,8 @@ require 'contrast/utils/invalid_configuration_util'
|
|
32
32
|
# Collect findings
|
33
33
|
require 'contrast/utils/findings'
|
34
34
|
|
35
|
+
# Collect Exploites and Attacks
|
36
|
+
require 'contrast/agent/protect/exploitable_collection'
|
35
37
|
# scoping
|
36
38
|
require 'contrast/agent/scope'
|
37
39
|
|
@@ -52,6 +54,7 @@ module Contrast
|
|
52
54
|
# build a map for tracking the context of the current request
|
53
55
|
REQUEST_TRACKER = Contrast::Utils::ThreadTracker.new
|
54
56
|
FINDINGS = Contrast::Utils::Findings.new
|
57
|
+
EXPLOITS = Contrast::Agent::Protect::ExploitableCollection.new
|
55
58
|
|
56
59
|
# @return [Contrast::Framework::Manager]
|
57
60
|
def self.framework_manager
|
@@ -68,10 +71,8 @@ module Contrast
|
|
68
71
|
thread_watcher.messaging_queue
|
69
72
|
end
|
70
73
|
|
71
|
-
# @return [nil, Contrast::Agent::Telemetry]
|
74
|
+
# @return [nil, Contrast::Agent::Telemetry::Base]
|
72
75
|
def self.telemetry_queue
|
73
|
-
return unless thread_watcher.telemetry_queue
|
74
|
-
|
75
76
|
thread_watcher.telemetry_queue
|
76
77
|
end
|
77
78
|
|
@@ -2,8 +2,10 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require 'contrast/components/logger'
|
5
|
+
require 'contrast/agent/assess/policy/trigger_method'
|
5
6
|
require 'contrast/agent/worker_thread'
|
6
7
|
require 'contrast/agent/reporting/reporting_utilities/audit'
|
8
|
+
require 'contrast/api/dtm.pb'
|
7
9
|
|
8
10
|
module Contrast
|
9
11
|
module Api
|
@@ -12,11 +14,13 @@ module Contrast
|
|
12
14
|
class MessagingQueue < Contrast::Agent::WorkerThread
|
13
15
|
include Contrast::Components::Logger::InstanceMethods
|
14
16
|
|
17
|
+
# @return [Contrast::Api::Communication::Speedracer, nil]
|
15
18
|
attr_reader :speedracer
|
16
19
|
|
17
20
|
def initialize
|
21
|
+
return if ::Contrast::CONTRAST_SERVICE.unnecessary?
|
22
|
+
|
18
23
|
@speedracer = Contrast::Api::Communication::Speedracer.new
|
19
|
-
@audit = Contrast::Agent::Reporting::Audit.new if ::Contrast::API.request_audit_enable?
|
20
24
|
super
|
21
25
|
end
|
22
26
|
|
@@ -33,18 +37,18 @@ module Contrast
|
|
33
37
|
logger.warn('Attempted to send event immediately with Agent disabled', caller: caller, event: event)
|
34
38
|
return
|
35
39
|
end
|
36
|
-
|
37
|
-
return response_data unless ::Contrast::API.request_audit_enable?
|
40
|
+
return if ::Contrast::CONTRAST_SERVICE.unnecessary?
|
38
41
|
|
39
|
-
|
40
|
-
response_data
|
42
|
+
speedracer.return_response(event)
|
41
43
|
end
|
42
44
|
|
43
45
|
# A simple Queue used to hold messages that are ready to be sent to SpeedRacer but for which we do not need an
|
44
46
|
# immediate response
|
45
47
|
#
|
46
|
-
# @return [Queue]
|
48
|
+
# @return [Queue, nil]
|
47
49
|
def queue
|
50
|
+
return if ::Contrast::CONTRAST_SERVICE.unnecessary?
|
51
|
+
|
48
52
|
@_queue ||= Queue.new
|
49
53
|
end
|
50
54
|
|
@@ -56,29 +60,42 @@ module Contrast
|
|
56
60
|
#
|
57
61
|
# @param event [Contrast::Api::Dtm] One of the DTMs valid for the event field of
|
58
62
|
# Contrast::Api::Dtm::Message|Contrast::Api::Dtm::Activity
|
59
|
-
|
63
|
+
# @param force [Boolean] if we should always queue this event, even if the service isn't running, in case the
|
64
|
+
# message may be ready before the service has initiated. usually for those events which happen in a separate
|
65
|
+
# thread or which may occur during initialization.
|
66
|
+
def send_event_eventually event, force: false
|
60
67
|
if ::Contrast::AGENT.disabled?
|
61
68
|
logger.warn('Attempted to queue event with Agent disabled', caller: caller, event: event)
|
62
69
|
return
|
63
70
|
end
|
71
|
+
return if ::Contrast::CONTRAST_SERVICE.unnecessary?
|
72
|
+
# If we're unable to start the Service, then we cannot afford to queue messages as this creates the potential
|
73
|
+
# for a memory leak, especially if the thread responsible for de-queueing the messages is dead.
|
74
|
+
return if !force && !(speedracer.status.connected? && running?)
|
75
|
+
|
76
|
+
# If we're in direct communication mode, the only message we should queue is the heartbeat to keep the
|
77
|
+
# service alive during Protect activities. All other messages should go through direct reporting.
|
78
|
+
if ::Contrast::CONTRAST_SERVICE.use_agent_communication?
|
79
|
+
return unless ::Contrast::PROTECT.enabled?
|
80
|
+
return unless event.cs__is_a?(Contrast::Api::Dtm::Poll)
|
81
|
+
end
|
82
|
+
|
64
83
|
logger.debug('Enqueued event for sending', event_type: event.cs__class)
|
65
84
|
queue << event if event
|
66
|
-
return unless ::Contrast::API.request_audit_enable?
|
67
|
-
|
68
|
-
@audit&.audit_event(event)
|
69
85
|
end
|
70
86
|
|
71
87
|
# Create the reporting thread, which will pull from the queue in order to send messages to SpeedRacer. If
|
72
88
|
# SpeedRacer is not running and should be, meaning the Agent is configured to control it, then we will also
|
73
89
|
# try to start that process.
|
74
90
|
def start_thread!
|
91
|
+
return if ::Contrast::CONTRAST_SERVICE.unnecessary?
|
92
|
+
|
75
93
|
speedracer.ensure_startup!
|
76
94
|
return if running?
|
77
95
|
|
78
96
|
@_thread = Contrast::Agent::Thread.new do
|
79
97
|
loop do
|
80
98
|
event = queue.pop
|
81
|
-
|
82
99
|
begin
|
83
100
|
logger.debug('Dequeued event for sending', event_type: event.cs__class)
|
84
101
|
speedracer.process_internally(event)
|
@@ -8,12 +8,8 @@ module Contrast
|
|
8
8
|
module Api
|
9
9
|
module Communication
|
10
10
|
# Handles processing deferred messages sent to SpeedRacer.
|
11
|
-
#
|
12
|
-
# @attr_reader last_app_update_ms [Integer] the time, in ms, that application settings last changed
|
13
|
-
# @attr_reader last_server_update_ms [Integer] the time, in ms, that server settings last changed
|
14
11
|
class ResponseProcessor
|
15
12
|
include Contrast::Components::Logger::InstanceMethods
|
16
|
-
attr_reader :last_app_update_ms, :last_server_update_ms
|
17
13
|
|
18
14
|
# Use the given response to update the Agent's server features and application settings, allowing it to reflect
|
19
15
|
# the latest options configured by the user in TeamServer
|
@@ -48,7 +44,6 @@ module Contrast
|
|
48
44
|
logger.trace('Agent: Received updated server features')
|
49
45
|
|
50
46
|
::Contrast::SETTINGS.update_from_server_features(server_features)
|
51
|
-
@last_server_update_ms = Contrast::Utils::Timer.now_ms
|
52
47
|
server_features
|
53
48
|
end
|
54
49
|
|
@@ -58,22 +53,24 @@ module Contrast
|
|
58
53
|
# @param response [Contrast::Api::Settings::AgentSettings]
|
59
54
|
# @return [Contrast::Api::Settings::ApplicationSettings]
|
60
55
|
def process_application_response response
|
56
|
+
logger.debug('[!] process_application_response', response: response)
|
61
57
|
app_settings = response&.application_settings
|
62
58
|
return unless app_settings
|
63
59
|
|
64
|
-
logger.debug('Agent: Received updated application settings')
|
65
|
-
|
60
|
+
logger.debug('[!] Agent: Received updated application settings', settings: app_settings)
|
66
61
|
::Contrast::SETTINGS.update_from_application_settings(app_settings)
|
67
|
-
@last_app_update_ms = Contrast::Utils::Timer.now_ms
|
68
62
|
app_settings
|
69
63
|
end
|
70
64
|
|
71
65
|
# This can't go in the Settings component because protect and assess depend on settings
|
72
66
|
# I don't think it should go into contrast_service because that only handles connection specific data.
|
73
67
|
#
|
74
|
-
# @param server_features
|
75
|
-
#
|
68
|
+
# @param server_features
|
69
|
+
# [Contrast::Api::Settings::AgentSettings, Contrast::Agent::Reporting::Settings::FeatureSettings]
|
70
|
+
# @param app_settings
|
71
|
+
# [Contrast::Api::Settings::ApplicationSettings, Contrast::Agent::Reporting::Settings::ApplicationSettings]
|
76
72
|
def update_features server_features, app_settings
|
73
|
+
logger.info('Updating features')
|
77
74
|
return unless !!(server_features || app_settings)
|
78
75
|
return unless ::Contrast::AGENT.enabled?
|
79
76
|
|