datadog 2.14.0 → 2.16.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 +67 -1
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +7 -6
- 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 +69 -0
- data/ext/datadog_profiling_native_extension/encoded_profile.h +7 -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 +25 -32
- data/ext/datadog_profiling_native_extension/profiling.c +2 -0
- data/ext/datadog_profiling_native_extension/stack_recorder.c +22 -21
- data/ext/libdatadog_api/crashtracker.c +1 -9
- 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/process_discovery.c +117 -0
- data/ext/libdatadog_api/process_discovery.h +5 -0
- data/lib/datadog/appsec/actions_handler.rb +3 -2
- 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 +31 -18
- 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/devise/data_extractor.rb +2 -3
- data/lib/datadog/appsec/contrib/devise/ext.rb +1 -0
- data/lib/datadog/appsec/contrib/devise/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/patcher.rb +3 -5
- data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +17 -4
- 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/gateway/watcher.rb +22 -32
- data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +16 -16
- 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 +95 -134
- data/lib/datadog/appsec/instrumentation/gateway/argument.rb +5 -2
- data/lib/datadog/appsec/metrics/telemetry.rb +1 -1
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +42 -12
- data/lib/datadog/appsec/processor/rule_loader.rb +26 -28
- data/lib/datadog/appsec/processor/rule_merger.rb +5 -5
- data/lib/datadog/appsec/processor.rb +1 -1
- data/lib/datadog/appsec/remote.rb +16 -11
- data/lib/datadog/appsec/response.rb +6 -6
- data/lib/datadog/appsec/security_engine/runner.rb +1 -1
- data/lib/datadog/appsec/security_event.rb +39 -0
- data/lib/datadog/appsec.rb +1 -1
- data/lib/datadog/core/configuration/agentless_settings_resolver.rb +176 -0
- data/lib/datadog/core/configuration/components.rb +19 -10
- data/lib/datadog/core/configuration/option.rb +61 -25
- data/lib/datadog/core/configuration/settings.rb +10 -0
- data/lib/datadog/core/configuration/stable_config.rb +23 -0
- data/lib/datadog/core/configuration.rb +24 -0
- data/lib/datadog/core/crashtracking/component.rb +1 -9
- data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
- data/lib/datadog/core/environment/git.rb +1 -0
- data/lib/datadog/core/environment/variable_helpers.rb +1 -1
- data/lib/datadog/core/metrics/client.rb +8 -7
- data/lib/datadog/core/process_discovery.rb +32 -0
- data/lib/datadog/core/remote/client.rb +7 -0
- data/lib/datadog/core/runtime/metrics.rb +1 -1
- data/lib/datadog/core/telemetry/component.rb +60 -50
- data/lib/datadog/core/telemetry/emitter.rb +17 -11
- data/lib/datadog/core/telemetry/event.rb +7 -4
- data/lib/datadog/core/telemetry/http/adapters/net.rb +12 -97
- data/lib/datadog/core/telemetry/metric.rb +5 -5
- 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 +52 -0
- data/lib/datadog/core/telemetry/worker.rb +45 -0
- data/lib/datadog/core/utils/time.rb +12 -0
- data/lib/datadog/core/workers/async.rb +20 -2
- 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/probe_notification_builder.rb +1 -1
- data/lib/datadog/di/remote.rb +2 -0
- data/lib/datadog/di/transport/http/diagnostics.rb +0 -1
- data/lib/datadog/di/transport/http/input.rb +0 -1
- data/lib/datadog/di/transport/http.rb +0 -6
- 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/identity.rb +1 -1
- data/lib/datadog/profiling/collectors/info.rb +3 -0
- data/lib/datadog/profiling/encoded_profile.rb +11 -0
- data/lib/datadog/profiling/exporter.rb +3 -4
- data/lib/datadog/profiling/ext.rb +0 -1
- data/lib/datadog/profiling/flush.rb +4 -7
- data/lib/datadog/profiling/http_transport.rb +10 -59
- data/lib/datadog/profiling/stack_recorder.rb +4 -4
- data/lib/datadog/profiling.rb +1 -0
- data/lib/datadog/tracing/analytics.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/integration.rb +1 -1
- data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +2 -0
- data/lib/datadog/tracing/contrib/karafka/monitor.rb +1 -1
- 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/rack/request_queue.rb +1 -1
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +1 -1
- data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
- data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
- data/lib/datadog/tracing/distributed/datadog.rb +2 -2
- data/lib/datadog/tracing/sampling/rate_sampler.rb +2 -1
- data/lib/datadog/tracing/span_event.rb +1 -1
- data/lib/datadog/tracing/span_operation.rb +38 -14
- data/lib/datadog/tracing/trace_operation.rb +15 -7
- data/lib/datadog/tracing/tracer.rb +7 -3
- data/lib/datadog/tracing/utils.rb +1 -1
- data/lib/datadog/version.rb +1 -1
- data/lib/datadog.rb +2 -3
- metadata +40 -10
- 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
@@ -4,7 +4,7 @@ if %w[1 true].include?((ENV['DD_APPSEC_ENABLED'] || '').downcase)
|
|
4
4
|
begin
|
5
5
|
require_relative 'contrib/auto_instrument'
|
6
6
|
Datadog::AppSec::Contrib::AutoInstrument.patch_all
|
7
|
-
rescue
|
7
|
+
rescue => e
|
8
8
|
Kernel.warn(
|
9
9
|
'[datadog] AppSec failed to instrument. No security check will be performed. error: ' \
|
10
10
|
" #{e.class.name} #{e.message}"
|
@@ -12,7 +12,25 @@ module Datadog
|
|
12
12
|
class << self
|
13
13
|
def build_appsec_component(settings, telemetry:)
|
14
14
|
return if !settings.respond_to?(:appsec) || !settings.appsec.enabled
|
15
|
-
|
15
|
+
|
16
|
+
ffi_version = Gem.loaded_specs['ffi']&.version
|
17
|
+
unless ffi_version
|
18
|
+
Datadog.logger.warn('FFI gem is not loaded, AppSec will be disabled.')
|
19
|
+
telemetry.error('AppSec: Component not loaded, due to missing FFI gem')
|
20
|
+
|
21
|
+
return
|
22
|
+
end
|
23
|
+
|
24
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.3') && ffi_version < Gem::Version.new('1.16.0')
|
25
|
+
Datadog.logger.warn(
|
26
|
+
'AppSec is not supported in Ruby versions above 3.3.0 when using `ffi` versions older than 1.16.0, ' \
|
27
|
+
'and will be forcibly disabled due to a memory leak in `ffi`. ' \
|
28
|
+
'Please upgrade your `ffi` version to 1.16.0 or higher.'
|
29
|
+
)
|
30
|
+
telemetry.error('AppSec: Component not loaded, ffi version is leaky with ruby > 3.3.0')
|
31
|
+
|
32
|
+
return
|
33
|
+
end
|
16
34
|
|
17
35
|
processor = create_processor(settings, telemetry)
|
18
36
|
|
@@ -29,22 +47,6 @@ module Datadog
|
|
29
47
|
|
30
48
|
private
|
31
49
|
|
32
|
-
def incompatible_ffi_version?
|
33
|
-
ffi_version = Gem.loaded_specs['ffi'] && Gem.loaded_specs['ffi'].version
|
34
|
-
return true unless ffi_version
|
35
|
-
|
36
|
-
return false unless Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.3') &&
|
37
|
-
ffi_version < Gem::Version.new('1.16.0')
|
38
|
-
|
39
|
-
Datadog.logger.warn(
|
40
|
-
'AppSec is not supported in Ruby versions above 3.3.0 when using `ffi` versions older than 1.16.0, ' \
|
41
|
-
'and will be forcibly disabled due to a memory leak in `ffi`. ' \
|
42
|
-
'Please upgrade your `ffi` version to 1.16.0 or higher.'
|
43
|
-
)
|
44
|
-
|
45
|
-
true
|
46
|
-
end
|
47
|
-
|
48
50
|
def create_processor(settings, telemetry)
|
49
51
|
rules = AppSec::Processor::RuleLoader.load_rules(
|
50
52
|
telemetry: telemetry,
|
@@ -59,9 +61,16 @@ module Datadog
|
|
59
61
|
|
60
62
|
exclusions = AppSec::Processor::RuleLoader.load_exclusions(ip_passlist: settings.appsec.ip_passlist)
|
61
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
|
+
|
62
69
|
ruleset = AppSec::Processor::RuleMerger.merge(
|
63
70
|
rules: [rules],
|
64
71
|
data: data,
|
72
|
+
scanners: scanners,
|
73
|
+
processors: processors,
|
65
74
|
exclusions: exclusions,
|
66
75
|
telemetry: telemetry
|
67
76
|
)
|
@@ -86,13 +95,13 @@ module Datadog
|
|
86
95
|
@mutex.synchronize do
|
87
96
|
new_processor = Processor.new(ruleset: ruleset, telemetry: telemetry)
|
88
97
|
|
89
|
-
if new_processor
|
98
|
+
if new_processor&.ready?
|
90
99
|
old_processor = @processor
|
91
100
|
|
92
101
|
@telemetry = telemetry
|
93
102
|
@processor = new_processor
|
94
103
|
|
95
|
-
old_processor
|
104
|
+
old_processor&.finalize
|
96
105
|
end
|
97
106
|
end
|
98
107
|
end
|
@@ -103,7 +112,7 @@ module Datadog
|
|
103
112
|
|
104
113
|
def shutdown!
|
105
114
|
@mutex.synchronize do
|
106
|
-
if processor
|
115
|
+
if processor&.ready?
|
107
116
|
processor.finalize
|
108
117
|
@processor = nil
|
109
118
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'zlib'
|
5
|
+
require 'stringio'
|
6
|
+
|
7
|
+
require_relative '../core/utils/base64'
|
8
|
+
|
9
|
+
module Datadog
|
10
|
+
module AppSec
|
11
|
+
# Converts derivative schema payloads into JSON and compresses them into a
|
12
|
+
# base64 encoded string if the payload is worth compressing.
|
13
|
+
#
|
14
|
+
# See: https://github.com/DataDog/dd-trace-rb/pull/3177#issuecomment-1747221082
|
15
|
+
module CompressedJson
|
16
|
+
MIN_SIZE_FOR_COMPRESSION = 260
|
17
|
+
|
18
|
+
def self.dump(payload)
|
19
|
+
value = JSON.dump(payload)
|
20
|
+
return value if value.bytesize < MIN_SIZE_FOR_COMPRESSION
|
21
|
+
|
22
|
+
compress_and_encode(value)
|
23
|
+
rescue ArgumentError, Encoding::UndefinedConversionError, JSON::JSONError => e
|
24
|
+
AppSec.telemetry.report(e, description: 'AppSec: Failed to convert value into JSON')
|
25
|
+
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
29
|
+
private_class_method def self.compress_and_encode(payload)
|
30
|
+
Core::Utils::Base64.strict_encode64(
|
31
|
+
Zlib.gzip(payload, level: Zlib::BEST_SPEED, strategy: Zlib::DEFAULT_STRATEGY)
|
32
|
+
)
|
33
|
+
rescue Zlib::Error, TypeError => e
|
34
|
+
AppSec.telemetry.report(e, description: 'AppSec: Failed to compress and encode value')
|
35
|
+
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -131,9 +131,12 @@ module Datadog
|
|
131
131
|
o.type :string, nilable: true
|
132
132
|
o.setter do |value|
|
133
133
|
if value
|
134
|
-
|
134
|
+
unless File.exist?(value)
|
135
|
+
raise(ArgumentError,
|
136
|
+
"appsec.templates.html: file not found: #{value}")
|
137
|
+
end
|
135
138
|
|
136
|
-
File.
|
139
|
+
File.binread(value) || ''
|
137
140
|
end
|
138
141
|
end
|
139
142
|
end
|
@@ -143,9 +146,12 @@ module Datadog
|
|
143
146
|
o.type :string, nilable: true
|
144
147
|
o.setter do |value|
|
145
148
|
if value
|
146
|
-
|
149
|
+
unless File.exist?(value)
|
150
|
+
raise(ArgumentError,
|
151
|
+
"appsec.templates.json: file not found: #{value}")
|
152
|
+
end
|
147
153
|
|
148
|
-
File.
|
154
|
+
File.binread(value) || ''
|
149
155
|
end
|
150
156
|
end
|
151
157
|
end
|
@@ -155,9 +161,12 @@ module Datadog
|
|
155
161
|
o.type :string, nilable: true
|
156
162
|
o.setter do |value|
|
157
163
|
if value
|
158
|
-
|
164
|
+
unless File.exist?(value)
|
165
|
+
raise(ArgumentError,
|
166
|
+
"appsec.templates.text: file not found: #{value}")
|
167
|
+
end
|
159
168
|
|
160
|
-
File.
|
169
|
+
File.binread(value) || ''
|
161
170
|
end
|
162
171
|
end
|
163
172
|
end
|
@@ -237,7 +246,7 @@ module Datadog
|
|
237
246
|
|
238
247
|
Datadog.logger.warn(
|
239
248
|
'The appsec.auto_user_instrumentation.mode value provided is not supported. ' \
|
240
|
-
"Supported values are: #{AUTO_USER_INSTRUMENTATION_MODES.join(
|
249
|
+
"Supported values are: #{AUTO_USER_INSTRUMENTATION_MODES.join(" | ")}. " \
|
241
250
|
"Using value: #{DISABLED_AUTO_USER_INSTRUMENTATION_MODE}."
|
242
251
|
)
|
243
252
|
|
@@ -259,11 +268,13 @@ module Datadog
|
|
259
268
|
APPSEC_VALID_TRACK_USER_EVENTS_ENABLED_VALUES.include?(env_value.strip.downcase)
|
260
269
|
end
|
261
270
|
end
|
262
|
-
o.after_set do
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
271
|
+
o.after_set do |_, _, precedence|
|
272
|
+
unless precedence == Datadog::Core::Configuration::Option::Precedence::DEFAULT
|
273
|
+
Core.log_deprecation(key: :appsec_track_user_events_enabled) do
|
274
|
+
'The appsec.track_user_events.enabled setting is deprecated. ' \
|
275
|
+
'Please remove it from your Datadog.configure block and use ' \
|
276
|
+
'appsec.auto_user_instrumentation.mode instead.'
|
277
|
+
end
|
267
278
|
end
|
268
279
|
end
|
269
280
|
end
|
@@ -280,18 +291,20 @@ module Datadog
|
|
280
291
|
else
|
281
292
|
Datadog.logger.warn(
|
282
293
|
'The appsec.track_user_events.mode value provided is not supported.' \
|
283
|
-
"Supported values are: #{APPSEC_VALID_TRACK_USER_EVENTS_MODE.join(
|
294
|
+
"Supported values are: #{APPSEC_VALID_TRACK_USER_EVENTS_MODE.join(" | ")}." \
|
284
295
|
"Using default value: #{SAFE_TRACK_USER_EVENTS_MODE}."
|
285
296
|
)
|
286
297
|
|
287
298
|
SAFE_TRACK_USER_EVENTS_MODE
|
288
299
|
end
|
289
300
|
end
|
290
|
-
o.after_set do
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
301
|
+
o.after_set do |_, _, precedence|
|
302
|
+
unless precedence == Datadog::Core::Configuration::Option::Precedence::DEFAULT
|
303
|
+
Core.log_deprecation(key: :appsec_track_user_events_mode) do
|
304
|
+
'The appsec.track_user_events.mode setting is deprecated. ' \
|
305
|
+
'Please remove it from your Datadog.configure block and use ' \
|
306
|
+
'appsec.auto_user_instrumentation.mode instead.'
|
307
|
+
end
|
295
308
|
end
|
296
309
|
end
|
297
310
|
end
|
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative '../../event'
|
4
|
+
require_relative '../../security_event'
|
5
|
+
|
3
6
|
module Datadog
|
4
7
|
module AppSec
|
5
8
|
module Contrib
|
@@ -28,18 +31,13 @@ module Datadog
|
|
28
31
|
result = context.run_rasp(Ext::RASP_SQLI, {}, ephemeral_data, waf_timeout)
|
29
32
|
|
30
33
|
if result.match?
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
actions: result.actions
|
39
|
-
}
|
40
|
-
context.events << event
|
41
|
-
|
42
|
-
ActionsHandler.handle(result.actions)
|
34
|
+
AppSec::Event.tag_and_keep!(context, result)
|
35
|
+
|
36
|
+
context.events.push(
|
37
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
38
|
+
)
|
39
|
+
|
40
|
+
AppSec::ActionsHandler.handle(result.actions)
|
43
41
|
end
|
44
42
|
end
|
45
43
|
|
@@ -13,10 +13,10 @@ module Datadog
|
|
13
13
|
|
14
14
|
MINIMUM_VERSION = Gem::Version.new('4')
|
15
15
|
|
16
|
-
register_as :active_record, auto_patch:
|
16
|
+
register_as :active_record, auto_patch: true
|
17
17
|
|
18
18
|
def self.version
|
19
|
-
Gem.loaded_specs['activerecord']
|
19
|
+
Gem.loaded_specs['activerecord']&.version
|
20
20
|
end
|
21
21
|
|
22
22
|
def self.loaded?
|
@@ -53,43 +53,43 @@ module Datadog
|
|
53
53
|
|
54
54
|
def patch_sqlite3_adapter
|
55
55
|
instrumentation_module = if ::ActiveRecord.gem_version >= Gem::Version.new('7.1')
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
56
|
+
Instrumentation::InternalExecQueryAdapterPatch
|
57
|
+
elsif ::ActiveRecord.gem_version.segments.first == 4
|
58
|
+
Instrumentation::Rails4ExecQueryAdapterPatch
|
59
|
+
else
|
60
|
+
Instrumentation::ExecQueryAdapterPatch
|
61
|
+
end
|
62
62
|
|
63
63
|
::ActiveRecord::ConnectionAdapters::SQLite3Adapter.prepend(instrumentation_module)
|
64
64
|
end
|
65
65
|
|
66
66
|
def patch_mysql2_adapter
|
67
67
|
instrumentation_module = if ::ActiveRecord.gem_version >= Gem::Version.new('7.1')
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
68
|
+
Instrumentation::InternalExecQueryAdapterPatch
|
69
|
+
elsif ::ActiveRecord.gem_version.segments.first == 4
|
70
|
+
Instrumentation::Rails4ExecQueryAdapterPatch
|
71
|
+
else
|
72
|
+
Instrumentation::ExecQueryAdapterPatch
|
73
|
+
end
|
74
74
|
|
75
75
|
::ActiveRecord::ConnectionAdapters::Mysql2Adapter.prepend(instrumentation_module)
|
76
76
|
end
|
77
77
|
|
78
78
|
def patch_postgresql_adapter
|
79
79
|
instrumentation_module = if ::ActiveRecord.gem_version.segments.first == 4
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
80
|
+
Instrumentation::Rails4ExecuteAndClearAdapterPatch
|
81
|
+
else
|
82
|
+
Instrumentation::ExecuteAndClearAdapterPatch
|
83
|
+
end
|
84
84
|
|
85
85
|
if defined?(::ActiveRecord::ConnectionAdapters::JdbcAdapter)
|
86
86
|
instrumentation_module = if ::ActiveRecord.gem_version >= Gem::Version.new('7.1')
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
87
|
+
Instrumentation::InternalExecQueryAdapterPatch
|
88
|
+
elsif ::ActiveRecord.gem_version.segments.first == 4
|
89
|
+
Instrumentation::Rails4ExecQueryAdapterPatch
|
90
|
+
else
|
91
|
+
Instrumentation::ExecQueryAdapterPatch
|
92
|
+
end
|
93
93
|
end
|
94
94
|
|
95
95
|
::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(instrumentation_module)
|
@@ -57,9 +57,8 @@ module Datadog
|
|
57
57
|
def find_devise_scope(object)
|
58
58
|
return if ::Devise.mappings.count == 1
|
59
59
|
|
60
|
-
@devise_scopes[object.class.name] ||=
|
61
|
-
|
62
|
-
end
|
60
|
+
@devise_scopes[object.class.name] ||= ::Devise.mappings
|
61
|
+
.each_value.find { |mapping| mapping.class_name == object.class.name }&.name
|
63
62
|
end
|
64
63
|
|
65
64
|
def transform(value)
|
@@ -18,6 +18,7 @@ module Datadog
|
|
18
18
|
TAG_DD_LOGIN_FAILURE_MODE = '_dd.appsec.events.users.login.failure.auto.mode'
|
19
19
|
|
20
20
|
TAG_USR_ID = 'usr.id'
|
21
|
+
TAG_SESSION_ID = 'usr.session_id'
|
21
22
|
TAG_SIGNUP_TRACK = 'appsec.events.users.signup.track'
|
22
23
|
TAG_SIGNUP_USR_ID = 'appsec.events.users.signup.usr.id'
|
23
24
|
TAG_SIGNUP_USR_LOGIN = 'appsec.events.users.signup.usr.login'
|
@@ -30,11 +30,9 @@ module Datadog
|
|
30
30
|
def patch
|
31
31
|
::ActiveSupport.on_load(:before_initialize) do |app|
|
32
32
|
GUARD_ONCE_PER_APP[app].run do
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
AppSec.telemetry.error('AppSec: unable to insert Devise TrackingMiddleware')
|
37
|
-
end
|
33
|
+
app.middleware.insert_after(Warden::Manager, TrackingMiddleware)
|
34
|
+
rescue RuntimeError
|
35
|
+
AppSec.telemetry.error('AppSec: unable to insert Devise TrackingMiddleware')
|
38
36
|
end
|
39
37
|
end
|
40
38
|
|
@@ -10,6 +10,7 @@ module Datadog
|
|
10
10
|
# A Rack middleware capable of tracking currently signed user
|
11
11
|
class TrackingMiddleware
|
12
12
|
WARDEN_KEY = 'warden'
|
13
|
+
SESSION_ID_KEY = 'session_id'
|
13
14
|
|
14
15
|
def initialize(app)
|
15
16
|
@app = app
|
@@ -32,16 +33,28 @@ module Datadog
|
|
32
33
|
return @app.call(env)
|
33
34
|
end
|
34
35
|
|
36
|
+
# NOTE: Rails session id will be set for unauthenticated users as well,
|
37
|
+
# so we need to make sure we are tracking only authenticated users.
|
35
38
|
id = transform(extract_id(env[WARDEN_KEY]))
|
39
|
+
session_id = env[WARDEN_KEY].raw_session[SESSION_ID_KEY] if id
|
40
|
+
|
36
41
|
if id
|
37
|
-
|
38
|
-
|
42
|
+
# NOTE: There is no option to set session id without setting user id via SDK.
|
43
|
+
unless context.span.has_tag?(Ext::TAG_USR_ID) && context.span.has_tag?(Ext::TAG_SESSION_ID)
|
44
|
+
user_id = context.span[Ext::TAG_USR_ID] || id
|
45
|
+
user_session_id = context.span[Ext::TAG_SESSION_ID] || session_id
|
46
|
+
|
47
|
+
# FIXME: The current implementation of event arguments is forsing us
|
48
|
+
# to bloat User class, and pass nil-value instead of skip
|
49
|
+
# passing them at first place.
|
50
|
+
# This is a temporary situation until we refactor events model.
|
39
51
|
AppSec::Instrumentation.gateway.push(
|
40
|
-
'identity.set_user', AppSec::Instrumentation::Gateway::User.new(
|
52
|
+
'identity.set_user', AppSec::Instrumentation::Gateway::User.new(user_id, nil, user_session_id)
|
41
53
|
)
|
42
54
|
end
|
43
55
|
|
44
|
-
context.span[Ext::
|
56
|
+
context.span[Ext::TAG_USR_ID] ||= id
|
57
|
+
context.span[Ext::TAG_DD_USR_ID] = id
|
45
58
|
context.span[Ext::TAG_DD_COLLECTION_MODE] ||= Configuration.auto_user_instrumentation_mode
|
46
59
|
end
|
47
60
|
|
@@ -3,6 +3,9 @@
|
|
3
3
|
|
4
4
|
require 'excon'
|
5
5
|
|
6
|
+
require_relative '../../event'
|
7
|
+
require_relative '../../security_event'
|
8
|
+
|
6
9
|
module Datadog
|
7
10
|
module AppSec
|
8
11
|
module Contrib
|
@@ -15,22 +18,18 @@ module Datadog
|
|
15
18
|
context = AppSec.active_context
|
16
19
|
|
17
20
|
request_url = URI.join("#{data[:scheme]}://#{data[:host]}", data[:path]).to_s
|
18
|
-
ephemeral_data = {
|
21
|
+
ephemeral_data = {'server.io.net.url' => request_url}
|
19
22
|
|
20
23
|
result = context.run_rasp(Ext::RASP_SSRF, {}, ephemeral_data, Datadog.configuration.appsec.waf_timeout)
|
21
24
|
|
22
25
|
if result.match?
|
23
|
-
|
26
|
+
AppSec::Event.tag_and_keep!(context, result)
|
24
27
|
|
25
|
-
context.events
|
26
|
-
|
27
|
-
|
28
|
-
span: context.span,
|
29
|
-
request_url: request_url,
|
30
|
-
actions: result.actions
|
31
|
-
}
|
28
|
+
context.events.push(
|
29
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
30
|
+
)
|
32
31
|
|
33
|
-
ActionsHandler.handle(result.actions)
|
32
|
+
AppSec::ActionsHandler.handle(result.actions)
|
34
33
|
end
|
35
34
|
|
36
35
|
super
|
@@ -1,6 +1,9 @@
|
|
1
1
|
# rubocop:disable Naming/FileName
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require_relative '../../event'
|
5
|
+
require_relative '../../security_event'
|
6
|
+
|
4
7
|
module Datadog
|
5
8
|
module AppSec
|
6
9
|
module Contrib
|
@@ -19,17 +22,13 @@ module Datadog
|
|
19
22
|
result = context.run_rasp(Ext::RASP_SSRF, {}, ephemeral_data, Datadog.configuration.appsec.waf_timeout)
|
20
23
|
|
21
24
|
if result.match?
|
22
|
-
|
25
|
+
AppSec::Event.tag_and_keep!(context, result)
|
23
26
|
|
24
|
-
context.events
|
25
|
-
|
26
|
-
|
27
|
-
span: context.span,
|
28
|
-
request_url: request_env.url,
|
29
|
-
actions: result.actions
|
30
|
-
}
|
27
|
+
context.events.push(
|
28
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
29
|
+
)
|
31
30
|
|
32
|
-
ActionsHandler.handle(result.actions)
|
31
|
+
AppSec::ActionsHandler.handle(result.actions)
|
33
32
|
end
|
34
33
|
|
35
34
|
@app.call(request_env)
|
@@ -1,6 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'json'
|
4
|
+
|
5
|
+
require_relative '../../../event'
|
6
|
+
require_relative '../../../security_event'
|
4
7
|
require_relative '../../../instrumentation/gateway'
|
5
8
|
|
6
9
|
module Datadog
|
@@ -29,17 +32,13 @@ module Datadog
|
|
29
32
|
result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
|
30
33
|
|
31
34
|
if result.match?
|
32
|
-
|
35
|
+
AppSec::Event.tag_and_keep!(context, result)
|
33
36
|
|
34
|
-
context.events
|
35
|
-
|
36
|
-
|
37
|
-
span: context.span,
|
38
|
-
multiplex: gateway_multiplex,
|
39
|
-
actions: result.actions
|
40
|
-
}
|
37
|
+
context.events.push(
|
38
|
+
AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
|
39
|
+
)
|
41
40
|
|
42
|
-
|
41
|
+
AppSec::ActionsHandler.handle(result.actions)
|
43
42
|
end
|
44
43
|
end
|
45
44
|
|