contrast-agent 6.2.0 → 6.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -3
- data/.simplecov +1 -0
- data/Rakefile +0 -27
- data/ext/cs__assess_basic_object/cs__assess_basic_object.c +7 -5
- data/ext/cs__assess_kernel/cs__assess_kernel.c +14 -3
- data/ext/cs__assess_kernel/cs__assess_kernel.h +2 -0
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +10 -3
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.h +2 -1
- data/ext/cs__assess_regexp/cs__assess_regexp.c +9 -7
- data/ext/{cs__assess_string_interpolation26/cs__assess_string_interpolation26.c → cs__assess_string_interpolation/cs__assess_string_interpolation.c} +14 -3
- data/ext/{cs__assess_string_interpolation26/cs__assess_string_interpolation26.h → cs__assess_string_interpolation/cs__assess_string_interpolation.h} +1 -1
- data/ext/{cs__assess_string_interpolation26 → cs__assess_string_interpolation}/extconf.rb +0 -0
- data/ext/cs__common/cs__common.c +5 -4
- data/ext/cs__contrast_patch/cs__contrast_patch.c +17 -11
- data/lib/contrast/agent/assess/events/source_event.rb +16 -12
- data/lib/contrast/agent/assess/finalizers/hash.rb +1 -0
- data/lib/contrast/agent/assess/policy/policy_node.rb +6 -0
- data/lib/contrast/agent/assess/policy/propagation_method.rb +8 -42
- data/lib/contrast/agent/assess/policy/propagation_node.rb +8 -0
- data/lib/contrast/agent/assess/policy/propagator/base.rb +2 -0
- data/lib/contrast/agent/assess/policy/propagator/custom.rb +4 -0
- data/lib/contrast/agent/assess/policy/propagator/database_write.rb +5 -0
- data/lib/contrast/agent/assess/policy/propagator/split.rb +3 -0
- data/lib/contrast/agent/assess/policy/source_method.rb +7 -47
- data/lib/contrast/agent/assess/policy/source_node.rb +1 -0
- data/lib/contrast/agent/assess/policy/trigger_method.rb +9 -3
- data/lib/contrast/agent/assess/policy/trigger_node.rb +8 -0
- data/lib/contrast/agent/assess/property/evented.rb +4 -18
- data/lib/contrast/agent/assess/tag.rb +19 -0
- data/lib/contrast/agent/assess/tracker.rb +12 -0
- data/lib/contrast/agent/at_exit_hook.rb +8 -8
- data/lib/contrast/agent/inventory/database_config.rb +6 -3
- data/lib/contrast/agent/inventory/dependency_analysis.rb +5 -4
- data/lib/contrast/agent/inventory/dependency_usage_analysis.rb +11 -11
- data/lib/contrast/agent/inventory/policy/datastores.rb +1 -1
- data/lib/contrast/agent/inventory/policy/policy.rb +1 -1
- data/lib/contrast/agent/middleware.rb +4 -0
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +27 -2
- data/lib/contrast/agent/patching/policy/method_policy.rb +3 -3
- data/lib/contrast/agent/patching/policy/policy.rb +5 -0
- data/lib/contrast/agent/patching/policy/policy_node.rb +6 -0
- data/lib/contrast/agent/patching/policy/trigger_node.rb +3 -0
- data/lib/contrast/agent/protect/policy/applies_deserialization_rule.rb +3 -4
- data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +1 -0
- data/lib/contrast/agent/protect/policy/rule_applicator.rb +2 -2
- data/lib/contrast/agent/protect/rule/base.rb +1 -0
- data/lib/contrast/agent/protect/rule/no_sqli.rb +2 -0
- data/lib/contrast/agent/reporting/reporter.rb +32 -7
- data/lib/contrast/agent/reporting/reporter_heartbeat.rb +22 -18
- data/lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb +17 -21
- data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample_activity.rb +26 -3
- data/lib/contrast/agent/reporting/reporting_events/application_update.rb +5 -24
- data/lib/contrast/agent/reporting/reporting_events/architecture_component.rb +8 -1
- data/lib/contrast/agent/reporting/reporting_events/discovered_route.rb +8 -1
- data/lib/contrast/agent/reporting/reporting_events/finding.rb +7 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +10 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_object.rb +11 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_parent_object.rb +11 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_property.rb +12 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_signature.rb +10 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_source.rb +11 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_stack.rb +11 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_taint_range.rb +11 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_request.rb +11 -1
- data/lib/contrast/agent/reporting/reporting_events/library_discovery.rb +29 -32
- data/lib/contrast/agent/reporting/reporting_events/library_usage_observation.rb +13 -1
- data/lib/contrast/agent/reporting/reporting_events/observed_library_usage.rb +11 -8
- data/lib/contrast/agent/reporting/reporting_events/observed_route.rb +12 -5
- data/lib/contrast/agent/reporting/reporting_events/preflight_message.rb +8 -1
- data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +9 -1
- data/lib/contrast/agent/reporting/reporting_events/route_discovery.rb +10 -1
- data/lib/contrast/agent/reporting/reporting_events/route_discovery_observation.rb +11 -4
- data/lib/contrast/agent/reporting/reporting_events/server_activity.rb +0 -8
- data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +1 -4
- data/lib/contrast/agent/reporting/reporting_utilities/dtm_message.rb +0 -22
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +1 -3
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +1 -11
- data/lib/contrast/agent/request.rb +5 -7
- data/lib/contrast/agent/request_context.rb +16 -17
- data/lib/contrast/agent/request_context_extend.rb +8 -9
- data/lib/contrast/agent/request_handler.rb +9 -38
- data/lib/contrast/agent/rule_set.rb +4 -0
- data/lib/contrast/agent/service_heartbeat.rb +3 -4
- data/lib/contrast/agent/static_analysis.rb +7 -12
- data/lib/contrast/agent/telemetry/base.rb +35 -35
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_base.rb +2 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_event.rb +2 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_message.rb +5 -2
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_message_exception.rb +3 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_stack_frame.rb +3 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exceptions.rb +0 -1
- data/lib/contrast/agent/thread_watcher.rb +1 -4
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/agent/worker_thread.rb +10 -0
- data/lib/contrast/api/communication/socket.rb +1 -0
- data/lib/contrast/api/decorators/message.rb +0 -6
- data/lib/contrast/api/decorators.rb +0 -2
- data/lib/contrast/api/dtm.pb.rb +1 -1
- data/lib/contrast/api/settings.pb.rb +1 -1
- data/lib/contrast/components/agent.rb +51 -13
- data/lib/contrast/components/assess.rb +16 -6
- data/lib/contrast/components/config.rb +18 -2
- data/lib/contrast/components/contrast_service.rb +1 -1
- data/lib/contrast/components/heap_dump.rb +51 -1
- data/lib/contrast/components/inventory.rb +19 -13
- data/lib/contrast/components/logger.rb +18 -0
- data/lib/contrast/config/assess_configuration.rb +28 -0
- data/lib/contrast/config/base_configuration.rb +8 -15
- data/lib/contrast/config/root_configuration.rb +12 -8
- data/lib/contrast/config/ruby_configuration.rb +2 -9
- data/lib/contrast/config/service_configuration.rb +4 -4
- data/lib/contrast/config.rb +0 -6
- data/lib/contrast/configuration.rb +0 -2
- data/lib/contrast/extension/assess/eval_trigger.rb +0 -4
- data/lib/contrast/extension/assess/hash.rb +3 -2
- data/lib/contrast/extension/assess/kernel.rb +22 -0
- data/lib/contrast/extension/assess/marshal.rb +16 -0
- data/lib/contrast/extension/assess/string.rb +21 -20
- data/lib/contrast/extension/object.rb +19 -0
- data/lib/contrast/framework/base_support.rb +8 -0
- data/lib/contrast/framework/manager.rb +6 -20
- data/lib/contrast/framework/manager_extend.rb +0 -1
- data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +11 -16
- data/lib/contrast/framework/rails/support.rb +4 -1
- data/lib/contrast/logger/aliased_logging.rb +2 -0
- data/lib/contrast/logger/log.rb +2 -1
- data/lib/contrast/utils/assess/event_limit_utils.rb +96 -0
- data/lib/contrast/utils/assess/propagation_method_utils.rb +27 -7
- data/lib/contrast/utils/assess/source_method_utils.rb +0 -9
- data/lib/contrast/utils/log_utils.rb +2 -2
- data/lib/contrast/utils/lru_cache.rb +3 -0
- data/lib/contrast/utils/middleware_utils.rb +2 -0
- data/lib/contrast/utils/patching/policy/patch_utils.rb +6 -23
- data/lib/contrast/utils/telemetry_client.rb +7 -7
- data/lib/contrast.rb +37 -18
- data/lib/protobuf/code_generator.rb +129 -0
- data/lib/protobuf/decoder.rb +28 -0
- data/lib/protobuf/deprecation.rb +117 -0
- data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +79 -0
- data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +360 -0
- data/lib/protobuf/descriptors.rb +3 -0
- data/lib/protobuf/encoder.rb +11 -0
- data/lib/protobuf/enum.rb +365 -0
- data/lib/protobuf/exceptions.rb +9 -0
- data/lib/protobuf/field/base_field.rb +380 -0
- data/lib/protobuf/field/base_field_object_definitions.rb +504 -0
- data/lib/protobuf/field/bool_field.rb +64 -0
- data/lib/protobuf/field/bytes_field.rb +67 -0
- data/lib/protobuf/field/double_field.rb +25 -0
- data/lib/protobuf/field/enum_field.rb +56 -0
- data/lib/protobuf/field/field_array.rb +102 -0
- data/lib/protobuf/field/field_hash.rb +122 -0
- data/lib/protobuf/field/fixed32_field.rb +25 -0
- data/lib/protobuf/field/fixed64_field.rb +28 -0
- data/lib/protobuf/field/float_field.rb +43 -0
- data/lib/protobuf/field/int32_field.rb +21 -0
- data/lib/protobuf/field/int64_field.rb +34 -0
- data/lib/protobuf/field/integer_field.rb +23 -0
- data/lib/protobuf/field/message_field.rb +51 -0
- data/lib/protobuf/field/sfixed32_field.rb +27 -0
- data/lib/protobuf/field/sfixed64_field.rb +28 -0
- data/lib/protobuf/field/signed_integer_field.rb +29 -0
- data/lib/protobuf/field/sint32_field.rb +21 -0
- data/lib/protobuf/field/sint64_field.rb +21 -0
- data/lib/protobuf/field/string_field.rb +51 -0
- data/lib/protobuf/field/uint32_field.rb +21 -0
- data/lib/protobuf/field/uint64_field.rb +21 -0
- data/lib/protobuf/field/varint_field.rb +77 -0
- data/lib/protobuf/field.rb +74 -0
- data/lib/protobuf/generators/base.rb +85 -0
- data/lib/protobuf/generators/enum_generator.rb +39 -0
- data/lib/protobuf/generators/extension_generator.rb +27 -0
- data/lib/protobuf/generators/field_generator.rb +193 -0
- data/lib/protobuf/generators/file_generator.rb +262 -0
- data/lib/protobuf/generators/group_generator.rb +122 -0
- data/lib/protobuf/generators/message_generator.rb +104 -0
- data/lib/protobuf/generators/option_generator.rb +17 -0
- data/lib/protobuf/generators/printable.rb +160 -0
- data/lib/protobuf/generators/service_generator.rb +50 -0
- data/lib/protobuf/lifecycle.rb +33 -0
- data/lib/protobuf/logging.rb +39 -0
- data/lib/protobuf/message/fields.rb +233 -0
- data/lib/protobuf/message/serialization.rb +85 -0
- data/lib/protobuf/message.rb +241 -0
- data/lib/protobuf/optionable.rb +72 -0
- data/lib/protobuf/tasks/compile.rake +80 -0
- data/lib/protobuf/tasks.rb +1 -0
- data/lib/protobuf/varint.rb +20 -0
- data/lib/protobuf/varint_pure.rb +31 -0
- data/lib/protobuf/version.rb +3 -0
- data/lib/protobuf/wire_type.rb +10 -0
- data/lib/protobuf.rb +91 -0
- data/proto/dynamic_discovery.proto +46 -0
- data/proto/google/protobuf/compiler/plugin.proto +183 -0
- data/proto/google/protobuf/descriptor.proto +911 -0
- data/proto/rpc.proto +71 -0
- data/resources/assess/policy.json +6 -23
- data/ruby-agent.gemspec +4 -2
- metadata +122 -33
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exceptions_report.rb +0 -30
- data/lib/contrast/api/decorators/application_update.rb +0 -44
- data/lib/contrast/api/decorators/library.rb +0 -56
- data/lib/contrast/config/agent_configuration.rb +0 -63
- data/lib/contrast/config/heap_dump_configuration.rb +0 -59
- data/lib/contrast/config/inventory_configuration.rb +0 -33
- data/lib/contrast/config/logger_configuration.rb +0 -26
- data/lib/contrast/framework/platform_version.rb +0 -22
@@ -30,8 +30,6 @@ module Contrast
|
|
30
30
|
# @return [Hash] context used to log the request
|
31
31
|
attr_reader :logging_hash
|
32
32
|
# @return [Contrast::Agent::Reporting::ObservedRoute] the route, used for coverage, of this request
|
33
|
-
attr_reader :new_observed_route
|
34
|
-
# @return [Contrast::Api::Dtm::ObservedRoute] the route, used for coverage, of this request
|
35
33
|
attr_reader :observed_route
|
36
34
|
# @return [Contrast::Agent::Request] our wrapper around the Rack::Request for this context
|
37
35
|
attr_reader :request
|
@@ -40,15 +38,12 @@ module Contrast
|
|
40
38
|
attr_reader :response
|
41
39
|
# @return [Contrast::Api::Dtm::RouteCoverage] the route, used for findings, of this request
|
42
40
|
attr_reader :route
|
43
|
-
# @return [Contrast::Api::Dtm::ServerActivity] the server activity found in this request
|
44
|
-
attr_reader :server_activity
|
45
41
|
# @return [Contrast::Api::Settings::InputAnalysis] the protect input analysis of sources on this request
|
46
42
|
attr_reader :speedracer_input_analysis
|
47
43
|
# @return [Contrast::Utils::Timer] when the context was created
|
48
44
|
attr_reader :timer
|
49
|
-
|
50
|
-
|
51
|
-
attr_reader :observed_library_usage
|
45
|
+
|
46
|
+
attr_accessor :propagation_event_count, :source_event_count
|
52
47
|
|
53
48
|
def initialize rack_request, app_loaded: true
|
54
49
|
with_contrast_scope do
|
@@ -62,9 +57,6 @@ module Contrast
|
|
62
57
|
@activity = Contrast::Api::Dtm::Activity.new
|
63
58
|
@activity.http_request = request.dtm
|
64
59
|
|
65
|
-
@server_activity = Contrast::Api::Dtm::ServerActivity.new
|
66
|
-
@observed_library_usage = Contrast::Agent::Reporting::ObservedLibraryUsage.new
|
67
|
-
|
68
60
|
# build analyzer
|
69
61
|
@do_not_track = false
|
70
62
|
@speedracer_input_analysis = EMPTY_INPUT_ANALYSIS_PB
|
@@ -78,6 +70,12 @@ module Contrast
|
|
78
70
|
# generic holder for properties that can be set throughout this request
|
79
71
|
@_properties = {}
|
80
72
|
|
73
|
+
# count of propagation events
|
74
|
+
@propagation_event_count = 0
|
75
|
+
|
76
|
+
# count of source events
|
77
|
+
@source_event_count = 0
|
78
|
+
|
81
79
|
if ::Contrast::ASSESS.enabled?
|
82
80
|
@sample_req, @sample_res = Contrast::Utils::Assess::SamplingUtil.instance.sample?(@request)
|
83
81
|
end
|
@@ -128,20 +126,21 @@ module Contrast
|
|
128
126
|
|
129
127
|
def reset_activity
|
130
128
|
@activity = Contrast::Api::Dtm::Activity.new(http_request: request.dtm)
|
131
|
-
@
|
132
|
-
@observed_route = Contrast::Api::Dtm::ObservedRoute.new # TODO: RUBY-1438 -- remove
|
133
|
-
@new_observed_route = Contrast::Agent::Reporting::ObservedRoute.new
|
129
|
+
@observed_route = Contrast::Agent::Reporting::ObservedRoute.new
|
134
130
|
end
|
135
131
|
|
136
132
|
private
|
137
133
|
|
138
134
|
def handle_routes
|
139
|
-
@observed_route = Contrast::
|
140
|
-
|
135
|
+
@observed_route = Contrast::Agent::Reporting::ObservedRoute.new
|
136
|
+
# TODO: RUBY-1705 when we no longer need the DTM style, delete this method and use the get_route_information
|
137
|
+
# instead.
|
141
138
|
route_dtm = Contrast::Agent.framework_manager.get_route_dtm(@request)
|
142
|
-
new_route_coverage_dtm = Contrast::Agent.framework_manager.get_route_information(@request)
|
139
|
+
# new_route_coverage_dtm = Contrast::Agent.framework_manager.get_route_information(@request)
|
140
|
+
# TODO: RUBY-1705 -- delete append_route_coverage
|
143
141
|
append_route_coverage(route_dtm)
|
144
|
-
|
142
|
+
# TODO: RUBY-1705 -- change to take [Contrast::Agent::Reporting::ObservedRoute]
|
143
|
+
append_to_observed_route(route_dtm)
|
145
144
|
end
|
146
145
|
end
|
147
146
|
end
|
@@ -38,23 +38,20 @@ module Contrast
|
|
38
38
|
@activity.routes << route
|
39
39
|
|
40
40
|
# For TS routes
|
41
|
-
@observed_route.signature = route.route
|
42
|
-
@observed_route.verb = route.verb
|
43
|
-
@observed_route.url = route.url if route.url
|
44
41
|
@request.route = route
|
45
|
-
@request.observed_route = @observed_route
|
46
42
|
end
|
47
43
|
|
48
44
|
# Convert the discovered route for this request to appropriate forms and disseminate it to those locations
|
49
45
|
# where it is necessary for our route coverage and finding vulnerability discovery features to function.
|
50
46
|
#
|
51
|
-
|
47
|
+
# @param route [Contrast::Api::Dtm::RouteCoverage]
|
48
|
+
def append_to_observed_route route
|
52
49
|
return unless route
|
53
50
|
|
54
|
-
@
|
55
|
-
@
|
56
|
-
@
|
57
|
-
@request.
|
51
|
+
@observed_route.signature = route.route
|
52
|
+
@observed_route.verb = route.verb
|
53
|
+
@observed_route.url = route.url if route.url
|
54
|
+
@request.observed_route = @observed_route
|
58
55
|
end
|
59
56
|
|
60
57
|
# Collect the results for the given rule with the given action
|
@@ -71,6 +68,7 @@ module Contrast
|
|
71
68
|
end
|
72
69
|
end
|
73
70
|
|
71
|
+
# @raise [Contrast::SecurityException]
|
74
72
|
def service_extract_request
|
75
73
|
return false unless ::Contrast::AGENT.enabled?
|
76
74
|
return false unless ::Contrast::PROTECT.enabled?
|
@@ -105,6 +103,7 @@ module Contrast
|
|
105
103
|
# Normally these should be generated on Speedracer for any attacks detected during prefilter.
|
106
104
|
#
|
107
105
|
# @param agent_settings [Contrast::Api::Settings::AgentSettings]
|
106
|
+
# @raise[Contrast::SecurityException]
|
108
107
|
def handle_protect_state agent_settings
|
109
108
|
return unless agent_settings&.protect_state
|
110
109
|
|
@@ -22,56 +22,27 @@ module Contrast
|
|
22
22
|
@ruleset = ::Contrast::AGENT.ruleset
|
23
23
|
end
|
24
24
|
|
25
|
-
# Send Activities messages to TS [Contrast::
|
26
|
-
#
|
27
|
-
#
|
28
|
-
# Contrast::Api::Dtm::ObservedRoute]
|
29
|
-
# If bypass is enabled use the reporting service if not than the messages are
|
30
|
-
# send with speedracer
|
31
|
-
# TODO: RUBY-1355
|
32
|
-
# TODO: RUBY-1358
|
33
|
-
# TODO: RUBY-1438 -- remove
|
25
|
+
# Send Activities messages to TS [Contrast::Api::Dtm::Activity]
|
26
|
+
# TODO: RUBY-1704
|
27
|
+
# TODO: RUBY-1438
|
34
28
|
def send_activity_messages
|
35
|
-
|
36
|
-
unless Contrast::Agent::Reporter.enabled?
|
37
|
-
events << context.server_activity
|
38
|
-
events << context.observed_route
|
39
|
-
end
|
40
|
-
events.each do |message|
|
41
|
-
Contrast::Agent.messaging_queue&.send_event_eventually(message)
|
42
|
-
end
|
29
|
+
Contrast::Agent.messaging_queue&.send_event_eventually(context.activity)
|
43
30
|
end
|
44
31
|
|
45
32
|
# reports events[Contrast::Agent::Reporting::ReporterEvent] to TS
|
46
33
|
# This method is used to send our JSON messages directly to TeamServer at the end of each request. As we move
|
47
34
|
# more endpoints over, this method will take the messages originally sent by #send_actiivty_messages. At the end,
|
48
35
|
# that method should be removed.
|
49
|
-
def report_activity
|
50
|
-
Contrast::Agent
|
51
|
-
generate_library_usage(context.observed_library_usage)
|
36
|
+
def report_activity
|
37
|
+
return unless (reporter = Contrast::Agent.reporter)
|
52
38
|
|
53
|
-
|
39
|
+
reporter.send_event(context.observed_route)
|
54
40
|
return unless Contrast::Agent::Reporter.enabled?
|
55
41
|
|
56
|
-
reporter = Contrast::Agent.reporter
|
57
|
-
return unless reporter
|
58
|
-
|
59
42
|
# Mask Sensitive Data
|
60
43
|
Contrast::Agent::Reporting::Masker.mask(context.activity)
|
61
|
-
|
62
|
-
|
63
|
-
generate_library_usage(context.observed_library_usage)
|
64
|
-
[
|
65
|
-
context.new_observed_route,
|
66
|
-
context.observed_library_usage,
|
67
|
-
Contrast::Agent::Reporting::DtmMessage.dtm_to_event(context.server_activity),
|
68
|
-
Contrast::Agent::Reporting::DtmMessage.dtm_to_event(context.activity)
|
69
|
-
].each do |event|
|
70
|
-
reporter.send_event(event)
|
71
|
-
rescue StandardError => e
|
72
|
-
logger.warn('Unable to send Event Activity', e)
|
73
|
-
end
|
74
|
-
context.observed_library_usage.clear # TODO: RUBY-1355 remove when no longer using activity
|
44
|
+
event = Contrast::Agent::Reporting::DtmMessage.dtm_to_event(context.activity)
|
45
|
+
reporter.send_event(event)
|
75
46
|
end
|
76
47
|
|
77
48
|
# If the response is streaming, we should only perform filtering on our stream safe rules
|
@@ -14,6 +14,8 @@ module Contrast
|
|
14
14
|
# The main action here is snapshotting the request as provided to the application from the
|
15
15
|
# user before any application code has acted upon it. Additionally, this is where Protect will
|
16
16
|
# terminate requests on attack detection if set to block at perimeter
|
17
|
+
#
|
18
|
+
# @raise [Contrast::SecurityException] raises error if security exception is thrown in prefilter
|
17
19
|
def prefilter
|
18
20
|
context = Contrast::Agent::REQUEST_TRACKER.current
|
19
21
|
return unless context&.analyze_request?
|
@@ -30,6 +32,8 @@ module Contrast
|
|
30
32
|
|
31
33
|
# The filtering that needs occur after the application has acted on the request and the response
|
32
34
|
# has been created. The main actions here are analyzing the response for unsafe state or actions.
|
35
|
+
#
|
36
|
+
# @raise [Contrast::SecurityException] raises error if security exception is thrown in postfilter
|
33
37
|
def postfilter
|
34
38
|
context = Contrast::Agent::REQUEST_TRACKER.current
|
35
39
|
return unless context&.analyze_response?
|
@@ -1,7 +1,6 @@
|
|
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/logger'
|
5
4
|
require 'contrast/agent/worker_thread'
|
6
5
|
require 'contrast/agent/reporting/report'
|
7
6
|
|
@@ -10,8 +9,6 @@ module Contrast
|
|
10
9
|
# The ServiceHeartbeat functions to keep the Contrast Service alive and ensure that it maintains this Agent's
|
11
10
|
# ApplicationContext.
|
12
11
|
class ServiceHeartbeat < WorkerThread
|
13
|
-
include Contrast::Components::Logger::InstanceMethods
|
14
|
-
|
15
12
|
# Spec recommends 30 seconds, we're going with 15.
|
16
13
|
REFRESH_INTERVAL_SEC = 15
|
17
14
|
|
@@ -22,7 +19,9 @@ module Contrast
|
|
22
19
|
@_thread = Contrast::Agent::Thread.new do
|
23
20
|
logger.info('Starting heartbeat thread.')
|
24
21
|
loop do
|
25
|
-
Contrast::Agent.messaging_queue.
|
22
|
+
logger.info("Queue Size: #{ Contrast::Agent.messaging_queue.queue&.length }")
|
23
|
+
Contrast::Agent.messaging_queue&.send_event_eventually(poll_message)
|
24
|
+
clean_properties
|
26
25
|
sleep(REFRESH_INTERVAL_SEC)
|
27
26
|
end
|
28
27
|
end
|
@@ -4,7 +4,6 @@
|
|
4
4
|
require 'contrast/components/logger'
|
5
5
|
require 'contrast/components/scope'
|
6
6
|
require 'contrast/agent/reporting/reporting_events/application_update'
|
7
|
-
require 'contrast/api/decorators/application_update'
|
8
7
|
|
9
8
|
module Contrast
|
10
9
|
module Agent
|
@@ -24,20 +23,16 @@ module Contrast
|
|
24
23
|
end
|
25
24
|
end
|
26
25
|
|
27
|
-
# TODO: RUBY-1703
|
28
26
|
def send_inventory_message
|
29
|
-
return unless ::Contrast::INVENTORY.
|
27
|
+
return unless ::Contrast::INVENTORY.enable
|
30
28
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
Contrast::Agent.reporter.send_event(
|
37
|
-
else
|
38
|
-
Contrast::Agent.messaging_queue.send_event_eventually(app_update_msg, force: true)
|
29
|
+
report = Contrast::Agent::Reporting::ApplicationUpdate.new
|
30
|
+
# This convert here is left as it'll be easier to be replaced when the Library is being changed
|
31
|
+
report.libraries = Contrast::Agent::Inventory::DependencyAnalysis.instance.library_pb_list
|
32
|
+
Contrast::Agent::Inventory::DatabaseConfig.append_db_config(report)
|
33
|
+
[report, Contrast::Agent::Reporting::ApplicationInventory.new].each do |e|
|
34
|
+
Contrast::Agent.reporter.send_event(e)
|
39
35
|
end
|
40
|
-
Contrast::Agent.reporter.send_event(Contrast::Agent::Reporting::ApplicationInventory.new)
|
41
36
|
end
|
42
37
|
|
43
38
|
private
|
@@ -7,7 +7,6 @@ require 'contrast/utils/telemetry_client'
|
|
7
7
|
require 'contrast/agent/worker_thread'
|
8
8
|
require 'contrast/utils/telemetry'
|
9
9
|
require 'contrast/agent/telemetry/events/exceptions/telemetry_exceptions'
|
10
|
-
require 'contrast/agent/telemetry/events/exceptions/telemetry_exceptions_report'
|
11
10
|
|
12
11
|
module Contrast
|
13
12
|
module Agent
|
@@ -15,7 +14,6 @@ module Contrast
|
|
15
14
|
# This class will initialize and hold everything needed for the telemetry
|
16
15
|
class Base < WorkerThread
|
17
16
|
include Contrast::Components::Logger::InstanceMethods
|
18
|
-
include Contrast::Agent::Telemetry::TelemetryExceptionReport
|
19
17
|
|
20
18
|
# this is where we will send the data from the agents
|
21
19
|
URL = 'https://telemetry.ruby.contrastsecurity.com/'
|
@@ -66,10 +64,6 @@ module Contrast
|
|
66
64
|
@_connection ||= client.initialize_connection(URL)
|
67
65
|
end
|
68
66
|
|
69
|
-
def error_messages
|
70
|
-
@_error_messages ||= []
|
71
|
-
end
|
72
|
-
|
73
67
|
def attempt_to_start?
|
74
68
|
unless cs__class.enabled?
|
75
69
|
logger.warn('Telemetry service is disabled!')
|
@@ -83,34 +77,8 @@ module Contrast
|
|
83
77
|
def start_thread!
|
84
78
|
return if running?
|
85
79
|
|
86
|
-
|
87
|
-
|
88
|
-
@_thread = Contrast::Agent::Thread.new do
|
89
|
-
logger.debug('Starting background telemetry thread.')
|
90
|
-
loop do
|
91
|
-
next unless client && connection
|
92
|
-
|
93
|
-
# Start pushing exceptions to queue for reporting.
|
94
|
-
push_exceptions
|
95
|
-
until queue.empty?
|
96
|
-
event = queue.pop
|
97
|
-
begin
|
98
|
-
logger.debug('This is the current processed event', event)
|
99
|
-
sleep_time = request_with_response(event)
|
100
|
-
if sleep_time
|
101
|
-
sleep(sleep_time)
|
102
|
-
logger.debug('Retrying to process event', event)
|
103
|
-
retry_sleep_time = request_with_response(event)
|
104
|
-
sleep(retry_sleep_time) unless retry_sleep_time.nil?
|
105
|
-
end
|
106
|
-
rescue StandardError => e
|
107
|
-
logger.error('Could not send message to service from telemetry queue.', e)
|
108
|
-
stop!
|
109
|
-
end
|
110
|
-
end
|
111
|
-
sleep(SUGGESTED_TIMEOUT)
|
112
|
-
end
|
113
|
-
end
|
80
|
+
logger.debug('Starting background telemetry thread.')
|
81
|
+
@_thread = create_thread
|
114
82
|
end
|
115
83
|
|
116
84
|
def send_event event
|
@@ -126,7 +94,6 @@ module Contrast
|
|
126
94
|
end
|
127
95
|
|
128
96
|
def delete_queue!
|
129
|
-
@_queue&.clear
|
130
97
|
@_queue&.close
|
131
98
|
@_queue = nil
|
132
99
|
end
|
@@ -149,6 +116,39 @@ module Contrast
|
|
149
116
|
def queue
|
150
117
|
@_queue ||= Queue.new
|
151
118
|
end
|
119
|
+
|
120
|
+
# It is recommended that implementations send a single payload of general metrics every 3 hours, starting from
|
121
|
+
# implementation startup. This returns a thread configured to do so.
|
122
|
+
#
|
123
|
+
# @return [Contrast::Agent::Thread]
|
124
|
+
def create_thread
|
125
|
+
Contrast::Agent::Thread.new do
|
126
|
+
loop do
|
127
|
+
next unless client && connection
|
128
|
+
|
129
|
+
# Start pushing exceptions to queue for reporting.
|
130
|
+
Contrast::TELEMETRY_EXCEPTIONS.each_value { |value| queue << value }
|
131
|
+
Contrast::TELEMETRY_EXCEPTIONS.clear
|
132
|
+
until queue.empty?
|
133
|
+
event = queue.pop
|
134
|
+
begin
|
135
|
+
logger.debug('This is the current processed event', event)
|
136
|
+
sleep_time = request_with_response(event)
|
137
|
+
if sleep_time
|
138
|
+
sleep(sleep_time)
|
139
|
+
logger.debug('Retrying to process event', event)
|
140
|
+
retry_sleep_time = request_with_response(event)
|
141
|
+
sleep(retry_sleep_time) unless retry_sleep_time.nil?
|
142
|
+
end
|
143
|
+
rescue StandardError => e
|
144
|
+
logger.error('Could not send message to service from telemetry queue.', e)
|
145
|
+
stop!
|
146
|
+
end
|
147
|
+
end
|
148
|
+
sleep(SUGGESTED_TIMEOUT)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
152
|
end
|
153
153
|
end
|
154
154
|
end
|
@@ -28,6 +28,7 @@ module Contrast
|
|
28
28
|
#
|
29
29
|
# @param validation_pair [Hash] Validation hash to use
|
30
30
|
# @param key[String] The key to check in VALIDATIONS
|
31
|
+
# @raise [ArgumentError]
|
31
32
|
def validate_field validation_pair, key
|
32
33
|
value_to_validate = send(key.to_sym)
|
33
34
|
validate_class(value_to_validate, validation_pair[:class], key) if validation_pair.key?(:class)
|
@@ -48,6 +49,7 @@ module Contrast
|
|
48
49
|
# @param message [Object] The message we want to check the class of
|
49
50
|
# @param klass [Class] The klass we want to check the message with
|
50
51
|
# @param field [Object] The field with the error
|
52
|
+
# @raise [ArgumentError]
|
51
53
|
def validate_class message, klass, field
|
52
54
|
message = message[0] if message.cs__is_a?(Array)
|
53
55
|
raise(ArgumentError, "The provided value for #{ field } is of wrong class") unless message.cs__is_a?(klass)
|
@@ -18,6 +18,7 @@ module Contrast
|
|
18
18
|
# to be created
|
19
19
|
#
|
20
20
|
# @param message [Contrast::Agent::Telemetry::TelemetryException::Message]
|
21
|
+
# @raise[ArgumentError]
|
21
22
|
def initialize message
|
22
23
|
super()
|
23
24
|
validate_class(message, Contrast::Agent::Telemetry::TelemetryException::Message, 'exception_message')
|
@@ -25,6 +26,7 @@ module Contrast
|
|
25
26
|
end
|
26
27
|
|
27
28
|
# @param message [Contrast::Agent::Telemetry::TelemetryException::Message]
|
29
|
+
# @raise[ArgumentError]
|
28
30
|
def push message
|
29
31
|
validate_class(message, Contrast::Agent::Telemetry::TelemetryException::Message, 'exception_message')
|
30
32
|
@exceptions << message
|
@@ -50,6 +50,7 @@ module Contrast
|
|
50
50
|
# @return [String | nil] A string message to provide additional context to the errors.
|
51
51
|
attr_reader :message
|
52
52
|
|
53
|
+
# @raise[ArgumentError]
|
53
54
|
def initialize instance, tags, exceptions
|
54
55
|
super()
|
55
56
|
@tags = tags
|
@@ -63,17 +64,19 @@ module Contrast
|
|
63
64
|
# Optional parameters will be set separately from the required
|
64
65
|
#
|
65
66
|
# @param logger[String]
|
67
|
+
# @raise[ArgumentError]
|
66
68
|
def logger= logger
|
67
|
-
validate_field(VALIDATIONS[:logger], 'logger')
|
68
69
|
@logger = logger
|
70
|
+
validate_field(VALIDATIONS[:logger], 'logger')
|
69
71
|
end
|
70
72
|
|
71
73
|
# Optional parameters will be set separately from the required
|
72
74
|
#
|
73
75
|
# @param message[String]
|
76
|
+
# @raise[ArgumentError]
|
74
77
|
def message= message
|
75
|
-
validate_field(VALIDATIONS[:message], 'message')
|
76
78
|
@message = message
|
79
|
+
validate_field(VALIDATIONS[:message], 'message')
|
77
80
|
end
|
78
81
|
|
79
82
|
# Optional parameters will be set separately from the required
|
data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_message_exception.rb
CHANGED
@@ -43,16 +43,19 @@ module Contrast
|
|
43
43
|
end
|
44
44
|
|
45
45
|
# @param stack_frame [Contrast::Agent::Telemetry::TelemetryException::StackFrame]
|
46
|
+
# @raise[ArgumentError]
|
46
47
|
def push stack_frame
|
47
48
|
validate_class(stack_frame, Contrast::Agent::Telemetry::TelemetryException::StackFrame, 'stack_frame')
|
48
49
|
@stack_frames << stack_frame
|
49
50
|
end
|
50
51
|
|
52
|
+
# @raise[ArgumentError]
|
51
53
|
def module_name= module_name
|
52
54
|
@module_name = module_name
|
53
55
|
validate_field(VALIDATIONS[:module_name], 'module_name')
|
54
56
|
end
|
55
57
|
|
58
|
+
# @raise[ArgumentError]
|
56
59
|
def value= value
|
57
60
|
@value = value
|
58
61
|
validate_field(VALIDATIONS[:value], 'value')
|
@@ -28,6 +28,7 @@ module Contrast
|
|
28
28
|
# @return [String]
|
29
29
|
attr_reader :module_name
|
30
30
|
|
31
|
+
# @raise [ArgumentError]
|
31
32
|
def initialize function, type
|
32
33
|
super()
|
33
34
|
@function = function
|
@@ -36,11 +37,13 @@ module Contrast
|
|
36
37
|
validate(VALIDATIONS)
|
37
38
|
end
|
38
39
|
|
40
|
+
# @raise [ArgumentError]
|
39
41
|
def module_name= module_name
|
40
42
|
@module_name = module_name
|
41
43
|
validate_field(VALIDATIONS[:module_name], 'module_name')
|
42
44
|
end
|
43
45
|
|
46
|
+
# @raise [ArgumentError]
|
44
47
|
def to_controlled_hash
|
45
48
|
super
|
46
49
|
{ function: function, type: type, module: module_name, inContrast: in_contrast }.compact
|
@@ -17,4 +17,3 @@ require 'contrast/agent/telemetry/events/exceptions/telemetry_exception_stack_fr
|
|
17
17
|
require 'contrast/agent/telemetry/events/exceptions/telemetry_exception_message_exception'
|
18
18
|
require 'contrast/agent/telemetry/events/exceptions/telemetry_exception_message'
|
19
19
|
require 'contrast/agent/telemetry/events/exceptions/telemetry_exception_event'
|
20
|
-
require 'contrast/agent/telemetry/events/exceptions/telemetry_exceptions_report'
|
@@ -33,7 +33,7 @@ module Contrast
|
|
33
33
|
@messaging_queue = Contrast::Api::Communication::MessagingQueue.new
|
34
34
|
end
|
35
35
|
@reporter = Contrast::Agent::Reporter.new
|
36
|
-
@reporter_heartbeat = Contrast::Agent::ReporterHeartbeat.new
|
36
|
+
@reporter_heartbeat = Contrast::Agent::ReporterHeartbeat.new
|
37
37
|
@telemetry = Contrast::Agent::Telemetry::Base.new if Contrast::Agent::Telemetry::Base.enabled?
|
38
38
|
end
|
39
39
|
|
@@ -50,9 +50,6 @@ module Contrast
|
|
50
50
|
@pids[Process.pid] = @pids[Process.pid] && telemetry_status
|
51
51
|
end
|
52
52
|
reporter_status = init_thread(reporter)
|
53
|
-
|
54
|
-
return @pids unless Contrast::Agent::Reporter.enabled?
|
55
|
-
|
56
53
|
reporter_heartbeat_status = init_thread(reporter_heartbeat)
|
57
54
|
@pids[Process.pid] = @pids[Process.pid] && reporter_status && reporter_heartbeat_status
|
58
55
|
@pids
|
@@ -1,10 +1,14 @@
|
|
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/logger'
|
5
|
+
|
4
6
|
module Contrast
|
5
7
|
module Agent
|
6
8
|
# Base class for threads that do async processing
|
7
9
|
class WorkerThread
|
10
|
+
include Contrast::Components::Logger::InstanceMethods
|
11
|
+
|
8
12
|
def initialize
|
9
13
|
@_thread = nil
|
10
14
|
end
|
@@ -27,6 +31,12 @@ module Contrast
|
|
27
31
|
def attempt_to_start?
|
28
32
|
true
|
29
33
|
end
|
34
|
+
|
35
|
+
def clean_properties
|
36
|
+
logger.debug("Cleaning PROPERTIES_HASH size: #{ Contrast::Agent::Assess::Tracker::PROPERTIES_HASH.size }")
|
37
|
+
Contrast::Agent::Assess::Tracker.cleanup!
|
38
|
+
logger.debug("Cleaned PROPERTIES_HASH size: #{ Contrast::Agent::Assess::Tracker::PROPERTIES_HASH.size }")
|
39
|
+
end
|
30
40
|
end
|
31
41
|
end
|
32
42
|
end
|
@@ -34,6 +34,7 @@ module Contrast
|
|
34
34
|
end
|
35
35
|
|
36
36
|
# Override this method to return a socket. Should be interface compatible with TCPSocket, UNIXSocket, etc.
|
37
|
+
# @raise[NoMethodError] abstract method, needs to be implemented
|
37
38
|
def new_socket
|
38
39
|
raise(NoMethodError, 'This is abstract, override it.')
|
39
40
|
end
|
@@ -19,14 +19,10 @@ module Contrast
|
|
19
19
|
|
20
20
|
def append_event event
|
21
21
|
case event
|
22
|
-
when Contrast::Api::Dtm::ServerActivity
|
23
|
-
self.server_activity = event
|
24
22
|
when Contrast::Api::Dtm::AgentStartup
|
25
23
|
self.agent_startup = event
|
26
24
|
when Contrast::Api::Dtm::ApplicationCreate
|
27
25
|
self.application_create = event
|
28
|
-
when Contrast::Api::Dtm::ApplicationUpdate
|
29
|
-
self.application_update = event
|
30
26
|
when Contrast::Api::Dtm::Activity
|
31
27
|
self.activity = event
|
32
28
|
when Contrast::Api::Dtm::HttpRequest
|
@@ -35,8 +31,6 @@ module Contrast
|
|
35
31
|
self.postfilter = event
|
36
32
|
when Contrast::Api::Dtm::Poll
|
37
33
|
self.poll = event
|
38
|
-
when Contrast::Api::Dtm::ObservedRoute
|
39
|
-
self.observed_route = event
|
40
34
|
else
|
41
35
|
logger.error('Unknown event type received. Unsure how to send.', event_type: event.cs__class.cs__name)
|
42
36
|
return
|
@@ -12,12 +12,10 @@ end
|
|
12
12
|
require 'contrast/api/decorators/message'
|
13
13
|
require 'contrast/api/decorators/agent_startup'
|
14
14
|
require 'contrast/api/decorators/application_startup'
|
15
|
-
require 'contrast/api/decorators/application_update'
|
16
15
|
require 'contrast/api/decorators/architecture_component'
|
17
16
|
require 'contrast/api/decorators/input_analysis'
|
18
17
|
require 'contrast/api/decorators/application_settings'
|
19
18
|
require 'contrast/api/decorators/server_features'
|
20
|
-
require 'contrast/api/decorators/library'
|
21
19
|
require 'contrast/api/decorators/route_coverage'
|
22
20
|
require 'contrast/api/decorators/trace_event_object'
|
23
21
|
require 'contrast/api/decorators/trace_event_signature'
|
data/lib/contrast/api/dtm.pb.rb
CHANGED