contrast-agent 4.3.2 → 4.7.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/.gitmodules +1 -1
- data/.simplecov +1 -1
- data/Gemfile +1 -1
- data/LICENSE.txt +1 -1
- data/Rakefile +2 -3
- data/exe/contrast_service +1 -1
- data/ext/build_funchook.rb +4 -4
- data/ext/cs__assess_active_record_named/cs__active_record_named.c +1 -1
- data/ext/cs__assess_active_record_named/extconf.rb +1 -1
- data/ext/cs__assess_array/cs__assess_array.c +1 -1
- data/ext/cs__assess_array/extconf.rb +1 -1
- data/ext/cs__assess_basic_object/cs__assess_basic_object.c +1 -1
- data/ext/cs__assess_basic_object/extconf.rb +1 -1
- data/ext/cs__assess_fiber_track/cs__assess_fiber_track.c +1 -1
- data/ext/cs__assess_fiber_track/extconf.rb +1 -1
- data/ext/cs__assess_hash/cs__assess_hash.c +4 -2
- data/ext/cs__assess_hash/extconf.rb +1 -1
- data/ext/cs__assess_kernel/cs__assess_kernel.c +1 -1
- data/ext/cs__assess_kernel/extconf.rb +1 -1
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +1 -1
- data/ext/cs__assess_marshal_module/extconf.rb +1 -1
- data/ext/cs__assess_module/cs__assess_module.c +1 -1
- data/ext/cs__assess_module/extconf.rb +1 -1
- data/ext/cs__assess_regexp/cs__assess_regexp.c +1 -1
- data/ext/cs__assess_regexp/extconf.rb +1 -1
- data/ext/cs__assess_string/cs__assess_string.c +1 -1
- data/ext/cs__assess_string/extconf.rb +1 -1
- data/ext/cs__assess_string_interpolation26/cs__assess_string_interpolation26.c +1 -1
- data/ext/cs__assess_string_interpolation26/extconf.rb +1 -1
- data/ext/cs__assess_yield_track/cs__assess_yield_track.c +1 -1
- data/ext/cs__assess_yield_track/extconf.rb +1 -1
- data/ext/cs__common/cs__common.c +5 -5
- data/ext/cs__common/cs__common.h +4 -4
- data/ext/cs__common/extconf.rb +1 -1
- data/ext/cs__contrast_patch/cs__contrast_patch.c +22 -25
- data/ext/cs__contrast_patch/extconf.rb +1 -1
- data/ext/cs__protect_kernel/cs__protect_kernel.c +1 -1
- data/ext/cs__protect_kernel/extconf.rb +1 -1
- data/ext/extconf_common.rb +2 -6
- data/lib/contrast-agent.rb +1 -1
- data/lib/contrast.rb +20 -1
- data/lib/contrast/agent.rb +6 -4
- data/lib/contrast/agent/assess.rb +2 -11
- data/lib/contrast/agent/assess/contrast_event.rb +54 -71
- data/lib/contrast/agent/assess/contrast_object.rb +7 -4
- data/lib/contrast/agent/assess/events/event_factory.rb +3 -2
- data/lib/contrast/agent/assess/events/source_event.rb +7 -2
- data/lib/contrast/agent/assess/finalizers/freeze.rb +1 -1
- data/lib/contrast/agent/assess/finalizers/hash.rb +33 -34
- data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +34 -16
- data/lib/contrast/agent/assess/policy/patcher.rb +11 -18
- data/lib/contrast/agent/assess/policy/policy.rb +1 -1
- data/lib/contrast/agent/assess/policy/policy_node.rb +26 -34
- data/lib/contrast/agent/assess/policy/policy_scanner.rb +1 -1
- data/lib/contrast/agent/assess/policy/preshift.rb +4 -2
- data/lib/contrast/agent/assess/policy/propagation_method.rb +32 -30
- data/lib/contrast/agent/assess/policy/propagation_node.rb +20 -9
- data/lib/contrast/agent/assess/policy/propagator.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/append.rb +29 -14
- data/lib/contrast/agent/assess/policy/propagator/base.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/center.rb +3 -2
- data/lib/contrast/agent/assess/policy/propagator/custom.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/database_write.rb +22 -17
- data/lib/contrast/agent/assess/policy/propagator/insert.rb +4 -2
- data/lib/contrast/agent/assess/policy/propagator/keep.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/match_data.rb +3 -2
- data/lib/contrast/agent/assess/policy/propagator/next.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/prepend.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/remove.rb +23 -19
- data/lib/contrast/agent/assess/policy/propagator/replace.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/reverse.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/select.rb +3 -13
- data/lib/contrast/agent/assess/policy/propagator/splat.rb +24 -14
- data/lib/contrast/agent/assess/policy/propagator/split.rb +18 -15
- data/lib/contrast/agent/assess/policy/propagator/substitution.rb +32 -22
- data/lib/contrast/agent/assess/policy/propagator/trim.rb +64 -45
- data/lib/contrast/agent/assess/policy/rewriter_patch.rb +7 -4
- data/lib/contrast/agent/assess/policy/source_method.rb +92 -81
- data/lib/contrast/agent/assess/policy/source_node.rb +1 -1
- data/lib/contrast/agent/assess/policy/source_validation/cross_site_validator.rb +8 -6
- data/lib/contrast/agent/assess/policy/source_validation/source_validation.rb +2 -4
- data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +7 -3
- data/lib/contrast/agent/assess/policy/trigger/xpath.rb +7 -8
- data/lib/contrast/agent/assess/policy/trigger_method.rb +109 -76
- data/lib/contrast/agent/assess/policy/trigger_node.rb +33 -11
- data/lib/contrast/agent/assess/policy/trigger_validation/redos_validator.rb +60 -0
- data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +3 -5
- data/lib/contrast/agent/assess/policy/trigger_validation/trigger_validation.rb +7 -5
- data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +4 -13
- data/lib/contrast/agent/assess/properties.rb +1 -3
- data/lib/contrast/agent/assess/property/evented.rb +9 -6
- data/lib/contrast/agent/assess/property/tagged.rb +38 -20
- data/lib/contrast/agent/assess/property/updated.rb +1 -1
- data/lib/contrast/agent/assess/rule/provider.rb +1 -1
- data/lib/contrast/agent/assess/rule/provider/hardcoded_key.rb +12 -6
- data/lib/contrast/agent/assess/rule/provider/hardcoded_password.rb +5 -2
- data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +4 -6
- data/lib/contrast/agent/assess/tag.rb +1 -1
- data/lib/contrast/agent/assess/tracker.rb +2 -2
- data/lib/contrast/agent/at_exit_hook.rb +1 -1
- data/lib/contrast/agent/class_reopener.rb +4 -2
- data/lib/contrast/agent/deadzone/policy/deadzone_node.rb +1 -1
- data/lib/contrast/agent/deadzone/policy/policy.rb +7 -3
- data/lib/contrast/agent/disable_reaction.rb +2 -4
- data/lib/contrast/agent/exclusion_matcher.rb +6 -12
- data/lib/contrast/agent/inventory.rb +1 -2
- data/lib/contrast/agent/inventory/dependencies.rb +3 -1
- data/lib/contrast/agent/inventory/dependency_analysis.rb +1 -1
- data/lib/contrast/agent/inventory/dependency_usage_analysis.rb +35 -23
- data/lib/contrast/agent/inventory/policy/datastores.rb +1 -1
- data/lib/contrast/agent/inventory/policy/policy.rb +1 -1
- data/lib/contrast/agent/inventory/policy/trigger_node.rb +1 -1
- data/lib/contrast/agent/middleware.rb +111 -110
- data/lib/contrast/agent/module_data.rb +4 -4
- data/lib/contrast/agent/patching/policy/after_load_patch.rb +1 -1
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +9 -4
- data/lib/contrast/agent/patching/policy/method_policy.rb +7 -3
- data/lib/contrast/agent/patching/policy/module_policy.rb +15 -8
- data/lib/contrast/agent/patching/policy/patch.rb +23 -29
- data/lib/contrast/agent/patching/policy/patch_status.rb +8 -9
- data/lib/contrast/agent/patching/policy/patcher.rb +72 -64
- data/lib/contrast/agent/patching/policy/policy.rb +14 -21
- data/lib/contrast/agent/patching/policy/policy_node.rb +15 -5
- data/lib/contrast/agent/patching/policy/trigger_node.rb +26 -10
- data/lib/contrast/agent/protect/policy/applies_command_injection_rule.rb +2 -2
- data/lib/contrast/agent/protect/policy/applies_deserialization_rule.rb +2 -2
- data/lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb +2 -2
- data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +3 -4
- data/lib/contrast/agent/protect/policy/applies_sqli_rule.rb +2 -2
- data/lib/contrast/agent/protect/policy/applies_xxe_rule.rb +6 -10
- data/lib/contrast/agent/protect/policy/policy.rb +1 -1
- data/lib/contrast/agent/protect/policy/rule_applicator.rb +6 -6
- data/lib/contrast/agent/protect/policy/trigger_node.rb +1 -1
- data/lib/contrast/agent/protect/rule.rb +1 -1
- data/lib/contrast/agent/protect/rule/base.rb +19 -33
- data/lib/contrast/agent/protect/rule/base_service.rb +10 -6
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +15 -19
- data/lib/contrast/agent/protect/rule/default_scanner.rb +1 -1
- data/lib/contrast/agent/protect/rule/deserialization.rb +7 -14
- data/lib/contrast/agent/protect/rule/http_method_tampering.rb +4 -15
- data/lib/contrast/agent/protect/rule/no_sqli.rb +7 -3
- data/lib/contrast/agent/protect/rule/no_sqli/mongo_no_sql_scanner.rb +2 -4
- data/lib/contrast/agent/protect/rule/path_traversal.rb +6 -6
- data/lib/contrast/agent/protect/rule/sqli.rb +19 -13
- data/lib/contrast/agent/protect/rule/sqli/default_sql_scanner.rb +1 -1
- data/lib/contrast/agent/protect/rule/sqli/mysql_sql_scanner.rb +1 -1
- data/lib/contrast/agent/protect/rule/sqli/postgres_sql_scanner.rb +2 -2
- data/lib/contrast/agent/protect/rule/sqli/sqlite_sql_scanner.rb +1 -1
- data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +2 -2
- data/lib/contrast/agent/protect/rule/xss.rb +2 -2
- data/lib/contrast/agent/protect/rule/xxe.rb +6 -13
- data/lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb +2 -3
- data/lib/contrast/agent/railtie.rb +1 -1
- data/lib/contrast/agent/reaction_processor.rb +12 -11
- data/lib/contrast/agent/request.rb +25 -24
- data/lib/contrast/agent/request_context.rb +25 -23
- data/lib/contrast/agent/request_handler.rb +1 -1
- data/lib/contrast/agent/response.rb +1 -1
- data/lib/contrast/agent/rewriter.rb +6 -4
- data/lib/contrast/agent/rule_set.rb +3 -3
- data/lib/contrast/agent/scope.rb +1 -1
- data/lib/contrast/agent/service_heartbeat.rb +3 -4
- data/lib/contrast/agent/static_analysis.rb +1 -1
- data/lib/contrast/agent/thread.rb +2 -2
- data/lib/contrast/agent/thread_watcher.rb +21 -6
- data/lib/contrast/agent/tracepoint_hook.rb +2 -2
- data/lib/contrast/agent/version.rb +2 -2
- data/lib/contrast/agent/worker_thread.rb +1 -1
- data/lib/contrast/api.rb +1 -1
- data/lib/contrast/api/communication.rb +1 -1
- data/lib/contrast/api/communication/connection_status.rb +1 -1
- data/lib/contrast/api/communication/messaging_queue.rb +19 -22
- data/lib/contrast/api/communication/response_processor.rb +13 -8
- data/lib/contrast/api/communication/service_lifecycle.rb +5 -3
- data/lib/contrast/api/communication/socket.rb +1 -1
- data/lib/contrast/api/communication/socket_client.rb +30 -35
- data/lib/contrast/api/communication/speedracer.rb +6 -10
- data/lib/contrast/api/communication/tcp_socket.rb +1 -1
- data/lib/contrast/api/communication/unix_socket.rb +1 -1
- data/lib/contrast/api/decorators.rb +3 -1
- data/lib/contrast/api/decorators/address.rb +1 -1
- data/lib/contrast/api/decorators/agent_startup.rb +58 -0
- data/lib/contrast/api/decorators/application_settings.rb +1 -1
- data/lib/contrast/api/decorators/application_startup.rb +57 -0
- data/lib/contrast/api/decorators/application_update.rb +1 -1
- data/lib/contrast/api/decorators/http_request.rb +1 -1
- data/lib/contrast/api/decorators/input_analysis.rb +1 -1
- data/lib/contrast/api/decorators/instrumentation_mode.rb +37 -0
- data/lib/contrast/api/decorators/library.rb +9 -7
- data/lib/contrast/api/decorators/library_usage_update.rb +1 -1
- data/lib/contrast/api/decorators/message.rb +4 -4
- data/lib/contrast/api/decorators/rasp_rule_sample.rb +1 -1
- data/lib/contrast/api/decorators/route_coverage.rb +16 -6
- data/lib/contrast/api/decorators/server_features.rb +1 -1
- data/lib/contrast/api/decorators/trace_event.rb +46 -16
- data/lib/contrast/api/decorators/trace_event_object.rb +2 -4
- data/lib/contrast/api/decorators/trace_event_signature.rb +1 -1
- data/lib/contrast/api/decorators/trace_taint_range.rb +1 -1
- data/lib/contrast/api/decorators/trace_taint_range_tags.rb +2 -7
- data/lib/contrast/api/decorators/user_input.rb +1 -1
- data/lib/contrast/components/agent.rb +16 -15
- data/lib/contrast/components/app_context.rb +11 -29
- data/lib/contrast/components/assess.rb +6 -11
- data/lib/contrast/components/config.rb +3 -2
- data/lib/contrast/components/contrast_service.rb +8 -9
- data/lib/contrast/components/heap_dump.rb +1 -1
- data/lib/contrast/components/interface.rb +4 -3
- data/lib/contrast/components/inventory.rb +1 -1
- data/lib/contrast/components/logger.rb +1 -1
- data/lib/contrast/components/protect.rb +11 -14
- data/lib/contrast/components/sampling.rb +55 -7
- data/lib/contrast/components/scope.rb +2 -1
- data/lib/contrast/components/settings.rb +29 -99
- data/lib/contrast/config.rb +1 -1
- data/lib/contrast/config/agent_configuration.rb +1 -1
- data/lib/contrast/config/application_configuration.rb +1 -1
- data/lib/contrast/config/assess_configuration.rb +1 -1
- data/lib/contrast/config/assess_rules_configuration.rb +2 -4
- data/lib/contrast/config/base_configuration.rb +5 -6
- data/lib/contrast/config/default_value.rb +1 -1
- data/lib/contrast/config/exception_configuration.rb +2 -6
- data/lib/contrast/config/heap_dump_configuration.rb +13 -7
- data/lib/contrast/config/inventory_configuration.rb +1 -1
- data/lib/contrast/config/logger_configuration.rb +2 -6
- data/lib/contrast/config/protect_configuration.rb +1 -1
- data/lib/contrast/config/protect_rule_configuration.rb +23 -1
- data/lib/contrast/config/protect_rules_configuration.rb +1 -1
- data/lib/contrast/config/root_configuration.rb +1 -1
- data/lib/contrast/config/ruby_configuration.rb +1 -1
- data/lib/contrast/config/sampling_configuration.rb +1 -1
- data/lib/contrast/config/server_configuration.rb +1 -1
- data/lib/contrast/config/service_configuration.rb +1 -1
- data/lib/contrast/configuration.rb +4 -15
- data/lib/contrast/delegators/input_analysis.rb +12 -0
- data/lib/contrast/extension/assess.rb +1 -1
- data/lib/contrast/extension/assess/array.rb +2 -7
- data/lib/contrast/extension/assess/erb.rb +2 -8
- data/lib/contrast/extension/assess/eval_trigger.rb +3 -11
- data/lib/contrast/extension/assess/exec_trigger.rb +4 -14
- data/lib/contrast/extension/assess/fiber.rb +3 -13
- data/lib/contrast/extension/assess/hash.rb +1 -1
- data/lib/contrast/extension/assess/kernel.rb +3 -10
- data/lib/contrast/extension/assess/marshal.rb +3 -11
- data/lib/contrast/extension/assess/regexp.rb +2 -7
- data/lib/contrast/extension/assess/string.rb +4 -2
- data/lib/contrast/extension/delegator.rb +1 -1
- data/lib/contrast/extension/inventory.rb +1 -1
- data/lib/contrast/extension/kernel.rb +5 -3
- data/lib/contrast/extension/module.rb +1 -1
- data/lib/contrast/extension/protect.rb +1 -1
- data/lib/contrast/extension/protect/kernel.rb +1 -1
- data/lib/contrast/extension/protect/psych.rb +1 -1
- data/lib/contrast/extension/thread.rb +1 -1
- data/lib/contrast/framework/base_support.rb +1 -1
- data/lib/contrast/framework/manager.rb +14 -17
- data/lib/contrast/framework/platform_version.rb +1 -1
- data/lib/contrast/framework/rack/patch/session_cookie.rb +6 -19
- data/lib/contrast/framework/rack/patch/support.rb +7 -5
- data/lib/contrast/framework/rack/support.rb +1 -1
- data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +1 -1
- data/lib/contrast/framework/rails/patch/assess_configuration.rb +8 -3
- data/lib/contrast/framework/rails/patch/rails_application_configuration.rb +4 -4
- data/lib/contrast/framework/rails/patch/support.rb +5 -3
- data/lib/contrast/framework/rails/rewrite/action_controller_railties_helper_inherited.rb +5 -2
- data/lib/contrast/framework/rails/rewrite/active_record_attribute_methods_read.rb +3 -1
- data/lib/contrast/framework/rails/rewrite/active_record_named.rb +3 -1
- data/lib/contrast/framework/rails/rewrite/active_record_time_zone_inherited.rb +3 -1
- data/lib/contrast/framework/rails/support.rb +45 -46
- data/lib/contrast/framework/sinatra/support.rb +103 -42
- data/lib/contrast/funchook/funchook.rb +2 -6
- data/lib/contrast/logger/application.rb +13 -10
- data/lib/contrast/logger/format.rb +3 -6
- data/lib/contrast/logger/log.rb +36 -19
- data/lib/contrast/logger/request.rb +2 -3
- data/lib/contrast/logger/time.rb +1 -1
- data/lib/contrast/security_exception.rb +2 -2
- data/lib/contrast/tasks/config.rb +1 -1
- data/lib/contrast/tasks/service.rb +6 -2
- data/lib/contrast/utils/assess/sampling_util.rb +1 -1
- data/lib/contrast/utils/assess/tracking_util.rb +2 -3
- data/lib/contrast/utils/class_util.rb +18 -12
- data/lib/contrast/utils/duck_utils.rb +1 -1
- data/lib/contrast/utils/env_configuration_item.rb +1 -1
- data/lib/contrast/utils/hash_digest.rb +16 -24
- data/lib/contrast/utils/heap_dump_util.rb +104 -88
- data/lib/contrast/utils/invalid_configuration_util.rb +22 -13
- data/lib/contrast/utils/inventory_util.rb +1 -1
- data/lib/contrast/utils/io_util.rb +2 -2
- data/lib/contrast/utils/job_servers_running.rb +10 -5
- data/lib/contrast/utils/object_share.rb +1 -1
- data/lib/contrast/utils/os.rb +3 -2
- data/lib/contrast/utils/preflight_util.rb +1 -1
- data/lib/contrast/utils/resource_loader.rb +1 -1
- data/lib/contrast/utils/ruby_ast_rewriter.rb +3 -2
- data/lib/contrast/utils/sha256_builder.rb +1 -1
- data/lib/contrast/utils/stack_trace_utils.rb +1 -1
- data/lib/contrast/utils/string_utils.rb +1 -1
- data/lib/contrast/utils/tag_util.rb +1 -1
- data/lib/contrast/utils/thread_tracker.rb +1 -1
- data/lib/contrast/utils/timer.rb +1 -1
- data/resources/assess/policy.json +8 -11
- data/resources/deadzone/policy.json +7 -17
- data/ruby-agent.gemspec +66 -27
- data/service_executables/VERSION +1 -1
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
- data/sonar-project.properties +9 -0
- metadata +154 -156
- data/lib/contrast/agent/assess/rule.rb +0 -18
- data/lib/contrast/agent/assess/rule/base.rb +0 -52
- data/lib/contrast/agent/assess/rule/redos.rb +0 -67
- data/lib/contrast/agent/inventory/gemfile_digest_cache.rb +0 -38
- data/lib/contrast/common_agent_configuration.rb +0 -87
- data/lib/contrast/framework/sinatra/patch/base.rb +0 -83
- data/lib/contrast/framework/sinatra/patch/support.rb +0 -27
- data/lib/contrast/utils/prevent_serialization.rb +0 -52
data/lib/contrast/logger/log.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'logger'
|
|
@@ -27,8 +27,7 @@ module Contrast
|
|
|
27
27
|
STDOUT_STR = 'STDOUT'
|
|
28
28
|
STDERR_STR = 'STDERR'
|
|
29
29
|
|
|
30
|
-
attr_reader :previous_path,
|
|
31
|
-
:previous_level
|
|
30
|
+
attr_reader :previous_path, :previous_level
|
|
32
31
|
|
|
33
32
|
def initialize
|
|
34
33
|
update
|
|
@@ -37,28 +36,22 @@ module Contrast
|
|
|
37
36
|
# Given new settings from TeamServer, update our logging to use the new
|
|
38
37
|
# file and level, assuming they weren't set by local configuration.
|
|
39
38
|
#
|
|
40
|
-
# @param log_file [String] the file to which to log
|
|
41
|
-
# @param log_level [String] the level at which to log
|
|
39
|
+
# @param log_file [String] the file to which to log, as provided by TeamServer settings
|
|
40
|
+
# @param log_level [String] the level at which to log, as provided by TeamServer settings
|
|
42
41
|
def update log_file = nil, log_level = nil
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
config_path = config.path&.length.to_i.positive? ? config.path : nil
|
|
46
|
-
config_level = config.level&.length&.positive? ? config.level : nil
|
|
47
|
-
|
|
48
|
-
# config > settings > default
|
|
49
|
-
path = valid_path(config_path || log_file)
|
|
50
|
-
level_const = valid_level(config_level || log_level)
|
|
42
|
+
current_path = find_valid_path(log_file)
|
|
43
|
+
current_level_const = find_valid_level(log_level)
|
|
51
44
|
|
|
52
|
-
path_change =
|
|
53
|
-
level_change =
|
|
45
|
+
path_change = current_path != previous_path
|
|
46
|
+
level_change = current_level_const != previous_level
|
|
54
47
|
|
|
55
48
|
# don't needlessly recreate logger
|
|
56
49
|
return if @_logger && !(path_change || level_change)
|
|
57
50
|
|
|
58
|
-
@previous_path =
|
|
59
|
-
@previous_level =
|
|
51
|
+
@previous_path = current_path
|
|
52
|
+
@previous_level = current_level_const
|
|
60
53
|
|
|
61
|
-
@_logger = build(path:
|
|
54
|
+
@_logger = build(path: current_path, level_const: current_level_const)
|
|
62
55
|
# If we're logging to a new path, then let's start it w/ our helpful
|
|
63
56
|
# data gathering messages
|
|
64
57
|
log_update if path_change
|
|
@@ -108,6 +101,17 @@ module Contrast
|
|
|
108
101
|
logger.extend(Contrast::Logger::Time)
|
|
109
102
|
end
|
|
110
103
|
|
|
104
|
+
# Determine the valid path to which to log, given the precedence of config > settings > default.
|
|
105
|
+
#
|
|
106
|
+
# @param log_file [String, nil] the file to which to log as provided by the settings retrieved from the
|
|
107
|
+
# TeamServer.
|
|
108
|
+
# @return [String] the path to which to log or STDOUT / STDERR if one of those values provided.
|
|
109
|
+
def find_valid_path log_file
|
|
110
|
+
config = CONFIG.root.agent.logger
|
|
111
|
+
config_path = config.path&.length.to_i.positive? ? config.path : nil
|
|
112
|
+
valid_path(config_path || log_file)
|
|
113
|
+
end
|
|
114
|
+
|
|
111
115
|
def valid_path path
|
|
112
116
|
path = path.nil? ? Contrast::Utils::ObjectShare::EMPTY_STRING : path
|
|
113
117
|
return path if path == STDOUT_STR
|
|
@@ -119,7 +123,9 @@ module Contrast
|
|
|
119
123
|
elsif write_permission?(DEFAULT_NAME)
|
|
120
124
|
# Log once when the path is invalid. We'll change to this path, so no
|
|
121
125
|
# need to log again.
|
|
122
|
-
|
|
126
|
+
if previous_path != DEFAULT_NAME
|
|
127
|
+
puts "[!] Unable to write to '#{ path }'. Writing to default log '#{ DEFAULT_NAME }' instead."
|
|
128
|
+
end
|
|
123
129
|
DEFAULT_NAME
|
|
124
130
|
else
|
|
125
131
|
# Log once when the path is invalid. We'll change to this path, so no
|
|
@@ -129,6 +135,17 @@ module Contrast
|
|
|
129
135
|
end
|
|
130
136
|
end
|
|
131
137
|
|
|
138
|
+
# Determine the valid level to which to log, given the precedence of config > settings > default.
|
|
139
|
+
#
|
|
140
|
+
# @param log_level [String, nil] the level at which to log as provided by the settings retrieved from the
|
|
141
|
+
# TeamServer.
|
|
142
|
+
# @return [::Ougai::Logging::Severity] the level at which to log
|
|
143
|
+
def find_valid_level log_level
|
|
144
|
+
config = CONFIG.root.agent.logger
|
|
145
|
+
config_level = config.level&.length&.positive? ? config.level : nil
|
|
146
|
+
valid_level(config_level || log_level)
|
|
147
|
+
end
|
|
148
|
+
|
|
132
149
|
def valid_level level
|
|
133
150
|
level ||= DEFAULT_LEVEL
|
|
134
151
|
level = level.upcase
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'contrast/components/interface'
|
|
@@ -22,8 +22,7 @@ module Contrast
|
|
|
22
22
|
def request_end
|
|
23
23
|
context = Contrast::Agent::REQUEST_TRACKER.current
|
|
24
24
|
elapsed_time = context ? (Contrast::Utils::Timer.now_ms - context.timer.start_ms) : -1
|
|
25
|
-
debug('Ending request analysis',
|
|
26
|
-
elapsed_time_ms: elapsed_time)
|
|
25
|
+
debug('Ending request analysis', elapsed_time_ms: elapsed_time)
|
|
27
26
|
end
|
|
28
27
|
end
|
|
29
28
|
end
|
data/lib/contrast/logger/time.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
module Contrast
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
module Contrast
|
|
@@ -8,7 +8,7 @@ module Contrast
|
|
|
8
8
|
# to be handled by our customer's applications.
|
|
9
9
|
class SecurityException < StandardError
|
|
10
10
|
def initialize rule, message = nil
|
|
11
|
-
super(message || "Rule #{ rule.
|
|
11
|
+
super(message || "Rule #{ rule.rule_name } threw a security exception")
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
14
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'yaml'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'contrast/components/interface'
|
|
@@ -74,7 +74,11 @@ module Contrast
|
|
|
74
74
|
sleep(0.05) while Contrast::Utils::OS.running?
|
|
75
75
|
end
|
|
76
76
|
watcher.join(1)
|
|
77
|
-
|
|
77
|
+
if Contrast::Utils::OS.running?
|
|
78
|
+
puts 'Contrast Service did not stop.'
|
|
79
|
+
else
|
|
80
|
+
puts 'Contrast Service stopped successfully.'
|
|
81
|
+
end
|
|
78
82
|
else
|
|
79
83
|
puts 'Contrast Service is not already running. No need to stop.'
|
|
80
84
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'singleton'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'contrast/agent/assess/tracker'
|
|
@@ -53,8 +53,7 @@ module Contrast
|
|
|
53
53
|
idx += 1
|
|
54
54
|
if Contrast::Utils::DuckUtils.iterable_hash?(obj)
|
|
55
55
|
obj.each_pair do |k, v|
|
|
56
|
-
return true if _tracked?(k, idx)
|
|
57
|
-
return true if _tracked?(v, idx)
|
|
56
|
+
return true if _tracked?(k, idx) || _tracked?(v, idx)
|
|
58
57
|
end
|
|
59
58
|
false
|
|
60
59
|
elsif Contrast::Utils::DuckUtils.iterable_enumerable?(obj)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'contrast/extension/module'
|
|
@@ -9,14 +9,6 @@ module Contrast
|
|
|
9
9
|
# Utility methods for exploring the complete space of Objects
|
|
10
10
|
class ClassUtil
|
|
11
11
|
class << self
|
|
12
|
-
# Given a module, return all of its descendants
|
|
13
|
-
#
|
|
14
|
-
# @param mod [Module] the module whose descendants you want to find.
|
|
15
|
-
# @return [Array<Module>] those Modules that inherit from the given.
|
|
16
|
-
def descendants mod
|
|
17
|
-
ObjectSpace.each_object(mod).to_a
|
|
18
|
-
end
|
|
19
|
-
|
|
20
12
|
# some classes have had things prepended to them, like Marshal in Rails
|
|
21
13
|
# 5 and higher. Their ActiveSupport::MarshalWithAutoloading will break
|
|
22
14
|
# our alias patching approach, as will any other prepend on something
|
|
@@ -52,7 +44,7 @@ module Contrast
|
|
|
52
44
|
# Return a String representing the object invoking this method in the
|
|
53
45
|
# form expected by our dataflow events.
|
|
54
46
|
#
|
|
55
|
-
# @param object [Object] the entity to convert to a String
|
|
47
|
+
# @param object [Object, nil] the entity to convert to a String
|
|
56
48
|
# @return [String] the human readable form of the String, as defined by
|
|
57
49
|
# https://bitbucket.org/contrastsecurity/assess-specifications/src/master/vulnerability/capture-snapshot.md
|
|
58
50
|
def to_contrast_string object
|
|
@@ -63,14 +55,16 @@ module Contrast
|
|
|
63
55
|
return cached if cached
|
|
64
56
|
|
|
65
57
|
object.dup
|
|
58
|
+
elsif object.nil?
|
|
59
|
+
Contrast::Utils::ObjectShare::NIL_STRING
|
|
66
60
|
elsif object.cs__is_a?(Symbol)
|
|
67
61
|
":#{ object }"
|
|
68
|
-
elsif object.cs__is_a?(Numeric)
|
|
69
|
-
object.to_s
|
|
70
62
|
elsif object.cs__is_a?(Module) || object.cs__is_a?(Class)
|
|
71
63
|
"#{ object.cs__name }@#{ object.__id__ }"
|
|
72
64
|
elsif object.cs__is_a?(Regexp)
|
|
73
65
|
object.source
|
|
66
|
+
elsif use_to_s?(object)
|
|
67
|
+
object.to_s
|
|
74
68
|
else
|
|
75
69
|
"#{ object.cs__class.cs__name }@#{ object.__id__ }"
|
|
76
70
|
end
|
|
@@ -106,6 +100,18 @@ module Contrast
|
|
|
106
100
|
|
|
107
101
|
private
|
|
108
102
|
|
|
103
|
+
# Some objects have nice to_s that we can use to make them human readable. If they do, we should leverage them.
|
|
104
|
+
# We used to do this by default, but this opened us up to danger, so we're instead using an allow list approach.
|
|
105
|
+
#
|
|
106
|
+
# @param object [Object] something that may have a safe to_s method
|
|
107
|
+
# @return [Boolean] if we should invoke to_s to represent the object
|
|
108
|
+
def use_to_s? object
|
|
109
|
+
return true if object.cs__is_a?(Numeric)
|
|
110
|
+
return true if defined?(Arel::Nodes::SqlLiteral) && object.cs__is_a?(Arel::Nodes::SqlLiteral)
|
|
111
|
+
|
|
112
|
+
false
|
|
113
|
+
end
|
|
114
|
+
|
|
109
115
|
def determine_target_class mod, is_instance
|
|
110
116
|
return mod if mod.singleton_class?
|
|
111
117
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
module Contrast
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
module Contrast
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'digest'
|
|
@@ -15,10 +15,7 @@ module Contrast
|
|
|
15
15
|
include Digest::Instance
|
|
16
16
|
|
|
17
17
|
CONTENT_LENGTH_HEADER = 'Content-Length'
|
|
18
|
-
CRYPTO_RULES = %w[
|
|
19
|
-
crypto-bad-ciphers
|
|
20
|
-
crypto-bad-mac
|
|
21
|
-
].cs__freeze
|
|
18
|
+
CRYPTO_RULES = %w[crypto-bad-ciphers crypto-bad-mac].cs__freeze
|
|
22
19
|
CONFIG_PATH_KEY = 'path'
|
|
23
20
|
CONFIG_SESSION_ID_KEY = 'sessionId'
|
|
24
21
|
CLASS_SOURCE_KEY = 'source'
|
|
@@ -37,13 +34,13 @@ module Contrast
|
|
|
37
34
|
hash.finish
|
|
38
35
|
end
|
|
39
36
|
|
|
40
|
-
def generate_event_hash finding, source
|
|
41
|
-
return generate_dataflow_hash(finding) if finding.events.length.to_i > 1
|
|
37
|
+
def generate_event_hash finding, source, request
|
|
38
|
+
return generate_dataflow_hash(finding, request) if finding.events.length.to_i > 1
|
|
42
39
|
|
|
43
40
|
id = finding.rule_id
|
|
44
|
-
return generate_crypto_hash(finding, source) if CRYPTO_RULES.include?(id)
|
|
41
|
+
return generate_crypto_hash(finding, source, request) if CRYPTO_RULES.include?(id)
|
|
45
42
|
|
|
46
|
-
generate_trigger_hash(finding)
|
|
43
|
+
generate_trigger_hash(finding, request)
|
|
47
44
|
end
|
|
48
45
|
|
|
49
46
|
def generate_config_hash finding
|
|
@@ -71,40 +68,35 @@ module Contrast
|
|
|
71
68
|
|
|
72
69
|
private
|
|
73
70
|
|
|
74
|
-
def generate_crypto_hash finding, algorithm
|
|
71
|
+
def generate_crypto_hash finding, algorithm, request
|
|
75
72
|
hash = new
|
|
76
73
|
hash.update(finding.rule_id)
|
|
77
74
|
hash.update(algorithm)
|
|
78
|
-
hash.update_on_request
|
|
75
|
+
hash.update_on_request(finding, request)
|
|
79
76
|
hash.finish
|
|
80
77
|
end
|
|
81
78
|
|
|
82
|
-
def generate_dataflow_hash finding
|
|
79
|
+
def generate_dataflow_hash finding, request
|
|
83
80
|
hash = new
|
|
84
81
|
hash.update(finding.rule_id)
|
|
85
82
|
hash.update_on_sources(finding.events)
|
|
86
|
-
hash.update_on_request
|
|
83
|
+
hash.update_on_request(finding, request)
|
|
87
84
|
hash.finish
|
|
88
85
|
end
|
|
89
86
|
|
|
90
|
-
def generate_trigger_hash finding
|
|
87
|
+
def generate_trigger_hash finding, request
|
|
91
88
|
hash = new
|
|
92
89
|
hash.update(finding.rule_id)
|
|
93
|
-
hash.update_on_request
|
|
90
|
+
hash.update_on_request(finding, request)
|
|
94
91
|
hash.finish
|
|
95
92
|
end
|
|
96
93
|
end
|
|
97
94
|
|
|
98
|
-
def update_on_request
|
|
99
|
-
|
|
100
|
-
return unless context
|
|
101
|
-
|
|
102
|
-
route = context.route
|
|
103
|
-
request = context.request
|
|
104
|
-
if route
|
|
95
|
+
def update_on_request finding, request
|
|
96
|
+
if (route = finding.routes[0])
|
|
105
97
|
update(route.route)
|
|
106
98
|
update(route.verb)
|
|
107
|
-
elsif request
|
|
99
|
+
elsif request ||= Contrast::Agent::REQUEST_TRACKER.current&.request
|
|
108
100
|
update(request.normalized_uri)
|
|
109
101
|
update(request.request_method)
|
|
110
102
|
end
|
|
@@ -116,7 +108,7 @@ module Contrast
|
|
|
116
108
|
events.each do |event|
|
|
117
109
|
event.event_sources.each do |source|
|
|
118
110
|
update(source.type)
|
|
119
|
-
update(source.name)
|
|
111
|
+
update(source.name) # rubocop:disable Security/Module/Name -- API attribute.
|
|
120
112
|
end
|
|
121
113
|
end
|
|
122
114
|
end
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'objspace'
|
|
5
|
+
require 'singleton'
|
|
5
6
|
require 'contrast/components/interface'
|
|
6
7
|
|
|
7
8
|
module Contrast
|
|
8
9
|
module Utils
|
|
9
10
|
# Implementation of a heap dump util to automate generation
|
|
10
|
-
class HeapDumpUtil
|
|
11
|
+
class HeapDumpUtil < Contrast::Agent::WorkerThread
|
|
11
12
|
include Contrast::Components::Interface
|
|
12
13
|
access_component :heap_dump, :logging
|
|
13
14
|
|
|
@@ -15,98 +16,113 @@ module Contrast
|
|
|
15
16
|
FILE_WRITE_FLAGS = 'w'
|
|
16
17
|
|
|
17
18
|
class << self
|
|
18
|
-
def
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return unless File.writable?(dir)
|
|
25
|
-
|
|
26
|
-
delay = heap_dump_control[:delay]
|
|
27
|
-
Contrast::Agent::Thread.new do
|
|
28
|
-
logger.info("HEAP DUMP THREAD INITIALIZED. WAITING #{ delay } SECONDS TO BEGIN.")
|
|
29
|
-
sleep(delay)
|
|
30
|
-
capture_heap_dump
|
|
31
|
-
end
|
|
32
|
-
rescue StandardError => e
|
|
33
|
-
logger.info(LOG_ERROR_DUMPS, e)
|
|
34
|
-
nil
|
|
19
|
+
def enabled?
|
|
20
|
+
heap_dump_enabled?
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def control
|
|
24
|
+
heap_dump_control
|
|
35
25
|
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def start_thread!
|
|
29
|
+
return unless Contrast::Utils::HeapDumpUtil.enabled?
|
|
36
30
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
*****************************************************
|
|
49
|
-
|
|
50
|
-
Heap dump is a debugging tool that snapshots the entire
|
|
51
|
-
state of the Ruby VM. It is an exceptionally expensive
|
|
52
|
-
process, and should only be used to debug especially
|
|
53
|
-
pernicious errors.
|
|
54
|
-
|
|
55
|
-
It will write multiple memory snaphots, which are liable
|
|
56
|
-
to be multiple gigabytes in size.
|
|
57
|
-
They will be named "[unix timestamp]-heap.dump",
|
|
58
|
-
e.g.: 1020304050-heap.dump
|
|
59
|
-
|
|
60
|
-
It will then call Ruby `exit()`.
|
|
61
|
-
|
|
62
|
-
If this is not your specific intent, you can (and should)
|
|
63
|
-
disable this option in your Contrast config file.
|
|
64
|
-
|
|
65
|
-
HEAP DUMP PARAMETERS:
|
|
66
|
-
\t[write files to this directory] dir: #{ dir }
|
|
67
|
-
\t[wait this many seconds in between dumps] window: #{ window }
|
|
68
|
-
\t[heap dump this many times] count: #{ count }
|
|
69
|
-
\t[wait this many seconds into app lifetime] delay: #{ delay }
|
|
70
|
-
\t[perform gc pass before dump] clean: #{ clean }
|
|
71
|
-
|
|
72
|
-
*****************************************************
|
|
73
|
-
******** YOU HAVE BEEN WARNED ********
|
|
74
|
-
*****************************************************
|
|
75
|
-
WARNING
|
|
31
|
+
control = Contrast::Utils::HeapDumpUtil.control
|
|
32
|
+
log_enabled_warning
|
|
33
|
+
dir = control[:path]
|
|
34
|
+
Dir.mkdir(dir) unless Dir.exist?(dir)
|
|
35
|
+
return unless File.writable?(dir)
|
|
36
|
+
|
|
37
|
+
delay = control[:delay]
|
|
38
|
+
@_thread = Contrast::Agent::Thread.new do
|
|
39
|
+
logger.info("HEAP DUMP THREAD INITIALIZED. WAITING #{ delay } SECONDS TO BEGIN.")
|
|
40
|
+
sleep(delay)
|
|
41
|
+
capture_heap_dump
|
|
76
42
|
end
|
|
43
|
+
rescue StandardError => e
|
|
44
|
+
logger.info(LOG_ERROR_DUMPS, e)
|
|
45
|
+
nil
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def log_enabled_warning
|
|
49
|
+
control = Contrast::Utils::HeapDumpUtil.control
|
|
50
|
+
dir = control[:path]
|
|
51
|
+
window = control[:window]
|
|
52
|
+
count = control[:count]
|
|
53
|
+
delay = control[:delay]
|
|
54
|
+
clean = control[:clean]
|
|
55
|
+
|
|
56
|
+
logger.info <<~WARNING
|
|
57
|
+
*****************************************************
|
|
58
|
+
******** HEAP DUMP HAS BEEN ENABLED ********
|
|
59
|
+
*** APPLICATION PROCESS WILL EXIT UPON COMPLETION ***
|
|
60
|
+
*****************************************************
|
|
61
|
+
|
|
62
|
+
Heap dump is a debugging tool that snapshots the entire
|
|
63
|
+
state of the Ruby VM. It is an exceptionally expensive
|
|
64
|
+
process, and should only be used to debug especially
|
|
65
|
+
pernicious errors.
|
|
66
|
+
|
|
67
|
+
It will write multiple memory snaphots, which are liable
|
|
68
|
+
to be multiple gigabytes in size.
|
|
69
|
+
They will be named "[unix timestamp]-heap.dump",
|
|
70
|
+
e.g.: 1020304050-heap.dump
|
|
71
|
+
|
|
72
|
+
It will then call Ruby `exit()`.
|
|
73
|
+
|
|
74
|
+
If this is not your specific intent, you can (and should)
|
|
75
|
+
disable this option in your Contrast config file.
|
|
76
|
+
|
|
77
|
+
HEAP DUMP PARAMETERS:
|
|
78
|
+
\t[write files to this directory] dir: #{ dir }
|
|
79
|
+
\t[wait this many seconds in between dumps] window: #{ window }
|
|
80
|
+
\t[heap dump this many times] count: #{ count }
|
|
81
|
+
\t[wait this many seconds into app lifetime] delay: #{ delay }
|
|
82
|
+
\t[perform gc pass before dump] clean: #{ clean }
|
|
83
|
+
|
|
84
|
+
*****************************************************
|
|
85
|
+
******** YOU HAVE BEEN WARNED ********
|
|
86
|
+
*****************************************************
|
|
87
|
+
WARNING
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def capture_heap_dump
|
|
91
|
+
control = Contrast::Utils::HeapDumpUtil.control
|
|
92
|
+
dir = control[:path]
|
|
93
|
+
window = control[:window]
|
|
94
|
+
count = control[:count]
|
|
95
|
+
clean = control[:clean]
|
|
96
|
+
logger.info('HEAP DUMP MAIN LOOP')
|
|
97
|
+
ObjectSpace.trace_object_allocations_start
|
|
98
|
+
count.times do |i|
|
|
99
|
+
logger.info('STARTING HEAP DUMP PASS', current_pass: i, max: count)
|
|
100
|
+
snapshot_heap(dir, clean)
|
|
101
|
+
logger.info('FINISHING HEAP DUMP PASS', current_pass: i, max: count)
|
|
102
|
+
sleep(window)
|
|
103
|
+
end
|
|
104
|
+
ensure
|
|
105
|
+
ObjectSpace.trace_object_allocations_stop
|
|
106
|
+
logger.info('*****************************************************')
|
|
107
|
+
logger.info('******** HEAP DUMP HAS CONCLUDED ********')
|
|
108
|
+
logger.info('*** APPLICATION PROCESS WILL EXIT SHORTLY ***')
|
|
109
|
+
logger.info('*****************************************************')
|
|
110
|
+
exit # rubocop:disable Rails/Exit We weren't kidding!
|
|
111
|
+
end
|
|
77
112
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
output = "#{ Time.now.to_f }-heap.dump"
|
|
88
|
-
output = File.join(dir, output)
|
|
89
|
-
begin
|
|
90
|
-
logger.info('OPENING HEADUMP FILE', dir: dir, file: output)
|
|
91
|
-
file = File.new(output, FILE_WRITE_FLAGS)
|
|
92
|
-
if clean
|
|
93
|
-
logger.info('PERFORMING GARBAGE COLLECTION BEFORE HEAP DUMP')
|
|
94
|
-
GC.start
|
|
95
|
-
end
|
|
96
|
-
ObjectSpace.dump_all(output: file)
|
|
97
|
-
logger.info('FINISHING HEAP DUMP PASS', current_pass: i + 1, max: count)
|
|
98
|
-
ensure
|
|
99
|
-
file.close
|
|
100
|
-
end
|
|
101
|
-
sleep(window)
|
|
113
|
+
def snapshot_heap dir, clean
|
|
114
|
+
output = "#{ Time.now.to_f }-heap.dump"
|
|
115
|
+
output = File.join(dir, output)
|
|
116
|
+
begin
|
|
117
|
+
logger.info('OPENING HEADUMP FILE', dir: dir, file: output)
|
|
118
|
+
file = File.new(output, FILE_WRITE_FLAGS)
|
|
119
|
+
if clean
|
|
120
|
+
logger.info('PERFORMING GARBAGE COLLECTION BEFORE HEAP DUMP')
|
|
121
|
+
GC.start
|
|
102
122
|
end
|
|
123
|
+
ObjectSpace.dump_all(output: file)
|
|
103
124
|
ensure
|
|
104
|
-
|
|
105
|
-
logger.info('*****************************************************')
|
|
106
|
-
logger.info('******** HEAP DUMP HAS CONCLUDED ********')
|
|
107
|
-
logger.info('*** APPLICATION PROCESS WILL EXIT SHORTLY ***')
|
|
108
|
-
logger.info('*****************************************************')
|
|
109
|
-
exit # rubocop:disable Rails/Exit We weren't kidding!
|
|
125
|
+
file.close
|
|
110
126
|
end
|
|
111
127
|
end
|
|
112
128
|
end
|