contrast-agent 6.8.0 → 6.9.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/trigger_method.rb +1 -1
- data/lib/contrast/agent/assess/property/evented.rb +11 -11
- data/lib/contrast/agent/assess.rb +0 -1
- data/lib/contrast/agent/excluder.rb +1 -1
- data/lib/contrast/agent/middleware.rb +8 -2
- data/lib/contrast/agent/protect/input_analyzer/worth_watching_analyzer.rb +116 -0
- data/lib/contrast/agent/protect/rule/base.rb +2 -2
- data/lib/contrast/agent/protect/rule/bot_blocker.rb +1 -1
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +8 -7
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_chained_command.rb +0 -5
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_dangerous_path.rb +0 -5
- data/lib/contrast/agent/protect/rule/path_traversal.rb +4 -3
- data/lib/contrast/agent/protect/rule/sqli.rb +4 -3
- data/lib/contrast/agent/protect/rule/xss.rb +1 -0
- data/lib/contrast/agent/reporting/attack_result/rasp_rule_sample.rb +1 -1
- data/lib/contrast/agent/reporting/report.rb +1 -0
- data/lib/contrast/agent/reporting/reporter.rb +34 -0
- data/lib/contrast/agent/reporting/reporter_heartbeat.rb +3 -9
- data/lib/contrast/agent/reporting/reporting_events/application_activity.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb +12 -7
- data/lib/contrast/agent/reporting/reporting_events/application_inventory_activity.rb +6 -1
- data/lib/contrast/agent/reporting/reporting_events/finding.rb +2 -2
- data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +239 -93
- data/lib/contrast/agent/reporting/reporting_events/finding_event_signature.rb +10 -23
- data/lib/contrast/agent/reporting/reporting_events/finding_event_source.rb +10 -9
- data/lib/contrast/agent/reporting/reporting_events/observed_route.rb +12 -0
- data/lib/contrast/agent/reporting/reporting_events/server_reporting_event.rb +8 -0
- data/lib/contrast/agent/reporting/reporting_events/server_settings.rb +40 -0
- data/lib/contrast/agent/reporting/reporting_utilities/endpoints.rb +6 -0
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +43 -1
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +8 -4
- data/lib/contrast/agent/reporting/reporting_utilities/response_extractor.rb +58 -4
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +4 -3
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +76 -16
- data/lib/contrast/agent/reporting/server_settings_worker.rb +44 -0
- data/lib/contrast/agent/reporting/settings/assess_server_feature.rb +14 -2
- data/lib/contrast/agent/reporting/settings/helpers.rb +7 -0
- data/lib/contrast/agent/reporting/settings/protect_server_feature.rb +39 -2
- data/lib/contrast/agent/reporting/settings/rule_definition.rb +3 -0
- data/lib/contrast/agent/reporting/settings/security_logger.rb +77 -0
- data/lib/contrast/agent/reporting/settings/server_features.rb +9 -0
- data/lib/contrast/agent/reporting/settings/syslog.rb +34 -5
- data/lib/contrast/agent/request.rb +1 -0
- data/lib/contrast/agent/request_handler.rb +5 -10
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_event.rb +1 -1
- data/lib/contrast/agent/thread_watcher.rb +35 -1
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/agent.rb +6 -0
- data/lib/contrast/api/communication/connection_status.rb +15 -0
- data/lib/contrast/components/agent.rb +34 -0
- data/lib/contrast/components/api.rb +23 -0
- data/lib/contrast/components/app_context.rb +23 -3
- data/lib/contrast/components/assess.rb +34 -4
- data/lib/contrast/components/assess_rules.rb +18 -0
- data/lib/contrast/components/base.rb +40 -0
- data/lib/contrast/components/config/sources.rb +95 -0
- data/lib/contrast/components/config.rb +18 -1
- data/lib/contrast/components/heap_dump.rb +10 -0
- data/lib/contrast/components/inventory.rb +15 -2
- data/lib/contrast/components/logger.rb +18 -0
- data/lib/contrast/components/polling.rb +36 -0
- data/lib/contrast/components/protect.rb +48 -1
- data/lib/contrast/components/ruby_component.rb +15 -0
- data/lib/contrast/components/sampling.rb +70 -13
- data/lib/contrast/components/security_logger.rb +13 -0
- data/lib/contrast/components/settings.rb +74 -7
- data/lib/contrast/config/certification_configuration.rb +14 -0
- data/lib/contrast/config/config.rb +46 -0
- data/lib/contrast/config/diagnostics.rb +114 -0
- data/lib/contrast/config/diagnostics_tools.rb +98 -0
- data/lib/contrast/config/effective_config.rb +65 -0
- data/lib/contrast/config/effective_config_value.rb +32 -0
- data/lib/contrast/config/exception_configuration.rb +12 -0
- data/lib/contrast/config/protect_rule_configuration.rb +1 -1
- data/lib/contrast/config/protect_rules_configuration.rb +8 -7
- data/lib/contrast/config/request_audit_configuration.rb +13 -0
- data/lib/contrast/config/server_configuration.rb +41 -2
- data/lib/contrast/configuration.rb +28 -2
- data/lib/contrast/extension/assess/erb.rb +1 -1
- data/lib/contrast/utils/assess/event_limit_utils.rb +31 -9
- data/lib/contrast/utils/assess/trigger_method_utils.rb +5 -4
- data/lib/contrast/utils/hash_digest.rb +2 -2
- data/lib/contrast/utils/input_classification_base.rb +1 -2
- data/lib/contrast/utils/reporting/application_activity_batch_utils.rb +81 -0
- data/lib/contrast/utils/routes_sent.rb +60 -0
- data/lib/contrast/utils/telemetry_client.rb +1 -2
- data/lib/contrast/utils/timer.rb +16 -0
- data/lib/contrast.rb +3 -1
- data/ruby-agent.gemspec +5 -1
- metadata +29 -20
- data/lib/contrast/agent/assess/contrast_event.rb +0 -157
- data/lib/contrast/agent/assess/events/event_factory.rb +0 -34
- data/lib/contrast/agent/assess/events/source_event.rb +0 -46
- data/lib/contrast/agent/reporting/reporting_events/server_activity.rb +0 -36
|
@@ -0,0 +1,95 @@
|
|
|
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/env_configuration_item'
|
|
5
|
+
require 'ougai'
|
|
6
|
+
require 'contrast/configuration'
|
|
7
|
+
|
|
8
|
+
module Contrast
|
|
9
|
+
module Components
|
|
10
|
+
module Config
|
|
11
|
+
# This component encapsulates storing the source for each entry in the config,
|
|
12
|
+
# so that we can report on where the value was set from.
|
|
13
|
+
class Sources
|
|
14
|
+
ENVIRONMENT = 'ENV'
|
|
15
|
+
CLI = 'CLI'
|
|
16
|
+
CONTRASTUI = 'ContrastUI'
|
|
17
|
+
DEFAULT = 'Default'
|
|
18
|
+
YAML = 'YAML'
|
|
19
|
+
|
|
20
|
+
# @return [Hash]
|
|
21
|
+
attr_reader :data
|
|
22
|
+
|
|
23
|
+
def initialize data = {}
|
|
24
|
+
@data = data
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Retrieves the current config source for the specified config path. If no source is
|
|
28
|
+
# set then returns the Default value.
|
|
29
|
+
#
|
|
30
|
+
# @param path [String] the canonical name for the config entry (such as api.proxy.enable)
|
|
31
|
+
# @return [String] the source for the entry
|
|
32
|
+
def get path
|
|
33
|
+
data.dig(*parts_for(path)) || DEFAULT
|
|
34
|
+
rescue TypeError
|
|
35
|
+
DEFAULT
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Assigns the config source for a specified config path.
|
|
39
|
+
#
|
|
40
|
+
# @param path [String] the canonical name for the config entry (such as api.proxy.enable)
|
|
41
|
+
# @param [String] the source for the entry
|
|
42
|
+
# @return [String] the source type for the entry
|
|
43
|
+
def set path, source
|
|
44
|
+
assign_value(data, parts_for(path), source)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Finds entries within config source data for the specified type, and returns
|
|
48
|
+
# them along with the current values for each.
|
|
49
|
+
#
|
|
50
|
+
# @param type [String] a source type (ENV, CLI, ContrastUI, YAML)
|
|
51
|
+
# @return [Hash] the entries for the provided source, along with the associated values
|
|
52
|
+
def for type
|
|
53
|
+
deep_select(data.dup, type, [])
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
# @param path [String] the canonical name for a config entry (such as api.proxy.enable)
|
|
59
|
+
# @return [Array] the path split on periods, and converted to symbols
|
|
60
|
+
def parts_for path
|
|
61
|
+
path.split('.').map(&:to_sym)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @param current_level [Hash] all, or some of, the config source information
|
|
65
|
+
# @param parts [Array] the parts for canonical name of the config entry
|
|
66
|
+
# @param source [String] the source to be set for the specified entry
|
|
67
|
+
# @return [Array] the path split on periods, and converted to symbols
|
|
68
|
+
def assign_value current_level, parts, source
|
|
69
|
+
parts[0...-1].each do |segment|
|
|
70
|
+
current_level[segment] ||= {}
|
|
71
|
+
current_level = current_level[segment]
|
|
72
|
+
end
|
|
73
|
+
return unless current_level.cs__is_a?(Hash)
|
|
74
|
+
|
|
75
|
+
current_level[parts[-1]] = source
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# @param sources [Hash] all, or some of, the config source information
|
|
79
|
+
# @param type [Array] the source type to look for entries of
|
|
80
|
+
# @param path [String] the entries followed to get to this part of the config
|
|
81
|
+
# @return [Hash] the entries for the provided source, along with the associated values
|
|
82
|
+
def deep_select sources, type, path
|
|
83
|
+
sources.each_with_object({}) do |(k, v), grouping|
|
|
84
|
+
if v.cs__is_a?(Hash)
|
|
85
|
+
nested_data = deep_select(v, type, path.dup.append(k.to_sym))
|
|
86
|
+
grouping[k] = nested_data unless nested_data.empty?
|
|
87
|
+
elsif v == type
|
|
88
|
+
grouping[k] = Contrast::CONFIG.config.loaded_config.dig(*path, k)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -4,6 +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
8
|
|
|
8
9
|
module Contrast
|
|
9
10
|
module Components
|
|
@@ -26,6 +27,7 @@ module Contrast
|
|
|
26
27
|
CONTRAST_ENV_MARKER = 'CONTRAST__'
|
|
27
28
|
CONTRAST_LOG = 'contrast_agent.log'
|
|
28
29
|
CONTRAST_NAME = 'Contrast Agent'
|
|
30
|
+
DATE_TIME = '%Y-%m-%dT%H:%M:%S.%L%z'
|
|
29
31
|
|
|
30
32
|
class Interface # :nodoc: # rubocop:disable Metrics/ClassLength
|
|
31
33
|
SESSION_VARIABLES = 'Invalid configuration. '\
|
|
@@ -50,7 +52,7 @@ module Contrast
|
|
|
50
52
|
@_proto_logger.progname = CONTRAST_NAME
|
|
51
53
|
@_proto_logger.level = ::Ougai::Logging::Severity::WARN
|
|
52
54
|
@_proto_logger.formatter = Contrast::Logger::Format.new
|
|
53
|
-
@_proto_logger.formatter.datetime_format =
|
|
55
|
+
@_proto_logger.formatter.datetime_format = DATE_TIME
|
|
54
56
|
@_proto_logger
|
|
55
57
|
end
|
|
56
58
|
end
|
|
@@ -109,6 +111,10 @@ module Contrast
|
|
|
109
111
|
@config.enable
|
|
110
112
|
end
|
|
111
113
|
|
|
114
|
+
def sources
|
|
115
|
+
@config.sources
|
|
116
|
+
end
|
|
117
|
+
|
|
112
118
|
def invalid?
|
|
113
119
|
!valid?
|
|
114
120
|
end
|
|
@@ -130,6 +136,11 @@ module Contrast
|
|
|
130
136
|
application.session_metadata
|
|
131
137
|
end
|
|
132
138
|
|
|
139
|
+
# @return [String, nil] the path to the YAML config file, if any.
|
|
140
|
+
def config_file_path
|
|
141
|
+
config.config_file
|
|
142
|
+
end
|
|
143
|
+
|
|
133
144
|
private
|
|
134
145
|
|
|
135
146
|
# The config has information about how to construct the logger. If the config is invalid, and you want to know
|
|
@@ -221,6 +232,11 @@ module Contrast
|
|
|
221
232
|
agent.logger.path
|
|
222
233
|
end
|
|
223
234
|
|
|
235
|
+
# This methods is here to add the proper forward towards @config
|
|
236
|
+
def enable= value
|
|
237
|
+
@config.enable = value
|
|
238
|
+
end
|
|
239
|
+
|
|
224
240
|
# Assign the value from an ENV variable to the Contrast::Config::RootConfiguration object, when
|
|
225
241
|
# appropriate.
|
|
226
242
|
#
|
|
@@ -233,6 +249,7 @@ module Contrast
|
|
|
233
249
|
return unless current_level.nil? == false && current_level.cs__respond_to?(dot_path_array[-1])
|
|
234
250
|
|
|
235
251
|
current_level.send("#{ dot_path_array[-1] }=", value)
|
|
252
|
+
sources.set(dot_path_array.join('.'), Contrast::Components::Config::Sources::ENVIRONMENT)
|
|
236
253
|
end
|
|
237
254
|
end
|
|
238
255
|
end
|
|
@@ -10,12 +10,22 @@ module Contrast
|
|
|
10
10
|
# Interface used to build the HeapDump settings and component.
|
|
11
11
|
class Interface
|
|
12
12
|
include Contrast::Config::BaseConfiguration
|
|
13
|
+
include Contrast::Components::ComponentBase
|
|
14
|
+
|
|
15
|
+
# @return [String]
|
|
16
|
+
attr_reader :canon_name
|
|
17
|
+
# @return [Array]
|
|
18
|
+
attr_reader :config_values
|
|
13
19
|
|
|
14
20
|
DEFAULT_PATH = 'contrast_heap_dumps' # saved
|
|
15
21
|
DEFAULT_MS = 10_000
|
|
16
22
|
DEFAULT_COUNT = 5
|
|
23
|
+
CANON_NAME = 'agent.heap_dump'
|
|
24
|
+
CONFIG_VALUES = %w[enable path delay_ms window_ms count clean].cs__freeze
|
|
17
25
|
|
|
18
26
|
def initialize hsh = {}
|
|
27
|
+
@config_values = CONFIG_VALUES
|
|
28
|
+
@canon_name = CANON_NAME
|
|
19
29
|
return unless hsh
|
|
20
30
|
|
|
21
31
|
@_enable = hsh[:enable]
|
|
@@ -11,10 +11,18 @@ module Contrast
|
|
|
11
11
|
class Interface
|
|
12
12
|
include Contrast::Components::ComponentBase
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
CANON_NAME = 'inventory'
|
|
15
|
+
CONFIG_VALUES = %w[enable analyze_libraries tags].cs__freeze
|
|
16
|
+
|
|
17
|
+
attr_writer :tags
|
|
18
|
+
# @return [String]
|
|
19
|
+
attr_reader :canon_name
|
|
20
|
+
# @return [Array]
|
|
21
|
+
attr_reader :config_values
|
|
16
22
|
|
|
17
23
|
def initialize hsh = {}
|
|
24
|
+
@config_values = CONFIG_VALUES
|
|
25
|
+
@canon_name = CANON_NAME
|
|
18
26
|
return unless hsh
|
|
19
27
|
|
|
20
28
|
@enable = !false?(hsh[:enable])
|
|
@@ -31,6 +39,11 @@ module Contrast
|
|
|
31
39
|
def analyze_libraries
|
|
32
40
|
@analyze_libraries.nil? ? true : @analyze_libraries
|
|
33
41
|
end
|
|
42
|
+
|
|
43
|
+
# @return [String, nil] tags
|
|
44
|
+
def tags
|
|
45
|
+
stringify_array(@tags)
|
|
46
|
+
end
|
|
34
47
|
end
|
|
35
48
|
end
|
|
36
49
|
end
|
|
@@ -13,6 +13,14 @@ module Contrast
|
|
|
13
13
|
Contrast::Logger::Log.instance.logger
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
# When calling this method from any instance
|
|
17
|
+
# The CEF logger will be initialized and it's
|
|
18
|
+
# path and level will be set. Since we don't
|
|
19
|
+
# call this method unless protect is started,
|
|
20
|
+
# on Agent Startup no file is created before is
|
|
21
|
+
# needed.
|
|
22
|
+
#
|
|
23
|
+
# @return [Logger]
|
|
16
24
|
def cef_logger
|
|
17
25
|
@_cef_logger ||= Contrast::Logger::CEFLog.instance.tap(&:build_logger)
|
|
18
26
|
end
|
|
@@ -23,6 +31,10 @@ module Contrast
|
|
|
23
31
|
# instance methods and will initialize new instances for where they're needed
|
|
24
32
|
class Interface
|
|
25
33
|
include InstanceMethods
|
|
34
|
+
include Contrast::Components::ComponentBase
|
|
35
|
+
|
|
36
|
+
CANON_NAME = 'agent.logger'
|
|
37
|
+
CONFIG_VALUES = %w[path level progname].cs__freeze
|
|
26
38
|
|
|
27
39
|
# @return [String, nil]
|
|
28
40
|
attr_accessor :path
|
|
@@ -30,8 +42,14 @@ module Contrast
|
|
|
30
42
|
attr_accessor :level
|
|
31
43
|
# @return [String, nil]
|
|
32
44
|
attr_accessor :progname
|
|
45
|
+
# @return [String]
|
|
46
|
+
attr_reader :canon_name
|
|
47
|
+
# @return [Array]
|
|
48
|
+
attr_reader :config_values
|
|
33
49
|
|
|
34
50
|
def initialize hsh = {}
|
|
51
|
+
@config_values = CONFIG_VALUES
|
|
52
|
+
@canon_name = CANON_NAME
|
|
35
53
|
return unless hsh
|
|
36
54
|
|
|
37
55
|
@path = hsh[:path]
|
|
@@ -0,0 +1,36 @@
|
|
|
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/components/base'
|
|
5
|
+
|
|
6
|
+
module Contrast
|
|
7
|
+
module Components
|
|
8
|
+
module Polling
|
|
9
|
+
# A wrapper build around the agent.polling config
|
|
10
|
+
class Interface
|
|
11
|
+
include Contrast::Components::ComponentBase
|
|
12
|
+
|
|
13
|
+
# @return [Integer, nil]
|
|
14
|
+
attr_reader :server_settings_ms
|
|
15
|
+
# @return [String]
|
|
16
|
+
attr_reader :canon_name
|
|
17
|
+
# @return [Array]
|
|
18
|
+
attr_reader :config_values
|
|
19
|
+
# @return [Integer, nil]
|
|
20
|
+
attr_reader :batch_reporting_interval_ms
|
|
21
|
+
|
|
22
|
+
CANON_NAME = 'agent.polling'
|
|
23
|
+
CONFIG_VALUES = %w[server_settings_ms batch_reporting_interval_ms].cs__freeze
|
|
24
|
+
|
|
25
|
+
def initialize hsh = {}
|
|
26
|
+
@config_values = CONFIG_VALUES
|
|
27
|
+
@canon_name = CANON_NAME
|
|
28
|
+
return unless hsh
|
|
29
|
+
|
|
30
|
+
@server_settings_ms = hsh[:server_settings_ms]
|
|
31
|
+
@batch_reporting_interval_ms = hsh[:batch_reporting_interval_ms]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -14,12 +14,23 @@ module Contrast
|
|
|
14
14
|
include Contrast::Components::ComponentBase
|
|
15
15
|
include Contrast::Config::BaseConfiguration
|
|
16
16
|
|
|
17
|
+
CANON_NAME = 'protect'
|
|
18
|
+
CONFIG_VALUES = %w[enabled?].cs__freeze
|
|
19
|
+
RULES = 'rules'
|
|
20
|
+
MODE = 'mode'
|
|
21
|
+
|
|
17
22
|
# @return [Boolean, nil]
|
|
18
23
|
attr_accessor :enable
|
|
24
|
+
# @return [String]
|
|
25
|
+
attr_reader :canon_name
|
|
26
|
+
# @return [Array]
|
|
27
|
+
attr_reader :config_values
|
|
19
28
|
# @return [Boolean, nil]
|
|
20
29
|
attr_accessor :agent_lib
|
|
21
30
|
|
|
22
31
|
def initialize hsh = {}
|
|
32
|
+
@config_values = CONFIG_VALUES
|
|
33
|
+
@canon_name = CANON_NAME
|
|
23
34
|
return unless hsh
|
|
24
35
|
|
|
25
36
|
@_exceptions = Contrast::Config::ExceptionConfiguration.new(hsh[:exceptions])
|
|
@@ -57,6 +68,9 @@ module Contrast
|
|
|
57
68
|
::Contrast::SETTINGS.protect_state.enabled == true
|
|
58
69
|
end
|
|
59
70
|
|
|
71
|
+
# Current Configuration for the protect rules
|
|
72
|
+
#
|
|
73
|
+
# @return [Contrast::Config::ProtectRulesConfiguration]
|
|
60
74
|
def rule_config
|
|
61
75
|
::Contrast::CONFIG.protect.rules
|
|
62
76
|
end
|
|
@@ -65,11 +79,17 @@ module Contrast
|
|
|
65
79
|
# protect rules.
|
|
66
80
|
#
|
|
67
81
|
# @return defend_rules[Hash<Contrast::SETTINGS.protect_state.rules>]
|
|
68
|
-
#
|
|
69
82
|
def defend_rules
|
|
70
83
|
::Contrast::SETTINGS.protect_state.rules
|
|
71
84
|
end
|
|
72
85
|
|
|
86
|
+
# The Contrast::CONFIG.protect.rules is object so we need to check it's
|
|
87
|
+
# corresponding method call for each rule of interest. If there is no
|
|
88
|
+
# status available we search for any Settings available received form
|
|
89
|
+
# TS response.
|
|
90
|
+
#
|
|
91
|
+
# @param rule_id [String]
|
|
92
|
+
# @return mode [Symbol]
|
|
73
93
|
def rule_mode rule_id
|
|
74
94
|
str = rule_id.tr('-', '_')
|
|
75
95
|
::Contrast::CONFIG.protect.rules[str]&.applicable_mode ||
|
|
@@ -77,6 +97,9 @@ module Contrast
|
|
|
77
97
|
:NO_ACTION
|
|
78
98
|
end
|
|
79
99
|
|
|
100
|
+
# Name of the protect rule
|
|
101
|
+
#
|
|
102
|
+
# @return [String]
|
|
80
103
|
def rule name
|
|
81
104
|
::Contrast::SETTINGS.protect_state.rules[name]
|
|
82
105
|
end
|
|
@@ -104,8 +127,32 @@ module Contrast
|
|
|
104
127
|
@_forcibly_disabled = false?(::Contrast::CONFIG.protect.enable)
|
|
105
128
|
end
|
|
106
129
|
|
|
130
|
+
# Converts current configuration to effective config values class and appends them to
|
|
131
|
+
# EffectiveConfig class.
|
|
132
|
+
#
|
|
133
|
+
# @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
|
|
134
|
+
def to_effective_config effective_config
|
|
135
|
+
super
|
|
136
|
+
protect_rules_to_effective_config(effective_config)
|
|
137
|
+
end
|
|
138
|
+
|
|
107
139
|
private
|
|
108
140
|
|
|
141
|
+
# @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
|
|
142
|
+
def protect_rules_to_effective_config effective_config
|
|
143
|
+
return unless defend_rules
|
|
144
|
+
|
|
145
|
+
defend_rules.each do |key, value|
|
|
146
|
+
next unless key && value
|
|
147
|
+
|
|
148
|
+
config_prefix = "#{ CANON_NAME }.#{ RULES }.#{ key }"
|
|
149
|
+
name_prefix = "#{ CONTRAST }.#{ CANON_NAME }.#{ RULES }.#{ key }"
|
|
150
|
+
add_single_effective_value(effective_config, ENABLE, value.enabled?, config_prefix, name_prefix)
|
|
151
|
+
# Get the mode by checking Current Configs or Settings received:
|
|
152
|
+
add_single_effective_value(effective_config, MODE, rule_mode(key), config_prefix, name_prefix)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
109
156
|
def forcibly_enabled?
|
|
110
157
|
return @_forcibly_enabled unless @_forcibly_enabled.nil?
|
|
111
158
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Copyright (c) 2022 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/components/base'
|
|
5
|
+
|
|
4
6
|
module Contrast
|
|
5
7
|
module Components
|
|
6
8
|
module Ruby
|
|
@@ -23,11 +25,24 @@ module Contrast
|
|
|
23
25
|
].cs__freeze
|
|
24
26
|
|
|
25
27
|
DEFAULT_UNINSTRUMENTED_NAMESPACES = %w[FactoryGirl FactoryBot].cs__freeze
|
|
28
|
+
CANON_NAME = 'agent.ruby'
|
|
29
|
+
CONFIG_VALUES = %w[
|
|
30
|
+
disabled_agent_rake_tasks
|
|
31
|
+
propagate_yield require_scan
|
|
32
|
+
non_request_tracking
|
|
33
|
+
uninstrument_namespace
|
|
34
|
+
].cs__freeze
|
|
26
35
|
|
|
27
36
|
attr_writer :disabled_agent_rake_tasks, :exceptions, :propagate_yield, :require_scan,
|
|
28
37
|
:non_request_tracking, :uninstrument_namespace
|
|
38
|
+
# @return [String]
|
|
39
|
+
attr_reader :canon_name
|
|
40
|
+
# @return [Array]
|
|
41
|
+
attr_reader :config_values
|
|
29
42
|
|
|
30
43
|
def initialize hsh = {}
|
|
44
|
+
@config_values = CONFIG_VALUES
|
|
45
|
+
@canon_name = CANON_NAME
|
|
31
46
|
return unless hsh
|
|
32
47
|
|
|
33
48
|
@disabled_agent_rake_tasks = hsh[:disabled_agent_rake_tasks]
|
|
@@ -28,10 +28,10 @@ module Contrast
|
|
|
28
28
|
settings = ::Contrast::SETTINGS&.assess_state&.sampling_settings
|
|
29
29
|
{
|
|
30
30
|
enabled: enabled?(config_settings, settings),
|
|
31
|
-
baseline:
|
|
32
|
-
request_frequency:
|
|
33
|
-
response_frequency:
|
|
34
|
-
window:
|
|
31
|
+
baseline: check_baseline(config_settings, settings),
|
|
32
|
+
request_frequency: check_request_frequency(config_settings, settings),
|
|
33
|
+
response_frequency: check_response_frequency(config_settings, settings),
|
|
34
|
+
window: check_window(config_settings, settings)
|
|
35
35
|
}
|
|
36
36
|
end
|
|
37
37
|
end
|
|
@@ -45,7 +45,8 @@ module Contrast
|
|
|
45
45
|
|
|
46
46
|
# @param config_settings [Contrast::Config::SamplingConfiguration] the Sampling configuration as provided by
|
|
47
47
|
# local user input
|
|
48
|
-
# @param settings [Contrast::
|
|
48
|
+
# @param settings [Contrast::Agent::Reporting::Settings::Sampling, nil] the Sampling settings as provided by
|
|
49
|
+
# TeamServer
|
|
49
50
|
# @return [Boolean] the resolution of the config_settings, settings, and default value
|
|
50
51
|
def enabled? config_settings, settings
|
|
51
52
|
true?([config_settings&.enable, settings&.enabled, DEFAULT_SAMPLING_ENABLED].compact[0])
|
|
@@ -53,35 +54,39 @@ module Contrast
|
|
|
53
54
|
|
|
54
55
|
# @param config_settings [Contrast::Config::SamplingConfiguration] the Sampling configuration as provided by
|
|
55
56
|
# local user input
|
|
56
|
-
# @param settings [Contrast::
|
|
57
|
+
# @param settings [Contrast::Agent::Reporting::Settings::Sampling] the Sampling settings as provided by
|
|
58
|
+
# TeamServer
|
|
57
59
|
# @return [Integer] the resolution of the config_settings, settings, and default value
|
|
58
|
-
def
|
|
60
|
+
def check_baseline config_settings, settings
|
|
59
61
|
[config_settings&.baseline, settings&.baseline].map(&:to_i).find(&:positive?) || DEFAULT_SAMPLING_BASELINE
|
|
60
62
|
end
|
|
61
63
|
|
|
62
64
|
# @param config_settings [Contrast::Config::SamplingConfiguration] the Sampling configuration as provided by
|
|
63
65
|
# local user input
|
|
64
|
-
# @param settings [Contrast::
|
|
66
|
+
# @param settings [Contrast::Agent::Reporting::Settings::Sampling] the Sampling settings as provided by
|
|
67
|
+
# TeamServer
|
|
65
68
|
# @return [Integer] the resolution of the config_settings, settings, and default value
|
|
66
|
-
def
|
|
69
|
+
def check_request_frequency config_settings, settings
|
|
67
70
|
[config_settings&.request_frequency, settings&.request_frequency].map(&:to_i).find(&:positive?) ||
|
|
68
71
|
DEFAULT_SAMPLING_REQUEST_FREQUENCY
|
|
69
72
|
end
|
|
70
73
|
|
|
71
74
|
# @param config_settings [Contrast::Config::SamplingConfiguration] the Sampling configuration as provided by
|
|
72
75
|
# local user input
|
|
73
|
-
# @param settings [Contrast::
|
|
76
|
+
# @param settings [Contrast::Agent::Reporting::Settings::Sampling] the Sampling settings as provided by
|
|
77
|
+
# TeamServer
|
|
74
78
|
# @return [Integer] the resolution of the config_settings, settings, and default value
|
|
75
|
-
def
|
|
79
|
+
def check_response_frequency config_settings, settings
|
|
76
80
|
[config_settings&.response_frequency, settings&.response_frequency].map(&:to_i).find(&:positive?) ||
|
|
77
81
|
DEFAULT_SAMPLING_RESPONSE_FREQUENCY
|
|
78
82
|
end
|
|
79
83
|
|
|
80
84
|
# @param config_settings [Contrast::Config::SamplingConfiguration] the Sampling configuration as provided by
|
|
81
85
|
# local user input
|
|
82
|
-
# @param settings [Contrast::
|
|
86
|
+
# @param settings [Contrast::Agent::Reporting::Settings::Sampling] the Sampling settings as provided by
|
|
87
|
+
# TeamServer
|
|
83
88
|
# @return [Integer] the resolution of the config_settings, settings, and default value
|
|
84
|
-
def
|
|
89
|
+
def check_window config_settings, settings
|
|
85
90
|
[config_settings&.window_ms, settings&.window_ms].map(&:to_i).find(&:positive?) || DEFAULT_SAMPLING_WINDOW_MS
|
|
86
91
|
end
|
|
87
92
|
end
|
|
@@ -94,8 +99,13 @@ module Contrast
|
|
|
94
99
|
|
|
95
100
|
class Interface # :nodoc:
|
|
96
101
|
include InstanceMethods
|
|
102
|
+
extend ClassMethods
|
|
97
103
|
include Contrast::Config::BaseConfiguration
|
|
98
104
|
|
|
105
|
+
CANON_NAME = 'assess.sampling'
|
|
106
|
+
NAME_PREFIX = "#{ CONTRAST }.#{ CANON_NAME }"
|
|
107
|
+
CONFIG_VALUES = %w[enable baseline request_frequency response_frequency window_ms].cs__freeze
|
|
108
|
+
|
|
99
109
|
# @return [Integer, nil]
|
|
100
110
|
attr_reader :baseline
|
|
101
111
|
# @return [Integer, nil]
|
|
@@ -104,8 +114,11 @@ module Contrast
|
|
|
104
114
|
attr_reader :response_frequency
|
|
105
115
|
# @return [Integer, nil]
|
|
106
116
|
attr_reader :window_ms
|
|
117
|
+
# @return [String]
|
|
118
|
+
attr_reader :canon_name
|
|
107
119
|
|
|
108
120
|
def initialize hsh = {}
|
|
121
|
+
@canon_name = CANON_NAME
|
|
109
122
|
return unless hsh
|
|
110
123
|
|
|
111
124
|
@enable = hsh[:enable]
|
|
@@ -119,6 +132,50 @@ module Contrast
|
|
|
119
132
|
def enable
|
|
120
133
|
!!@enable
|
|
121
134
|
end
|
|
135
|
+
|
|
136
|
+
# Converts current configuration to effective config values class and appends them to
|
|
137
|
+
# EffectiveConfig class.
|
|
138
|
+
#
|
|
139
|
+
# @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig]
|
|
140
|
+
def to_effective_config effective_config
|
|
141
|
+
confirm_sources
|
|
142
|
+
|
|
143
|
+
add_single_effective_value(effective_config, 'enable', sampling_control[:enabled], canon_name, NAME_PREFIX)
|
|
144
|
+
add_single_effective_value(effective_config, 'baseline', sampling_control[:baseline], canon_name, NAME_PREFIX)
|
|
145
|
+
add_single_effective_value(effective_config, 'window_ms', sampling_control[:window], canon_name, NAME_PREFIX)
|
|
146
|
+
add_single_effective_value(effective_config,
|
|
147
|
+
'request_frequency',
|
|
148
|
+
sampling_control[:request_frequency],
|
|
149
|
+
canon_name,
|
|
150
|
+
NAME_PREFIX)
|
|
151
|
+
add_single_effective_value(effective_config,
|
|
152
|
+
'response_frequency',
|
|
153
|
+
sampling_control[:response_frequency],
|
|
154
|
+
canon_name,
|
|
155
|
+
NAME_PREFIX)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
private
|
|
159
|
+
|
|
160
|
+
# Confirm the sources for the sample entries to ensure that we use 'Default' if we've fallen
|
|
161
|
+
# back to the default values.
|
|
162
|
+
def confirm_sources
|
|
163
|
+
if sampling_control[:enabled] == DEFAULT_SAMPLING_ENABLED
|
|
164
|
+
Contrast::CONFIG.sources.set('assess.sampling.enable', Contrast::Components::Config::Sources::DEFAULT)
|
|
165
|
+
end
|
|
166
|
+
if sampling_control[:window] == DEFAULT_SAMPLING_WINDOW_MS
|
|
167
|
+
Contrast::CONFIG.sources.set('assess.sampling.window_ms', Contrast::Components::Config::Sources::DEFAULT)
|
|
168
|
+
end
|
|
169
|
+
{
|
|
170
|
+
'baseline' => :baseline,
|
|
171
|
+
'request_frequency' => :request_frequency,
|
|
172
|
+
'response_frequency' => :response_frequency
|
|
173
|
+
}.each do |k, v|
|
|
174
|
+
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
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
122
179
|
end
|
|
123
180
|
end
|
|
124
181
|
end
|
|
@@ -1,17 +1,30 @@
|
|
|
1
1
|
# Copyright (c) 2022 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/components/base'
|
|
5
|
+
|
|
4
6
|
module Contrast
|
|
5
7
|
module Components
|
|
6
8
|
module SecurityLogger
|
|
7
9
|
# Here we will read and store the setting for the CEF Logging functionality
|
|
8
10
|
class Interface
|
|
11
|
+
include Contrast::Components::ComponentBase
|
|
12
|
+
|
|
13
|
+
CANON_NAME = 'agent.security_logger'
|
|
14
|
+
CONFIG_VALUES = %w[path level].cs__freeze
|
|
15
|
+
|
|
9
16
|
# @return [String, nil]
|
|
10
17
|
attr_accessor :path
|
|
11
18
|
# @return [String, nil]
|
|
12
19
|
attr_accessor :level
|
|
20
|
+
# @return [String]
|
|
21
|
+
attr_reader :canon_name
|
|
22
|
+
# @return [Array]
|
|
23
|
+
attr_reader :config_values
|
|
13
24
|
|
|
14
25
|
def initialize hsh = {}
|
|
26
|
+
@config_values = CONFIG_VALUES
|
|
27
|
+
@canon_name = CANON_NAME
|
|
15
28
|
return unless hsh
|
|
16
29
|
|
|
17
30
|
@path = hsh[:path]
|