datadog 2.8.0 → 2.9.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 +36 -1
- data/ext/datadog_profiling_native_extension/clock_id.h +2 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +64 -54
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +1 -1
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +16 -16
- data/ext/datadog_profiling_native_extension/collectors_stack.c +7 -7
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +219 -122
- data/ext/datadog_profiling_native_extension/heap_recorder.h +1 -1
- data/ext/datadog_profiling_native_extension/http_transport.c +4 -4
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +3 -0
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +3 -1
- data/ext/datadog_profiling_native_extension/profiling.c +10 -8
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +8 -8
- data/ext/datadog_profiling_native_extension/stack_recorder.c +54 -54
- data/ext/datadog_profiling_native_extension/stack_recorder.h +1 -1
- data/ext/datadog_profiling_native_extension/time_helpers.h +1 -1
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +47 -0
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +31 -0
- data/ext/libdatadog_api/crashtracker.c +3 -0
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +355 -157
- data/lib/datadog/appsec/assets/waf_rules/strict.json +62 -32
- data/lib/datadog/appsec/context.rb +54 -0
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +7 -7
- data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +6 -6
- data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +4 -4
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +19 -28
- data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +5 -5
- data/lib/datadog/appsec/contrib/rack/gateway/response.rb +3 -3
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +64 -96
- data/lib/datadog/appsec/contrib/rack/reactive/request.rb +10 -10
- data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +5 -5
- data/lib/datadog/appsec/contrib/rack/reactive/response.rb +6 -6
- data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +10 -11
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +43 -49
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +21 -32
- data/lib/datadog/appsec/contrib/rails/patcher.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/reactive/action.rb +6 -6
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +41 -63
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +2 -2
- data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +5 -5
- data/lib/datadog/appsec/event.rb +6 -6
- data/lib/datadog/appsec/ext.rb +3 -1
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +22 -32
- data/lib/datadog/appsec/monitor/reactive/set_user.rb +5 -5
- data/lib/datadog/appsec/processor/rule_loader.rb +0 -3
- data/lib/datadog/appsec.rb +3 -3
- data/lib/datadog/auto_instrument.rb +3 -0
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +39 -11
- data/lib/datadog/core/configuration/components.rb +4 -2
- data/lib/datadog/core/configuration.rb +1 -1
- data/lib/datadog/{tracing → core}/contrib/rails/utils.rb +1 -3
- data/lib/datadog/core/crashtracking/component.rb +1 -3
- data/lib/datadog/core/telemetry/event.rb +87 -3
- data/lib/datadog/core/telemetry/logging.rb +2 -2
- data/lib/datadog/core/telemetry/metric.rb +22 -0
- data/lib/datadog/core/telemetry/worker.rb +33 -0
- data/lib/datadog/di/base.rb +115 -0
- data/lib/datadog/di/code_tracker.rb +7 -4
- data/lib/datadog/di/component.rb +17 -11
- data/lib/datadog/di/configuration/settings.rb +11 -1
- data/lib/datadog/di/contrib/railtie.rb +15 -0
- data/lib/datadog/di/contrib.rb +26 -0
- data/lib/datadog/di/error.rb +5 -0
- data/lib/datadog/di/instrumenter.rb +39 -18
- data/lib/datadog/di/{init.rb → preload.rb} +2 -4
- data/lib/datadog/di/probe_manager.rb +4 -4
- data/lib/datadog/di/probe_notification_builder.rb +16 -2
- data/lib/datadog/di/probe_notifier_worker.rb +5 -6
- data/lib/datadog/di/remote.rb +4 -4
- data/lib/datadog/di/transport.rb +2 -4
- data/lib/datadog/di.rb +5 -108
- data/lib/datadog/kit/appsec/events.rb +3 -3
- data/lib/datadog/kit/identity.rb +4 -4
- data/lib/datadog/profiling/component.rb +55 -53
- data/lib/datadog/profiling/http_transport.rb +1 -26
- data/lib/datadog/tracing/contrib/action_cable/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/action_mailer/integration.rb +6 -2
- data/lib/datadog/tracing/contrib/action_pack/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/action_view/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/active_job/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/active_record/integration.rb +6 -2
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +3 -1
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +3 -1
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +10 -0
- data/lib/datadog/tracing/contrib/active_support/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/auto_instrument.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/httprb/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/kafka/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/mongodb/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/opensearch/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/presto/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/rack/integration.rb +2 -2
- data/lib/datadog/tracing/contrib/rails/framework.rb +2 -2
- data/lib/datadog/tracing/contrib/rails/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/rest_client/integration.rb +3 -0
- data/lib/datadog/tracing/span.rb +12 -4
- data/lib/datadog/tracing/span_event.rb +123 -3
- data/lib/datadog/tracing/span_operation.rb +6 -0
- data/lib/datadog/tracing/transport/serializable_trace.rb +24 -6
- data/lib/datadog/version.rb +1 -1
- metadata +19 -10
- data/lib/datadog/appsec/reactive/operation.rb +0 -68
- data/lib/datadog/appsec/scope.rb +0 -58
- data/lib/datadog/core/crashtracking/agent_base_url.rb +0 -21
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../../../instrumentation/gateway'
|
4
|
-
require_relative '../../../reactive/
|
4
|
+
require_relative '../../../reactive/engine'
|
5
5
|
require_relative '../reactive/request'
|
6
6
|
require_relative '../reactive/request_body'
|
7
7
|
require_relative '../reactive/response'
|
@@ -25,126 +25,94 @@ module Datadog
|
|
25
25
|
|
26
26
|
def watch_request(gateway = Instrumentation.gateway)
|
27
27
|
gateway.watch('rack.request', :appsec) do |stack, gateway_request|
|
28
|
-
block = false
|
29
28
|
event = nil
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
end
|
29
|
+
context = gateway_request.env[Datadog::AppSec::Ext::CONTEXT_KEY]
|
30
|
+
engine = AppSec::Reactive::Engine.new
|
31
|
+
|
32
|
+
Rack::Reactive::Request.subscribe(engine, context) do |result|
|
33
|
+
if result.status == :match
|
34
|
+
# TODO: should this hash be an Event instance instead?
|
35
|
+
event = {
|
36
|
+
waf_result: result,
|
37
|
+
trace: context.trace,
|
38
|
+
span: context.span,
|
39
|
+
request: gateway_request,
|
40
|
+
actions: result.actions
|
41
|
+
}
|
42
|
+
|
43
|
+
# We want to keep the trace in case of security event
|
44
|
+
context.trace.keep! if context.trace
|
45
|
+
Datadog::AppSec::Event.tag_and_keep!(context, result)
|
46
|
+
context.waf_runner.events << event
|
49
47
|
end
|
50
|
-
|
51
|
-
block = Rack::Reactive::Request.publish(op, gateway_request)
|
52
48
|
end
|
53
49
|
|
54
|
-
|
55
|
-
|
56
|
-
ret, res = stack.call(gateway_request.request)
|
57
|
-
|
58
|
-
if event
|
59
|
-
res ||= []
|
60
|
-
res << [:monitor, event]
|
61
|
-
end
|
50
|
+
block = Rack::Reactive::Request.publish(engine, gateway_request)
|
51
|
+
throw(Datadog::AppSec::Ext::INTERRUPT, event[:actions]) if block
|
62
52
|
|
63
|
-
|
53
|
+
stack.call(gateway_request.request)
|
64
54
|
end
|
65
55
|
end
|
66
56
|
|
67
57
|
def watch_response(gateway = Instrumentation.gateway)
|
68
58
|
gateway.watch('rack.response', :appsec) do |stack, gateway_response|
|
69
|
-
block = false
|
70
|
-
|
71
59
|
event = nil
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
end
|
60
|
+
context = gateway_response.context
|
61
|
+
engine = AppSec::Reactive::Engine.new
|
62
|
+
|
63
|
+
Rack::Reactive::Response.subscribe(engine, context) do |result|
|
64
|
+
if result.status == :match
|
65
|
+
# TODO: should this hash be an Event instance instead?
|
66
|
+
event = {
|
67
|
+
waf_result: result,
|
68
|
+
trace: context.trace,
|
69
|
+
span: context.span,
|
70
|
+
response: gateway_response,
|
71
|
+
actions: result.actions
|
72
|
+
}
|
73
|
+
|
74
|
+
# We want to keep the trace in case of security event
|
75
|
+
context.trace.keep! if context.trace
|
76
|
+
Datadog::AppSec::Event.tag_and_keep!(context, result)
|
77
|
+
context.waf_runner.events << event
|
91
78
|
end
|
92
|
-
|
93
|
-
block = Rack::Reactive::Response.publish(op, gateway_response)
|
94
79
|
end
|
95
80
|
|
96
|
-
|
97
|
-
|
98
|
-
ret, res = stack.call(gateway_response.response)
|
81
|
+
block = Rack::Reactive::Response.publish(engine, gateway_response)
|
82
|
+
throw(Datadog::AppSec::Ext::INTERRUPT, event[:actions]) if block
|
99
83
|
|
100
|
-
|
101
|
-
res ||= []
|
102
|
-
res << [:monitor, event]
|
103
|
-
end
|
104
|
-
|
105
|
-
[ret, res]
|
84
|
+
stack.call(gateway_response.response)
|
106
85
|
end
|
107
86
|
end
|
108
87
|
|
109
88
|
def watch_request_body(gateway = Instrumentation.gateway)
|
110
89
|
gateway.watch('rack.request.body', :appsec) do |stack, gateway_request|
|
111
|
-
block = false
|
112
|
-
|
113
90
|
event = nil
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
end
|
91
|
+
context = gateway_request.env[Datadog::AppSec::Ext::CONTEXT_KEY]
|
92
|
+
engine = AppSec::Reactive::Engine.new
|
93
|
+
|
94
|
+
Rack::Reactive::RequestBody.subscribe(engine, context) do |result|
|
95
|
+
if result.status == :match
|
96
|
+
# TODO: should this hash be an Event instance instead?
|
97
|
+
event = {
|
98
|
+
waf_result: result,
|
99
|
+
trace: context.trace,
|
100
|
+
span: context.span,
|
101
|
+
request: gateway_request,
|
102
|
+
actions: result.actions
|
103
|
+
}
|
104
|
+
|
105
|
+
# We want to keep the trace in case of security event
|
106
|
+
context.trace.keep! if context.trace
|
107
|
+
Datadog::AppSec::Event.tag_and_keep!(context, result)
|
108
|
+
context.waf_runner.events << event
|
133
109
|
end
|
134
|
-
|
135
|
-
block = Rack::Reactive::RequestBody.publish(op, gateway_request)
|
136
110
|
end
|
137
111
|
|
138
|
-
|
139
|
-
|
140
|
-
ret, res = stack.call(gateway_request.request)
|
141
|
-
|
142
|
-
if event
|
143
|
-
res ||= []
|
144
|
-
res << [:monitor, event]
|
145
|
-
end
|
112
|
+
block = Rack::Reactive::RequestBody.publish(engine, gateway_request)
|
113
|
+
throw(Datadog::AppSec::Ext::INTERRUPT, event[:actions]) if block
|
146
114
|
|
147
|
-
|
115
|
+
stack.call(gateway_request.request)
|
148
116
|
end
|
149
117
|
end
|
150
118
|
end
|
@@ -17,21 +17,21 @@ module Datadog
|
|
17
17
|
].freeze
|
18
18
|
private_constant :ADDRESSES
|
19
19
|
|
20
|
-
def self.publish(
|
20
|
+
def self.publish(engine, gateway_request)
|
21
21
|
catch(:block) do
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
22
|
+
engine.publish('request.query', gateway_request.query)
|
23
|
+
engine.publish('request.headers', gateway_request.headers)
|
24
|
+
engine.publish('request.uri.raw', gateway_request.fullpath)
|
25
|
+
engine.publish('request.cookies', gateway_request.cookies)
|
26
|
+
engine.publish('request.client_ip', gateway_request.client_ip)
|
27
|
+
engine.publish('server.request.method', gateway_request.method)
|
28
28
|
|
29
29
|
nil
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
def self.subscribe(
|
34
|
-
|
33
|
+
def self.subscribe(engine, context)
|
34
|
+
engine.subscribe(*ADDRESSES) do |*values|
|
35
35
|
Datadog.logger.debug { "reacted to #{ADDRESSES.inspect}: #{values.inspect}" }
|
36
36
|
|
37
37
|
headers = values[0]
|
@@ -53,7 +53,7 @@ module Datadog
|
|
53
53
|
}
|
54
54
|
|
55
55
|
waf_timeout = Datadog.configuration.appsec.waf_timeout
|
56
|
-
result =
|
56
|
+
result = context.run_waf(persistent_data, {}, waf_timeout)
|
57
57
|
|
58
58
|
next if result.status != :match
|
59
59
|
|
@@ -12,17 +12,17 @@ module Datadog
|
|
12
12
|
].freeze
|
13
13
|
private_constant :ADDRESSES
|
14
14
|
|
15
|
-
def self.publish(
|
15
|
+
def self.publish(engine, gateway_request)
|
16
16
|
catch(:block) do
|
17
17
|
# params have been parsed from the request body
|
18
|
-
|
18
|
+
engine.publish('request.body', gateway_request.form_hash)
|
19
19
|
|
20
20
|
nil
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
def self.subscribe(
|
25
|
-
|
24
|
+
def self.subscribe(engine, context)
|
25
|
+
engine.subscribe(*ADDRESSES) do |*values|
|
26
26
|
Datadog.logger.debug { "reacted to #{ADDRESSES.inspect}: #{values.inspect}" }
|
27
27
|
body = values[0]
|
28
28
|
|
@@ -31,7 +31,7 @@ module Datadog
|
|
31
31
|
}
|
32
32
|
|
33
33
|
waf_timeout = Datadog.configuration.appsec.waf_timeout
|
34
|
-
result =
|
34
|
+
result = context.run_waf(persistent_data, {}, waf_timeout)
|
35
35
|
|
36
36
|
next if result.status != :match
|
37
37
|
|
@@ -13,17 +13,17 @@ module Datadog
|
|
13
13
|
].freeze
|
14
14
|
private_constant :ADDRESSES
|
15
15
|
|
16
|
-
def self.publish(
|
16
|
+
def self.publish(engine, gateway_response)
|
17
17
|
catch(:block) do
|
18
|
-
|
19
|
-
|
18
|
+
engine.publish('response.status', gateway_response.status)
|
19
|
+
engine.publish('response.headers', gateway_response.headers)
|
20
20
|
|
21
21
|
nil
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
def self.subscribe(
|
26
|
-
|
25
|
+
def self.subscribe(engine, context)
|
26
|
+
engine.subscribe(*ADDRESSES) do |*values|
|
27
27
|
Datadog.logger.debug { "reacted to #{ADDRESSES.inspect}: #{values.inspect}" }
|
28
28
|
|
29
29
|
response_status = values[0]
|
@@ -37,7 +37,7 @@ module Datadog
|
|
37
37
|
}
|
38
38
|
|
39
39
|
waf_timeout = Datadog.configuration.appsec.waf_timeout
|
40
|
-
result =
|
40
|
+
result = context.run_waf(persistent_data, {}, waf_timeout)
|
41
41
|
|
42
42
|
next if result.status != :match
|
43
43
|
|
@@ -17,25 +17,24 @@ module Datadog
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def call(env)
|
20
|
-
context = env[Datadog::AppSec::Ext::
|
20
|
+
context = env[Datadog::AppSec::Ext::CONTEXT_KEY]
|
21
21
|
|
22
22
|
return @app.call(env) unless context
|
23
23
|
|
24
24
|
# TODO: handle exceptions, except for @app.call
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
Gateway::Request.new(env)
|
29
|
-
|
30
|
-
|
31
|
-
end
|
26
|
+
http_response = nil
|
27
|
+
block_actions = catch(::Datadog::AppSec::Ext::INTERRUPT) do
|
28
|
+
http_response, = Instrumentation.gateway.push('rack.request.body', Gateway::Request.new(env)) do
|
29
|
+
@app.call(env)
|
30
|
+
end
|
32
31
|
|
33
|
-
|
34
|
-
blocked_event = request_response.find { |action, _event| action == :block }
|
35
|
-
request_return = AppSec::Response.negotiate(env, blocked_event.last[:actions]).to_rack if blocked_event
|
32
|
+
nil
|
36
33
|
end
|
37
34
|
|
38
|
-
|
35
|
+
return AppSec::Response.negotiate(env, block_actions).to_rack if block_actions
|
36
|
+
|
37
|
+
http_response
|
39
38
|
end
|
40
39
|
end
|
41
40
|
end
|
@@ -36,7 +36,7 @@ module Datadog
|
|
36
36
|
@rack_headers = {}
|
37
37
|
end
|
38
38
|
|
39
|
-
# rubocop:disable Metrics/AbcSize,Metrics/
|
39
|
+
# rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
40
40
|
def call(env)
|
41
41
|
return @app.call(env) unless Datadog::AppSec.enabled?
|
42
42
|
|
@@ -45,19 +45,22 @@ module Datadog
|
|
45
45
|
|
46
46
|
processor = nil
|
47
47
|
ready = false
|
48
|
-
|
48
|
+
ctx = nil
|
49
49
|
|
50
50
|
# For a given request, keep using the first Rack stack scope for
|
51
51
|
# nested apps. Don't set `context` local variable so that on popping
|
52
52
|
# out of this nested stack we don't finalize the parent's context
|
53
|
-
return @app.call(env) if
|
53
|
+
return @app.call(env) if active_context(env)
|
54
54
|
|
55
55
|
Datadog::AppSec.reconfigure_lock do
|
56
56
|
processor = Datadog::AppSec.processor
|
57
57
|
|
58
58
|
if !processor.nil? && processor.ready?
|
59
|
-
|
60
|
-
|
59
|
+
ctx = Datadog::AppSec::Context.activate(
|
60
|
+
Datadog::AppSec::Context.new(active_trace, active_span, processor)
|
61
|
+
)
|
62
|
+
|
63
|
+
env[Datadog::AppSec::Ext::CONTEXT_KEY] = ctx
|
61
64
|
ready = true
|
62
65
|
end
|
63
66
|
end
|
@@ -66,66 +69,57 @@ module Datadog
|
|
66
69
|
|
67
70
|
return @app.call(env) unless ready
|
68
71
|
|
69
|
-
|
72
|
+
add_appsec_tags(processor, ctx)
|
73
|
+
add_request_tags(ctx, env)
|
70
74
|
|
71
|
-
|
72
|
-
|
75
|
+
http_response = nil
|
76
|
+
gateway_request = Gateway::Request.new(env)
|
77
|
+
gateway_response = nil
|
73
78
|
|
74
|
-
|
75
|
-
Instrumentation.gateway.push('rack.request', gateway_request) do
|
79
|
+
block_actions = catch(::Datadog::AppSec::Ext::INTERRUPT) do
|
80
|
+
http_response, = Instrumentation.gateway.push('rack.request', gateway_request) do
|
76
81
|
@app.call(env)
|
77
82
|
end
|
78
|
-
end
|
79
83
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
end
|
84
|
+
gateway_response = Gateway::Response.new(
|
85
|
+
http_response[2], http_response[0], http_response[1], context: ctx
|
86
|
+
)
|
84
87
|
|
85
|
-
|
86
|
-
request_return[2],
|
87
|
-
request_return[0],
|
88
|
-
request_return[1],
|
89
|
-
scope: scope,
|
90
|
-
)
|
88
|
+
Instrumentation.gateway.push('rack.response', gateway_response)
|
91
89
|
|
92
|
-
|
90
|
+
nil
|
91
|
+
end
|
93
92
|
|
94
|
-
|
93
|
+
http_response = AppSec::Response.negotiate(env, block_actions).to_rack if block_actions
|
95
94
|
|
96
|
-
if result
|
97
|
-
|
98
|
-
trace:
|
99
|
-
span:
|
95
|
+
if (result = ctx.waf_runner.extract_schema)
|
96
|
+
ctx.waf_runner.events << {
|
97
|
+
trace: ctx.trace,
|
98
|
+
span: ctx.span,
|
100
99
|
waf_result: result,
|
101
100
|
}
|
102
101
|
end
|
103
102
|
|
104
|
-
|
103
|
+
ctx.waf_runner.events.each do |e|
|
105
104
|
e[:response] ||= gateway_response
|
106
105
|
e[:request] ||= gateway_request
|
107
106
|
end
|
108
107
|
|
109
|
-
AppSec::Event.record(
|
110
|
-
|
111
|
-
if response_response
|
112
|
-
blocked_event = response_response.find { |action, _options| action == :block }
|
113
|
-
request_return = AppSec::Response.negotiate(env, blocked_event.last[:actions]).to_rack if blocked_event
|
114
|
-
end
|
108
|
+
AppSec::Event.record(ctx.span, *ctx.waf_runner.events)
|
115
109
|
|
116
|
-
|
110
|
+
http_response
|
117
111
|
ensure
|
118
|
-
if
|
119
|
-
add_waf_runtime_tags(
|
120
|
-
Datadog::AppSec::
|
112
|
+
if ctx
|
113
|
+
add_waf_runtime_tags(ctx)
|
114
|
+
Datadog::AppSec::Context.deactivate
|
121
115
|
end
|
122
116
|
end
|
123
|
-
# rubocop:enable Metrics/AbcSize,Metrics/
|
117
|
+
# rubocop:enable Metrics/AbcSize,Metrics/MethodLength
|
124
118
|
|
125
119
|
private
|
126
120
|
|
127
|
-
def
|
128
|
-
env[Datadog::AppSec::Ext::
|
121
|
+
def active_context(env)
|
122
|
+
env[Datadog::AppSec::Ext::CONTEXT_KEY]
|
129
123
|
end
|
130
124
|
|
131
125
|
def active_trace
|
@@ -144,9 +138,9 @@ module Datadog
|
|
144
138
|
Datadog::Tracing.active_span
|
145
139
|
end
|
146
140
|
|
147
|
-
def add_appsec_tags(processor,
|
148
|
-
span =
|
149
|
-
trace =
|
141
|
+
def add_appsec_tags(processor, context)
|
142
|
+
span = context.span
|
143
|
+
trace = context.trace
|
150
144
|
|
151
145
|
return unless trace && span
|
152
146
|
|
@@ -181,8 +175,8 @@ module Datadog
|
|
181
175
|
end
|
182
176
|
end
|
183
177
|
|
184
|
-
def add_request_tags(
|
185
|
-
span =
|
178
|
+
def add_request_tags(context, env)
|
179
|
+
span = context.span
|
186
180
|
|
187
181
|
return unless span
|
188
182
|
|
@@ -204,9 +198,9 @@ module Datadog
|
|
204
198
|
end
|
205
199
|
end
|
206
200
|
|
207
|
-
def add_waf_runtime_tags(
|
208
|
-
span =
|
209
|
-
context =
|
201
|
+
def add_waf_runtime_tags(context)
|
202
|
+
span = context.span
|
203
|
+
context = context.waf_runner
|
210
204
|
|
211
205
|
return unless span && context
|
212
206
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../../../instrumentation/gateway'
|
4
|
-
require_relative '../../../reactive/
|
4
|
+
require_relative '../../../reactive/engine'
|
5
5
|
require_relative '../reactive/action'
|
6
6
|
require_relative '../../../event'
|
7
7
|
|
@@ -21,43 +21,32 @@ module Datadog
|
|
21
21
|
|
22
22
|
def watch_request_action(gateway = Instrumentation.gateway)
|
23
23
|
gateway.watch('rails.request.action', :appsec) do |stack, gateway_request|
|
24
|
-
block = false
|
25
|
-
|
26
24
|
event = nil
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
25
|
+
context = gateway_request.env[Datadog::AppSec::Ext::CONTEXT_KEY]
|
26
|
+
engine = AppSec::Reactive::Engine.new
|
27
|
+
|
28
|
+
Rails::Reactive::Action.subscribe(engine, context) do |result|
|
29
|
+
if result.status == :match
|
30
|
+
# TODO: should this hash be an Event instance instead?
|
31
|
+
event = {
|
32
|
+
waf_result: result,
|
33
|
+
trace: context.trace,
|
34
|
+
span: context.span,
|
35
|
+
request: gateway_request,
|
36
|
+
actions: result.actions
|
37
|
+
}
|
38
|
+
|
39
|
+
# We want to keep the trace in case of security event
|
40
|
+
context.trace.keep! if context.trace
|
41
|
+
Datadog::AppSec::Event.tag_and_keep!(context, result)
|
42
|
+
context.waf_runner.events << event
|
46
43
|
end
|
47
|
-
|
48
|
-
block = Rails::Reactive::Action.publish(op, gateway_request)
|
49
44
|
end
|
50
45
|
|
46
|
+
block = Rails::Reactive::Action.publish(engine, gateway_request)
|
51
47
|
next [nil, [[:block, event]]] if block
|
52
48
|
|
53
|
-
|
54
|
-
|
55
|
-
if event
|
56
|
-
res ||= []
|
57
|
-
res << [:monitor, event]
|
58
|
-
end
|
59
|
-
|
60
|
-
[ret, res]
|
49
|
+
stack.call(gateway_request.request)
|
61
50
|
end
|
62
51
|
end
|
63
52
|
end
|
@@ -15,18 +15,18 @@ module Datadog
|
|
15
15
|
].freeze
|
16
16
|
private_constant :ADDRESSES
|
17
17
|
|
18
|
-
def self.publish(
|
18
|
+
def self.publish(engine, gateway_request)
|
19
19
|
catch(:block) do
|
20
20
|
# params have been parsed from the request body
|
21
|
-
|
22
|
-
|
21
|
+
engine.publish('rails.request.body', gateway_request.parsed_body)
|
22
|
+
engine.publish('rails.request.route_params', gateway_request.route_params)
|
23
23
|
|
24
24
|
nil
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
def self.subscribe(
|
29
|
-
|
28
|
+
def self.subscribe(engine, context)
|
29
|
+
engine.subscribe(*ADDRESSES) do |*values|
|
30
30
|
Datadog.logger.debug { "reacted to #{ADDRESSES.inspect}: #{values.inspect}" }
|
31
31
|
body = values[0]
|
32
32
|
path_params = values[1]
|
@@ -37,7 +37,7 @@ module Datadog
|
|
37
37
|
}
|
38
38
|
|
39
39
|
waf_timeout = Datadog.configuration.appsec.waf_timeout
|
40
|
-
result =
|
40
|
+
result = context.run_waf(persistent_data, {}, waf_timeout)
|
41
41
|
|
42
42
|
next if result.status != :match
|
43
43
|
|