datadog 2.46.0 → 2.48.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/CHANGELOG.md +56 -2
- data/LICENSE-3rdparty.csv +1 -0
- data/ext/datadog_profiling_native_extension/collectors_stack.c +143 -86
- data/ext/datadog_profiling_native_extension/collectors_stack.h +9 -1
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +6 -1
- data/ext/datadog_profiling_native_extension/extconf.rb +7 -13
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +3 -3
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +67 -14
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +8 -1
- data/ext/datadog_profiling_native_extension/profiling.c +1 -1
- data/ext/libdatadog_api/extconf.rb +9 -7
- data/ext/libdatadog_api/trace_exporter.c +34 -7
- data/ext/libdatadog_extconf_helpers.rb +2 -2
- data/lib/datadog/ai_guard/component.rb +1 -1
- data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +1 -9
- data/lib/datadog/ai_guard/contrib/rails/patcher.rb +1 -1
- data/lib/datadog/ai_guard/contrib/ruby_llm/message_adapter.rb +1 -1
- data/lib/datadog/ai_guard/contrib/ruby_llm/redaction_change_set.rb +3 -3
- data/lib/datadog/ai_guard/evaluation/client.rb +3 -3
- data/lib/datadog/ai_guard/evaluation.rb +2 -2
- data/lib/datadog/ai_guard/http_client.rb +3 -2
- data/lib/datadog/ai_guard/redaction.rb +1 -1
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +1 -1
- data/lib/datadog/appsec/assets/waf_rules/README.md +3 -3
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +5366 -1517
- data/lib/datadog/appsec/assets/waf_rules/strict.json +2 -2
- data/lib/datadog/appsec/autoload.rb +1 -1
- data/lib/datadog/appsec/component.rb +1 -1
- data/lib/datadog/appsec/compressed_json.rb +1 -1
- data/lib/datadog/appsec/configuration.rb +3 -3
- data/lib/datadog/appsec/context.rb +1 -1
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +11 -1
- data/lib/datadog/appsec/contrib/active_record/patcher.rb +12 -4
- data/lib/datadog/appsec/contrib/aws_lambda/gateway/watcher.rb +2 -2
- data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/configuration.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +1 -1
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +1 -1
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +1 -1
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +7 -7
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +3 -3
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +5 -5
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +31 -4
- data/lib/datadog/appsec/contrib/rails/patcher.rb +2 -2
- data/lib/datadog/appsec/contrib/rails/patches/render_to_body_patch.rb +8 -7
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +17 -5
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/patches/json_patch.rb +8 -7
- data/lib/datadog/appsec/metrics/collector.rb +5 -5
- data/lib/datadog/appsec/metrics/telemetry_exporter.rb +3 -3
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +2 -2
- data/lib/datadog/appsec/processor/rule_loader.rb +1 -1
- data/lib/datadog/appsec/response.rb +1 -1
- data/lib/datadog/appsec/security_engine/engine.rb +8 -7
- data/lib/datadog/appsec/security_engine/runner.rb +2 -2
- data/lib/datadog/appsec/trace_keeper.rb +1 -1
- data/lib/datadog/appsec.rb +1 -1
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +14 -13
- data/lib/datadog/core/configuration/agentless_settings_resolver.rb +2 -2
- data/lib/datadog/core/configuration/components.rb +12 -11
- data/lib/datadog/core/configuration/components_state.rb +8 -1
- data/lib/datadog/core/configuration/settings.rb +5 -2
- data/lib/datadog/core/configuration/supported_configurations.rb +3 -0
- data/lib/datadog/core/configuration.rb +2 -2
- data/lib/datadog/core/crashtracking/component.rb +1 -1
- data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
- data/lib/datadog/core/environment/cgroup.rb +2 -2
- data/lib/datadog/core/environment/container.rb +3 -3
- data/lib/datadog/core/metrics/client.rb +6 -6
- data/lib/datadog/core/process_discovery.rb +1 -1
- data/lib/datadog/core/remote/client.rb +44 -3
- data/lib/datadog/core/remote/dispatcher.rb +34 -3
- data/lib/datadog/core/remote/tie/tracing.rb +4 -3
- data/lib/datadog/core/remote/transport/http.rb +2 -2
- data/lib/datadog/core/runtime/metrics.rb +14 -14
- data/lib/datadog/core/semaphore.rb +3 -1
- data/lib/datadog/core/telemetry/event/app_started.rb +9 -9
- data/lib/datadog/core/telemetry/logger.rb +1 -1
- data/lib/datadog/core/telemetry/logging.rb +1 -1
- data/lib/datadog/core/telemetry/request.rb +9 -3
- data/lib/datadog/core/telemetry/transport/http.rb +2 -2
- data/lib/datadog/core/telemetry/worker.rb +1 -1
- data/lib/datadog/core/transport/http/adapters/net.rb +1 -1
- data/lib/datadog/core/transport/http/adapters/unix_socket.rb +1 -1
- data/lib/datadog/core/transport/http/builder.rb +1 -1
- data/lib/datadog/core/transport/http.rb +3 -3
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +2 -2
- data/lib/datadog/core/workers/async.rb +1 -1
- data/lib/datadog/core/workers/runtime_metrics.rb +2 -2
- data/lib/datadog/data_streams/pathway_context.rb +1 -1
- data/lib/datadog/data_streams/processor.rb +48 -27
- data/lib/datadog/data_streams/transport/http.rb +1 -1
- data/lib/datadog/data_streams.rb +16 -0
- data/lib/datadog/di/capture_expression_evaluator.rb +48 -11
- data/lib/datadog/di/component.rb +73 -2
- data/lib/datadog/di/configuration.rb +19 -0
- data/lib/datadog/di/contrib/active_record.rb +1 -1
- data/lib/datadog/di/el/compiler.rb +4 -4
- data/lib/datadog/di/el/evaluator.rb +247 -43
- data/lib/datadog/di/el/expression.rb +36 -6
- data/lib/datadog/di/error.rb +16 -0
- data/lib/datadog/di/guardrails_telemetry/reason.rb +3 -2
- data/lib/datadog/di/instrumenter.rb +39 -10
- data/lib/datadog/di/probe_notification_builder.rb +58 -10
- data/lib/datadog/di/probe_notifier_worker.rb +1 -1
- data/lib/datadog/di/remote.rb +46 -2
- data/lib/datadog/di/serializer.rb +47 -13
- data/lib/datadog/di.rb +27 -0
- data/lib/datadog/error_tracking/component.rb +1 -1
- data/lib/datadog/error_tracking/configuration.rb +1 -1
- data/lib/datadog/kit/appsec/events/v2.rb +6 -6
- data/lib/datadog/kit/appsec/events.rb +1 -1
- data/lib/datadog/kit/enable_core_dumps.rb +1 -1
- data/lib/datadog/kit/identity.rb +1 -1
- data/lib/datadog/open_feature/activation.rb +26 -1
- data/lib/datadog/open_feature/agentless/configuration_source.rb +94 -15
- data/lib/datadog/open_feature/component.rb +22 -2
- data/lib/datadog/open_feature/configuration/agentless_endpoint.rb +6 -0
- data/lib/datadog/open_feature/configuration.rb +10 -4
- data/lib/datadog/open_feature/evaluation_engine.rb +62 -4
- data/lib/datadog/open_feature/exposures/buffer.rb +4 -0
- data/lib/datadog/open_feature/exposures/reporter.rb +17 -4
- data/lib/datadog/open_feature/exposures/worker.rb +37 -6
- data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +5 -5
- data/lib/datadog/open_feature/flag_evaluation/writer.rb +1 -1
- data/lib/datadog/open_feature/hooks/debug_logging_hook.rb +56 -0
- data/lib/datadog/open_feature/hooks/evaluation_telemetry_opt_out_hook.rb +25 -0
- data/lib/datadog/open_feature/hooks/span_enrichment_hook.rb +2 -2
- data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +1 -1
- data/lib/datadog/open_feature/native_evaluator.rb +1 -1
- data/lib/datadog/open_feature/noop_evaluator.rb +1 -1
- data/lib/datadog/open_feature/provider.rb +69 -12
- data/lib/datadog/open_feature/remote.rb +8 -1
- data/lib/datadog/open_feature/resolution_details.rb +2 -2
- data/lib/datadog/open_feature/transport.rb +6 -6
- data/lib/datadog/opentelemetry/api/context.rb +3 -3
- data/lib/datadog/opentelemetry/logs.rb +5 -5
- data/lib/datadog/opentelemetry/metrics.rb +3 -3
- data/lib/datadog/opentelemetry/sdk/propagator.rb +3 -3
- data/lib/datadog/opentelemetry/sdk/span_processor.rb +2 -2
- data/lib/datadog/opentelemetry/sdk/trace/span.rb +1 -1
- data/lib/datadog/profiling/collectors/code_provenance.rb +3 -3
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +4 -4
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -1
- data/lib/datadog/profiling/collectors/info.rb +37 -6
- data/lib/datadog/profiling/collectors/thread_context.rb +1 -1
- data/lib/datadog/profiling/component.rb +41 -39
- data/lib/datadog/profiling/exporter.rb +4 -6
- data/lib/datadog/profiling/http_transport.rb +3 -3
- data/lib/datadog/profiling/profiler.rb +2 -2
- data/lib/datadog/profiling/scheduler.rb +2 -2
- data/lib/datadog/profiling/tag_builder.rb +1 -1
- data/lib/datadog/symbol_database/extractor.rb +8 -8
- data/lib/datadog/symbol_database/uploader.rb +1 -1
- data/lib/datadog/tracing/buffer.rb +3 -3
- data/lib/datadog/tracing/client_ip.rb +1 -1
- data/lib/datadog/tracing/component.rb +15 -10
- data/lib/datadog/tracing/configuration/dynamic/option.rb +2 -2
- data/lib/datadog/tracing/configuration/ext.rb +2 -0
- data/lib/datadog/tracing/configuration/settings.rb +14 -3
- data/lib/datadog/tracing/context.rb +1 -1
- data/lib/datadog/tracing/context_provider.rb +8 -0
- data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +2 -2
- data/lib/datadog/tracing/contrib/active_job/data_streams.rb +27 -2
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +2 -2
- data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/utils.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +2 -2
- data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +2 -2
- data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +17 -12
- data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +1 -1
- data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/excon/middleware.rb +16 -9
- data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +14 -8
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +4 -4
- data/lib/datadog/tracing/contrib/graphql/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +3 -3
- data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +2 -2
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +1 -1
- data/lib/datadog/tracing/contrib/grpc.rb +1 -1
- data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +1 -1
- data/lib/datadog/tracing/contrib/hanami/plugin.rb +1 -1
- data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +1 -1
- data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +1 -1
- data/lib/datadog/tracing/contrib/http/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +21 -6
- data/lib/datadog/tracing/contrib/http.rb +1 -1
- data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +14 -8
- data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +14 -8
- data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +2 -2
- data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +2 -2
- data/lib/datadog/tracing/contrib/karafka/monitor.rb +1 -1
- data/lib/datadog/tracing/contrib/karafka/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/karafka.rb +1 -1
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/mongodb/parsers.rb +1 -1
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +1 -1
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +3 -3
- data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +4 -4
- data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/presto/instrumentation.rb +4 -4
- data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +1 -1
- data/lib/datadog/tracing/contrib/que/tracer.rb +1 -1
- data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/racecar/events/batch.rb +1 -1
- data/lib/datadog/tracing/contrib/racecar/events/message.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +3 -3
- data/lib/datadog/tracing/contrib/rack/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/framework.rb +7 -7
- data/lib/datadog/tracing/contrib/rails/log_injection.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/runner.rb +4 -4
- data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/redis/quantize.rb +1 -1
- data/lib/datadog/tracing/contrib/redis/tags.rb +1 -1
- data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +17 -10
- data/lib/datadog/tracing/contrib/sequel/database.rb +1 -1
- data/lib/datadog/tracing/contrib/sequel/dataset.rb +1 -1
- data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +1 -1
- data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +2 -2
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +2 -2
- data/lib/datadog/tracing/contrib/sidekiq.rb +1 -1
- data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +1 -1
- data/lib/datadog/tracing/contrib/status_range_env_parser.rb +1 -1
- data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +3 -3
- data/lib/datadog/tracing/contrib/utils/quantization/http.rb +102 -0
- data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +2 -2
- data/lib/datadog/tracing/contrib/waterdrop.rb +1 -1
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +1 -1
- data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
- data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
- data/lib/datadog/tracing/distributed/baggage.rb +3 -3
- data/lib/datadog/tracing/distributed/datadog.rb +3 -3
- data/lib/datadog/tracing/distributed/propagation.rb +7 -7
- data/lib/datadog/tracing/distributed/trace_context.rb +1 -1
- data/lib/datadog/tracing/distributed/trace_state/open_telemetry.rb +1 -1
- data/lib/datadog/tracing/otel_thread_context.rb +3 -3
- data/lib/datadog/tracing/pipeline.rb +1 -1
- data/lib/datadog/tracing/remote.rb +50 -19
- data/lib/datadog/tracing/sampling/priority_sampler.rb +1 -1
- data/lib/datadog/tracing/sampling/rule.rb +1 -1
- data/lib/datadog/tracing/sampling/rule_sampler.rb +1 -1
- data/lib/datadog/tracing/sampling/span/rule_parser.rb +2 -2
- data/lib/datadog/tracing/span_operation.rb +1 -1
- data/lib/datadog/tracing/trace_digest.rb +1 -1
- data/lib/datadog/tracing/trace_operation.rb +6 -6
- data/lib/datadog/tracing/tracer.rb +6 -6
- data/lib/datadog/tracing/transport/http/telemetry.rb +1 -1
- data/lib/datadog/tracing/transport/http.rb +2 -2
- data/lib/datadog/tracing/transport/io.rb +1 -1
- data/lib/datadog/tracing/transport/native.rb +3 -3
- data/lib/datadog/tracing/transport/statistics.rb +2 -2
- data/lib/datadog/tracing/transport/telemetry.rb +3 -1
- data/lib/datadog/tracing/transport/trace_formatter.rb +12 -12
- data/lib/datadog/tracing/transport/traces.rb +1 -1
- data/lib/datadog/tracing/utils.rb +1 -1
- data/lib/datadog/tracing/workers.rb +1 -1
- data/lib/datadog/version.rb +1 -1
- metadata +9 -8
- data/lib/datadog/appsec/utils/hash_coercion.rb +0 -23
|
@@ -7,7 +7,7 @@ if %w[1 true].include?((Datadog::DATADOG_ENV["DD_APPSEC_ENABLED"] || "").downcas
|
|
|
7
7
|
rescue => e
|
|
8
8
|
Kernel.warn(
|
|
9
9
|
"[datadog] AppSec failed to instrument. No security check will be performed. error: " \
|
|
10
|
-
" #{e.class}: #{e.message}"
|
|
10
|
+
" #{e.class}: #{e.message}",
|
|
11
11
|
)
|
|
12
12
|
end
|
|
13
13
|
end
|
|
@@ -26,7 +26,7 @@ module Datadog
|
|
|
26
26
|
Datadog.logger.warn(
|
|
27
27
|
"AppSec is not supported in Ruby versions above 3.3.0 when using `ffi` versions older than 1.16.0, " \
|
|
28
28
|
"and will be forcibly disabled due to a memory leak in `ffi`. " \
|
|
29
|
-
"Please upgrade your `ffi` version to 1.16.0 or higher."
|
|
29
|
+
"Please upgrade your `ffi` version to 1.16.0 or higher.",
|
|
30
30
|
)
|
|
31
31
|
telemetry.error("AppSec: Component not loaded, ffi version is leaky with ruby > 3.3.0")
|
|
32
32
|
|
|
@@ -28,7 +28,7 @@ module Datadog
|
|
|
28
28
|
|
|
29
29
|
private_class_method def self.compress_and_encode(payload)
|
|
30
30
|
Core::Utils::Base64Codec.strict_encode64(
|
|
31
|
-
Zlib.gzip(payload, level: Zlib::BEST_SPEED, strategy: Zlib::DEFAULT_STRATEGY)
|
|
31
|
+
Zlib.gzip(payload, level: Zlib::BEST_SPEED, strategy: Zlib::DEFAULT_STRATEGY),
|
|
32
32
|
)
|
|
33
33
|
rescue Zlib::Error, TypeError => e
|
|
34
34
|
AppSec.telemetry.report(e, description: "AppSec: Failed to compress and encode value")
|
|
@@ -34,7 +34,7 @@ module Datadog
|
|
|
34
34
|
SAFE_TRACK_USER_EVENTS_MODE, EXTENDED_TRACK_USER_EVENTS_MODE,
|
|
35
35
|
].freeze
|
|
36
36
|
APPSEC_VALID_TRACK_USER_EVENTS_ENABLED_VALUES = ["1", "true"].concat(
|
|
37
|
-
APPSEC_VALID_TRACK_USER_EVENTS_MODE
|
|
37
|
+
APPSEC_VALID_TRACK_USER_EVENTS_MODE,
|
|
38
38
|
).freeze
|
|
39
39
|
|
|
40
40
|
def self.extended(base)
|
|
@@ -297,7 +297,7 @@ module Datadog
|
|
|
297
297
|
Datadog.logger.warn(
|
|
298
298
|
"The appsec.auto_user_instrumentation.mode value provided is not supported. " \
|
|
299
299
|
"Supported values are: #{AUTO_USER_INSTRUMENTATION_MODES.join(" | ")}. " \
|
|
300
|
-
"Using value: #{DISABLED_AUTO_USER_INSTRUMENTATION_MODE}."
|
|
300
|
+
"Using value: #{DISABLED_AUTO_USER_INSTRUMENTATION_MODE}.",
|
|
301
301
|
)
|
|
302
302
|
|
|
303
303
|
DISABLED_AUTO_USER_INSTRUMENTATION_MODE
|
|
@@ -342,7 +342,7 @@ module Datadog
|
|
|
342
342
|
Datadog.logger.warn(
|
|
343
343
|
"The appsec.track_user_events.mode value provided is not supported." \
|
|
344
344
|
"Supported values are: #{APPSEC_VALID_TRACK_USER_EVENTS_MODE.join(" | ")}." \
|
|
345
|
-
"Using default value: #{SAFE_TRACK_USER_EVENTS_MODE}."
|
|
345
|
+
"Using default value: #{SAFE_TRACK_USER_EVENTS_MODE}.",
|
|
346
346
|
)
|
|
347
347
|
|
|
348
348
|
SAFE_TRACK_USER_EVENTS_MODE
|
|
@@ -57,7 +57,7 @@ module Datadog
|
|
|
57
57
|
@waf_runner = waf_runner
|
|
58
58
|
@metrics = Metrics::Collector.new
|
|
59
59
|
@downstream_body_sampler = CounterSampler.new(
|
|
60
|
-
Datadog.configuration.appsec.api_security.downstream_body_analysis.sample_rate
|
|
60
|
+
Datadog.configuration.appsec.api_security.downstream_body_analysis.sample_rate,
|
|
61
61
|
)
|
|
62
62
|
@state = {
|
|
63
63
|
events: [],
|
|
@@ -36,13 +36,23 @@ module Datadog
|
|
|
36
36
|
TraceKeeper.keep!(context.trace) if result.keep?
|
|
37
37
|
|
|
38
38
|
context.events.push(
|
|
39
|
-
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
|
39
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span),
|
|
40
40
|
)
|
|
41
41
|
|
|
42
42
|
AppSec::ActionsHandler.handle(result.actions)
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
+
module PreprocessQueryAdapterPatch
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def preprocess_query(sql)
|
|
50
|
+
Instrumentation.detect_sql_injection(sql, adapter_name)
|
|
51
|
+
|
|
52
|
+
super
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
46
56
|
# patch for mysql2, sqlite3, and postgres+jdbc adapters in ActiveRecord >= 7.1
|
|
47
57
|
module InternalExecQueryAdapterPatch
|
|
48
58
|
def internal_exec_query(sql, *args, **rest)
|
|
@@ -52,7 +52,9 @@ module Datadog
|
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def patch_sqlite3_adapter
|
|
55
|
-
instrumentation_module = if ::ActiveRecord.gem_version >= Gem::Version.new("
|
|
55
|
+
instrumentation_module = if ::ActiveRecord.gem_version >= Gem::Version.new("8.0")
|
|
56
|
+
Instrumentation::PreprocessQueryAdapterPatch
|
|
57
|
+
elsif ::ActiveRecord.gem_version >= Gem::Version.new("7.1")
|
|
56
58
|
Instrumentation::InternalExecQueryAdapterPatch
|
|
57
59
|
elsif ::ActiveRecord.gem_version.segments.first == 4
|
|
58
60
|
Instrumentation::Rails4ExecQueryAdapterPatch
|
|
@@ -65,7 +67,9 @@ module Datadog
|
|
|
65
67
|
end
|
|
66
68
|
|
|
67
69
|
def patch_mysql2_adapter
|
|
68
|
-
instrumentation_module = if ::ActiveRecord.gem_version >= Gem::Version.new("
|
|
70
|
+
instrumentation_module = if ::ActiveRecord.gem_version >= Gem::Version.new("8.0")
|
|
71
|
+
Instrumentation::PreprocessQueryAdapterPatch
|
|
72
|
+
elsif ::ActiveRecord.gem_version >= Gem::Version.new("7.1")
|
|
69
73
|
Instrumentation::InternalExecQueryAdapterPatch
|
|
70
74
|
elsif ::ActiveRecord.gem_version.segments.first == 4
|
|
71
75
|
Instrumentation::Rails4ExecQueryAdapterPatch
|
|
@@ -78,14 +82,18 @@ module Datadog
|
|
|
78
82
|
end
|
|
79
83
|
|
|
80
84
|
def patch_postgresql_adapter
|
|
81
|
-
instrumentation_module = if ::ActiveRecord.gem_version.
|
|
85
|
+
instrumentation_module = if ::ActiveRecord.gem_version >= Gem::Version.new("8.0")
|
|
86
|
+
Instrumentation::PreprocessQueryAdapterPatch
|
|
87
|
+
elsif ::ActiveRecord.gem_version.segments.first == 4
|
|
82
88
|
Instrumentation::Rails4ExecuteAndClearAdapterPatch
|
|
83
89
|
else
|
|
84
90
|
Instrumentation::ExecuteAndClearAdapterPatch
|
|
85
91
|
end
|
|
86
92
|
|
|
87
93
|
if defined?(::ActiveRecord::ConnectionAdapters::JdbcAdapter)
|
|
88
|
-
instrumentation_module = if ::ActiveRecord.gem_version >= Gem::Version.new("
|
|
94
|
+
instrumentation_module = if ::ActiveRecord.gem_version >= Gem::Version.new("8.0")
|
|
95
|
+
Instrumentation::PreprocessQueryAdapterPatch
|
|
96
|
+
elsif ::ActiveRecord.gem_version >= Gem::Version.new("7.1")
|
|
89
97
|
Instrumentation::InternalExecQueryAdapterPatch
|
|
90
98
|
elsif ::ActiveRecord.gem_version.segments.first == 4
|
|
91
99
|
Instrumentation::Rails4ExecQueryAdapterPatch
|
|
@@ -30,7 +30,7 @@ module Datadog
|
|
|
30
30
|
|
|
31
31
|
if result.match? || !result.attributes.empty?
|
|
32
32
|
context.events.push(
|
|
33
|
-
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
|
33
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span),
|
|
34
34
|
)
|
|
35
35
|
end
|
|
36
36
|
|
|
@@ -57,7 +57,7 @@ module Datadog
|
|
|
57
57
|
TraceKeeper.keep!(context.trace) if result.keep?
|
|
58
58
|
|
|
59
59
|
context.events.push(
|
|
60
|
-
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
|
60
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span),
|
|
61
61
|
)
|
|
62
62
|
|
|
63
63
|
AppSec::ActionsHandler.handle(result.actions)
|
|
@@ -113,7 +113,7 @@ module Datadog
|
|
|
113
113
|
|
|
114
114
|
body = Core::Utils::Base64Codec.strict_decode64(body) if payload["base64_encoded"]
|
|
115
115
|
AppSec::Utils::HTTP::Body.parse(
|
|
116
|
-
body, media_type: media_type, limit: Datadog.configuration.appsec.body_parsing_size_limit
|
|
116
|
+
body, media_type: media_type, limit: Datadog.configuration.appsec.body_parsing_size_limit,
|
|
117
117
|
)
|
|
118
118
|
rescue ArgumentError => e
|
|
119
119
|
AppSec.telemetry.report(e, description: "AppSec: Failed to decode base64 body")
|
|
@@ -39,7 +39,7 @@ module Datadog
|
|
|
39
39
|
if !appsec.track_user_events.options[:mode].default_precedence? &&
|
|
40
40
|
appsec.auto_user_instrumentation.options[:mode].default_precedence?
|
|
41
41
|
return TRACK_USER_EVENTS_CONVERSION_RULES.fetch(
|
|
42
|
-
appsec.track_user_events.mode, appsec.auto_user_instrumentation.mode
|
|
42
|
+
appsec.track_user_events.mode, appsec.auto_user_instrumentation.mode,
|
|
43
43
|
)
|
|
44
44
|
end
|
|
45
45
|
|
|
@@ -64,7 +64,7 @@ module Datadog
|
|
|
64
64
|
# and because of that we will trigger an additional event even
|
|
65
65
|
# if it was already done via the SDK
|
|
66
66
|
AppSec::Instrumentation.gateway.push(
|
|
67
|
-
"identity.set_user", AppSec::Instrumentation::Gateway::User.new(id, login)
|
|
67
|
+
"identity.set_user", AppSec::Instrumentation::Gateway::User.new(id, login),
|
|
68
68
|
)
|
|
69
69
|
end
|
|
70
70
|
|
|
@@ -59,7 +59,7 @@ module Datadog
|
|
|
59
59
|
# and because of that we will trigger an additional event even
|
|
60
60
|
# if it was already done via the SDK
|
|
61
61
|
AppSec::Instrumentation.gateway.push(
|
|
62
|
-
"identity.set_user", AppSec::Instrumentation::Gateway::User.new(id, login)
|
|
62
|
+
"identity.set_user", AppSec::Instrumentation::Gateway::User.new(id, login),
|
|
63
63
|
)
|
|
64
64
|
end
|
|
65
65
|
end
|
|
@@ -49,7 +49,7 @@ module Datadog
|
|
|
49
49
|
# passing them at first place.
|
|
50
50
|
# This is a temporary situation until we refactor events model.
|
|
51
51
|
AppSec::Instrumentation.gateway.push(
|
|
52
|
-
"identity.set_user", AppSec::Instrumentation::Gateway::User.new(user_id, nil, user_session_id)
|
|
52
|
+
"identity.set_user", AppSec::Instrumentation::Gateway::User.new(user_id, nil, user_session_id),
|
|
53
53
|
)
|
|
54
54
|
end
|
|
55
55
|
|
|
@@ -169,7 +169,7 @@ module Datadog
|
|
|
169
169
|
TraceKeeper.keep!(context.trace) if result.keep?
|
|
170
170
|
|
|
171
171
|
context.events.push(
|
|
172
|
-
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
|
172
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span),
|
|
173
173
|
)
|
|
174
174
|
|
|
175
175
|
AppSec::ActionsHandler.handle(result.actions)
|
|
@@ -154,7 +154,7 @@ module Datadog
|
|
|
154
154
|
TraceKeeper.keep!(context.trace) if result.keep?
|
|
155
155
|
|
|
156
156
|
context.events.push(
|
|
157
|
-
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
|
157
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span),
|
|
158
158
|
)
|
|
159
159
|
|
|
160
160
|
AppSec::ActionsHandler.handle(result.actions)
|
|
@@ -60,7 +60,7 @@ module Datadog
|
|
|
60
60
|
when ::GraphQL::Language::Nodes::FragmentSpread
|
|
61
61
|
fragment_name = selection.name
|
|
62
62
|
append_arguments(
|
|
63
|
-
args_hash, fragment_name, nil, arguments_from_directives(selection.directives, query_variables)
|
|
63
|
+
args_hash, fragment_name, nil, arguments_from_directives(selection.directives, query_variables),
|
|
64
64
|
)
|
|
65
65
|
|
|
66
66
|
next if visited_fragments[fragment_name]
|
|
@@ -69,13 +69,13 @@ module Datadog
|
|
|
69
69
|
next unless fragment
|
|
70
70
|
|
|
71
71
|
append_arguments(
|
|
72
|
-
args_hash, fragment_name, nil, arguments_from_directives(fragment.directives, query_variables)
|
|
72
|
+
args_hash, fragment_name, nil, arguments_from_directives(fragment.directives, query_variables),
|
|
73
73
|
)
|
|
74
74
|
|
|
75
75
|
# re-used fragments are not expanded
|
|
76
76
|
visited_fragments[fragment_name] = true
|
|
77
77
|
arguments_from_selections(
|
|
78
|
-
fragment.selections, query_variables, args_hash, fragments, visited_fragments
|
|
78
|
+
fragment.selections, query_variables, args_hash, fragments, visited_fragments,
|
|
79
79
|
)
|
|
80
80
|
when ::GraphQL::Language::Nodes::Field
|
|
81
81
|
selection_name = selection.alias || selection.name
|
|
@@ -84,19 +84,19 @@ module Datadog
|
|
|
84
84
|
args_hash,
|
|
85
85
|
selection_name,
|
|
86
86
|
field_arguments,
|
|
87
|
-
arguments_from_directives(selection.directives, query_variables)
|
|
87
|
+
arguments_from_directives(selection.directives, query_variables),
|
|
88
88
|
)
|
|
89
89
|
|
|
90
90
|
arguments_from_selections(
|
|
91
|
-
selection.selections, query_variables, args_hash, fragments, visited_fragments
|
|
91
|
+
selection.selections, query_variables, args_hash, fragments, visited_fragments,
|
|
92
92
|
)
|
|
93
93
|
when ::GraphQL::Language::Nodes::InlineFragment
|
|
94
94
|
append_arguments(
|
|
95
|
-
args_hash, selection.type.name, nil, arguments_from_directives(selection.directives, query_variables)
|
|
95
|
+
args_hash, selection.type.name, nil, arguments_from_directives(selection.directives, query_variables),
|
|
96
96
|
)
|
|
97
97
|
|
|
98
98
|
arguments_from_selections(
|
|
99
|
-
selection.selections, query_variables, args_hash, fragments, visited_fragments
|
|
99
|
+
selection.selections, query_variables, args_hash, fragments, visited_fragments,
|
|
100
100
|
)
|
|
101
101
|
end
|
|
102
102
|
end
|
|
@@ -37,7 +37,7 @@ module Datadog
|
|
|
37
37
|
TraceKeeper.keep!(context.trace) if result.keep?
|
|
38
38
|
|
|
39
39
|
context.events.push(
|
|
40
|
-
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
|
40
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span),
|
|
41
41
|
)
|
|
42
42
|
|
|
43
43
|
AppSec::ActionsHandler.handle(result.actions)
|
|
@@ -41,7 +41,7 @@ module Datadog
|
|
|
41
41
|
|
|
42
42
|
if result.match? || !result.attributes.empty?
|
|
43
43
|
context.events.push(
|
|
44
|
-
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
|
44
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span),
|
|
45
45
|
)
|
|
46
46
|
end
|
|
47
47
|
|
|
@@ -73,7 +73,7 @@ module Datadog
|
|
|
73
73
|
TraceKeeper.keep!(context.trace) if result.keep?
|
|
74
74
|
|
|
75
75
|
context.events.push(
|
|
76
|
-
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
|
76
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span),
|
|
77
77
|
)
|
|
78
78
|
|
|
79
79
|
AppSec::ActionsHandler.handle(result.actions)
|
|
@@ -119,7 +119,7 @@ module Datadog
|
|
|
119
119
|
TraceKeeper.keep!(context.trace) if result.keep?
|
|
120
120
|
|
|
121
121
|
context.events.push(
|
|
122
|
-
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
|
122
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span),
|
|
123
123
|
)
|
|
124
124
|
|
|
125
125
|
AppSec::ActionsHandler.handle(result.actions)
|
|
@@ -49,7 +49,7 @@ module Datadog
|
|
|
49
49
|
return @app.call(env) unless security_engine
|
|
50
50
|
|
|
51
51
|
ctx = Datadog::AppSec::Context.activate(
|
|
52
|
-
Datadog::AppSec::Context.new(active_trace, active_span, security_engine.new_runner)
|
|
52
|
+
Datadog::AppSec::Context.new(active_trace, active_span, security_engine.new_runner),
|
|
53
53
|
)
|
|
54
54
|
env[Datadog::AppSec::Ext::CONTEXT_KEY] = ctx
|
|
55
55
|
|
|
@@ -68,7 +68,7 @@ module Datadog
|
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
gateway_response = Gateway::Response.new(
|
|
71
|
-
http_response[2], http_response[0], http_response[1], context: ctx
|
|
71
|
+
http_response[2], http_response[0], http_response[1], context: ctx,
|
|
72
72
|
)
|
|
73
73
|
|
|
74
74
|
Instrumentation.gateway.push("rack.request.finish", gateway_request)
|
|
@@ -165,7 +165,7 @@ module Datadog
|
|
|
165
165
|
trace.keep!
|
|
166
166
|
trace.set_tag(
|
|
167
167
|
Datadog::Tracing::Metadata::Ext::Distributed::TAG_DECISION_MAKER,
|
|
168
|
-
Datadog::Tracing::Sampling::Ext::Decision::ASM
|
|
168
|
+
Datadog::Tracing::Sampling::Ext::Decision::ASM,
|
|
169
169
|
)
|
|
170
170
|
end
|
|
171
171
|
end
|
|
@@ -182,7 +182,7 @@ module Datadog
|
|
|
182
182
|
if span.get_tag(Tracing::Metadata::Ext::HTTP::TAG_CLIENT_IP).nil?
|
|
183
183
|
# always collect client ip, as this is part of AppSec provided functionality
|
|
184
184
|
Datadog::Tracing::ClientIp.set_client_ip_tag!(
|
|
185
|
-
span, headers: headers, remote_ip: env["REMOTE_ADDR"]
|
|
185
|
+
span, headers: headers, remote_ip: env["REMOTE_ADDR"],
|
|
186
186
|
)
|
|
187
187
|
end
|
|
188
188
|
end
|
|
@@ -192,7 +192,7 @@ module Datadog
|
|
|
192
192
|
return unless span
|
|
193
193
|
|
|
194
194
|
AppSec::DefaultHeaderTags.tag_response(
|
|
195
|
-
span, Datadog::Core::HeaderCollection.from_hash(response.headers)
|
|
195
|
+
span, Datadog::Core::HeaderCollection.from_hash(response.headers),
|
|
196
196
|
)
|
|
197
197
|
|
|
198
198
|
unless response.headers.key?("content-length")
|
|
@@ -49,7 +49,7 @@ module Datadog
|
|
|
49
49
|
|
|
50
50
|
if result.match?
|
|
51
51
|
context.events.push(
|
|
52
|
-
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
|
52
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span),
|
|
53
53
|
)
|
|
54
54
|
|
|
55
55
|
AppSec::Event.tag(context, result)
|
|
@@ -66,14 +66,27 @@ module Datadog
|
|
|
66
66
|
gateway.watch("rails.response.body.json") do |stack, container|
|
|
67
67
|
context = container.context
|
|
68
68
|
|
|
69
|
+
body_bytesize = container.data.bytesize
|
|
70
|
+
limit = Datadog.configuration.appsec.body_parsing_size_limit
|
|
71
|
+
|
|
69
72
|
persistent_data = {
|
|
70
|
-
"server.response.body" =>
|
|
73
|
+
"server.response.body.byte_length" => body_bytesize,
|
|
71
74
|
}
|
|
72
|
-
|
|
75
|
+
|
|
76
|
+
if limit > 0 && body_bytesize <= limit
|
|
77
|
+
json = extract_json(container.data)
|
|
78
|
+
persistent_data["server.response.body"] = WAF::JSONString.new(json) if json
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
result = begin
|
|
82
|
+
context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
|
|
83
|
+
rescue WAF::ConversionError
|
|
84
|
+
next stack.call(container)
|
|
85
|
+
end
|
|
73
86
|
|
|
74
87
|
if result.match?
|
|
75
88
|
context.events.push(
|
|
76
|
-
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
|
89
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span),
|
|
77
90
|
)
|
|
78
91
|
|
|
79
92
|
AppSec::Event.tag(context, result)
|
|
@@ -85,6 +98,20 @@ module Datadog
|
|
|
85
98
|
stack.call(container)
|
|
86
99
|
end
|
|
87
100
|
end
|
|
101
|
+
|
|
102
|
+
private
|
|
103
|
+
|
|
104
|
+
def extract_json(body)
|
|
105
|
+
return body unless body.start_with?("/**/")
|
|
106
|
+
return unless body.end_with?(")")
|
|
107
|
+
|
|
108
|
+
# NOTE: Best-effort support for standard Rails JSONP callbacks.
|
|
109
|
+
# Callback expressions with parentheses may prevent extraction
|
|
110
|
+
opening_parenthesis_index = body.b.index("(")
|
|
111
|
+
return unless opening_parenthesis_index
|
|
112
|
+
|
|
113
|
+
body.byteslice(opening_parenthesis_index + 1, body.bytesize - opening_parenthesis_index - 2) #: String
|
|
114
|
+
end
|
|
88
115
|
end
|
|
89
116
|
end
|
|
90
117
|
end
|
|
@@ -66,7 +66,7 @@ module Datadog
|
|
|
66
66
|
if include_middleware?(Datadog::Tracing::Contrib::Rack::TraceMiddleware, app)
|
|
67
67
|
app.middleware.insert_after(
|
|
68
68
|
Datadog::Tracing::Contrib::Rack::TraceMiddleware,
|
|
69
|
-
Datadog::AppSec::Contrib::Rack::RequestMiddleware
|
|
69
|
+
Datadog::AppSec::Contrib::Rack::RequestMiddleware,
|
|
70
70
|
)
|
|
71
71
|
else
|
|
72
72
|
app.middleware.insert_before(0, Datadog::AppSec::Contrib::Rack::RequestMiddleware)
|
|
@@ -162,7 +162,7 @@ module Datadog
|
|
|
162
162
|
|
|
163
163
|
GUARD_ROUTES_REPORTING_ONCE_PER_APP[::Rails.application].run do
|
|
164
164
|
AppSec.telemetry.app_endpoints_loaded(
|
|
165
|
-
APISecurity::EndpointCollection::RailsCollector.new(routes).to_enum
|
|
165
|
+
APISecurity::EndpointCollection::RailsCollector.new(routes).to_enum,
|
|
166
166
|
)
|
|
167
167
|
end
|
|
168
168
|
rescue => e
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "../../../utils/hash_coercion"
|
|
4
3
|
require_relative "../../../instrumentation/gateway/argument"
|
|
5
4
|
|
|
6
5
|
module Datadog
|
|
@@ -8,8 +7,8 @@ module Datadog
|
|
|
8
7
|
module Contrib
|
|
9
8
|
module Rails
|
|
10
9
|
module Patches
|
|
11
|
-
# A patch
|
|
12
|
-
#
|
|
10
|
+
# A patch for `AbstractController::Rendering#render_to_body` that captures
|
|
11
|
+
# the serialized JSON response body for AppSec inspection
|
|
13
12
|
module RenderToBodyPatch
|
|
14
13
|
def render_to_body(options = {})
|
|
15
14
|
return super unless options.key?(:json)
|
|
@@ -17,13 +16,15 @@ module Datadog
|
|
|
17
16
|
context = request.env[Datadog::AppSec::Ext::CONTEXT_KEY]
|
|
18
17
|
return super unless context
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
# NOTE: Custom renderers can return streaming bodies, which we
|
|
20
|
+
# currently do not inspect
|
|
21
|
+
body = super
|
|
22
|
+
return body unless body.is_a?(String)
|
|
22
23
|
|
|
23
|
-
container = Instrumentation::Gateway::DataContainer.new(
|
|
24
|
+
container = Instrumentation::Gateway::DataContainer.new(body, context: context)
|
|
24
25
|
Instrumentation.gateway.push("rails.response.body.json", container)
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
body
|
|
27
28
|
end
|
|
28
29
|
end
|
|
29
30
|
end
|
|
@@ -181,7 +181,7 @@ module Datadog
|
|
|
181
181
|
TraceKeeper.keep!(context.trace) if result.keep?
|
|
182
182
|
|
|
183
183
|
context.events.push(
|
|
184
|
-
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
|
184
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span),
|
|
185
185
|
)
|
|
186
186
|
|
|
187
187
|
AppSec::ActionsHandler.handle(result.actions)
|
|
@@ -56,7 +56,7 @@ module Datadog
|
|
|
56
56
|
|
|
57
57
|
if result.match? || !result.attributes.empty?
|
|
58
58
|
context.events.push(
|
|
59
|
-
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
|
59
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span),
|
|
60
60
|
)
|
|
61
61
|
end
|
|
62
62
|
|
|
@@ -87,7 +87,7 @@ module Datadog
|
|
|
87
87
|
TraceKeeper.keep!(context.trace) if result.keep?
|
|
88
88
|
|
|
89
89
|
context.events.push(
|
|
90
|
-
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
|
90
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span),
|
|
91
91
|
)
|
|
92
92
|
|
|
93
93
|
AppSec::ActionsHandler.handle(result.actions)
|
|
@@ -101,14 +101,26 @@ module Datadog
|
|
|
101
101
|
gateway.watch("sinatra.response.body.json") do |stack, container|
|
|
102
102
|
context = container.context # : Context
|
|
103
103
|
|
|
104
|
+
body_bytesize = container.data.bytesize
|
|
105
|
+
limit = Datadog.configuration.appsec.body_parsing_size_limit
|
|
106
|
+
|
|
104
107
|
persistent_data = {
|
|
105
|
-
"server.response.body" =>
|
|
108
|
+
"server.response.body.byte_length" => body_bytesize,
|
|
106
109
|
}
|
|
107
|
-
|
|
110
|
+
|
|
111
|
+
if limit > 0 && body_bytesize <= limit
|
|
112
|
+
persistent_data["server.response.body"] = WAF::JSONString.new(container.data)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
result = begin
|
|
116
|
+
context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
|
|
117
|
+
rescue WAF::ConversionError
|
|
118
|
+
next stack.call(container)
|
|
119
|
+
end
|
|
108
120
|
|
|
109
121
|
if result.match?
|
|
110
122
|
context.events.push(
|
|
111
|
-
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
|
123
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span),
|
|
112
124
|
)
|
|
113
125
|
|
|
114
126
|
AppSec::Event.tag(context, result)
|
|
@@ -37,7 +37,7 @@ module Datadog
|
|
|
37
37
|
tracing_sinatra_framework.add_middleware_after(
|
|
38
38
|
tracing_middleware,
|
|
39
39
|
Datadog::AppSec::Contrib::Rack::RequestMiddleware,
|
|
40
|
-
builder
|
|
40
|
+
builder,
|
|
41
41
|
)
|
|
42
42
|
else
|
|
43
43
|
tracing_sinatra_framework.add_middleware(Datadog::AppSec::Contrib::Rack::RequestMiddleware, builder)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "../../../utils/hash_coercion"
|
|
4
3
|
require_relative "../../../instrumentation/gateway/argument"
|
|
5
4
|
|
|
6
5
|
module Datadog
|
|
@@ -8,20 +7,22 @@ module Datadog
|
|
|
8
7
|
module Contrib
|
|
9
8
|
module Sinatra
|
|
10
9
|
module Patches
|
|
11
|
-
# A patch
|
|
12
|
-
# body
|
|
10
|
+
# A patch for `Sinatra::JSON#json` that captures the serialized
|
|
11
|
+
# response body for AppSec inspection
|
|
13
12
|
module JsonPatch
|
|
14
13
|
def json(object, options = {})
|
|
15
14
|
context = @request.env[Datadog::AppSec::Ext::CONTEXT_KEY] # : Context?
|
|
16
15
|
return super unless context
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
# NOTE: Custom renderers can return streaming bodies, which we
|
|
18
|
+
# currently do not inspect
|
|
19
|
+
body = super
|
|
20
|
+
return body unless body.is_a?(String)
|
|
20
21
|
|
|
21
|
-
container = Instrumentation::Gateway::DataContainer.new(
|
|
22
|
+
container = Instrumentation::Gateway::DataContainer.new(body, context: context)
|
|
22
23
|
Instrumentation.gateway.push("sinatra.response.body.json", container)
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
body
|
|
25
26
|
end
|
|
26
27
|
end
|
|
27
28
|
end
|
|
@@ -14,7 +14,7 @@ module Datadog
|
|
|
14
14
|
:duration_ext_ns,
|
|
15
15
|
:inputs_truncated,
|
|
16
16
|
:downstream_requests,
|
|
17
|
-
keyword_init: true
|
|
17
|
+
keyword_init: true,
|
|
18
18
|
)
|
|
19
19
|
|
|
20
20
|
DownstreamResponseStore = Struct.new(
|
|
@@ -22,7 +22,7 @@ module Datadog
|
|
|
22
22
|
:content_length_missing,
|
|
23
23
|
:content_length_too_big,
|
|
24
24
|
:content_exceed_content_length,
|
|
25
|
-
keyword_init: true
|
|
25
|
+
keyword_init: true,
|
|
26
26
|
)
|
|
27
27
|
|
|
28
28
|
attr_reader :waf, :rasp, :downstream_responses
|
|
@@ -32,17 +32,17 @@ module Datadog
|
|
|
32
32
|
|
|
33
33
|
@waf = Store.new(
|
|
34
34
|
evals: 0, matches: 0, errors: 0, timeouts: 0, duration_ns: 0,
|
|
35
|
-
duration_ext_ns: 0, inputs_truncated: 0, downstream_requests: 0
|
|
35
|
+
duration_ext_ns: 0, inputs_truncated: 0, downstream_requests: 0,
|
|
36
36
|
)
|
|
37
37
|
|
|
38
38
|
@rasp = Store.new(
|
|
39
39
|
evals: 0, matches: 0, errors: 0, timeouts: 0, duration_ns: 0,
|
|
40
|
-
duration_ext_ns: 0, inputs_truncated: 0, downstream_requests: 0
|
|
40
|
+
duration_ext_ns: 0, inputs_truncated: 0, downstream_requests: 0,
|
|
41
41
|
)
|
|
42
42
|
|
|
43
43
|
@downstream_responses = DownstreamResponseStore.new(
|
|
44
44
|
content_type_invalid: 0, content_length_missing: 0,
|
|
45
|
-
content_length_too_big: 0, content_exceed_content_length: 0
|
|
45
|
+
content_length_too_big: 0, content_exceed_content_length: 0,
|
|
46
46
|
)
|
|
47
47
|
end
|
|
48
48
|
|