datadog 2.12.1 → 2.19.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 +243 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +63 -56
- data/ext/datadog_profiling_native_extension/collectors_stack.c +263 -76
- data/ext/datadog_profiling_native_extension/collectors_stack.h +20 -3
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +78 -26
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +1 -0
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +1 -4
- data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +10 -0
- data/ext/datadog_profiling_native_extension/encoded_profile.c +79 -0
- data/ext/datadog_profiling_native_extension/encoded_profile.h +8 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +10 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.c +247 -364
- data/ext/datadog_profiling_native_extension/heap_recorder.h +4 -6
- data/ext/datadog_profiling_native_extension/http_transport.c +60 -94
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +22 -0
- data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +8 -5
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +41 -21
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +6 -4
- data/ext/datadog_profiling_native_extension/profiling.c +2 -0
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +1 -13
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +3 -11
- data/ext/datadog_profiling_native_extension/stack_recorder.c +173 -76
- data/ext/libdatadog_api/crashtracker.c +11 -12
- data/ext/libdatadog_api/crashtracker.h +5 -0
- data/ext/libdatadog_api/datadog_ruby_common.c +1 -4
- data/ext/libdatadog_api/datadog_ruby_common.h +10 -0
- data/ext/libdatadog_api/extconf.rb +2 -2
- data/ext/libdatadog_api/init.c +15 -0
- data/ext/libdatadog_api/library_config.c +164 -0
- data/ext/libdatadog_api/library_config.h +25 -0
- data/ext/libdatadog_api/macos_development.md +3 -3
- data/ext/libdatadog_api/process_discovery.c +112 -0
- data/ext/libdatadog_api/process_discovery.h +5 -0
- data/ext/libdatadog_extconf_helpers.rb +2 -2
- data/lib/datadog/appsec/actions_handler/serializable_backtrace.rb +89 -0
- data/lib/datadog/appsec/actions_handler.rb +24 -2
- data/lib/datadog/appsec/anonymizer.rb +16 -0
- data/lib/datadog/appsec/api_security/lru_cache.rb +56 -0
- data/lib/datadog/appsec/api_security/route_extractor.rb +71 -0
- data/lib/datadog/appsec/api_security/sampler.rb +59 -0
- data/lib/datadog/appsec/api_security.rb +23 -0
- data/lib/datadog/appsec/assets/waf_rules/README.md +50 -5
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +257 -85
- data/lib/datadog/appsec/assets/waf_rules/strict.json +10 -78
- data/lib/datadog/appsec/autoload.rb +1 -1
- data/lib/datadog/appsec/component.rb +46 -61
- data/lib/datadog/appsec/compressed_json.rb +40 -0
- data/lib/datadog/appsec/configuration/settings.rb +153 -30
- data/lib/datadog/appsec/context.rb +7 -7
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +10 -12
- data/lib/datadog/appsec/contrib/active_record/integration.rb +2 -2
- data/lib/datadog/appsec/contrib/active_record/patcher.rb +22 -22
- data/lib/datadog/appsec/contrib/auto_instrument.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/configuration.rb +7 -31
- data/lib/datadog/appsec/contrib/devise/data_extractor.rb +78 -0
- data/lib/datadog/appsec/contrib/devise/ext.rb +22 -0
- data/lib/datadog/appsec/contrib/devise/integration.rb +1 -2
- data/lib/datadog/appsec/contrib/devise/patcher.rb +34 -23
- data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +102 -0
- data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +69 -0
- data/lib/datadog/appsec/contrib/devise/{patcher/rememberable_patch.rb → patches/skip_signin_tracking_patch.rb} +2 -2
- data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +106 -0
- data/lib/datadog/appsec/contrib/excon/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +9 -10
- data/lib/datadog/appsec/contrib/faraday/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +8 -9
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +8 -9
- data/lib/datadog/appsec/contrib/graphql/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/ext.rb +34 -0
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +49 -32
- data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +42 -30
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +11 -13
- data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/patcher.rb +21 -21
- data/lib/datadog/appsec/contrib/rest_client/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +10 -11
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +17 -23
- data/lib/datadog/appsec/contrib/sinatra/integration.rb +1 -1
- data/lib/datadog/appsec/event.rb +96 -135
- data/lib/datadog/appsec/ext.rb +4 -2
- data/lib/datadog/appsec/instrumentation/gateway/argument.rb +7 -2
- data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +24 -0
- data/lib/datadog/appsec/instrumentation/gateway.rb +17 -22
- data/lib/datadog/appsec/metrics/telemetry.rb +1 -1
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +49 -14
- data/lib/datadog/appsec/processor/rule_loader.rb +30 -33
- data/lib/datadog/appsec/remote.rb +31 -59
- data/lib/datadog/appsec/response.rb +6 -6
- data/lib/datadog/appsec/security_engine/engine.rb +194 -0
- data/lib/datadog/appsec/security_engine/runner.rb +13 -14
- data/lib/datadog/appsec/security_event.rb +39 -0
- data/lib/datadog/appsec/utils.rb +0 -2
- data/lib/datadog/appsec.rb +5 -8
- data/lib/datadog/core/buffer/random.rb +18 -2
- data/lib/datadog/core/configuration/agent_settings.rb +52 -0
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +4 -46
- data/lib/datadog/core/configuration/agentless_settings_resolver.rb +176 -0
- data/lib/datadog/core/configuration/components.rb +48 -31
- data/lib/datadog/core/configuration/components_state.rb +23 -0
- data/lib/datadog/core/configuration/ext.rb +4 -0
- data/lib/datadog/core/configuration/option.rb +81 -45
- data/lib/datadog/core/configuration/option_definition.rb +4 -4
- data/lib/datadog/core/configuration/options.rb +3 -3
- data/lib/datadog/core/configuration/settings.rb +109 -44
- data/lib/datadog/core/configuration/stable_config.rb +22 -0
- data/lib/datadog/core/configuration.rb +40 -16
- data/lib/datadog/core/crashtracking/component.rb +3 -10
- data/lib/datadog/core/crashtracking/tag_builder.rb +4 -22
- data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
- data/lib/datadog/core/encoding.rb +1 -1
- data/lib/datadog/core/environment/agent_info.rb +4 -3
- data/lib/datadog/core/environment/cgroup.rb +10 -12
- data/lib/datadog/core/environment/container.rb +38 -40
- data/lib/datadog/core/environment/ext.rb +6 -6
- data/lib/datadog/core/environment/git.rb +1 -0
- data/lib/datadog/core/environment/identity.rb +3 -3
- data/lib/datadog/core/environment/platform.rb +3 -3
- data/lib/datadog/core/environment/variable_helpers.rb +1 -1
- data/lib/datadog/core/error.rb +11 -9
- data/lib/datadog/core/logger.rb +2 -2
- data/lib/datadog/core/metrics/client.rb +20 -21
- data/lib/datadog/core/metrics/logging.rb +5 -5
- data/lib/datadog/core/process_discovery/tracer_memfd.rb +15 -0
- data/lib/datadog/core/process_discovery.rb +36 -0
- data/lib/datadog/core/rate_limiter.rb +4 -2
- data/lib/datadog/core/remote/client.rb +40 -32
- data/lib/datadog/core/remote/component.rb +6 -9
- data/lib/datadog/core/remote/configuration/digest.rb +7 -7
- data/lib/datadog/core/remote/configuration/path.rb +1 -1
- data/lib/datadog/core/remote/configuration/repository.rb +14 -1
- data/lib/datadog/core/remote/negotiation.rb +9 -9
- data/lib/datadog/core/remote/transport/config.rb +4 -3
- data/lib/datadog/core/remote/transport/http/client.rb +5 -4
- data/lib/datadog/core/remote/transport/http/config.rb +27 -37
- data/lib/datadog/core/remote/transport/http/negotiation.rb +7 -33
- data/lib/datadog/core/remote/transport/http.rb +22 -57
- data/lib/datadog/core/remote/transport/negotiation.rb +4 -3
- data/lib/datadog/core/runtime/metrics.rb +12 -5
- data/lib/datadog/core/tag_builder.rb +56 -0
- data/lib/datadog/core/telemetry/component.rb +81 -52
- data/lib/datadog/core/telemetry/emitter.rb +23 -11
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +66 -0
- data/lib/datadog/core/telemetry/event/app_closing.rb +18 -0
- data/lib/datadog/core/telemetry/event/app_dependencies_loaded.rb +33 -0
- data/lib/datadog/core/telemetry/event/app_heartbeat.rb +18 -0
- data/lib/datadog/core/telemetry/event/app_integrations_change.rb +58 -0
- data/lib/datadog/core/telemetry/event/app_started.rb +287 -0
- data/lib/datadog/core/telemetry/event/base.rb +40 -0
- data/lib/datadog/core/telemetry/event/distributions.rb +18 -0
- data/lib/datadog/core/telemetry/event/generate_metrics.rb +43 -0
- data/lib/datadog/core/telemetry/event/log.rb +76 -0
- data/lib/datadog/core/telemetry/event/message_batch.rb +42 -0
- data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +43 -0
- data/lib/datadog/core/telemetry/event.rb +17 -472
- data/lib/datadog/core/telemetry/http/adapters/net.rb +12 -97
- data/lib/datadog/core/telemetry/logger.rb +5 -4
- data/lib/datadog/core/telemetry/logging.rb +11 -5
- data/lib/datadog/core/telemetry/metric.rb +8 -8
- data/lib/datadog/core/telemetry/request.rb +4 -4
- data/lib/datadog/core/telemetry/transport/http/api.rb +43 -0
- data/lib/datadog/core/telemetry/transport/http/client.rb +49 -0
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +92 -0
- data/lib/datadog/core/telemetry/transport/http.rb +63 -0
- data/lib/datadog/core/telemetry/transport/telemetry.rb +51 -0
- data/lib/datadog/core/telemetry/worker.rb +90 -24
- data/lib/datadog/core/transport/http/adapters/net.rb +17 -2
- data/lib/datadog/core/transport/http/adapters/test.rb +2 -1
- data/lib/datadog/core/transport/http/api/instance.rb +17 -0
- data/lib/datadog/core/transport/http/api/spec.rb +17 -0
- data/lib/datadog/core/transport/http/builder.rb +19 -17
- data/lib/datadog/core/transport/http/env.rb +8 -0
- data/lib/datadog/core/transport/http.rb +39 -2
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +6 -6
- data/lib/datadog/core/utils/duration.rb +32 -32
- data/lib/datadog/core/utils/forking.rb +2 -2
- data/lib/datadog/core/utils/network.rb +6 -6
- data/lib/datadog/core/utils/only_once_successful.rb +16 -5
- data/lib/datadog/core/utils/time.rb +20 -0
- data/lib/datadog/core/utils/truncation.rb +21 -0
- data/lib/datadog/core/utils.rb +7 -0
- data/lib/datadog/core/vendor/multipart-post/multipart/post/composite_read_io.rb +1 -1
- data/lib/datadog/core/vendor/multipart-post/multipart/post/multipartable.rb +8 -8
- data/lib/datadog/core/vendor/multipart-post/multipart/post/parts.rb +7 -7
- data/lib/datadog/core/worker.rb +1 -1
- data/lib/datadog/core/workers/async.rb +29 -12
- data/lib/datadog/core/workers/interval_loop.rb +12 -1
- data/lib/datadog/core/workers/runtime_metrics.rb +2 -2
- data/lib/datadog/core.rb +8 -0
- data/lib/datadog/di/boot.rb +34 -0
- data/lib/datadog/di/component.rb +0 -2
- data/lib/datadog/di/instrumenter.rb +48 -5
- data/lib/datadog/di/probe_notification_builder.rb +38 -43
- data/lib/datadog/di/probe_notifier_worker.rb +25 -17
- data/lib/datadog/di/remote.rb +2 -0
- data/lib/datadog/di/serializer.rb +10 -2
- data/lib/datadog/di/transport/diagnostics.rb +4 -3
- data/lib/datadog/di/transport/http/api.rb +2 -12
- data/lib/datadog/di/transport/http/client.rb +4 -3
- data/lib/datadog/di/transport/http/diagnostics.rb +7 -34
- data/lib/datadog/di/transport/http/input.rb +18 -35
- data/lib/datadog/di/transport/http.rb +14 -62
- data/lib/datadog/di/transport/input.rb +14 -5
- data/lib/datadog/di/utils.rb +5 -0
- data/lib/datadog/di.rb +0 -33
- data/lib/datadog/error_tracking/collector.rb +87 -0
- data/lib/datadog/error_tracking/component.rb +167 -0
- data/lib/datadog/error_tracking/configuration/settings.rb +63 -0
- data/lib/datadog/error_tracking/configuration.rb +11 -0
- data/lib/datadog/error_tracking/ext.rb +18 -0
- data/lib/datadog/error_tracking/extensions.rb +16 -0
- data/lib/datadog/error_tracking/filters.rb +77 -0
- data/lib/datadog/error_tracking.rb +18 -0
- data/lib/datadog/kit/appsec/events/v2.rb +195 -0
- data/lib/datadog/kit/appsec/events.rb +12 -0
- data/lib/datadog/kit/identity.rb +5 -1
- data/lib/datadog/opentelemetry/api/baggage.rb +90 -0
- data/lib/datadog/opentelemetry/api/baggage.rbs +26 -0
- data/lib/datadog/opentelemetry/api/context.rb +16 -2
- data/lib/datadog/opentelemetry/sdk/trace/span.rb +1 -1
- data/lib/datadog/opentelemetry.rb +2 -1
- data/lib/datadog/profiling/collectors/code_provenance.rb +18 -9
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +6 -0
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -0
- data/lib/datadog/profiling/collectors/info.rb +44 -0
- data/lib/datadog/profiling/collectors/thread_context.rb +17 -2
- data/lib/datadog/profiling/component.rb +8 -9
- data/lib/datadog/profiling/encoded_profile.rb +11 -0
- data/lib/datadog/profiling/exporter.rb +12 -7
- data/lib/datadog/profiling/ext.rb +0 -14
- data/lib/datadog/profiling/flush.rb +5 -8
- data/lib/datadog/profiling/http_transport.rb +7 -61
- data/lib/datadog/profiling/profiler.rb +2 -0
- data/lib/datadog/profiling/scheduler.rb +10 -2
- data/lib/datadog/profiling/sequence_tracker.rb +44 -0
- data/lib/datadog/profiling/stack_recorder.rb +9 -9
- data/lib/datadog/profiling/tag_builder.rb +7 -41
- data/lib/datadog/profiling/tasks/setup.rb +2 -0
- data/lib/datadog/profiling.rb +7 -2
- data/lib/datadog/single_step_instrument.rb +9 -0
- data/lib/datadog/tracing/analytics.rb +1 -1
- data/lib/datadog/tracing/component.rb +15 -12
- data/lib/datadog/tracing/configuration/ext.rb +7 -1
- data/lib/datadog/tracing/configuration/settings.rb +18 -2
- data/lib/datadog/tracing/context_provider.rb +1 -1
- data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +15 -0
- data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +19 -12
- data/lib/datadog/tracing/contrib/action_pack/ext.rb +2 -0
- data/lib/datadog/tracing/contrib/active_record/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +11 -2
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +33 -0
- data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +4 -0
- data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +2 -4
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +13 -0
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +10 -0
- data/lib/datadog/tracing/contrib/aws/parsed_context.rb +5 -1
- data/lib/datadog/tracing/contrib/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -5
- data/lib/datadog/tracing/contrib/excon/middleware.rb +5 -3
- data/lib/datadog/tracing/contrib/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +5 -3
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +7 -1
- data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +3 -0
- data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +0 -15
- data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +4 -1
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +6 -10
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -16
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +7 -15
- data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +27 -0
- data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +48 -0
- data/lib/datadog/tracing/contrib/karafka/ext.rb +27 -0
- data/lib/datadog/tracing/contrib/karafka/integration.rb +45 -0
- data/lib/datadog/tracing/contrib/karafka/monitor.rb +66 -0
- data/lib/datadog/tracing/contrib/karafka/patcher.rb +71 -0
- data/lib/datadog/tracing/contrib/karafka.rb +37 -0
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +4 -2
- data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +8 -0
- data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +18 -1
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +16 -6
- data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +17 -0
- data/lib/datadog/tracing/contrib/opensearch/ext.rb +9 -0
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +5 -1
- data/lib/datadog/tracing/contrib/patcher.rb +5 -2
- data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/patcher.rb +4 -1
- data/lib/datadog/tracing/contrib/rails/runner.rb +61 -40
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +5 -3
- data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +6 -1
- data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +3 -0
- data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +5 -2
- data/lib/datadog/tracing/contrib/support.rb +28 -0
- data/lib/datadog/tracing/contrib.rb +1 -0
- data/lib/datadog/tracing/correlation.rb +9 -2
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +3 -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 +131 -0
- data/lib/datadog/tracing/distributed/datadog.rb +4 -2
- data/lib/datadog/tracing/distributed/propagation.rb +25 -4
- data/lib/datadog/tracing/distributed/propagation_policy.rb +42 -0
- data/lib/datadog/tracing/metadata/errors.rb +4 -4
- data/lib/datadog/tracing/metadata/ext.rb +5 -0
- data/lib/datadog/tracing/metadata/metastruct.rb +36 -0
- data/lib/datadog/tracing/metadata/metastruct_tagging.rb +42 -0
- data/lib/datadog/tracing/metadata.rb +2 -0
- data/lib/datadog/tracing/sampling/rate_sampler.rb +2 -1
- data/lib/datadog/tracing/sampling/span/rule.rb +0 -1
- data/lib/datadog/tracing/span.rb +10 -1
- data/lib/datadog/tracing/span_event.rb +2 -2
- data/lib/datadog/tracing/span_operation.rb +68 -16
- data/lib/datadog/tracing/sync_writer.rb +2 -3
- data/lib/datadog/tracing/trace_digest.rb +9 -2
- data/lib/datadog/tracing/trace_operation.rb +55 -27
- data/lib/datadog/tracing/trace_segment.rb +6 -4
- data/lib/datadog/tracing/tracer.rb +51 -7
- data/lib/datadog/tracing/transport/http/api.rb +2 -10
- data/lib/datadog/tracing/transport/http/client.rb +5 -4
- data/lib/datadog/tracing/transport/http/traces.rb +13 -41
- data/lib/datadog/tracing/transport/http.rb +11 -44
- data/lib/datadog/tracing/transport/serializable_trace.rb +3 -1
- data/lib/datadog/tracing/transport/trace_formatter.rb +7 -0
- data/lib/datadog/tracing/transport/traces.rb +26 -9
- data/lib/datadog/tracing/utils.rb +1 -1
- data/lib/datadog/tracing/workers/trace_writer.rb +2 -6
- data/lib/datadog/tracing/writer.rb +2 -6
- data/lib/datadog/tracing.rb +16 -3
- data/lib/datadog/version.rb +2 -2
- data/lib/datadog.rb +8 -2
- metadata +88 -23
- data/lib/datadog/appsec/assets/waf_rules/processors.json +0 -92
- data/lib/datadog/appsec/assets/waf_rules/scanners.json +0 -114
- data/lib/datadog/appsec/contrib/devise/event.rb +0 -54
- data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +0 -72
- data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +0 -47
- data/lib/datadog/appsec/contrib/devise/resource.rb +0 -35
- data/lib/datadog/appsec/contrib/devise/tracking.rb +0 -57
- data/lib/datadog/appsec/processor/rule_merger.rb +0 -170
- data/lib/datadog/appsec/processor.rb +0 -107
- data/lib/datadog/appsec/utils/trace_operation.rb +0 -15
- data/lib/datadog/core/telemetry/http/env.rb +0 -20
- data/lib/datadog/core/telemetry/http/ext.rb +0 -28
- data/lib/datadog/core/telemetry/http/response.rb +0 -70
- data/lib/datadog/core/telemetry/http/transport.rb +0 -90
@@ -0,0 +1,164 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <datadog/library-config.h>
|
3
|
+
|
4
|
+
#include "library_config.h"
|
5
|
+
#include "datadog_ruby_common.h"
|
6
|
+
|
7
|
+
static VALUE _native_configurator_new(VALUE klass);
|
8
|
+
static VALUE _native_configurator_get(VALUE self);
|
9
|
+
|
10
|
+
// Used for testing in RSpec
|
11
|
+
static VALUE _native_configurator_with_local_path(DDTRACE_UNUSED VALUE _self, VALUE rb_configurator, VALUE path);
|
12
|
+
static VALUE _native_configurator_with_fleet_path(DDTRACE_UNUSED VALUE _self, VALUE rb_configurator, VALUE path);
|
13
|
+
|
14
|
+
static VALUE config_vec_class = Qnil;
|
15
|
+
|
16
|
+
// ddog_Configurator memory management
|
17
|
+
static void configurator_free(void *configurator_ptr) {
|
18
|
+
ddog_Configurator *configurator = (ddog_Configurator *)configurator_ptr;
|
19
|
+
|
20
|
+
ddog_library_configurator_drop(configurator);
|
21
|
+
}
|
22
|
+
|
23
|
+
static const rb_data_type_t configurator_typed_data = {
|
24
|
+
.wrap_struct_name = "Datadog::Core::Configuration::StableConfig::Configurator",
|
25
|
+
.function = {
|
26
|
+
.dfree = configurator_free,
|
27
|
+
.dsize = NULL,
|
28
|
+
},
|
29
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
30
|
+
};
|
31
|
+
|
32
|
+
// ddog_Vec_LibraryConfig memory management
|
33
|
+
static void config_vec_free(void *config_vec_ptr) {
|
34
|
+
ddog_Vec_LibraryConfig *config_vec = (ddog_Vec_LibraryConfig *)config_vec_ptr;
|
35
|
+
|
36
|
+
ddog_library_config_drop(*config_vec);
|
37
|
+
ruby_xfree(config_vec_ptr);
|
38
|
+
}
|
39
|
+
|
40
|
+
static const rb_data_type_t config_vec_typed_data = {
|
41
|
+
.wrap_struct_name = "Datadog::Core::Configuration::StableConfigVec",
|
42
|
+
.function = {
|
43
|
+
.dfree = config_vec_free,
|
44
|
+
.dsize = NULL,
|
45
|
+
},
|
46
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
47
|
+
};
|
48
|
+
|
49
|
+
void library_config_init(VALUE core_module) {
|
50
|
+
rb_global_variable(&config_vec_class);
|
51
|
+
VALUE configuration_module = rb_define_module_under(core_module, "Configuration");
|
52
|
+
VALUE stable_config_module = rb_define_module_under(configuration_module, "StableConfig");
|
53
|
+
VALUE configurator_class = rb_define_class_under(stable_config_module, "Configurator", rb_cObject);
|
54
|
+
config_vec_class = rb_define_class_under(configuration_module, "StableConfigVec", rb_cObject);
|
55
|
+
|
56
|
+
rb_define_alloc_func(configurator_class, _native_configurator_new);
|
57
|
+
rb_define_method(configurator_class, "get", _native_configurator_get, 0);
|
58
|
+
|
59
|
+
// Used for testing in RSpec
|
60
|
+
VALUE testing_module = rb_define_module_under(stable_config_module, "Testing");
|
61
|
+
rb_define_singleton_method(testing_module, "with_local_path", _native_configurator_with_local_path, 2);
|
62
|
+
rb_define_singleton_method(testing_module, "with_fleet_path", _native_configurator_with_fleet_path, 2);
|
63
|
+
|
64
|
+
rb_undef_alloc_func(config_vec_class); // It cannot be created from Ruby code and only serves as an intermediate object for the Ruby GC
|
65
|
+
}
|
66
|
+
|
67
|
+
static VALUE _native_configurator_new(VALUE klass) {
|
68
|
+
ddog_Configurator *configurator = ddog_library_configurator_new(false, DDOG_CHARSLICE_C("ruby"));
|
69
|
+
|
70
|
+
ddog_library_configurator_with_detect_process_info(configurator);
|
71
|
+
|
72
|
+
return TypedData_Wrap_Struct(klass, &configurator_typed_data, configurator);
|
73
|
+
}
|
74
|
+
|
75
|
+
static VALUE _native_configurator_with_local_path(DDTRACE_UNUSED VALUE _self, VALUE rb_configurator, VALUE path) {
|
76
|
+
ddog_Configurator *configurator;
|
77
|
+
TypedData_Get_Struct(rb_configurator, ddog_Configurator, &configurator_typed_data, configurator);
|
78
|
+
|
79
|
+
ENFORCE_TYPE(path, T_STRING);
|
80
|
+
|
81
|
+
ddog_library_configurator_with_local_path(configurator, cstr_from_ruby_string(path));
|
82
|
+
|
83
|
+
return Qnil;
|
84
|
+
}
|
85
|
+
|
86
|
+
static VALUE _native_configurator_with_fleet_path(DDTRACE_UNUSED VALUE _self, VALUE rb_configurator, VALUE path) {
|
87
|
+
ddog_Configurator *configurator;
|
88
|
+
TypedData_Get_Struct(rb_configurator, ddog_Configurator, &configurator_typed_data, configurator);
|
89
|
+
|
90
|
+
ENFORCE_TYPE(path, T_STRING);
|
91
|
+
|
92
|
+
ddog_library_configurator_with_fleet_path(configurator, cstr_from_ruby_string(path));
|
93
|
+
|
94
|
+
return Qnil;
|
95
|
+
}
|
96
|
+
|
97
|
+
static VALUE _native_configurator_get(VALUE self) {
|
98
|
+
ddog_Configurator *configurator;
|
99
|
+
TypedData_Get_Struct(self, ddog_Configurator, &configurator_typed_data, configurator);
|
100
|
+
|
101
|
+
ddog_Result_VecLibraryConfig configurator_result = ddog_library_configurator_get(configurator);
|
102
|
+
|
103
|
+
if (configurator_result.tag == DDOG_RESULT_VEC_LIBRARY_CONFIG_ERR_VEC_LIBRARY_CONFIG) {
|
104
|
+
ddog_Error err = configurator_result.err;
|
105
|
+
VALUE message = get_error_details_and_drop(&err);
|
106
|
+
if (is_config_loaded()) {
|
107
|
+
log_warning(message);
|
108
|
+
} else {
|
109
|
+
log_warning_without_config(message);
|
110
|
+
}
|
111
|
+
return rb_hash_new();
|
112
|
+
}
|
113
|
+
|
114
|
+
// Wrapping config_vec into a Ruby object enables the Ruby GC to manage its memory
|
115
|
+
// We need to allocate memory for config_vec because once it is out of scope, it will be freed (at the end of this function)
|
116
|
+
// So we cannot reference it with &config_vec
|
117
|
+
// We are doing this in case one of the ruby API raises an exception before the end of this function,
|
118
|
+
// so the allocated memory will still be freed
|
119
|
+
ddog_Vec_LibraryConfig *config_vec = ruby_xmalloc(sizeof(ddog_Vec_LibraryConfig));
|
120
|
+
*config_vec = configurator_result.ok;
|
121
|
+
VALUE config_vec_rb = TypedData_Wrap_Struct(config_vec_class, &config_vec_typed_data, config_vec);
|
122
|
+
|
123
|
+
VALUE local_config_hash = rb_hash_new();
|
124
|
+
VALUE fleet_config_hash = rb_hash_new();
|
125
|
+
|
126
|
+
bool local_config_id_set = false;
|
127
|
+
bool fleet_config_id_set = false;
|
128
|
+
VALUE local_hash = rb_hash_new();
|
129
|
+
VALUE fleet_hash = rb_hash_new();
|
130
|
+
for (uintptr_t i = 0; i < config_vec->len; i++) {
|
131
|
+
ddog_LibraryConfig config = config_vec->ptr[i];
|
132
|
+
VALUE selected_hash;
|
133
|
+
if (config.source == DDOG_LIBRARY_CONFIG_SOURCE_LOCAL_STABLE_CONFIG) {
|
134
|
+
selected_hash = local_config_hash;
|
135
|
+
if (!local_config_id_set) {
|
136
|
+
local_config_id_set = true;
|
137
|
+
if (config.config_id.length > 0) {
|
138
|
+
rb_hash_aset(local_hash, ID2SYM(rb_intern("id")), rb_utf8_str_new_cstr(config.config_id.ptr));
|
139
|
+
}
|
140
|
+
}
|
141
|
+
}
|
142
|
+
else {
|
143
|
+
selected_hash = fleet_config_hash;
|
144
|
+
if (!fleet_config_id_set) {
|
145
|
+
fleet_config_id_set = true;
|
146
|
+
if (config.config_id.length > 0) {
|
147
|
+
rb_hash_aset(fleet_hash, ID2SYM(rb_intern("id")), rb_utf8_str_new_cstr(config.config_id.ptr));
|
148
|
+
}
|
149
|
+
}
|
150
|
+
}
|
151
|
+
|
152
|
+
rb_hash_aset(selected_hash, rb_utf8_str_new_cstr(config.name.ptr), rb_utf8_str_new_cstr(config.value.ptr));
|
153
|
+
}
|
154
|
+
|
155
|
+
rb_hash_aset(local_hash, ID2SYM(rb_intern("config")), local_config_hash);
|
156
|
+
rb_hash_aset(fleet_hash, ID2SYM(rb_intern("config")), fleet_config_hash);
|
157
|
+
|
158
|
+
VALUE result = rb_hash_new();
|
159
|
+
rb_hash_aset(result, ID2SYM(rb_intern("local")), local_hash);
|
160
|
+
rb_hash_aset(result, ID2SYM(rb_intern("fleet")), fleet_hash);
|
161
|
+
|
162
|
+
RB_GC_GUARD(config_vec_rb);
|
163
|
+
return result;
|
164
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "datadog_ruby_common.h"
|
4
|
+
|
5
|
+
void library_config_init(VALUE core_module);
|
6
|
+
|
7
|
+
static inline bool is_config_loaded(void) {
|
8
|
+
VALUE datadog_module = rb_const_get(rb_cObject, rb_intern("Datadog"));
|
9
|
+
VALUE is_config_loaded = rb_funcall(datadog_module, rb_intern("configuration?"), 0);
|
10
|
+
|
11
|
+
return is_config_loaded == Qtrue;
|
12
|
+
}
|
13
|
+
|
14
|
+
static inline VALUE log_warning_without_config(VALUE warning) {
|
15
|
+
VALUE datadog_module = rb_const_get(rb_cObject, rb_intern("Datadog"));
|
16
|
+
VALUE logger = rb_funcall(datadog_module, rb_intern("logger_without_configuration"), 0);
|
17
|
+
|
18
|
+
return rb_funcall(logger, rb_intern("warn"), 1, warning);
|
19
|
+
}
|
20
|
+
|
21
|
+
static inline ddog_CStr cstr_from_ruby_string(VALUE string) {
|
22
|
+
ENFORCE_TYPE(string, T_STRING);
|
23
|
+
ddog_CStr cstr = {.ptr = RSTRING_PTR(string), .length = RSTRING_LEN(string)};
|
24
|
+
return cstr;
|
25
|
+
}
|
@@ -17,9 +17,9 @@ export DD_RUBY_PLATFORM=`ruby -e 'puts Gem::Platform.local.to_s'`
|
|
17
17
|
mkdir -p my-libdatadog-build/$DD_RUBY_PLATFORM
|
18
18
|
```
|
19
19
|
|
20
|
-
5.
|
21
|
-
6. Tell
|
22
|
-
7.
|
20
|
+
5. From inside of the libdatadog repo, build libdatadog into this folder: `./build-profiling-ffi.sh my-libdatadog-build/$DD_RUBY_PLATFORM`
|
21
|
+
6. Tell Ruby where to find libdatadog: `export LIBDATADOG_VENDOR_OVERRIDE=/full/path/to/my-libdatadog-build/` (Notice no platform here)
|
22
|
+
7. From dd-trace-rb, run `bundle exec rake clean compile`
|
23
23
|
|
24
24
|
If you additionally want to run the profiler test suite, also remember to `export DD_PROFILING_MACOS_TESTING=true` and re-run `rake clean compile`.
|
25
25
|
|
@@ -0,0 +1,112 @@
|
|
1
|
+
#include <errno.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
#include <ruby.h>
|
4
|
+
#include <datadog/library-config.h>
|
5
|
+
|
6
|
+
#include "datadog_ruby_common.h"
|
7
|
+
|
8
|
+
static VALUE _native_store_tracer_metadata(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self);
|
9
|
+
static VALUE _native_to_rb_int(DDTRACE_UNUSED VALUE _self, VALUE tracer_memfd);
|
10
|
+
static VALUE _native_close_tracer_memfd(DDTRACE_UNUSED VALUE _self, VALUE tracer_memfd, VALUE logger);
|
11
|
+
|
12
|
+
static void tracer_memfd_free(void *ptr) {
|
13
|
+
int *fd = (int *)ptr;
|
14
|
+
if (*fd != -1) {
|
15
|
+
close(*fd);
|
16
|
+
}
|
17
|
+
ruby_xfree(ptr);
|
18
|
+
}
|
19
|
+
|
20
|
+
static const rb_data_type_t tracer_memfd_type = {
|
21
|
+
.wrap_struct_name = "Datadog::Core::ProcessDiscovery::TracerMemfd",
|
22
|
+
.function = {
|
23
|
+
.dfree = tracer_memfd_free,
|
24
|
+
.dsize = NULL,
|
25
|
+
},
|
26
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
27
|
+
};
|
28
|
+
|
29
|
+
void process_discovery_init(VALUE core_module) {
|
30
|
+
VALUE process_discovery_class = rb_define_class_under(core_module, "ProcessDiscovery", rb_cObject);
|
31
|
+
VALUE tracer_memfd_class = rb_define_class_under(process_discovery_class, "TracerMemfd", rb_cObject);
|
32
|
+
rb_undef_alloc_func(tracer_memfd_class); // Class cannot be instantiated from Ruby
|
33
|
+
|
34
|
+
rb_define_singleton_method(process_discovery_class, "_native_store_tracer_metadata", _native_store_tracer_metadata, -1);
|
35
|
+
rb_define_singleton_method(process_discovery_class, "_native_to_rb_int", _native_to_rb_int, 1);
|
36
|
+
rb_define_singleton_method(process_discovery_class, "_native_close_tracer_memfd", _native_close_tracer_memfd, 2);
|
37
|
+
}
|
38
|
+
|
39
|
+
static VALUE _native_store_tracer_metadata(int argc, VALUE *argv, VALUE self) {
|
40
|
+
VALUE logger;
|
41
|
+
VALUE options;
|
42
|
+
rb_scan_args(argc, argv, "1:", &logger, &options);
|
43
|
+
if (options == Qnil) options = rb_hash_new();
|
44
|
+
|
45
|
+
VALUE schema_version = rb_hash_fetch(options, ID2SYM(rb_intern("schema_version")));
|
46
|
+
VALUE runtime_id = rb_hash_fetch(options, ID2SYM(rb_intern("runtime_id")));
|
47
|
+
VALUE tracer_language = rb_hash_fetch(options, ID2SYM(rb_intern("tracer_language")));
|
48
|
+
VALUE tracer_version = rb_hash_fetch(options, ID2SYM(rb_intern("tracer_version")));
|
49
|
+
VALUE hostname = rb_hash_fetch(options, ID2SYM(rb_intern("hostname")));
|
50
|
+
VALUE service_name = rb_hash_fetch(options, ID2SYM(rb_intern("service_name")));
|
51
|
+
VALUE service_env = rb_hash_fetch(options, ID2SYM(rb_intern("service_env")));
|
52
|
+
VALUE service_version = rb_hash_fetch(options, ID2SYM(rb_intern("service_version")));
|
53
|
+
|
54
|
+
ENFORCE_TYPE(schema_version, T_FIXNUM);
|
55
|
+
ENFORCE_TYPE(runtime_id, T_STRING);
|
56
|
+
ENFORCE_TYPE(tracer_language, T_STRING);
|
57
|
+
ENFORCE_TYPE(tracer_version, T_STRING);
|
58
|
+
ENFORCE_TYPE(hostname, T_STRING);
|
59
|
+
ENFORCE_TYPE(service_name, T_STRING);
|
60
|
+
ENFORCE_TYPE(service_env, T_STRING);
|
61
|
+
ENFORCE_TYPE(service_version, T_STRING);
|
62
|
+
|
63
|
+
ddog_Result_TracerMemfdHandle result = ddog_store_tracer_metadata(
|
64
|
+
(uint8_t) NUM2UINT(schema_version),
|
65
|
+
char_slice_from_ruby_string(runtime_id),
|
66
|
+
char_slice_from_ruby_string(tracer_language),
|
67
|
+
char_slice_from_ruby_string(tracer_version),
|
68
|
+
char_slice_from_ruby_string(hostname),
|
69
|
+
char_slice_from_ruby_string(service_name),
|
70
|
+
char_slice_from_ruby_string(service_env),
|
71
|
+
char_slice_from_ruby_string(service_version)
|
72
|
+
);
|
73
|
+
|
74
|
+
if (result.tag == DDOG_RESULT_TRACER_MEMFD_HANDLE_ERR_TRACER_MEMFD_HANDLE) {
|
75
|
+
rb_funcall(logger, rb_intern("debug"), 1, rb_sprintf("Failed to store the tracer configuration in a memory file descriptor: %"PRIsVALUE, get_error_details_and_drop(&result.err)));
|
76
|
+
return Qnil;
|
77
|
+
}
|
78
|
+
|
79
|
+
// &result.ok is a ddog_TracerMemfdHandle, which is a struct only containing int fd, which is a file descriptor
|
80
|
+
// We should just return the fd
|
81
|
+
int *fd = ruby_xmalloc(sizeof(int));
|
82
|
+
|
83
|
+
*fd = result.ok.fd;
|
84
|
+
VALUE tracer_memfd_class = rb_const_get(self, rb_intern("TracerMemfd"));
|
85
|
+
VALUE tracer_memfd = TypedData_Wrap_Struct(tracer_memfd_class, &tracer_memfd_type, fd);
|
86
|
+
return tracer_memfd;
|
87
|
+
}
|
88
|
+
|
89
|
+
static VALUE _native_to_rb_int(DDTRACE_UNUSED VALUE _self, VALUE tracer_memfd) {
|
90
|
+
int *fd;
|
91
|
+
TypedData_Get_Struct(tracer_memfd, int, &tracer_memfd_type, fd);
|
92
|
+
return INT2NUM(*fd);
|
93
|
+
}
|
94
|
+
|
95
|
+
static VALUE _native_close_tracer_memfd(DDTRACE_UNUSED VALUE _self, VALUE tracer_memfd, VALUE logger) {
|
96
|
+
int *fd;
|
97
|
+
TypedData_Get_Struct(tracer_memfd, int, &tracer_memfd_type, fd);
|
98
|
+
if (*fd == -1) {
|
99
|
+
rb_funcall(logger, rb_intern("debug"), 1, rb_sprintf("The tracer configuration memory file descriptor has already been closed"));
|
100
|
+
return Qnil;
|
101
|
+
}
|
102
|
+
|
103
|
+
int close_result = close(*fd);
|
104
|
+
*fd = -1;
|
105
|
+
|
106
|
+
if (close_result == -1) {
|
107
|
+
rb_funcall(logger, rb_intern("debug"), 1, rb_sprintf("Failed to close the tracer configuration memory file descriptor: %s", strerror(errno)));
|
108
|
+
return Qnil;
|
109
|
+
}
|
110
|
+
|
111
|
+
return Qnil;
|
112
|
+
}
|
@@ -8,7 +8,7 @@ module Datadog
|
|
8
8
|
module LibdatadogExtconfHelpers
|
9
9
|
# Used to make sure the correct gem version gets loaded, as extconf.rb does not get run with "bundle exec" and thus
|
10
10
|
# may see multiple libdatadog versions. See https://github.com/DataDog/dd-trace-rb/pull/2531 for the horror story.
|
11
|
-
LIBDATADOG_VERSION = '~>
|
11
|
+
LIBDATADOG_VERSION = '~> 18.1.0.1.0'
|
12
12
|
|
13
13
|
# Used as an workaround for a limitation with how dynamic linking works in environments where the datadog gem and
|
14
14
|
# libdatadog are moved after the extension gets compiled.
|
@@ -104,7 +104,7 @@ module Datadog
|
|
104
104
|
|
105
105
|
# mkmf sets $PKGCONFIG after the `pkg_config` gets used in extconf.rb. When `pkg_config` is unsuccessful, we use
|
106
106
|
# this helper to decide if we can show more specific error message vs a generic "something went wrong".
|
107
|
-
def self.pkg_config_missing?(command: $PKGCONFIG) #
|
107
|
+
def self.pkg_config_missing?(command: $PKGCONFIG) # standard:disable Style/GlobalVars
|
108
108
|
pkg_config_available = command && xsystem("#{command} --version")
|
109
109
|
|
110
110
|
pkg_config_available != true
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module AppSec
|
5
|
+
module ActionsHandler
|
6
|
+
# This module serves encapsulates MessagePack serialization for caller locations.
|
7
|
+
#
|
8
|
+
# It serializes part of the stack:
|
9
|
+
# up to 32 frames (configurable)
|
10
|
+
# keeping frames from top and bottom of the stack (75% to 25%, configurable).
|
11
|
+
#
|
12
|
+
# It represents the stack trace that is added to span metastruct field.
|
13
|
+
class SerializableBacktrace
|
14
|
+
CLASS_AND_FUNCTION_NAME_REGEX = /\b((?:\w+::)*\w+)?[#.]?\b(\w+)\z/.freeze
|
15
|
+
|
16
|
+
def initialize(locations:, stack_id:)
|
17
|
+
@stack_id = stack_id
|
18
|
+
@locations = locations
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_msgpack(packer = nil)
|
22
|
+
# JRuby doesn't pass the packer
|
23
|
+
packer ||= MessagePack::Packer.new
|
24
|
+
|
25
|
+
packer.write_map_header(3)
|
26
|
+
|
27
|
+
packer.write('id')
|
28
|
+
packer.write(@stack_id.encode('UTF-8'))
|
29
|
+
|
30
|
+
packer.write('language')
|
31
|
+
packer.write('ruby'.encode('UTF-8'))
|
32
|
+
|
33
|
+
serializable_locations_map = build_serializable_locations_map
|
34
|
+
|
35
|
+
packer.write('frames')
|
36
|
+
packer.write_array_header(serializable_locations_map.size)
|
37
|
+
|
38
|
+
serializable_locations_map.each do |frame_id, location|
|
39
|
+
packer.write_map_header(6)
|
40
|
+
|
41
|
+
packer.write('id')
|
42
|
+
packer.write(frame_id)
|
43
|
+
|
44
|
+
packer.write('text')
|
45
|
+
packer.write(location.to_s.encode('UTF-8'))
|
46
|
+
|
47
|
+
packer.write('file')
|
48
|
+
packer.write(location.path&.encode('UTF-8'))
|
49
|
+
|
50
|
+
packer.write('line')
|
51
|
+
packer.write(location.lineno)
|
52
|
+
|
53
|
+
class_name, function_name = location.label&.match(CLASS_AND_FUNCTION_NAME_REGEX)&.captures
|
54
|
+
|
55
|
+
packer.write('class_name')
|
56
|
+
packer.write(class_name&.encode('UTF-8'))
|
57
|
+
|
58
|
+
packer.write('function')
|
59
|
+
packer.write(function_name&.encode('UTF-8'))
|
60
|
+
end
|
61
|
+
|
62
|
+
packer
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def build_serializable_locations_map
|
68
|
+
max_depth = Datadog.configuration.appsec.stack_trace.max_depth
|
69
|
+
top_percent = Datadog.configuration.appsec.stack_trace.top_percentage
|
70
|
+
|
71
|
+
drop_from_idx = max_depth * top_percent / 100
|
72
|
+
drop_until_idx = @locations.size - (max_depth - drop_from_idx)
|
73
|
+
|
74
|
+
frame_idx = -1
|
75
|
+
@locations.each_with_object({}) do |location, map|
|
76
|
+
# we are dropping frames from library code without increasing frame index
|
77
|
+
next if location.path&.include?('lib/datadog')
|
78
|
+
|
79
|
+
frame_idx += 1
|
80
|
+
|
81
|
+
next if max_depth != 0 && frame_idx >= drop_from_idx && frame_idx < drop_until_idx
|
82
|
+
|
83
|
+
map[frame_idx] = location
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'actions_handler/serializable_backtrace'
|
4
|
+
|
3
5
|
module Datadog
|
4
6
|
module AppSec
|
5
7
|
# this module encapsulates functions for handling actions that libddawf returns
|
@@ -19,9 +21,29 @@ module Datadog
|
|
19
21
|
throw(Datadog::AppSec::Ext::INTERRUPT, action_params)
|
20
22
|
end
|
21
23
|
|
22
|
-
def generate_stack(
|
24
|
+
def generate_stack(action_params)
|
25
|
+
return unless Datadog.configuration.appsec.stack_trace.enabled
|
26
|
+
|
27
|
+
stack_id = action_params['stack_id']
|
28
|
+
return unless stack_id
|
29
|
+
|
30
|
+
active_span = AppSec.active_context&.span
|
31
|
+
return unless active_span
|
32
|
+
|
33
|
+
event_category = Ext::EXPLOIT_PREVENTION_EVENT_CATEGORY
|
34
|
+
tag_key = Ext::TAG_METASTRUCT_STACK_TRACE
|
23
35
|
|
24
|
-
|
36
|
+
existing_stack_data = active_span.get_metastruct_tag(tag_key).dup || {event_category => []}
|
37
|
+
max_stack_traces = Datadog.configuration.appsec.stack_trace.max_stack_traces
|
38
|
+
return if max_stack_traces != 0 && existing_stack_data[event_category].count >= max_stack_traces
|
39
|
+
|
40
|
+
backtrace = SerializableBacktrace.new(locations: Array(caller_locations), stack_id: stack_id)
|
41
|
+
existing_stack_data[event_category] << backtrace
|
42
|
+
active_span.set_metastruct_tag(tag_key, existing_stack_data)
|
43
|
+
end
|
44
|
+
|
45
|
+
def generate_schema(_action_params)
|
46
|
+
end
|
25
47
|
end
|
26
48
|
end
|
27
49
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'digest/sha2'
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module AppSec
|
7
|
+
# Manual anonymization of the potential PII data
|
8
|
+
module Anonymizer
|
9
|
+
def self.anonymize(payload)
|
10
|
+
raise ArgumentError, "expected String, received #{payload.class}" unless payload.is_a?(String)
|
11
|
+
|
12
|
+
"anon_#{Digest::SHA256.hexdigest(payload)[0, 32]}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module Datadog
|
6
|
+
module AppSec
|
7
|
+
module APISecurity
|
8
|
+
# An LRU (Least Recently Used) cache implementation that relies on the
|
9
|
+
# Ruby 1.9+ `Hash` implementation that guarantees insertion order.
|
10
|
+
#
|
11
|
+
# WARNING: This implementation is NOT thread-safe and should be used
|
12
|
+
# in a single-threaded context.
|
13
|
+
class LRUCache
|
14
|
+
extend Forwardable
|
15
|
+
|
16
|
+
def_delegators :@store, :clear, :empty?
|
17
|
+
|
18
|
+
def initialize(max_size)
|
19
|
+
raise ArgumentError, 'max_size must be an Integer' unless max_size.is_a?(Integer)
|
20
|
+
raise ArgumentError, 'max_size must be greater than 0' if max_size <= 0
|
21
|
+
|
22
|
+
@max_size = max_size
|
23
|
+
@store = {}
|
24
|
+
end
|
25
|
+
|
26
|
+
# NOTE: Accessing a key moves it to the end of the list.
|
27
|
+
def [](key)
|
28
|
+
if (entry = @store.delete(key))
|
29
|
+
@store[key] = entry
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def store(key, value)
|
34
|
+
return @store[key] = value if @store.delete(key)
|
35
|
+
|
36
|
+
# NOTE: evict the oldest entry if store reached the maximum allowed size
|
37
|
+
@store.shift if @store.size >= @max_size
|
38
|
+
@store[key] = value
|
39
|
+
end
|
40
|
+
|
41
|
+
# NOTE: If the key exists, it's moved to the end of the list and
|
42
|
+
# if does not, the given block will be executed and the result
|
43
|
+
# will be stored (which will add it to the end of the list).
|
44
|
+
def fetch_or_store(key)
|
45
|
+
if (entry = @store.delete(key))
|
46
|
+
return @store[key] = entry
|
47
|
+
end
|
48
|
+
|
49
|
+
# NOTE: evict the oldest entry if store reached the maximum allowed size
|
50
|
+
@store.shift if @store.size >= @max_size
|
51
|
+
@store[key] = yield
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module AppSec
|
5
|
+
module APISecurity
|
6
|
+
# This is a helper module to extract the route pattern from the Rack::Request.
|
7
|
+
module RouteExtractor
|
8
|
+
SINATRA_ROUTE_KEY = 'sinatra.route'
|
9
|
+
SINATRA_ROUTE_SEPARATOR = ' '
|
10
|
+
GRAPE_ROUTE_KEY = 'grape.routing_args'
|
11
|
+
RAILS_ROUTE_KEY = 'action_dispatch.route_uri_pattern'
|
12
|
+
RAILS_ROUTES_KEY = 'action_dispatch.routes'
|
13
|
+
RAILS_PATH_PARAMS_KEY = 'action_dispatch.request.path_parameters'
|
14
|
+
RAILS_FORMAT_SUFFIX = '(.:format)'
|
15
|
+
|
16
|
+
# HACK: We rely on the fact that each contrib will modify `request.env`
|
17
|
+
# and store information sufficient to compute the canonical
|
18
|
+
# route (ex: `/users/:id`).
|
19
|
+
#
|
20
|
+
# When contribs like Sinatra or Grape are used, they could be mounted
|
21
|
+
# into the Rails app, hence you can see the use of the `script_name`
|
22
|
+
# that will contain the path prefix of the mounted app.
|
23
|
+
#
|
24
|
+
# Rack
|
25
|
+
# does not support named arguments, so we have to use `path`
|
26
|
+
# Sinatra
|
27
|
+
# uses `sinatra.route` with a string like "GET /users/:id"
|
28
|
+
# Grape
|
29
|
+
# uses `grape.routing_args` with a hash with a `:route_info` key
|
30
|
+
# that contains a `Grape::Router::Route` object that contains
|
31
|
+
# `Grape::Router::Pattern` object with an `origin` method
|
32
|
+
# Rails < 7.1 (slow path)
|
33
|
+
# uses `action_dispatch.routes` to store `ActionDispatch::Routing::RouteSet`
|
34
|
+
# which can recognize requests
|
35
|
+
# Rails > 7.1 (fast path)
|
36
|
+
# uses `action_dispatch.route_uri_pattern` with a string like
|
37
|
+
# "/users/:id(.:format)"
|
38
|
+
#
|
39
|
+
# WARNING: This method works only *after* the request has been routed.
|
40
|
+
#
|
41
|
+
# WARNING: In Rails > 7.1 when a route was not found,
|
42
|
+
# action_dispatch.route_uri_pattern will not be set.
|
43
|
+
# In Rails < 7.1 it also will not be set even if a route was found,
|
44
|
+
# but in this case action_dispatch.request.path_parameters won't be empty.
|
45
|
+
def self.route_pattern(request)
|
46
|
+
if request.env.key?(GRAPE_ROUTE_KEY)
|
47
|
+
pattern = request.env[GRAPE_ROUTE_KEY][:route_info]&.pattern&.origin
|
48
|
+
"#{request.script_name}#{pattern}"
|
49
|
+
elsif request.env.key?(SINATRA_ROUTE_KEY)
|
50
|
+
pattern = request.env[SINATRA_ROUTE_KEY].split(SINATRA_ROUTE_SEPARATOR, 2)[1]
|
51
|
+
"#{request.script_name}#{pattern}"
|
52
|
+
elsif request.env.key?(RAILS_ROUTE_KEY)
|
53
|
+
request.env[RAILS_ROUTE_KEY].delete_suffix(RAILS_FORMAT_SUFFIX)
|
54
|
+
elsif request.env.key?(RAILS_ROUTES_KEY) && !request.env.fetch(RAILS_PATH_PARAMS_KEY, {}).empty?
|
55
|
+
pattern = request.env[RAILS_ROUTES_KEY].router
|
56
|
+
.recognize(request) { |route, _| break route.path.spec.to_s }
|
57
|
+
|
58
|
+
# NOTE: If rails is unable to recognize request it returns empty Array
|
59
|
+
pattern = nil if pattern&.empty?
|
60
|
+
|
61
|
+
# NOTE: If rails can't recognize the request, we are going to fallback
|
62
|
+
# to generic request path
|
63
|
+
(pattern || request.path).delete_suffix(RAILS_FORMAT_SUFFIX)
|
64
|
+
else
|
65
|
+
request.path
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'zlib'
|
4
|
+
require_relative 'lru_cache'
|
5
|
+
require_relative 'route_extractor'
|
6
|
+
require_relative '../../core/utils/time'
|
7
|
+
|
8
|
+
module Datadog
|
9
|
+
module AppSec
|
10
|
+
module APISecurity
|
11
|
+
# A thread-local sampler for API security based on defined delay between
|
12
|
+
# samples with caching capability.
|
13
|
+
class Sampler
|
14
|
+
THREAD_KEY = :datadog_appsec_api_security_sampler
|
15
|
+
MAX_CACHE_SIZE = 4096
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def thread_local
|
19
|
+
sampler = Thread.current.thread_variable_get(THREAD_KEY)
|
20
|
+
return sampler unless sampler.nil?
|
21
|
+
|
22
|
+
Thread.current.thread_variable_set(THREAD_KEY, new(sample_delay))
|
23
|
+
end
|
24
|
+
|
25
|
+
# @api private
|
26
|
+
def reset!
|
27
|
+
Thread.current.thread_variable_set(THREAD_KEY, nil)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def sample_delay
|
33
|
+
Datadog.configuration.appsec.api_security.sample_delay
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize(sample_delay)
|
38
|
+
raise ArgumentError, 'sample_delay must be an Integer' unless sample_delay.is_a?(Integer)
|
39
|
+
|
40
|
+
@cache = LRUCache.new(MAX_CACHE_SIZE)
|
41
|
+
@sample_delay_seconds = sample_delay
|
42
|
+
end
|
43
|
+
|
44
|
+
def sample?(request, response)
|
45
|
+
return true if @sample_delay_seconds.zero?
|
46
|
+
|
47
|
+
key = Zlib.crc32("#{request.request_method}#{RouteExtractor.route_pattern(request)}#{response.status}")
|
48
|
+
current_timestamp = Core::Utils::Time.now.to_i
|
49
|
+
cached_timestamp = @cache[key] || 0
|
50
|
+
|
51
|
+
return false if current_timestamp - cached_timestamp <= @sample_delay_seconds
|
52
|
+
|
53
|
+
@cache.store(key, current_timestamp)
|
54
|
+
true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|