datadog 2.12.1 → 2.17.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 +154 -2
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +16 -14
- 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 +3 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.c +8 -1
- data/ext/datadog_profiling_native_extension/http_transport.c +60 -94
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +8 -0
- data/ext/datadog_profiling_native_extension/profiling.c +2 -0
- data/ext/datadog_profiling_native_extension/stack_recorder.c +23 -23
- 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/init.c +15 -0
- data/ext/libdatadog_api/library_config.c +122 -0
- data/ext/libdatadog_api/library_config.h +19 -0
- data/ext/libdatadog_api/macos_development.md +3 -3
- data/ext/libdatadog_api/process_discovery.c +117 -0
- data/ext/libdatadog_api/process_discovery.h +5 -0
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- 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 +49 -0
- data/lib/datadog/appsec/api_security.rb +9 -0
- data/lib/datadog/appsec/assets/waf_rules/README.md +50 -5
- data/lib/datadog/appsec/assets/waf_rules/processors.json +239 -10
- data/lib/datadog/appsec/assets/waf_rules/scanners.json +926 -17
- data/lib/datadog/appsec/autoload.rb +1 -1
- data/lib/datadog/appsec/component.rb +29 -20
- data/lib/datadog/appsec/compressed_json.rb +40 -0
- data/lib/datadog/appsec/configuration/settings.rb +93 -28
- data/lib/datadog/appsec/context.rb +1 -1
- 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 +19 -18
- 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 +26 -28
- data/lib/datadog/appsec/processor/rule_merger.rb +7 -6
- data/lib/datadog/appsec/processor.rb +1 -1
- data/lib/datadog/appsec/remote.rb +23 -11
- data/lib/datadog/appsec/response.rb +6 -6
- data/lib/datadog/appsec/security_engine/runner.rb +3 -3
- data/lib/datadog/appsec/security_event.rb +39 -0
- data/lib/datadog/appsec/utils.rb +0 -2
- data/lib/datadog/appsec.rb +1 -1
- data/lib/datadog/core/buffer/random.rb +18 -2
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +5 -5
- data/lib/datadog/core/configuration/agentless_settings_resolver.rb +176 -0
- data/lib/datadog/core/configuration/components.rb +50 -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 +79 -43
- 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 +68 -35
- data/lib/datadog/core/configuration/stable_config.rb +23 -0
- data/lib/datadog/core/configuration.rb +40 -16
- data/lib/datadog/core/crashtracking/component.rb +3 -10
- 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.rb +32 -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 +2 -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/telemetry/component.rb +78 -53
- data/lib/datadog/core/telemetry/emitter.rb +23 -11
- data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +65 -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 +179 -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 +1 -1
- 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/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 +18 -16
- 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/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/probe_notification_builder.rb +1 -1
- data/lib/datadog/di/probe_notifier_worker.rb +16 -16
- data/lib/datadog/di/remote.rb +2 -0
- 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 +7 -34
- data/lib/datadog/di/transport/http.rb +14 -62
- data/lib/datadog/di/transport/input.rb +4 -3
- data/lib/datadog/di/utils.rb +5 -0
- data/lib/datadog/di.rb +5 -32
- 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.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 +1 -1
- data/lib/datadog/profiling/collectors/info.rb +3 -0
- data/lib/datadog/profiling/collectors/thread_context.rb +1 -1
- data/lib/datadog/profiling/encoded_profile.rb +11 -0
- data/lib/datadog/profiling/exporter.rb +3 -4
- data/lib/datadog/profiling/ext.rb +0 -2
- data/lib/datadog/profiling/flush.rb +5 -8
- data/lib/datadog/profiling/http_transport.rb +5 -59
- data/lib/datadog/profiling/scheduler.rb +8 -1
- data/lib/datadog/profiling/stack_recorder.rb +4 -4
- data/lib/datadog/profiling/tag_builder.rb +1 -5
- data/lib/datadog/profiling.rb +6 -2
- 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/active_record/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +4 -1
- 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/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/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/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/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/server_tracer.rb +1 -1
- 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/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 +1 -1
- data/lib/datadog/tracing/span_operation.rb +46 -16
- data/lib/datadog/tracing/sync_writer.rb +1 -2
- data/lib/datadog/tracing/trace_digest.rb +9 -2
- data/lib/datadog/tracing/trace_operation.rb +44 -24
- data/lib/datadog/tracing/trace_segment.rb +6 -4
- data/lib/datadog/tracing/tracer.rb +45 -5
- 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 +2 -3
- metadata +80 -19
- 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/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
data/lib/datadog/appsec/event.rb
CHANGED
@@ -1,181 +1,142 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'json'
|
4
|
-
require 'zlib'
|
5
|
-
|
6
4
|
require_relative 'rate_limiter'
|
7
|
-
require_relative '
|
5
|
+
require_relative 'compressed_json'
|
8
6
|
|
9
7
|
module Datadog
|
10
8
|
module AppSec
|
11
9
|
# AppSec event
|
12
10
|
module Event
|
11
|
+
DERIVATIVE_SCHEMA_KEY_PREFIX = '_dd.appsec.s.'
|
12
|
+
DERIVATIVE_SCHEMA_MAX_COMPRESSED_SIZE = 25000
|
13
13
|
ALLOWED_REQUEST_HEADERS = %w[
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
].
|
14
|
+
x-forwarded-for
|
15
|
+
x-client-ip
|
16
|
+
x-real-ip
|
17
|
+
x-forwarded
|
18
|
+
x-cluster-client-ip
|
19
|
+
forwarded-for
|
20
|
+
forwarded
|
21
|
+
via
|
22
|
+
true-client-ip
|
23
|
+
content-length
|
24
|
+
content-type
|
25
|
+
content-encoding
|
26
|
+
content-language
|
27
|
+
host
|
28
|
+
user-agent
|
29
|
+
accept
|
30
|
+
accept-encoding
|
31
|
+
accept-language
|
32
|
+
].freeze
|
33
33
|
|
34
34
|
ALLOWED_RESPONSE_HEADERS = %w[
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
].
|
40
|
-
|
41
|
-
MAX_ENCODED_SCHEMA_SIZE = 25000
|
42
|
-
# For more information about this number
|
43
|
-
# please check https://github.com/DataDog/dd-trace-rb/pull/3177#issuecomment-1747221082
|
44
|
-
MIN_SCHEMA_SIZE_FOR_COMPRESSION = 260
|
45
|
-
|
46
|
-
# Record events for a trace
|
47
|
-
#
|
48
|
-
# This is expected to be called only once per trace for the rate limiter
|
49
|
-
# to properly apply
|
50
|
-
class << self
|
51
|
-
def record(span, *events)
|
52
|
-
# ensure rate limiter is called only when there are events to record
|
53
|
-
return if events.empty? || span.nil?
|
35
|
+
content-length
|
36
|
+
content-type
|
37
|
+
content-encoding
|
38
|
+
content-language
|
39
|
+
].freeze
|
54
40
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
41
|
+
class << self
|
42
|
+
def tag_and_keep!(context, waf_result)
|
43
|
+
# We want to keep the trace in case of security event
|
44
|
+
context.trace&.keep!
|
59
45
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
Datadog.logger.debug { "{ error: 'no trace: cannot record', event_group: #{event_group.inspect}}" }
|
64
|
-
next
|
46
|
+
if context.span
|
47
|
+
if waf_result.actions.key?('block_request') || waf_result.actions.key?('redirect_request')
|
48
|
+
context.span.set_tag('appsec.blocked', 'true')
|
65
49
|
end
|
66
50
|
|
67
|
-
|
68
|
-
trace.set_tag(
|
69
|
-
Datadog::Tracing::Metadata::Ext::Distributed::TAG_DECISION_MAKER,
|
70
|
-
Datadog::Tracing::Sampling::Ext::Decision::ASM
|
71
|
-
)
|
72
|
-
|
73
|
-
# prepare and gather tags to apply
|
74
|
-
service_entry_tags = build_service_entry_tags(event_group)
|
75
|
-
|
76
|
-
# apply tags to service entry span
|
77
|
-
service_entry_tags.each do |key, value|
|
78
|
-
span.set_tag(key, value)
|
79
|
-
end
|
51
|
+
context.span.set_tag('appsec.event', 'true')
|
80
52
|
end
|
53
|
+
|
54
|
+
add_distributed_tags(context.trace)
|
81
55
|
end
|
82
56
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
57
|
+
def record(context, request: nil, response: nil)
|
58
|
+
return if context.events.empty? || context.span.nil?
|
59
|
+
|
60
|
+
Datadog::AppSec::RateLimiter.thread_local.limit do
|
61
|
+
context.events.group_by(&:trace).each do |trace, event_group|
|
62
|
+
unless trace
|
63
|
+
next Datadog.logger.debug do
|
64
|
+
"AppSec: Cannot record event group with #{event_group.count} events because it has no trace"
|
65
|
+
end
|
91
66
|
end
|
92
67
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
end
|
68
|
+
if event_group.any? { |event| event.attack? || event.schema? }
|
69
|
+
trace.keep!
|
70
|
+
trace[Tracing::Metadata::Ext::Distributed::TAG_DECISION_MAKER] = Tracing::Sampling::Ext::Decision::ASM
|
97
71
|
|
98
|
-
|
99
|
-
|
100
|
-
|
72
|
+
context.span['_dd.origin'] = 'appsec'
|
73
|
+
context.span.set_tags(request_tags(request)) if request
|
74
|
+
context.span.set_tags(response_tags(response)) if response
|
101
75
|
end
|
76
|
+
|
77
|
+
context.span.set_tags(waf_tags(event_group))
|
102
78
|
end
|
79
|
+
end
|
80
|
+
end
|
103
81
|
|
104
|
-
|
105
|
-
# accumulate triggers
|
106
|
-
waf_events += waf_result.events
|
82
|
+
private
|
107
83
|
|
108
|
-
|
109
|
-
|
110
|
-
next unless parsed_value
|
84
|
+
def request_tags(request)
|
85
|
+
tags = {}
|
111
86
|
|
112
|
-
|
87
|
+
tags['http.host'] = request.host if request.host
|
88
|
+
tags['http.useragent'] = request.user_agent if request.user_agent
|
89
|
+
tags['network.client.ip'] = request.remote_addr if request.remote_addr
|
113
90
|
|
114
|
-
|
115
|
-
|
116
|
-
else
|
117
|
-
parsed_value
|
118
|
-
end
|
119
|
-
next unless schema_value
|
91
|
+
request.headers.each_with_object(tags) do |(name, value), memo|
|
92
|
+
next unless ALLOWED_REQUEST_HEADERS.include?(name)
|
120
93
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
end
|
125
|
-
next
|
126
|
-
end
|
94
|
+
memo["http.request.headers.#{name}"] = value
|
95
|
+
end
|
96
|
+
end
|
127
97
|
|
128
|
-
|
129
|
-
|
98
|
+
def response_tags(response)
|
99
|
+
response.headers.each_with_object({}) do |(name, value), memo|
|
100
|
+
next unless ALLOWED_RESPONSE_HEADERS.include?(name)
|
130
101
|
|
131
|
-
|
102
|
+
memo["http.response.headers.#{name}"] = value
|
132
103
|
end
|
133
|
-
|
134
|
-
appsec_events = json_parse({ triggers: waf_events })
|
135
|
-
entry_tags['_dd.appsec.json'] = appsec_events if appsec_events
|
136
|
-
entry_tags
|
137
104
|
end
|
138
|
-
# rubocop:enable Metrics/MethodLength
|
139
105
|
|
140
|
-
def
|
141
|
-
|
142
|
-
context.trace.keep! if context.trace
|
106
|
+
def waf_tags(security_events)
|
107
|
+
triggers = []
|
143
108
|
|
144
|
-
|
145
|
-
|
146
|
-
context.span.set_tag('appsec.event', 'true')
|
147
|
-
end
|
109
|
+
tags = security_events.each_with_object({}) do |security_event, memo|
|
110
|
+
triggers.concat(security_event.waf_result.events)
|
148
111
|
|
149
|
-
|
150
|
-
|
112
|
+
security_event.waf_result.derivatives.each do |key, value|
|
113
|
+
next memo[key] = value unless key.start_with?(DERIVATIVE_SCHEMA_KEY_PREFIX)
|
151
114
|
|
152
|
-
|
115
|
+
value = CompressedJson.dump(value)
|
116
|
+
next if value.nil?
|
117
|
+
|
118
|
+
if value.size >= DERIVATIVE_SCHEMA_MAX_COMPRESSED_SIZE
|
119
|
+
Datadog.logger.debug { "AppSec: Schema key '#{key}' will not be included into span tags due to it's size" }
|
120
|
+
next
|
121
|
+
end
|
153
122
|
|
154
|
-
|
155
|
-
|
156
|
-
rescue TypeError => e
|
157
|
-
Datadog.logger.debug do
|
158
|
-
"Failed to compress and encode value when populating AppSec::Event. Error: #{e.message}"
|
123
|
+
memo[key] = value
|
124
|
+
end
|
159
125
|
end
|
160
|
-
|
126
|
+
|
127
|
+
tags['_dd.appsec.json'] = json_parse({triggers: triggers}) unless triggers.empty?
|
128
|
+
tags
|
161
129
|
end
|
162
130
|
|
131
|
+
# NOTE: Handling of Encoding::UndefinedConversionError is added as a quick fix to
|
132
|
+
# the issue between Ruby encoded strings and libddwaf produced events and now
|
133
|
+
# is under investigation.
|
163
134
|
def json_parse(value)
|
164
135
|
JSON.dump(value)
|
165
|
-
rescue ArgumentError => e
|
166
|
-
|
167
|
-
"Failed to parse value to JSON when populating AppSec::Event. Error: #{e.message}"
|
168
|
-
end
|
169
|
-
nil
|
170
|
-
end
|
136
|
+
rescue ArgumentError, Encoding::UndefinedConversionError, JSON::JSONError => e
|
137
|
+
AppSec.telemetry.report(e, description: 'AppSec: Failed to convert value into JSON')
|
171
138
|
|
172
|
-
|
173
|
-
sio = StringIO.new
|
174
|
-
# For an in depth comparison of Zlib options check https://github.com/DataDog/dd-trace-rb/pull/3177#issuecomment-1747215473
|
175
|
-
gz = Zlib::GzipWriter.new(sio, Zlib::BEST_SPEED, Zlib::DEFAULT_STRATEGY)
|
176
|
-
gz.write(value)
|
177
|
-
gz.close
|
178
|
-
sio.string
|
139
|
+
nil
|
179
140
|
end
|
180
141
|
|
181
142
|
# Propagate to downstream services the information that the current distributed trace is
|
@@ -187,7 +148,7 @@ module Datadog
|
|
187
148
|
Datadog::Tracing::Metadata::Ext::Distributed::TAG_DECISION_MAKER,
|
188
149
|
Datadog::Tracing::Sampling::Ext::Decision::ASM
|
189
150
|
)
|
190
|
-
trace.
|
151
|
+
trace.set_distributed_source(Datadog::AppSec::Ext::PRODUCT_BIT)
|
191
152
|
end
|
192
153
|
end
|
193
154
|
end
|
data/lib/datadog/appsec/ext.rb
CHANGED
@@ -7,13 +7,15 @@ module Datadog
|
|
7
7
|
RASP_LFI = 'lfi'
|
8
8
|
RASP_SSRF = 'ssrf'
|
9
9
|
|
10
|
+
PRODUCT_BIT = 0b00000010
|
11
|
+
|
10
12
|
INTERRUPT = :datadog_appsec_interrupt
|
11
13
|
CONTEXT_KEY = 'datadog.appsec.context'
|
12
14
|
ACTIVE_CONTEXT_KEY = :datadog_appsec_active_context
|
15
|
+
EXPLOIT_PREVENTION_EVENT_CATEGORY = 'exploit'
|
13
16
|
|
14
17
|
TAG_APPSEC_ENABLED = '_dd.appsec.enabled'
|
15
|
-
|
16
|
-
TAG_DISTRIBUTED_APPSEC_EVENT = '_dd.p.appsec'
|
18
|
+
TAG_METASTRUCT_STACK_TRACE = '_dd.stack'
|
17
19
|
|
18
20
|
TELEMETRY_METRICS_NAMESPACE = 'appsec'
|
19
21
|
end
|
@@ -8,12 +8,17 @@ module Datadog
|
|
8
8
|
class Argument; end # rubocop:disable Lint/EmptyClass
|
9
9
|
|
10
10
|
# Gateway User argument
|
11
|
+
# NOTE: This class is a subject of elimination and will be removed when
|
12
|
+
# the event system is refactored.
|
11
13
|
class User < Argument
|
12
|
-
attr_reader :id
|
14
|
+
attr_reader :id, :login, :session_id
|
13
15
|
|
14
|
-
def initialize(id)
|
16
|
+
def initialize(id, login = nil, session_id = nil)
|
15
17
|
super()
|
18
|
+
|
16
19
|
@id = id
|
20
|
+
@login = login
|
21
|
+
@session_id = session_id
|
17
22
|
end
|
18
23
|
end
|
19
24
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module AppSec
|
5
|
+
module Instrumentation
|
6
|
+
class Gateway
|
7
|
+
# NOTE: This class extracted as-is and will be deprecated
|
8
|
+
# Instrumentation gateway middleware
|
9
|
+
class Middleware
|
10
|
+
attr_reader :key, :block
|
11
|
+
|
12
|
+
def initialize(key, &block)
|
13
|
+
@key = key
|
14
|
+
@block = block
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(stack, env)
|
18
|
+
@block.call(stack, env)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,35 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'gateway/middleware'
|
4
|
+
|
3
5
|
module Datadog
|
4
6
|
module AppSec
|
5
7
|
# Instrumentation for AppSec
|
6
8
|
module Instrumentation
|
7
9
|
# Instrumentation gateway implementation
|
8
10
|
class Gateway
|
9
|
-
# Instrumentation gateway middleware
|
10
|
-
class Middleware
|
11
|
-
attr_reader :key, :block
|
12
|
-
|
13
|
-
def initialize(key, &block)
|
14
|
-
@key = key
|
15
|
-
@block = block
|
16
|
-
end
|
17
|
-
|
18
|
-
def call(stack, env)
|
19
|
-
@block.call(stack, env)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
private_constant :Middleware
|
24
|
-
|
25
11
|
def initialize
|
26
12
|
@middlewares = Hash.new { |h, k| h[k] = [] }
|
13
|
+
@pushed_events = {}
|
27
14
|
end
|
28
15
|
|
16
|
+
# NOTE: Be careful with pushed names because every pushed event name
|
17
|
+
# is recorded in order to provide an ability to any subscriber
|
18
|
+
# to check wether an arbitrary event had happened.
|
19
|
+
#
|
20
|
+
# WARNING: If we start pushing generated names we should consider
|
21
|
+
# limiting the storage of pushed names.
|
29
22
|
def push(name, env, &block)
|
30
|
-
|
23
|
+
@pushed_events[name] = true
|
31
24
|
|
32
|
-
|
25
|
+
block ||= -> {}
|
26
|
+
middlewares_for_name = @middlewares[name]
|
33
27
|
|
34
28
|
return [block.call, nil] if middlewares_for_name.empty?
|
35
29
|
|
@@ -48,14 +42,15 @@ module Datadog
|
|
48
42
|
end
|
49
43
|
|
50
44
|
def watch(name, key, &block)
|
51
|
-
@middlewares[name] << Middleware.new(key, &block) unless middlewares[name].any? { |m| m.key == key }
|
45
|
+
@middlewares[name] << Middleware.new(key, &block) unless @middlewares[name].any? { |m| m.key == key }
|
52
46
|
end
|
53
47
|
|
54
|
-
|
55
|
-
|
56
|
-
|
48
|
+
def pushed?(name)
|
49
|
+
@pushed_events.key?(name)
|
50
|
+
end
|
57
51
|
end
|
58
52
|
|
53
|
+
# NOTE: This left as-is and will be depricated soon.
|
59
54
|
def self.gateway
|
60
55
|
@gateway ||= Gateway.new # TODO: not thread safe
|
61
56
|
end
|
@@ -10,7 +10,7 @@ module Datadog
|
|
10
10
|
def report_rasp(type, result)
|
11
11
|
return if result.is_a?(SecurityEngine::Result::Error)
|
12
12
|
|
13
|
-
tags = {
|
13
|
+
tags = {rule_type: type, waf_version: Datadog::AppSec::WAF::VERSION::BASE_STRING}
|
14
14
|
namespace = Ext::TELEMETRY_METRICS_NAMESPACE
|
15
15
|
|
16
16
|
AppSec.telemetry.inc(namespace, 'rasp.rule.eval', 1, tags: tags)
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative '../../event'
|
4
|
+
require_relative '../../security_event'
|
3
5
|
require_relative '../../instrumentation/gateway'
|
4
6
|
|
5
7
|
module Datadog
|
@@ -8,38 +10,71 @@ module Datadog
|
|
8
10
|
module Gateway
|
9
11
|
# Watcher for Apssec internal events
|
10
12
|
module Watcher
|
13
|
+
ARBITRARY_VALUE = 'invalid'
|
14
|
+
EVENT_LOGIN_SUCCESS = 'users.login.success'
|
15
|
+
EVENT_LOGIN_FAILURE = 'users.login.failure'
|
16
|
+
WATCHED_LOGIN_EVENTS = [EVENT_LOGIN_SUCCESS, EVENT_LOGIN_FAILURE].freeze
|
17
|
+
|
11
18
|
class << self
|
12
19
|
def watch
|
13
20
|
gateway = Instrumentation.gateway
|
14
21
|
|
15
22
|
watch_user_id(gateway)
|
23
|
+
watch_user_login(gateway)
|
16
24
|
end
|
17
25
|
|
18
26
|
def watch_user_id(gateway = Instrumentation.gateway)
|
19
27
|
gateway.watch('identity.set_user', :appsec) do |stack, user|
|
20
|
-
context =
|
28
|
+
context = AppSec.active_context
|
29
|
+
|
30
|
+
if user.id.nil? && user.login.nil? && user.session_id.nil?
|
31
|
+
Datadog.logger.debug { 'AppSec: skipping WAF check because no user information was provided' }
|
32
|
+
next stack.call(user)
|
33
|
+
end
|
21
34
|
|
22
|
-
persistent_data = {
|
23
|
-
|
24
|
-
|
35
|
+
persistent_data = {}
|
36
|
+
persistent_data['usr.id'] = user.id if user.id
|
37
|
+
persistent_data['usr.login'] = user.login if user.login
|
38
|
+
persistent_data['usr.session_id'] = user.session_id if user.session_id
|
25
39
|
|
26
40
|
result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
|
27
41
|
|
42
|
+
if result.match? || result.derivatives.any?
|
43
|
+
context.events.push(
|
44
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
28
48
|
if result.match?
|
29
|
-
|
49
|
+
AppSec::Event.tag_and_keep!(context, result)
|
50
|
+
AppSec::ActionsHandler.handle(result.actions)
|
51
|
+
end
|
30
52
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
span: context.span,
|
35
|
-
user: user,
|
36
|
-
actions: result.actions
|
37
|
-
}
|
53
|
+
stack.call(user)
|
54
|
+
end
|
55
|
+
end
|
38
56
|
|
39
|
-
|
57
|
+
def watch_user_login(gateway = Instrumentation.gateway)
|
58
|
+
gateway.watch('appsec.events.user_lifecycle', :appsec) do |stack, kind|
|
59
|
+
context = AppSec.active_context
|
60
|
+
|
61
|
+
next stack.call(kind) unless WATCHED_LOGIN_EVENTS.include?(kind)
|
62
|
+
|
63
|
+
persistent_data = {"server.business_logic.#{kind}" => ARBITRARY_VALUE}
|
64
|
+
result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
|
65
|
+
|
66
|
+
if result.match? || result.derivatives.any?
|
67
|
+
context.events.push(
|
68
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
69
|
+
)
|
40
70
|
end
|
41
71
|
|
42
|
-
|
72
|
+
if result.match?
|
73
|
+
AppSec::Event.tag_and_keep!(context, result)
|
74
|
+
AppSec::ActionsHandler.handle(result.actions)
|
75
|
+
end
|
76
|
+
|
77
|
+
stack.call(kind)
|
43
78
|
end
|
44
79
|
end
|
45
80
|
end
|
@@ -10,35 +10,33 @@ module Datadog
|
|
10
10
|
module RuleLoader
|
11
11
|
class << self
|
12
12
|
def load_rules(ruleset:, telemetry:)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
13
|
+
case ruleset
|
14
|
+
when :recommended, :strict
|
15
|
+
JSON.parse(Datadog::AppSec::Assets.waf_rules(ruleset))
|
16
|
+
when :risky
|
17
|
+
Datadog.logger.warn(
|
18
|
+
'The :risky Application Security Management ruleset has been deprecated and no longer available.' \
|
19
|
+
'The `:recommended` ruleset will be used instead.' \
|
20
|
+
'Please remove the `appsec.ruleset = :risky` setting from your Datadog.configure block.'
|
21
|
+
)
|
22
|
+
JSON.parse(Datadog::AppSec::Assets.waf_rules(:recommended))
|
23
|
+
when String
|
24
|
+
JSON.parse(File.read(File.expand_path(ruleset)))
|
25
|
+
when File, StringIO
|
26
|
+
JSON.parse(ruleset.read || '').tap { ruleset.rewind }
|
27
|
+
when Hash
|
28
|
+
ruleset
|
29
|
+
else
|
30
|
+
raise ArgumentError, "unsupported value for ruleset setting: #{ruleset.inspect}"
|
31
|
+
end
|
32
|
+
rescue => e
|
33
|
+
Datadog.logger.error do
|
34
|
+
"libddwaf ruleset failed to load, ruleset: #{ruleset.inspect} error: #{e.inspect}"
|
35
|
+
end
|
37
36
|
|
38
|
-
|
37
|
+
telemetry.report(e, description: 'libddwaf ruleset failed to load')
|
39
38
|
|
40
|
-
|
41
|
-
end
|
39
|
+
nil
|
42
40
|
end
|
43
41
|
|
44
42
|
def load_data(ip_denylist: [], user_id_denylist: [])
|
@@ -62,7 +60,7 @@ module Datadog
|
|
62
60
|
{
|
63
61
|
'id' => id,
|
64
62
|
'type' => 'data_with_expiration',
|
65
|
-
'data' => denylist.map { |v| {
|
63
|
+
'data' => denylist.map { |v| {'value' => v.to_s, 'expiration' => 2**63} }
|
66
64
|
}
|
67
65
|
end
|
68
66
|
|
@@ -11,8 +11,8 @@ module Datadog
|
|
11
11
|
# RuleVersionMismatchError
|
12
12
|
class RuleVersionMismatchError < StandardError
|
13
13
|
def initialize(version1, version2)
|
14
|
-
msg = 'Merging rule files with different version could lead to unkown behaviour. '\
|
15
|
-
"We have receieve two rule files with versions: #{version1}, #{version2}. "\
|
14
|
+
msg = 'Merging rule files with different version could lead to unkown behaviour. ' \
|
15
|
+
"We have receieve two rule files with versions: #{version1}, #{version2}. " \
|
16
16
|
'Please validate the configuration is correct and try again.'
|
17
17
|
super(msg)
|
18
18
|
end
|
@@ -22,12 +22,12 @@ module Datadog
|
|
22
22
|
# TODO: `processors` and `scanners` are not provided by the caller, consider removing them
|
23
23
|
def merge(
|
24
24
|
telemetry:,
|
25
|
-
rules:, data: [], overrides: [], exclusions: [], custom_rules: [],
|
25
|
+
rules:, actions: [], data: [], overrides: [], exclusions: [], custom_rules: [],
|
26
26
|
processors: nil, scanners: nil
|
27
27
|
)
|
28
28
|
processors ||= begin
|
29
29
|
default_waf_processors
|
30
|
-
rescue
|
30
|
+
rescue => e
|
31
31
|
Datadog.logger.error("libddwaf rulemerger failed to parse default waf processors. Error: #{e.inspect}")
|
32
32
|
telemetry.report(
|
33
33
|
e,
|
@@ -38,7 +38,7 @@ module Datadog
|
|
38
38
|
|
39
39
|
scanners ||= begin
|
40
40
|
default_waf_scanners
|
41
|
-
rescue
|
41
|
+
rescue => e
|
42
42
|
Datadog.logger.error("libddwaf rulemerger failed to parse default waf scanners. Error: #{e.inspect}")
|
43
43
|
telemetry.report(
|
44
44
|
e,
|
@@ -54,6 +54,7 @@ module Datadog
|
|
54
54
|
combined_exclusions = combine_exclusions(exclusions) if exclusions.any?
|
55
55
|
combined_custom_rules = combine_custom_rules(custom_rules) if custom_rules.any?
|
56
56
|
|
57
|
+
combined_rules['actions'] = actions if actions.any?
|
57
58
|
combined_rules['rules_data'] = combined_data if combined_data
|
58
59
|
combined_rules['rules_override'] = combined_overrides if combined_overrides
|
59
60
|
combined_rules['exclusions'] = combined_exclusions if combined_exclusions
|
@@ -145,7 +146,7 @@ module Datadog
|
|
145
146
|
end
|
146
147
|
|
147
148
|
result.each_with_object([]) do |entry, acc|
|
148
|
-
value = {
|
149
|
+
value = {'value' => entry[0]}
|
149
150
|
value['expiration'] = entry[1] if entry[1]
|
150
151
|
|
151
152
|
acc << value
|