datadog 2.7.1 → 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 +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
|
|