datadog 2.16.0 → 2.18.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 +72 -1
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +12 -46
- data/ext/datadog_profiling_native_extension/collectors_stack.c +227 -49
- data/ext/datadog_profiling_native_extension/collectors_stack.h +19 -3
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +63 -12
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +1 -0
- data/ext/datadog_profiling_native_extension/encoded_profile.c +22 -12
- data/ext/datadog_profiling_native_extension/encoded_profile.h +1 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +7 -0
- data/ext/datadog_profiling_native_extension/heap_recorder.c +239 -363
- data/ext/datadog_profiling_native_extension/heap_recorder.h +4 -6
- data/ext/datadog_profiling_native_extension/http_transport.c +45 -72
- 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 +1 -0
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +6 -3
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +1 -13
- data/ext/datadog_profiling_native_extension/ruby_helpers.h +2 -10
- data/ext/datadog_profiling_native_extension/stack_recorder.c +156 -60
- data/ext/libdatadog_api/crashtracker.c +10 -3
- data/ext/libdatadog_api/extconf.rb +2 -2
- data/ext/libdatadog_api/library_config.c +54 -12
- data/ext/libdatadog_api/library_config.h +6 -0
- data/ext/libdatadog_api/macos_development.md +3 -3
- data/ext/libdatadog_api/process_discovery.c +2 -7
- data/ext/libdatadog_extconf_helpers.rb +2 -2
- data/lib/datadog/appsec/api_security/lru_cache.rb +56 -0
- data/lib/datadog/appsec/api_security/route_extractor.rb +65 -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/recommended.json +257 -85
- data/lib/datadog/appsec/assets/waf_rules/strict.json +10 -78
- data/lib/datadog/appsec/component.rb +30 -54
- data/lib/datadog/appsec/configuration/settings.rb +60 -2
- data/lib/datadog/appsec/context.rb +6 -6
- data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +27 -16
- data/lib/datadog/appsec/processor/rule_loader.rb +5 -6
- data/lib/datadog/appsec/remote.rb +15 -55
- data/lib/datadog/appsec/security_engine/engine.rb +194 -0
- data/lib/datadog/appsec/security_engine/runner.rb +10 -11
- data/lib/datadog/appsec.rb +4 -7
- 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/components.rb +31 -24
- data/lib/datadog/core/configuration/components_state.rb +23 -0
- data/lib/datadog/core/configuration/option.rb +27 -27
- data/lib/datadog/core/configuration/option_definition.rb +4 -4
- data/lib/datadog/core/configuration/options.rb +1 -1
- data/lib/datadog/core/configuration/settings.rb +32 -20
- data/lib/datadog/core/configuration/stable_config.rb +1 -2
- data/lib/datadog/core/configuration.rb +16 -16
- data/lib/datadog/core/crashtracking/component.rb +2 -1
- data/lib/datadog/core/crashtracking/tag_builder.rb +4 -22
- data/lib/datadog/core/encoding.rb +1 -1
- 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/identity.rb +3 -3
- data/lib/datadog/core/environment/platform.rb +3 -3
- data/lib/datadog/core/error.rb +11 -9
- data/lib/datadog/core/logger.rb +2 -2
- data/lib/datadog/core/metrics/client.rb +12 -14
- 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 +5 -1
- data/lib/datadog/core/rate_limiter.rb +4 -2
- data/lib/datadog/core/remote/client.rb +32 -31
- data/lib/datadog/core/remote/component.rb +3 -3
- 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 +12 -0
- data/lib/datadog/core/remote/transport/http/client.rb +1 -1
- data/lib/datadog/core/remote/transport/http/config.rb +21 -5
- data/lib/datadog/core/remote/transport/http/negotiation.rb +1 -1
- data/lib/datadog/core/runtime/metrics.rb +3 -3
- data/lib/datadog/core/tag_builder.rb +56 -0
- data/lib/datadog/core/telemetry/component.rb +39 -24
- data/lib/datadog/core/telemetry/emitter.rb +7 -1
- 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 +269 -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 -475
- 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 +3 -3
- data/lib/datadog/core/telemetry/transport/http/telemetry.rb +2 -2
- data/lib/datadog/core/telemetry/transport/telemetry.rb +0 -1
- data/lib/datadog/core/telemetry/worker.rb +48 -27
- 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/builder.rb +14 -14
- data/lib/datadog/core/transport/http/env.rb +8 -0
- 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 +10 -2
- 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 +9 -10
- data/lib/datadog/di/instrumenter.rb +52 -2
- data/lib/datadog/di/probe_notification_builder.rb +31 -41
- data/lib/datadog/di/probe_notifier_worker.rb +9 -1
- data/lib/datadog/di/serializer.rb +6 -2
- data/lib/datadog/di/transport/http/input.rb +10 -0
- data/lib/datadog/di/transport/input.rb +10 -2
- data/lib/datadog/error_tracking/component.rb +2 -2
- data/lib/datadog/profiling/collectors/code_provenance.rb +18 -9
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +4 -0
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -0
- data/lib/datadog/profiling/collectors/thread_context.rb +16 -1
- data/lib/datadog/profiling/component.rb +7 -9
- data/lib/datadog/profiling/ext.rb +0 -13
- data/lib/datadog/profiling/flush.rb +1 -1
- data/lib/datadog/profiling/http_transport.rb +3 -8
- data/lib/datadog/profiling/profiler.rb +2 -0
- data/lib/datadog/profiling/scheduler.rb +10 -2
- data/lib/datadog/profiling/stack_recorder.rb +5 -5
- data/lib/datadog/profiling/tag_builder.rb +5 -41
- data/lib/datadog/profiling/tasks/setup.rb +2 -0
- 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_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/http/instrumentation.rb +1 -5
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +1 -5
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +1 -5
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +4 -2
- data/lib/datadog/tracing/contrib/patcher.rb +5 -2
- 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/metadata/errors.rb +4 -4
- data/lib/datadog/tracing/sync_writer.rb +1 -1
- data/lib/datadog/tracing/trace_operation.rb +12 -4
- data/lib/datadog/tracing/tracer.rb +6 -2
- data/lib/datadog/version.rb +1 -1
- metadata +31 -12
- data/lib/datadog/appsec/assets/waf_rules/processors.json +0 -321
- data/lib/datadog/appsec/assets/waf_rules/scanners.json +0 -1023
- data/lib/datadog/appsec/processor/rule_merger.rb +0 -171
- data/lib/datadog/appsec/processor.rb +0 -107
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"version": "2.2",
|
3
3
|
"metadata": {
|
4
|
-
"rules_version": "1.
|
4
|
+
"rules_version": "1.14.2"
|
5
5
|
},
|
6
6
|
"rules": [
|
7
7
|
{
|
@@ -1750,24 +1750,7 @@
|
|
1750
1750
|
{
|
1751
1751
|
"id": "http-endpoint-fingerprint",
|
1752
1752
|
"generator": "http_endpoint_fingerprint",
|
1753
|
-
"conditions": [
|
1754
|
-
{
|
1755
|
-
"operator": "exists",
|
1756
|
-
"parameters": {
|
1757
|
-
"inputs": [
|
1758
|
-
{
|
1759
|
-
"address": "waf.context.event"
|
1760
|
-
},
|
1761
|
-
{
|
1762
|
-
"address": "server.business_logic.users.login.failure"
|
1763
|
-
},
|
1764
|
-
{
|
1765
|
-
"address": "server.business_logic.users.login.success"
|
1766
|
-
}
|
1767
|
-
]
|
1768
|
-
}
|
1769
|
-
}
|
1770
|
-
],
|
1753
|
+
"conditions": [],
|
1771
1754
|
"parameters": {
|
1772
1755
|
"mappings": [
|
1773
1756
|
{
|
@@ -1795,7 +1778,7 @@
|
|
1795
1778
|
}
|
1796
1779
|
]
|
1797
1780
|
},
|
1798
|
-
"evaluate":
|
1781
|
+
"evaluate": true,
|
1799
1782
|
"output": true
|
1800
1783
|
},
|
1801
1784
|
{
|
@@ -1951,24 +1934,7 @@
|
|
1951
1934
|
{
|
1952
1935
|
"id": "http-header-fingerprint",
|
1953
1936
|
"generator": "http_header_fingerprint",
|
1954
|
-
"conditions": [
|
1955
|
-
{
|
1956
|
-
"operator": "exists",
|
1957
|
-
"parameters": {
|
1958
|
-
"inputs": [
|
1959
|
-
{
|
1960
|
-
"address": "waf.context.event"
|
1961
|
-
},
|
1962
|
-
{
|
1963
|
-
"address": "server.business_logic.users.login.failure"
|
1964
|
-
},
|
1965
|
-
{
|
1966
|
-
"address": "server.business_logic.users.login.success"
|
1967
|
-
}
|
1968
|
-
]
|
1969
|
-
}
|
1970
|
-
}
|
1971
|
-
],
|
1937
|
+
"conditions": [],
|
1972
1938
|
"parameters": {
|
1973
1939
|
"mappings": [
|
1974
1940
|
{
|
@@ -1981,30 +1947,13 @@
|
|
1981
1947
|
}
|
1982
1948
|
]
|
1983
1949
|
},
|
1984
|
-
"evaluate":
|
1950
|
+
"evaluate": true,
|
1985
1951
|
"output": true
|
1986
1952
|
},
|
1987
1953
|
{
|
1988
1954
|
"id": "http-network-fingerprint",
|
1989
1955
|
"generator": "http_network_fingerprint",
|
1990
|
-
"conditions": [
|
1991
|
-
{
|
1992
|
-
"operator": "exists",
|
1993
|
-
"parameters": {
|
1994
|
-
"inputs": [
|
1995
|
-
{
|
1996
|
-
"address": "waf.context.event"
|
1997
|
-
},
|
1998
|
-
{
|
1999
|
-
"address": "server.business_logic.users.login.failure"
|
2000
|
-
},
|
2001
|
-
{
|
2002
|
-
"address": "server.business_logic.users.login.success"
|
2003
|
-
}
|
2004
|
-
]
|
2005
|
-
}
|
2006
|
-
}
|
2007
|
-
],
|
1956
|
+
"conditions": [],
|
2008
1957
|
"parameters": {
|
2009
1958
|
"mappings": [
|
2010
1959
|
{
|
@@ -2017,30 +1966,13 @@
|
|
2017
1966
|
}
|
2018
1967
|
]
|
2019
1968
|
},
|
2020
|
-
"evaluate":
|
1969
|
+
"evaluate": true,
|
2021
1970
|
"output": true
|
2022
1971
|
},
|
2023
1972
|
{
|
2024
1973
|
"id": "session-fingerprint",
|
2025
1974
|
"generator": "session_fingerprint",
|
2026
|
-
"conditions": [
|
2027
|
-
{
|
2028
|
-
"operator": "exists",
|
2029
|
-
"parameters": {
|
2030
|
-
"inputs": [
|
2031
|
-
{
|
2032
|
-
"address": "waf.context.event"
|
2033
|
-
},
|
2034
|
-
{
|
2035
|
-
"address": "server.business_logic.users.login.failure"
|
2036
|
-
},
|
2037
|
-
{
|
2038
|
-
"address": "server.business_logic.users.login.success"
|
2039
|
-
}
|
2040
|
-
]
|
2041
|
-
}
|
2042
|
-
}
|
2043
|
-
],
|
1975
|
+
"conditions": [],
|
2044
1976
|
"parameters": {
|
2045
1977
|
"mappings": [
|
2046
1978
|
{
|
@@ -2063,7 +1995,7 @@
|
|
2063
1995
|
}
|
2064
1996
|
]
|
2065
1997
|
},
|
2066
|
-
"evaluate":
|
1998
|
+
"evaluate": true,
|
2067
1999
|
"output": true
|
2068
2000
|
}
|
2069
2001
|
],
|
@@ -3090,4 +3022,4 @@
|
|
3090
3022
|
}
|
3091
3023
|
}
|
3092
3024
|
]
|
3093
|
-
}
|
3025
|
+
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
4
|
-
require_relative '
|
3
|
+
require_relative 'security_engine/engine'
|
4
|
+
require_relative 'security_engine/runner'
|
5
5
|
require_relative 'processor/rule_loader'
|
6
6
|
require_relative 'actions_handler'
|
7
7
|
|
@@ -32,7 +32,8 @@ module Datadog
|
|
32
32
|
return
|
33
33
|
end
|
34
34
|
|
35
|
-
|
35
|
+
require_libddwaf(telemetry: telemetry)
|
36
|
+
Datadog::AppSec::WAF.logger = Datadog.logger if Datadog.logger.debug? && settings.appsec.waf_debug
|
36
37
|
|
37
38
|
# We want to always instrument user events when AppSec is enabled.
|
38
39
|
# There could be cases in which users use the DD_APPSEC_ENABLED Env variable to
|
@@ -42,67 +43,44 @@ module Datadog
|
|
42
43
|
devise_integration = Datadog::AppSec::Contrib::Devise::Integration.new
|
43
44
|
settings.appsec.instrument(:devise) unless devise_integration.patcher.patched?
|
44
45
|
|
45
|
-
new(
|
46
|
+
security_engine = SecurityEngine::Engine.new(appsec_settings: settings.appsec, telemetry: telemetry)
|
47
|
+
new(security_engine: security_engine, telemetry: telemetry)
|
48
|
+
rescue
|
49
|
+
Datadog.logger.warn('AppSec is disabled, see logged errors above')
|
50
|
+
|
51
|
+
nil
|
46
52
|
end
|
47
53
|
|
48
54
|
private
|
49
55
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
)
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
# NOTE: This is a temporary solution before the RuleMerger refactoring
|
65
|
-
# with new RemoteConfig setup
|
66
|
-
processors = rules['processors']
|
67
|
-
scanners = rules['scanners']
|
68
|
-
|
69
|
-
ruleset = AppSec::Processor::RuleMerger.merge(
|
70
|
-
rules: [rules],
|
71
|
-
data: data,
|
72
|
-
scanners: scanners,
|
73
|
-
processors: processors,
|
74
|
-
exclusions: exclusions,
|
75
|
-
telemetry: telemetry
|
76
|
-
)
|
77
|
-
|
78
|
-
processor = Processor.new(ruleset: ruleset, telemetry: telemetry)
|
79
|
-
return nil unless processor.ready?
|
80
|
-
|
81
|
-
processor
|
56
|
+
def require_libddwaf(telemetry:)
|
57
|
+
require('libddwaf')
|
58
|
+
rescue LoadError => e
|
59
|
+
libddwaf_platform = Gem.loaded_specs['libddwaf']&.platform || 'unknown'
|
60
|
+
ruby_platforms = Gem.platforms.map(&:to_s)
|
61
|
+
|
62
|
+
error_message = "libddwaf failed to load - installed platform: #{libddwaf_platform}, " \
|
63
|
+
"ruby platforms: #{ruby_platforms}"
|
64
|
+
|
65
|
+
Datadog.logger.error("#{error_message}, error #{e.inspect}")
|
66
|
+
telemetry.report(e, description: error_message)
|
67
|
+
|
68
|
+
raise e
|
82
69
|
end
|
83
70
|
end
|
84
71
|
|
85
|
-
attr_reader :
|
72
|
+
attr_reader :security_engine, :telemetry
|
86
73
|
|
87
|
-
def initialize(
|
88
|
-
@
|
74
|
+
def initialize(security_engine:, telemetry:)
|
75
|
+
@security_engine = security_engine
|
89
76
|
@telemetry = telemetry
|
90
77
|
|
91
78
|
@mutex = Mutex.new
|
92
79
|
end
|
93
80
|
|
94
|
-
def reconfigure
|
81
|
+
def reconfigure!
|
95
82
|
@mutex.synchronize do
|
96
|
-
|
97
|
-
|
98
|
-
if new_processor&.ready?
|
99
|
-
old_processor = @processor
|
100
|
-
|
101
|
-
@telemetry = telemetry
|
102
|
-
@processor = new_processor
|
103
|
-
|
104
|
-
old_processor&.finalize
|
105
|
-
end
|
83
|
+
security_engine.reconfigure!
|
106
84
|
end
|
107
85
|
end
|
108
86
|
|
@@ -112,10 +90,8 @@ module Datadog
|
|
112
90
|
|
113
91
|
def shutdown!
|
114
92
|
@mutex.synchronize do
|
115
|
-
|
116
|
-
|
117
|
-
@processor = nil
|
118
|
-
end
|
93
|
+
security_engine.finalize!
|
94
|
+
@security_engine = nil
|
119
95
|
end
|
120
96
|
end
|
121
97
|
end
|
@@ -80,16 +80,49 @@ module Datadog
|
|
80
80
|
|
81
81
|
option :ip_passlist do |o|
|
82
82
|
o.default []
|
83
|
+
|
84
|
+
o.setter do |value|
|
85
|
+
next value if value.nil? || value.empty?
|
86
|
+
|
87
|
+
Datadog::Core.log_deprecation(disallowed_next_major: false) do
|
88
|
+
'The ip_passlist setting is deprecated and will be removed in the next release. ' \
|
89
|
+
'Please migrate this configuration to your service settings via the Datadog UI'
|
90
|
+
end
|
91
|
+
|
92
|
+
value
|
93
|
+
end
|
83
94
|
end
|
84
95
|
|
85
96
|
option :ip_denylist do |o|
|
86
97
|
o.type :array
|
87
98
|
o.default []
|
99
|
+
|
100
|
+
o.setter do |value|
|
101
|
+
next value if value.nil? || value.empty?
|
102
|
+
|
103
|
+
Datadog::Core.log_deprecation(disallowed_next_major: false) do
|
104
|
+
'The ip_denylist setting is deprecated and will be removed in the next release. ' \
|
105
|
+
'Please migrate this configuration to your service settings via the Datadog UI'
|
106
|
+
end
|
107
|
+
|
108
|
+
value
|
109
|
+
end
|
88
110
|
end
|
89
111
|
|
90
112
|
option :user_id_denylist do |o|
|
91
113
|
o.type :array
|
92
114
|
o.default []
|
115
|
+
|
116
|
+
o.setter do |value|
|
117
|
+
next value if value.nil? || value.empty?
|
118
|
+
|
119
|
+
Datadog::Core.log_deprecation(disallowed_next_major: false) do
|
120
|
+
'The user_id_denylist setting is deprecated and will be removed in the next release. ' \
|
121
|
+
'Please migrate this configuration to your service settings via the Datadog UI'
|
122
|
+
end
|
123
|
+
|
124
|
+
value
|
125
|
+
end
|
93
126
|
end
|
94
127
|
|
95
128
|
option :waf_timeout do |o|
|
@@ -311,12 +344,28 @@ module Datadog
|
|
311
344
|
end
|
312
345
|
|
313
346
|
settings :api_security do
|
347
|
+
define_method(:enabled?) { get_option(:enabled) }
|
348
|
+
|
314
349
|
option :enabled do |o|
|
315
350
|
o.type :bool
|
316
|
-
o.env '
|
317
|
-
o.default
|
351
|
+
o.env 'DD_API_SECURITY_ENABLED'
|
352
|
+
o.default true
|
318
353
|
end
|
319
354
|
|
355
|
+
# NOTE: Unfortunately, we have to go with Float due to other libs
|
356
|
+
# setup, even tho we don't plan to support sub-second delays.
|
357
|
+
#
|
358
|
+
# WARNING: The value will be converted to Integer.
|
359
|
+
option :sample_delay do |o|
|
360
|
+
o.type :float
|
361
|
+
o.env 'DD_API_SECURITY_SAMPLE_DELAY'
|
362
|
+
o.default 30
|
363
|
+
o.setter do |value|
|
364
|
+
value.to_i
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
# DEV-3.0: Remove `api_security.sample_rate` option
|
320
369
|
option :sample_rate do |o|
|
321
370
|
o.type :float
|
322
371
|
o.env 'DD_API_SECURITY_REQUEST_SAMPLE_RATE'
|
@@ -325,6 +374,15 @@ module Datadog
|
|
325
374
|
value = 1 if value > 1
|
326
375
|
SampleRate.new(value)
|
327
376
|
end
|
377
|
+
o.after_set do |_, _, precedence|
|
378
|
+
next if precedence == Datadog::Core::Configuration::Option::Precedence::DEFAULT
|
379
|
+
|
380
|
+
Core.log_deprecation(key: :appsec_api_security_sample_rate) do
|
381
|
+
'The appsec.api_security.sample_rate setting is deprecated. ' \
|
382
|
+
'Please remove it from your Datadog.configure block and use ' \
|
383
|
+
'appsec.api_security.sample_delay instead.'
|
384
|
+
end
|
385
|
+
end
|
328
386
|
end
|
329
387
|
end
|
330
388
|
|
@@ -9,6 +9,7 @@ module Datadog
|
|
9
9
|
class Context
|
10
10
|
ActiveContextError = Class.new(StandardError)
|
11
11
|
|
12
|
+
# TODO: add delegators for active trace span
|
12
13
|
attr_reader :trace, :span, :events
|
13
14
|
|
14
15
|
class << self
|
@@ -20,7 +21,7 @@ module Datadog
|
|
20
21
|
end
|
21
22
|
|
22
23
|
def deactivate
|
23
|
-
active&.finalize
|
24
|
+
active&.finalize!
|
24
25
|
ensure
|
25
26
|
Thread.current[Ext::ACTIVE_CONTEXT_KEY] = nil
|
26
27
|
end
|
@@ -30,12 +31,11 @@ module Datadog
|
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
33
|
-
def initialize(trace, span,
|
34
|
+
def initialize(trace, span, waf_runner)
|
34
35
|
@trace = trace
|
35
36
|
@span = span
|
36
37
|
@events = []
|
37
|
-
@
|
38
|
-
@waf_runner = security_engine.new_runner
|
38
|
+
@waf_runner = waf_runner
|
39
39
|
@metrics = Metrics::Collector.new
|
40
40
|
end
|
41
41
|
|
@@ -66,8 +66,8 @@ module Datadog
|
|
66
66
|
Metrics::Exporter.export_rasp_metrics(@metrics.rasp, @span)
|
67
67
|
end
|
68
68
|
|
69
|
-
def finalize
|
70
|
-
@waf_runner.finalize
|
69
|
+
def finalize!
|
70
|
+
@waf_runner.finalize!
|
71
71
|
end
|
72
72
|
end
|
73
73
|
end
|
@@ -7,7 +7,7 @@ require_relative 'gateway/response'
|
|
7
7
|
|
8
8
|
require_relative '../../event'
|
9
9
|
require_relative '../../response'
|
10
|
-
require_relative '../../
|
10
|
+
require_relative '../../api_security'
|
11
11
|
require_relative '../../security_event'
|
12
12
|
require_relative '../../instrumentation/gateway'
|
13
13
|
|
@@ -46,7 +46,7 @@ module Datadog
|
|
46
46
|
boot = Datadog::Core::Remote::Tie.boot
|
47
47
|
Datadog::Core::Remote::Tie::Tracing.tag(boot, active_span)
|
48
48
|
|
49
|
-
|
49
|
+
security_engine = nil
|
50
50
|
ready = false
|
51
51
|
ctx = nil
|
52
52
|
|
@@ -56,11 +56,11 @@ module Datadog
|
|
56
56
|
return @app.call(env) if active_context(env)
|
57
57
|
|
58
58
|
Datadog::AppSec.reconfigure_lock do
|
59
|
-
|
59
|
+
security_engine = Datadog::AppSec.security_engine
|
60
60
|
|
61
|
-
if
|
61
|
+
if security_engine
|
62
62
|
ctx = Datadog::AppSec::Context.activate(
|
63
|
-
Datadog::AppSec::Context.new(active_trace, active_span,
|
63
|
+
Datadog::AppSec::Context.new(active_trace, active_span, security_engine.new_runner)
|
64
64
|
)
|
65
65
|
|
66
66
|
env[Datadog::AppSec::Ext::CONTEXT_KEY] = ctx
|
@@ -72,7 +72,7 @@ module Datadog
|
|
72
72
|
|
73
73
|
return @app.call(env) unless ready
|
74
74
|
|
75
|
-
add_appsec_tags(
|
75
|
+
add_appsec_tags(security_engine, ctx)
|
76
76
|
add_request_tags(ctx, env)
|
77
77
|
|
78
78
|
http_response = nil
|
@@ -100,7 +100,23 @@ module Datadog
|
|
100
100
|
http_response = AppSec::Response.from_interrupt_params(interrupt_params, env['HTTP_ACCEPT']).to_rack
|
101
101
|
end
|
102
102
|
|
103
|
-
|
103
|
+
# NOTE: This is not optimal, but in the current implementation
|
104
|
+
# `gateway_response` is a container to dispatch response event
|
105
|
+
# and in case of interruption it suppose to be `nil`.
|
106
|
+
#
|
107
|
+
# `http_response` is a real response object in both cases, but
|
108
|
+
# to save us some computations, we will use already pre-computed
|
109
|
+
# `gateway_response` instead of re-creating it.
|
110
|
+
#
|
111
|
+
# WARNING: This part will be refactored.
|
112
|
+
tmp_response = if interrupt_params
|
113
|
+
Gateway::Response.new(http_response[2], http_response[0], http_response[1], context: ctx)
|
114
|
+
else
|
115
|
+
gateway_response
|
116
|
+
end
|
117
|
+
|
118
|
+
if AppSec::APISecurity.enabled? && AppSec::APISecurity.sample_trace?(ctx.trace) &&
|
119
|
+
AppSec::APISecurity.sample?(gateway_request.request, tmp_response.response)
|
104
120
|
ctx.events.push(
|
105
121
|
AppSec::SecurityEvent.new(ctx.extract_schema, trace: ctx.trace, span: ctx.span)
|
106
122
|
)
|
@@ -140,7 +156,7 @@ module Datadog
|
|
140
156
|
end
|
141
157
|
|
142
158
|
# standard:disable Metrics/MethodLength
|
143
|
-
def add_appsec_tags(
|
159
|
+
def add_appsec_tags(security_engine, context)
|
144
160
|
span = context.span
|
145
161
|
trace = context.trace
|
146
162
|
|
@@ -150,20 +166,15 @@ module Datadog
|
|
150
166
|
span.set_tag('_dd.runtime_family', 'ruby')
|
151
167
|
span.set_tag('_dd.appsec.waf.version', Datadog::AppSec::WAF::VERSION::BASE_STRING)
|
152
168
|
|
153
|
-
if
|
154
|
-
|
155
|
-
|
156
|
-
span.set_tag('_dd.appsec.event_rules.version', diagnostics['ruleset_version'])
|
169
|
+
if security_engine.ruleset_version
|
170
|
+
span.set_tag('_dd.appsec.event_rules.version', security_engine.ruleset_version)
|
157
171
|
|
158
172
|
unless @oneshot_tags_sent
|
159
173
|
# Small race condition, but it's inoccuous: worst case the tags
|
160
174
|
# are sent a couple of times more than expected
|
161
175
|
@oneshot_tags_sent = true
|
162
176
|
|
163
|
-
span.set_tag('_dd.appsec.event_rules.
|
164
|
-
span.set_tag('_dd.appsec.event_rules.error_count', diagnostics['rules']['failed'].size.to_f)
|
165
|
-
span.set_tag('_dd.appsec.event_rules.errors', JSON.dump(diagnostics['rules']['errors']))
|
166
|
-
span.set_tag('_dd.appsec.event_rules.addresses', JSON.dump(processor.addresses))
|
177
|
+
span.set_tag('_dd.appsec.event_rules.addresses', JSON.dump(security_engine.waf_addresses))
|
167
178
|
|
168
179
|
# Ensure these tags reach the backend
|
169
180
|
trace.keep!
|
@@ -36,22 +36,21 @@ module Datadog
|
|
36
36
|
|
37
37
|
telemetry.report(e, description: 'libddwaf ruleset failed to load')
|
38
38
|
|
39
|
-
|
39
|
+
raise e
|
40
40
|
end
|
41
41
|
|
42
42
|
def load_data(ip_denylist: [], user_id_denylist: [])
|
43
43
|
data = []
|
44
|
-
data <<
|
45
|
-
data <<
|
44
|
+
data << denylist_data('blocked_ips', ip_denylist) if ip_denylist.any?
|
45
|
+
data << denylist_data('blocked_users', user_id_denylist) if user_id_denylist.any?
|
46
46
|
|
47
47
|
data
|
48
48
|
end
|
49
49
|
|
50
50
|
def load_exclusions(ip_passlist: [])
|
51
|
-
|
52
|
-
exclusions << [passlist_exclusions(ip_passlist)] if ip_passlist.any?
|
51
|
+
return [] if ip_passlist.empty?
|
53
52
|
|
54
|
-
|
53
|
+
passlist_exclusions(ip_passlist)
|
55
54
|
end
|
56
55
|
|
57
56
|
private
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../core/remote/dispatcher'
|
4
|
-
require_relative 'processor/rule_merger'
|
5
4
|
require_relative 'processor/rule_loader'
|
6
5
|
|
7
6
|
module Datadog
|
@@ -57,74 +56,35 @@ module Datadog
|
|
57
56
|
remote_features_enabled? ? ASM_PRODUCTS : []
|
58
57
|
end
|
59
58
|
|
60
|
-
# rubocop:disable Metrics/MethodLength
|
61
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
62
59
|
def receivers(telemetry)
|
63
60
|
return [] unless remote_features_enabled?
|
64
61
|
|
65
62
|
matcher = Core::Remote::Dispatcher::Matcher::Product.new(ASM_PRODUCTS)
|
66
|
-
# rubocop:disable Metrics/BlockLength
|
67
63
|
receiver = Core::Remote::Dispatcher::Receiver.new(matcher) do |repository, changes|
|
68
|
-
|
69
|
-
Datadog.logger.debug { "remote config change: '#{change.path}'" }
|
70
|
-
end
|
71
|
-
|
72
|
-
rules = []
|
73
|
-
custom_rules = []
|
74
|
-
data = []
|
75
|
-
overrides = []
|
76
|
-
exclusions = []
|
77
|
-
actions = []
|
78
|
-
|
79
|
-
repository.contents.each do |content|
|
80
|
-
parsed_content = parse_content(content)
|
81
|
-
|
82
|
-
case content.path.product
|
83
|
-
when 'ASM_DD'
|
84
|
-
rules << parsed_content
|
85
|
-
when 'ASM_DATA'
|
86
|
-
data << parsed_content['rules_data'] if parsed_content['rules_data']
|
87
|
-
when 'ASM'
|
88
|
-
overrides << parsed_content['rules_override'] if parsed_content['rules_override']
|
89
|
-
exclusions << parsed_content['exclusions'] if parsed_content['exclusions']
|
90
|
-
custom_rules << parsed_content['custom_rules'] if parsed_content['custom_rules']
|
91
|
-
actions.concat(parsed_content['actions']) if parsed_content['actions']
|
92
|
-
end
|
93
|
-
end
|
64
|
+
next unless AppSec.security_engine
|
94
65
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
ruleset: Datadog.configuration.appsec.ruleset
|
99
|
-
)
|
66
|
+
changes.each do |change|
|
67
|
+
content = repository[change.path]
|
68
|
+
next unless content || change.type == :delete
|
100
69
|
|
101
|
-
|
70
|
+
case change.type
|
71
|
+
when :insert, :update
|
72
|
+
AppSec.security_engine.add_or_update_config(parse_content(content), path: change.path.to_s) # steep:ignore
|
102
73
|
|
103
|
-
|
74
|
+
content.applied # steep:ignore
|
75
|
+
when :delete
|
76
|
+
AppSec.security_engine.remove_config_at_path(change.path.to_s) # steep:ignore
|
77
|
+
end
|
104
78
|
end
|
105
79
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
overrides: overrides,
|
111
|
-
exclusions: exclusions,
|
112
|
-
custom_rules: custom_rules,
|
113
|
-
telemetry: telemetry
|
114
|
-
)
|
115
|
-
|
116
|
-
Datadog::AppSec.reconfigure(ruleset: ruleset, telemetry: telemetry)
|
117
|
-
|
118
|
-
repository.contents.each do |content|
|
119
|
-
content.applied if ASM_PRODUCTS.include?(content.path.product)
|
120
|
-
end
|
80
|
+
# This is subject to change - we need to remove the reconfiguration mutex
|
81
|
+
# and track usages of each WAF handle instead, so that we know when an old
|
82
|
+
# WAF handle can be finalized.
|
83
|
+
AppSec.reconfigure!
|
121
84
|
end
|
122
|
-
# rubocop:enable Metrics/BlockLength
|
123
85
|
|
124
86
|
[receiver]
|
125
87
|
end
|
126
|
-
# rubocop:enable Metrics/MethodLength
|
127
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
128
88
|
|
129
89
|
private
|
130
90
|
|