datadog 2.7.1 → 2.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +69 -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 +259 -132
- data/ext/datadog_profiling_native_extension/extconf.rb +0 -8
- data/ext/datadog_profiling_native_extension/heap_recorder.c +11 -89
- 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 +4 -1
- 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 -88
- 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/ext/libdatadog_extconf_helpers.rb +1 -1
- 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/component.rb +1 -8
- data/lib/datadog/appsec/context.rb +54 -0
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +73 -0
- data/lib/datadog/appsec/contrib/active_record/integration.rb +41 -0
- data/lib/datadog/appsec/contrib/active_record/patcher.rb +53 -0
- 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/context.rb +2 -2
- data/lib/datadog/appsec/processor/rule_loader.rb +0 -3
- data/lib/datadog/appsec/remote.rb +1 -3
- data/lib/datadog/appsec/response.rb +7 -11
- data/lib/datadog/appsec.rb +6 -5
- 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 +20 -2
- data/lib/datadog/core/configuration/settings.rb +10 -0
- data/lib/datadog/core/configuration.rb +10 -2
- data/lib/datadog/{tracing → core}/contrib/rails/utils.rb +1 -3
- data/lib/datadog/core/crashtracking/component.rb +1 -3
- data/lib/datadog/core/remote/client/capabilities.rb +6 -0
- data/lib/datadog/core/remote/client.rb +65 -59
- data/lib/datadog/core/telemetry/component.rb +9 -3
- data/lib/datadog/core/telemetry/event.rb +87 -3
- data/lib/datadog/core/telemetry/ext.rb +1 -0
- 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 +11 -7
- data/lib/datadog/di/component.rb +21 -11
- data/lib/datadog/di/configuration/settings.rb +11 -1
- data/lib/datadog/di/contrib/active_record.rb +1 -0
- 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 +111 -20
- data/lib/datadog/di/preload.rb +18 -0
- data/lib/datadog/di/probe.rb +11 -1
- data/lib/datadog/di/probe_builder.rb +1 -0
- data/lib/datadog/di/probe_manager.rb +8 -5
- data/lib/datadog/di/probe_notification_builder.rb +27 -7
- data/lib/datadog/di/probe_notifier_worker.rb +5 -6
- data/lib/datadog/di/remote.rb +124 -0
- data/lib/datadog/di/serializer.rb +14 -7
- data/lib/datadog/di/transport.rb +3 -5
- data/lib/datadog/di/utils.rb +7 -0
- data/lib/datadog/di.rb +23 -62
- data/lib/datadog/kit/appsec/events.rb +3 -3
- data/lib/datadog/kit/identity.rb +4 -4
- data/lib/datadog/profiling/component.rb +59 -69
- data/lib/datadog/profiling/http_transport.rb +1 -26
- data/lib/datadog/tracing/configuration/settings.rb +4 -8
- 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/cache/redis.rb +16 -4
- 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/elasticsearch/configuration/settings.rb +4 -0
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
- 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 +2 -2
- data/lib/datadog.rb +3 -0
- metadata +30 -17
- data/lib/datadog/appsec/processor/actions.rb +0 -49
- 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
@@ -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
|
|
@@ -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 '../../rack/reactive/request_body'
|
6
6
|
require_relative '../reactive/routed'
|
7
7
|
require_relative '../../../event'
|
@@ -23,85 +23,63 @@ module Datadog
|
|
23
23
|
|
24
24
|
def watch_request_dispatch(gateway = Instrumentation.gateway)
|
25
25
|
gateway.watch('sinatra.request.dispatch', :appsec) do |stack, gateway_request|
|
26
|
-
block = false
|
27
|
-
|
28
26
|
event = nil
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
27
|
+
context = gateway_request.env[Datadog::AppSec::Ext::CONTEXT_KEY]
|
28
|
+
engine = AppSec::Reactive::Engine.new
|
29
|
+
|
30
|
+
Rack::Reactive::RequestBody.subscribe(engine, context) do |result|
|
31
|
+
if result.status == :match
|
32
|
+
# TODO: should this hash be an Event instance instead?
|
33
|
+
event = {
|
34
|
+
waf_result: result,
|
35
|
+
trace: context.trace,
|
36
|
+
span: context.span,
|
37
|
+
request: gateway_request,
|
38
|
+
actions: result.actions
|
39
|
+
}
|
40
|
+
|
41
|
+
# We want to keep the trace in case of security event
|
42
|
+
context.trace.keep! if context.trace
|
43
|
+
Datadog::AppSec::Event.tag_and_keep!(context, result)
|
44
|
+
context.waf_runner.events << event
|
48
45
|
end
|
49
|
-
|
50
|
-
block = Rack::Reactive::RequestBody.publish(op, gateway_request)
|
51
46
|
end
|
52
47
|
|
48
|
+
block = Rack::Reactive::RequestBody.publish(engine, gateway_request)
|
53
49
|
next [nil, [[:block, event]]] if block
|
54
50
|
|
55
|
-
|
56
|
-
|
57
|
-
if event
|
58
|
-
res ||= []
|
59
|
-
res << [:monitor, event]
|
60
|
-
end
|
61
|
-
|
62
|
-
[ret, res]
|
51
|
+
stack.call(gateway_request.request)
|
63
52
|
end
|
64
53
|
end
|
65
54
|
|
66
55
|
def watch_request_routed(gateway = Instrumentation.gateway)
|
67
56
|
gateway.watch('sinatra.request.routed', :appsec) do |stack, (gateway_request, gateway_route_params)|
|
68
|
-
block = false
|
69
|
-
|
70
57
|
event = nil
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
end
|
58
|
+
context = gateway_request.env[Datadog::AppSec::Ext::CONTEXT_KEY]
|
59
|
+
engine = AppSec::Reactive::Engine.new
|
60
|
+
|
61
|
+
Sinatra::Reactive::Routed.subscribe(engine, context) do |result|
|
62
|
+
if result.status == :match
|
63
|
+
# TODO: should this hash be an Event instance instead?
|
64
|
+
event = {
|
65
|
+
waf_result: result,
|
66
|
+
trace: context.trace,
|
67
|
+
span: context.span,
|
68
|
+
request: gateway_request,
|
69
|
+
actions: result.actions
|
70
|
+
}
|
71
|
+
|
72
|
+
# We want to keep the trace in case of security event
|
73
|
+
context.trace.keep! if context.trace
|
74
|
+
Datadog::AppSec::Event.tag_and_keep!(context, result)
|
75
|
+
context.waf_runner.events << event
|
90
76
|
end
|
91
|
-
|
92
|
-
block = Sinatra::Reactive::Routed.publish(op, [gateway_request, gateway_route_params])
|
93
77
|
end
|
94
78
|
|
79
|
+
block = Sinatra::Reactive::Routed.publish(engine, [gateway_request, gateway_route_params])
|
95
80
|
next [nil, [[:block, event]]] if block
|
96
81
|
|
97
|
-
|
98
|
-
|
99
|
-
if event
|
100
|
-
res ||= []
|
101
|
-
res << [:monitor, event]
|
102
|
-
end
|
103
|
-
|
104
|
-
[ret, res]
|
82
|
+
stack.call(gateway_request.request)
|
105
83
|
end
|
106
84
|
end
|
107
85
|
end
|
@@ -54,7 +54,7 @@ module Datadog
|
|
54
54
|
def dispatch!
|
55
55
|
env = @request.env
|
56
56
|
|
57
|
-
context = env[Datadog::AppSec::Ext::
|
57
|
+
context = env[Datadog::AppSec::Ext::CONTEXT_KEY]
|
58
58
|
|
59
59
|
return super unless context
|
60
60
|
|
@@ -86,7 +86,7 @@ module Datadog
|
|
86
86
|
def process_route(*)
|
87
87
|
env = @request.env
|
88
88
|
|
89
|
-
context = env[Datadog::AppSec::Ext::
|
89
|
+
context = env[Datadog::AppSec::Ext::CONTEXT_KEY]
|
90
90
|
|
91
91
|
return super unless context
|
92
92
|
|
@@ -12,18 +12,18 @@ module Datadog
|
|
12
12
|
].freeze
|
13
13
|
private_constant :ADDRESSES
|
14
14
|
|
15
|
-
def self.publish(
|
15
|
+
def self.publish(engine, data)
|
16
16
|
_request, route_params = data
|
17
17
|
|
18
18
|
catch(:block) do
|
19
|
-
|
19
|
+
engine.publish('sinatra.request.route_params', route_params.params)
|
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
|
path_params = values[0]
|
29
29
|
|
@@ -32,7 +32,7 @@ module Datadog
|
|
32
32
|
}
|
33
33
|
|
34
34
|
waf_timeout = Datadog.configuration.appsec.waf_timeout
|
35
|
-
result =
|
35
|
+
result = context.run_waf(persistent_data, {}, waf_timeout)
|
36
36
|
|
37
37
|
next if result.status != :match
|
38
38
|
|
data/lib/datadog/appsec/event.rb
CHANGED
@@ -137,16 +137,16 @@ module Datadog
|
|
137
137
|
end
|
138
138
|
# rubocop:enable Metrics/MethodLength
|
139
139
|
|
140
|
-
def tag_and_keep!(
|
140
|
+
def tag_and_keep!(context, waf_result)
|
141
141
|
# We want to keep the trace in case of security event
|
142
|
-
|
142
|
+
context.trace.keep! if context.trace
|
143
143
|
|
144
|
-
if
|
145
|
-
|
146
|
-
|
144
|
+
if context.span
|
145
|
+
context.span.set_tag('appsec.blocked', 'true') if waf_result.actions.key?('block_request')
|
146
|
+
context.span.set_tag('appsec.event', 'true')
|
147
147
|
end
|
148
148
|
|
149
|
-
add_distributed_tags(
|
149
|
+
add_distributed_tags(context.trace)
|
150
150
|
end
|
151
151
|
|
152
152
|
private
|
data/lib/datadog/appsec/ext.rb
CHANGED
@@ -3,8 +3,10 @@
|
|
3
3
|
module Datadog
|
4
4
|
module AppSec
|
5
5
|
module Ext
|
6
|
+
RASP_SQLI = :sql_injection
|
6
7
|
INTERRUPT = :datadog_appsec_interrupt
|
7
|
-
|
8
|
+
CONTEXT_KEY = 'datadog.appsec.context'
|
9
|
+
ACTIVE_CONTEXT_KEY = :datadog_appsec_active_context
|
8
10
|
|
9
11
|
TAG_APPSEC_ENABLED = '_dd.appsec.enabled'
|
10
12
|
TAG_APM_ENABLED = '_dd.apm.enabled'
|
@@ -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/set_user'
|
6
6
|
|
7
7
|
module Datadog
|
@@ -19,42 +19,32 @@ module Datadog
|
|
19
19
|
|
20
20
|
def watch_user_id(gateway = Instrumentation.gateway)
|
21
21
|
gateway.watch('identity.set_user', :appsec) do |stack, user|
|
22
|
-
block = false
|
23
22
|
event = nil
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
23
|
+
context = Datadog::AppSec.active_context
|
24
|
+
engine = AppSec::Reactive::Engine.new
|
25
|
+
|
26
|
+
Monitor::Reactive::SetUser.subscribe(engine, context) do |result|
|
27
|
+
if result.status == :match
|
28
|
+
# TODO: should this hash be an Event instance instead?
|
29
|
+
event = {
|
30
|
+
waf_result: result,
|
31
|
+
trace: context.trace,
|
32
|
+
span: context.span,
|
33
|
+
user: user,
|
34
|
+
actions: result.actions
|
35
|
+
}
|
36
|
+
|
37
|
+
# We want to keep the trace in case of security event
|
38
|
+
context.trace.keep! if context.trace
|
39
|
+
Datadog::AppSec::Event.tag_and_keep!(context, result)
|
40
|
+
context.waf_runner.events << event
|
43
41
|
end
|
44
|
-
|
45
|
-
block = Monitor::Reactive::SetUser.publish(op, user)
|
46
42
|
end
|
47
43
|
|
48
|
-
|
49
|
-
|
50
|
-
ret, res = stack.call(user)
|
51
|
-
|
52
|
-
if event
|
53
|
-
res ||= []
|
54
|
-
res << [:monitor, event]
|
55
|
-
end
|
44
|
+
block = Monitor::Reactive::SetUser.publish(engine, user)
|
45
|
+
throw(Datadog::AppSec::Ext::INTERRUPT, event[:actions]) if block
|
56
46
|
|
57
|
-
|
47
|
+
stack.call(user)
|
58
48
|
end
|
59
49
|
end
|
60
50
|
end
|
@@ -11,16 +11,16 @@ module Datadog
|
|
11
11
|
].freeze
|
12
12
|
private_constant :ADDRESSES
|
13
13
|
|
14
|
-
def self.publish(
|
14
|
+
def self.publish(engine, user)
|
15
15
|
catch(:block) do
|
16
|
-
|
16
|
+
engine.publish('usr.id', user.id)
|
17
17
|
|
18
18
|
nil
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
def self.subscribe(
|
23
|
-
|
22
|
+
def self.subscribe(engine, context)
|
23
|
+
engine.subscribe(*ADDRESSES) do |*values|
|
24
24
|
Datadog.logger.debug { "reacted to #{ADDRESSES.inspect}: #{values.inspect}" }
|
25
25
|
|
26
26
|
user_id = values[0]
|
@@ -30,7 +30,7 @@ module Datadog
|
|
30
30
|
}
|
31
31
|
|
32
32
|
waf_timeout = Datadog.configuration.appsec.waf_timeout
|
33
|
-
result =
|
33
|
+
result = context.run_waf(persistent_data, {}, waf_timeout)
|
34
34
|
|
35
35
|
next if result.status != :match
|
36
36
|
|
@@ -19,7 +19,7 @@ module Datadog
|
|
19
19
|
@events = []
|
20
20
|
@run_mutex = Mutex.new
|
21
21
|
|
22
|
-
@libddwaf_debug_tag = "libddwaf:#{WAF::VERSION::STRING}"
|
22
|
+
@libddwaf_debug_tag = "libddwaf:#{WAF::VERSION::STRING} method:ddwaf_run"
|
23
23
|
end
|
24
24
|
|
25
25
|
def run(persistent_data, ephemeral_data, timeout = WAF::LibDDWAF::DDWAF_RUN_TIMEOUT)
|
@@ -79,7 +79,7 @@ module Datadog
|
|
79
79
|
@context.run(persistent_data, ephemeral_data, timeout)
|
80
80
|
rescue WAF::LibDDWAF::Error => e
|
81
81
|
Datadog.logger.debug { "#{@libddwaf_debug_tag} execution error: #{e} backtrace: #{e.backtrace&.first(3)}" }
|
82
|
-
@telemetry.report(e, description: 'libddwaf internal low-level error')
|
82
|
+
@telemetry.report(e, description: 'libddwaf-rb internal low-level error')
|
83
83
|
|
84
84
|
[:err_internal, WAF::Result.new(:err_internal, [], 0.0, false, [], [])]
|
85
85
|
end
|
@@ -67,7 +67,6 @@ module Datadog
|
|
67
67
|
data = []
|
68
68
|
overrides = []
|
69
69
|
exclusions = []
|
70
|
-
actions = []
|
71
70
|
|
72
71
|
repository.contents.each do |content|
|
73
72
|
parsed_content = parse_content(content)
|
@@ -81,7 +80,6 @@ module Datadog
|
|
81
80
|
overrides << parsed_content['rules_override'] if parsed_content['rules_override']
|
82
81
|
exclusions << parsed_content['exclusions'] if parsed_content['exclusions']
|
83
82
|
custom_rules << parsed_content['custom_rules'] if parsed_content['custom_rules']
|
84
|
-
actions.concat(parsed_content['actions']) if parsed_content['actions']
|
85
83
|
end
|
86
84
|
end
|
87
85
|
|
@@ -105,7 +103,7 @@ module Datadog
|
|
105
103
|
telemetry: telemetry
|
106
104
|
)
|
107
105
|
|
108
|
-
Datadog::AppSec.reconfigure(ruleset: ruleset,
|
106
|
+
Datadog::AppSec.reconfigure(ruleset: ruleset, telemetry: telemetry)
|
109
107
|
end
|
110
108
|
|
111
109
|
[receiver]
|
@@ -31,19 +31,16 @@ module Datadog
|
|
31
31
|
def negotiate(env, actions)
|
32
32
|
# @type var configured_response: Response?
|
33
33
|
configured_response = nil
|
34
|
-
actions.each do |
|
34
|
+
actions.each do |type, parameters|
|
35
35
|
# Need to use next to make steep happy :(
|
36
36
|
# I rather use break to stop the execution
|
37
37
|
next if configured_response
|
38
38
|
|
39
|
-
|
40
|
-
next unless action_configuration
|
41
|
-
|
42
|
-
configured_response = case action_configuration['type']
|
39
|
+
configured_response = case type
|
43
40
|
when 'block_request'
|
44
|
-
block_response(env,
|
41
|
+
block_response(env, parameters)
|
45
42
|
when 'redirect_request'
|
46
|
-
redirect_response(env,
|
43
|
+
redirect_response(env, parameters)
|
47
44
|
end
|
48
45
|
end
|
49
46
|
|
@@ -90,7 +87,7 @@ module Datadog
|
|
90
87
|
body << content(content_type)
|
91
88
|
|
92
89
|
Response.new(
|
93
|
-
status: options['status_code'] || 403,
|
90
|
+
status: options['status_code']&.to_i || 403,
|
94
91
|
headers: { 'Content-Type' => content_type },
|
95
92
|
body: body,
|
96
93
|
)
|
@@ -100,15 +97,14 @@ module Datadog
|
|
100
97
|
if options['location'] && !options['location'].empty?
|
101
98
|
content_type = content_type(env)
|
102
99
|
|
103
|
-
status = options['status_code'] >= 300 && options['status_code'] < 400 ? options['status_code'] : 303
|
104
|
-
|
105
100
|
headers = {
|
106
101
|
'Content-Type' => content_type,
|
107
102
|
'Location' => options['location']
|
108
103
|
}
|
109
104
|
|
105
|
+
status_code = options['status_code'].to_i
|
110
106
|
Response.new(
|
111
|
-
status:
|
107
|
+
status: (status_code >= 300 && status_code < 400 ? status_code : 303),
|
112
108
|
headers: headers,
|
113
109
|
body: [],
|
114
110
|
)
|
data/lib/datadog/appsec.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative 'appsec/configuration'
|
4
4
|
require_relative 'appsec/extensions'
|
5
|
-
require_relative 'appsec/
|
5
|
+
require_relative 'appsec/context'
|
6
6
|
require_relative 'appsec/ext'
|
7
7
|
require_relative 'appsec/utils'
|
8
8
|
|
@@ -14,8 +14,8 @@ module Datadog
|
|
14
14
|
Datadog.configuration.appsec.enabled
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
18
|
-
Datadog::AppSec::
|
17
|
+
def active_context
|
18
|
+
Datadog::AppSec::Context.active
|
19
19
|
end
|
20
20
|
|
21
21
|
def processor
|
@@ -24,12 +24,12 @@ module Datadog
|
|
24
24
|
appsec_component.processor if appsec_component
|
25
25
|
end
|
26
26
|
|
27
|
-
def reconfigure(ruleset:,
|
27
|
+
def reconfigure(ruleset:, telemetry:)
|
28
28
|
appsec_component = components.appsec
|
29
29
|
|
30
30
|
return unless appsec_component
|
31
31
|
|
32
|
-
appsec_component.reconfigure(ruleset: ruleset,
|
32
|
+
appsec_component.reconfigure(ruleset: ruleset, telemetry: telemetry)
|
33
33
|
end
|
34
34
|
|
35
35
|
def reconfigure_lock(&block)
|
@@ -56,6 +56,7 @@ end
|
|
56
56
|
require_relative 'appsec/contrib/rack/integration'
|
57
57
|
require_relative 'appsec/contrib/sinatra/integration'
|
58
58
|
require_relative 'appsec/contrib/rails/integration'
|
59
|
+
require_relative 'appsec/contrib/active_record/integration'
|
59
60
|
require_relative 'appsec/contrib/devise/integration'
|
60
61
|
require_relative 'appsec/contrib/graphql/integration'
|
61
62
|
|
@@ -6,6 +6,9 @@
|
|
6
6
|
require_relative '../datadog'
|
7
7
|
require_relative 'tracing/contrib/auto_instrument'
|
8
8
|
|
9
|
+
# DI is not loaded on Ruby 2.5 and JRuby
|
10
|
+
Datadog::DI::Contrib.load_now_or_later if defined?(Datadog::DI::Contrib)
|
11
|
+
|
9
12
|
Datadog::Profiling.start_if_enabled
|
10
13
|
|
11
14
|
module Datadog
|
@@ -19,21 +19,49 @@ module Datadog
|
|
19
19
|
# Whenever there is a conflict (different configurations are provided in different orders), it MUST warn the users
|
20
20
|
# about it and pick a value based on the following priority: code > environment variable > defaults.
|
21
21
|
class AgentSettingsResolver
|
22
|
-
|
23
|
-
|
24
|
-
:ssl,
|
25
|
-
|
26
|
-
:port,
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
22
|
+
# Immutable container for the resulting settings
|
23
|
+
class AgentSettings
|
24
|
+
attr_reader :adapter, :ssl, :hostname, :port, :uds_path, :timeout_seconds
|
25
|
+
|
26
|
+
def initialize(adapter: nil, ssl: nil, hostname: nil, port: nil, uds_path: nil, timeout_seconds: nil)
|
27
|
+
@adapter = adapter
|
28
|
+
@ssl = ssl
|
29
|
+
@hostname = hostname
|
30
|
+
@port = port
|
31
|
+
@uds_path = uds_path
|
32
|
+
@timeout_seconds = timeout_seconds
|
33
33
|
freeze
|
34
34
|
end
|
35
|
+
|
36
|
+
def url
|
37
|
+
case adapter
|
38
|
+
when Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
|
39
|
+
hostname = self.hostname
|
40
|
+
hostname = "[#{hostname}]" if hostname =~ IPV6_REGEXP
|
41
|
+
"#{ssl ? 'https' : 'http'}://#{hostname}:#{port}/"
|
42
|
+
when Datadog::Core::Configuration::Ext::Agent::UnixSocket::ADAPTER
|
43
|
+
"unix://#{uds_path}"
|
44
|
+
else
|
45
|
+
raise ArgumentError, "Unexpected adapter: #{adapter}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def ==(other)
|
50
|
+
self.class == other.class &&
|
51
|
+
adapter == other.adapter &&
|
52
|
+
ssl == other.ssl &&
|
53
|
+
hostname == other.hostname &&
|
54
|
+
port == other.port &&
|
55
|
+
uds_path == other.uds_path &&
|
56
|
+
timeout_seconds == other.timeout_seconds
|
57
|
+
end
|
35
58
|
end
|
36
59
|
|
60
|
+
# IPv6 regular expression from
|
61
|
+
# https://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses
|
62
|
+
# Does not match IPv4 addresses.
|
63
|
+
IPV6_REGEXP = /\A(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\z)/.freeze # rubocop:disable Layout/LineLength
|
64
|
+
|
37
65
|
def self.call(settings, logger: Datadog.logger)
|
38
66
|
new(settings, logger: logger).send(:call)
|
39
67
|
end
|
@@ -13,6 +13,7 @@ require_relative '../remote/component'
|
|
13
13
|
require_relative '../../tracing/component'
|
14
14
|
require_relative '../../profiling/component'
|
15
15
|
require_relative '../../appsec/component'
|
16
|
+
require_relative '../../di/component'
|
16
17
|
require_relative '../crashtracking/component'
|
17
18
|
|
18
19
|
module Datadog
|
@@ -83,6 +84,7 @@ module Datadog
|
|
83
84
|
:telemetry,
|
84
85
|
:tracer,
|
85
86
|
:crashtracker,
|
87
|
+
:dynamic_instrumentation,
|
86
88
|
:appsec
|
87
89
|
|
88
90
|
def initialize(settings)
|
@@ -103,19 +105,22 @@ module Datadog
|
|
103
105
|
@profiler, profiler_logger_extra = Datadog::Profiling::Component.build_profiler_component(
|
104
106
|
settings: settings,
|
105
107
|
agent_settings: agent_settings,
|
106
|
-
optional_tracer: @tracer
|
108
|
+
optional_tracer: @tracer,
|
109
|
+
logger: @logger,
|
107
110
|
)
|
108
111
|
@environment_logger_extra.merge!(profiler_logger_extra) if profiler_logger_extra
|
109
112
|
|
110
113
|
@runtime_metrics = self.class.build_runtime_metrics_worker(settings)
|
111
114
|
@health_metrics = self.class.build_health_metrics(settings)
|
112
115
|
@appsec = Datadog::AppSec::Component.build_appsec_component(settings, telemetry: telemetry)
|
116
|
+
@dynamic_instrumentation = Datadog::DI::Component.build(settings, agent_settings, @logger, telemetry: telemetry)
|
117
|
+
@environment_logger_extra[:dynamic_instrumentation_enabled] = !!@dynamic_instrumentation
|
113
118
|
|
114
119
|
self.class.configure_tracing(settings)
|
115
120
|
end
|
116
121
|
|
117
122
|
# Starts up components
|
118
|
-
def startup!(settings)
|
123
|
+
def startup!(settings, old_state: nil)
|
119
124
|
if settings.profiling.enabled
|
120
125
|
if profiler
|
121
126
|
profiler.start
|
@@ -126,6 +131,16 @@ module Datadog
|
|
126
131
|
end
|
127
132
|
end
|
128
133
|
|
134
|
+
if settings.remote.enabled && old_state&.[](:remote_started)
|
135
|
+
# The library was reconfigured and previously it already started
|
136
|
+
# the remote component (i.e., it received at least one request
|
137
|
+
# through the installed Rack middleware which started the remote).
|
138
|
+
# If the new configuration also has remote enabled, start the
|
139
|
+
# new remote right away.
|
140
|
+
# remote should always be not nil here but steep doesn't know this.
|
141
|
+
remote&.start
|
142
|
+
end
|
143
|
+
|
129
144
|
Core::Diagnostics::EnvironmentLogger.collect_and_log!(@environment_logger_extra)
|
130
145
|
end
|
131
146
|
|
@@ -136,6 +151,9 @@ module Datadog
|
|
136
151
|
# Shutdown remote configuration
|
137
152
|
remote.shutdown! if remote
|
138
153
|
|
154
|
+
# Shutdown DI after remote, since remote config triggers DI operations.
|
155
|
+
dynamic_instrumentation&.shutdown!
|
156
|
+
|
139
157
|
# Decommission AppSec
|
140
158
|
appsec.shutdown! if appsec
|
141
159
|
|