ddtrace 1.11.1 → 1.12.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 +49 -1
- data/ext/ddtrace_profiling_native_extension/NativeExtensionDesign.md +6 -4
- data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +34 -16
- data/ext/ddtrace_profiling_native_extension/extconf.rb +17 -3
- data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +2 -2
- data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +38 -4
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +489 -133
- data/lib/datadog/appsec/assets/waf_rules/strict.json +2 -47
- data/lib/datadog/appsec/configuration/settings.rb +2 -10
- data/lib/datadog/appsec/configuration.rb +3 -9
- data/lib/datadog/appsec/contrib/rack/ext.rb +0 -1
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +12 -0
- data/lib/datadog/appsec/contrib/rack/gateway/response.rb +3 -3
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +9 -9
- data/lib/datadog/appsec/contrib/rack/integration.rb +0 -5
- data/lib/datadog/appsec/contrib/rack/reactive/request.rb +7 -1
- data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +33 -25
- data/lib/datadog/appsec/contrib/rails/ext.rb +0 -1
- data/lib/datadog/appsec/contrib/rails/framework.rb +1 -13
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +3 -3
- data/lib/datadog/appsec/contrib/rails/integration.rb +0 -5
- data/lib/datadog/appsec/contrib/rails/patcher.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/ext.rb +0 -1
- data/lib/datadog/appsec/contrib/sinatra/framework.rb +1 -13
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +6 -6
- data/lib/datadog/appsec/contrib/sinatra/integration.rb +0 -5
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +5 -4
- data/lib/datadog/appsec/event.rb +5 -5
- data/lib/datadog/appsec/ext.rb +1 -0
- data/lib/datadog/appsec/extensions.rb +2 -6
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +3 -4
- data/lib/datadog/appsec/processor/rule_merger.rb +13 -7
- data/lib/datadog/appsec/processor.rb +0 -45
- data/lib/datadog/appsec/remote.rb +6 -0
- data/lib/datadog/appsec/scope.rb +61 -0
- data/lib/datadog/appsec.rb +6 -0
- data/lib/datadog/ci/ext/environment.rb +40 -4
- data/lib/datadog/core/configuration/settings.rb +66 -14
- data/lib/datadog/core/configuration.rb +5 -1
- data/lib/datadog/core/remote/client/capabilities.rb +1 -1
- data/lib/datadog/core/telemetry/collector.rb +2 -1
- data/lib/datadog/core/telemetry/v1/dependency.rb +2 -1
- data/lib/datadog/kit/appsec/events.rb +58 -13
- data/lib/datadog/kit/identity.rb +29 -10
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +2 -0
- data/lib/datadog/profiling/component.rb +54 -29
- data/lib/datadog/tracing/buffer.rb +0 -1
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +9 -1
- data/lib/datadog/tracing/contrib/aws/ext.rb +11 -1
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +7 -0
- data/lib/datadog/tracing/contrib/aws/parsed_context.rb +4 -0
- data/lib/datadog/tracing/contrib/aws/service/base.rb +16 -0
- data/lib/datadog/tracing/contrib/aws/service/dynamodb.rb +19 -0
- data/lib/datadog/tracing/contrib/aws/service/eventbridge.rb +19 -0
- data/lib/datadog/tracing/contrib/aws/service/kinesis.rb +29 -0
- data/lib/datadog/tracing/contrib/aws/service/s3.rb +19 -0
- data/lib/datadog/tracing/contrib/aws/service/sns.rb +27 -0
- data/lib/datadog/tracing/contrib/aws/service/sqs.rb +24 -0
- data/lib/datadog/tracing/contrib/aws/service/stepfunctions.rb +37 -0
- data/lib/datadog/tracing/contrib/aws/services.rb +10 -0
- data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +6 -1
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +5 -2
- data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +6 -1
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +4 -2
- data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +6 -1
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +5 -2
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +6 -1
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +5 -2
- data/lib/datadog/tracing/contrib/patcher.rb +0 -1
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +6 -1
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +5 -2
- data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +6 -1
- data/lib/datadog/tracing/contrib/presto/instrumentation.rb +4 -2
- data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +10 -2
- data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +9 -1
- data/lib/datadog/tracing/contrib/racecar/event.rb +3 -1
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +3 -1
- data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +6 -1
- data/lib/datadog/tracing/contrib/redis/tags.rb +4 -1
- data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +6 -1
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +4 -1
- data/lib/datadog/tracing/contrib/roda/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/sequel/database.rb +4 -1
- data/lib/datadog/tracing/contrib/sequel/dataset.rb +4 -1
- data/lib/datadog/tracing/contrib/sequel/utils.rb +4 -1
- data/lib/datadog/tracing/contrib/status_code_matcher.rb +0 -1
- data/lib/datadog/tracing/correlation.rb +0 -1
- data/lib/datadog/tracing/distributed/headers/ext.rb +1 -1
- data/lib/datadog/tracing/event.rb +0 -2
- data/lib/datadog/tracing/pipeline.rb +0 -2
- data/lib/datadog/tracing/runtime/metrics.rb +0 -2
- data/lib/datadog/tracing/sampling/rate_by_service_sampler.rb +0 -1
- data/lib/datadog/tracing/sampling/rate_sampler.rb +0 -2
- data/lib/datadog/tracing/sampling/rule.rb +0 -2
- data/lib/datadog/tracing/sampling/rule_sampler.rb +0 -2
- data/lib/datadog/tracing/span_operation.rb +0 -1
- data/lib/datadog/tracing/sync_writer.rb +0 -2
- data/lib/datadog/tracing/trace_operation.rb +0 -1
- data/lib/datadog/tracing/tracer.rb +0 -1
- data/lib/datadog/tracing/workers/trace_writer.rb +0 -1
- data/lib/datadog/tracing/workers.rb +0 -2
- data/lib/datadog/tracing/writer.rb +0 -2
- data/lib/ddtrace/version.rb +2 -2
- metadata +18 -19
- data/lib/datadog/appsec/contrib/configuration/settings.rb +0 -20
- data/lib/datadog/appsec/contrib/rack/configuration/settings.rb +0 -22
- data/lib/datadog/appsec/contrib/rails/configuration/settings.rb +0 -22
- data/lib/datadog/appsec/contrib/sinatra/configuration/settings.rb +0 -22
|
@@ -23,13 +23,13 @@ module Datadog
|
|
|
23
23
|
gateway.watch('sinatra.request.dispatch', :appsec) do |stack, gateway_request|
|
|
24
24
|
block = false
|
|
25
25
|
event = nil
|
|
26
|
-
|
|
26
|
+
scope = gateway_request.env[Datadog::AppSec::Ext::SCOPE_KEY]
|
|
27
27
|
|
|
28
28
|
AppSec::Reactive::Operation.new('sinatra.request.dispatch') do |op|
|
|
29
29
|
trace = active_trace
|
|
30
30
|
span = active_span
|
|
31
31
|
|
|
32
|
-
Rack::Reactive::RequestBody.subscribe(op,
|
|
32
|
+
Rack::Reactive::RequestBody.subscribe(op, scope.processor_context) do |result, _block|
|
|
33
33
|
if result.status == :match
|
|
34
34
|
# TODO: should this hash be an Event instance instead?
|
|
35
35
|
event = {
|
|
@@ -42,7 +42,7 @@ module Datadog
|
|
|
42
42
|
|
|
43
43
|
span.set_tag('appsec.event', 'true') if span
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
scope.processor_context.events << event
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
|
|
@@ -66,13 +66,13 @@ module Datadog
|
|
|
66
66
|
gateway.watch('sinatra.request.routed', :appsec) do |stack, (gateway_request, gateway_route_params)|
|
|
67
67
|
block = false
|
|
68
68
|
event = nil
|
|
69
|
-
|
|
69
|
+
scope = gateway_request.env[Datadog::AppSec::Ext::SCOPE_KEY]
|
|
70
70
|
|
|
71
71
|
AppSec::Reactive::Operation.new('sinatra.request.routed') do |op|
|
|
72
72
|
trace = active_trace
|
|
73
73
|
span = active_span
|
|
74
74
|
|
|
75
|
-
Sinatra::Reactive::Routed.subscribe(op,
|
|
75
|
+
Sinatra::Reactive::Routed.subscribe(op, scope.processor_context) do |result, _block|
|
|
76
76
|
if result.status == :match
|
|
77
77
|
# TODO: should this hash be an Event instance instead?
|
|
78
78
|
event = {
|
|
@@ -85,7 +85,7 @@ module Datadog
|
|
|
85
85
|
|
|
86
86
|
span.set_tag('appsec.event', 'true') if span
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
scope.processor_context.events << event
|
|
89
89
|
end
|
|
90
90
|
end
|
|
91
91
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
require_relative '../integration'
|
|
2
2
|
|
|
3
|
-
require_relative 'configuration/settings'
|
|
4
3
|
require_relative 'patcher'
|
|
5
4
|
require_relative 'request_middleware'
|
|
6
5
|
|
|
@@ -32,10 +31,6 @@ module Datadog
|
|
|
32
31
|
true
|
|
33
32
|
end
|
|
34
33
|
|
|
35
|
-
def default_configuration
|
|
36
|
-
Configuration::Settings.new
|
|
37
|
-
end
|
|
38
|
-
|
|
39
34
|
def patcher
|
|
40
35
|
Patcher
|
|
41
36
|
end
|
|
@@ -4,6 +4,7 @@ require_relative '../patcher'
|
|
|
4
4
|
require_relative '../../response'
|
|
5
5
|
require_relative '../rack/request_middleware'
|
|
6
6
|
require_relative 'framework'
|
|
7
|
+
require_relative 'ext'
|
|
7
8
|
require_relative 'gateway/watcher'
|
|
8
9
|
require_relative 'gateway/route_params'
|
|
9
10
|
require_relative 'gateway/request'
|
|
@@ -51,7 +52,7 @@ module Datadog
|
|
|
51
52
|
def dispatch!
|
|
52
53
|
env = @request.env
|
|
53
54
|
|
|
54
|
-
context = env[
|
|
55
|
+
context = env[Datadog::AppSec::Ext::SCOPE_KEY]
|
|
55
56
|
|
|
56
57
|
return super unless context
|
|
57
58
|
|
|
@@ -61,7 +62,7 @@ module Datadog
|
|
|
61
62
|
|
|
62
63
|
request_return, request_response = Instrumentation.gateway.push('sinatra.request.dispatch', gateway_request) do
|
|
63
64
|
# handle process_route interruption
|
|
64
|
-
catch(Ext::ROUTE_INTERRUPT) { super }
|
|
65
|
+
catch(Datadog::AppSec::Contrib::Sinatra::Ext::ROUTE_INTERRUPT) { super }
|
|
65
66
|
end
|
|
66
67
|
|
|
67
68
|
if request_response && request_response.any? { |action, _event| action == :block }
|
|
@@ -80,7 +81,7 @@ module Datadog
|
|
|
80
81
|
def process_route(*)
|
|
81
82
|
env = @request.env
|
|
82
83
|
|
|
83
|
-
context = env[
|
|
84
|
+
context = env[Datadog::AppSec::Ext::SCOPE_KEY]
|
|
84
85
|
|
|
85
86
|
return super unless context
|
|
86
87
|
|
|
@@ -106,7 +107,7 @@ module Datadog
|
|
|
106
107
|
self.response = AppSec::Response.negotiate(env).to_sinatra_response
|
|
107
108
|
|
|
108
109
|
# interrupt request and return response to dispatch! for consistency
|
|
109
|
-
throw(Ext::ROUTE_INTERRUPT, response)
|
|
110
|
+
throw(Datadog::AppSec::Contrib::Sinatra::Ext::ROUTE_INTERRUPT, response)
|
|
110
111
|
end
|
|
111
112
|
|
|
112
113
|
yield(*args)
|
data/lib/datadog/appsec/event.rb
CHANGED
|
@@ -38,17 +38,17 @@ module Datadog
|
|
|
38
38
|
#
|
|
39
39
|
# This is expected to be called only once per trace for the rate limiter
|
|
40
40
|
# to properly apply
|
|
41
|
-
def self.record(*events)
|
|
41
|
+
def self.record(span, *events)
|
|
42
42
|
# ensure rate limiter is called only when there are events to record
|
|
43
43
|
return if events.empty?
|
|
44
44
|
|
|
45
45
|
Datadog::AppSec::RateLimiter.limit(:traces) do
|
|
46
|
-
record_via_span(*events)
|
|
46
|
+
record_via_span(span, *events)
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
# rubocop:disable Metrics/MethodLength
|
|
51
|
-
def self.record_via_span(*events)
|
|
51
|
+
def self.record_via_span(span, *events)
|
|
52
52
|
events.group_by { |e| e[:trace] }.each do |trace, event_group|
|
|
53
53
|
unless trace
|
|
54
54
|
Datadog.logger.debug { "{ error: 'no trace: cannot record', event_group: #{event_group.inspect}}" }
|
|
@@ -100,10 +100,10 @@ module Datadog
|
|
|
100
100
|
|
|
101
101
|
# complex types are unsupported, we need to serialize to a string
|
|
102
102
|
triggers = trace_tags.delete('_dd.appsec.triggers')
|
|
103
|
-
|
|
103
|
+
span.set_tag('_dd.appsec.json', JSON.dump({ triggers: triggers }))
|
|
104
104
|
|
|
105
105
|
trace_tags.each do |key, value|
|
|
106
|
-
|
|
106
|
+
span.set_tag(key, value)
|
|
107
107
|
end
|
|
108
108
|
end
|
|
109
109
|
end
|
data/lib/datadog/appsec/ext.rb
CHANGED
|
@@ -30,9 +30,9 @@ module Datadog
|
|
|
30
30
|
|
|
31
31
|
# Writer methods
|
|
32
32
|
|
|
33
|
-
def instrument(name,
|
|
33
|
+
def instrument(name, _unused = {})
|
|
34
34
|
dsl = AppSec::Configuration::DSL.new
|
|
35
|
-
dsl.instrument(name
|
|
35
|
+
dsl.instrument(name)
|
|
36
36
|
@settings.merge(dsl)
|
|
37
37
|
end
|
|
38
38
|
|
|
@@ -92,10 +92,6 @@ module Datadog
|
|
|
92
92
|
|
|
93
93
|
# Reader methods
|
|
94
94
|
|
|
95
|
-
def [](key)
|
|
96
|
-
@settings[key]
|
|
97
|
-
end
|
|
98
|
-
|
|
99
95
|
def enabled
|
|
100
96
|
@settings.enabled
|
|
101
97
|
end
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative '../../ext'
|
|
4
3
|
require_relative '../../instrumentation/gateway'
|
|
5
4
|
require_relative '../../reactive/operation'
|
|
6
5
|
require_relative '../reactive/set_user'
|
|
@@ -22,13 +21,13 @@ module Datadog
|
|
|
22
21
|
gateway.watch('identity.set_user', :appsec) do |stack, user|
|
|
23
22
|
block = false
|
|
24
23
|
event = nil
|
|
25
|
-
|
|
24
|
+
scope = Datadog::AppSec.active_scope
|
|
26
25
|
|
|
27
26
|
AppSec::Reactive::Operation.new('identity.set_user') do |op|
|
|
28
27
|
trace = active_trace
|
|
29
28
|
span = active_span
|
|
30
29
|
|
|
31
|
-
Monitor::Reactive::SetUser.subscribe(op,
|
|
30
|
+
Monitor::Reactive::SetUser.subscribe(op, scope.processor_context) do |result, _block|
|
|
32
31
|
if result.status == :match
|
|
33
32
|
# TODO: should this hash be an Event instance instead?
|
|
34
33
|
event = {
|
|
@@ -41,7 +40,7 @@ module Datadog
|
|
|
41
40
|
|
|
42
41
|
span.set_tag('appsec.event', 'true') if span
|
|
43
42
|
|
|
44
|
-
|
|
43
|
+
scope.processor_context.events << event
|
|
45
44
|
end
|
|
46
45
|
end
|
|
47
46
|
|
|
@@ -17,16 +17,18 @@ module Datadog
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
class << self
|
|
20
|
-
def merge(rules:, data: [], overrides: [], exclusions: [])
|
|
20
|
+
def merge(rules:, data: [], overrides: [], exclusions: [], custom_rules: [])
|
|
21
21
|
combined_rules = combine_rules(rules)
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
combined_data = combine_data(data) if data.any?
|
|
24
|
+
combined_overrides = combine_overrides(overrides) if overrides.any?
|
|
25
|
+
combined_exclusions = combine_exclusions(exclusions) if exclusions.any?
|
|
26
|
+
combined_custom_rules = combine_custom_rules(custom_rules) if custom_rules.any?
|
|
26
27
|
|
|
27
|
-
combined_rules['rules_data'] =
|
|
28
|
-
combined_rules['rules_override'] =
|
|
29
|
-
combined_rules['exclusions'] =
|
|
28
|
+
combined_rules['rules_data'] = combined_data if combined_data
|
|
29
|
+
combined_rules['rules_override'] = combined_overrides if combined_overrides
|
|
30
|
+
combined_rules['exclusions'] = combined_exclusions if combined_exclusions
|
|
31
|
+
combined_rules['custom_rules'] = combined_custom_rules if combined_custom_rules
|
|
30
32
|
|
|
31
33
|
combined_rules
|
|
32
34
|
end
|
|
@@ -119,6 +121,10 @@ module Datadog
|
|
|
119
121
|
def combine_exclusions(exclusions)
|
|
120
122
|
exclusions.flatten
|
|
121
123
|
end
|
|
124
|
+
|
|
125
|
+
def combine_custom_rules(custom_rules)
|
|
126
|
+
custom_rules.flatten
|
|
127
|
+
end
|
|
122
128
|
end
|
|
123
129
|
end
|
|
124
130
|
end
|
|
@@ -43,30 +43,6 @@ module Datadog
|
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
class << self
|
|
47
|
-
def active_context
|
|
48
|
-
Thread.current[:datadog_current_waf_context]
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
private
|
|
52
|
-
|
|
53
|
-
def active_context=(context)
|
|
54
|
-
unless context.instance_of?(Context)
|
|
55
|
-
raise ArgumentError,
|
|
56
|
-
"The context provide: #{context.inspect} is not a Datadog::AppSec::Processor::Context"
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
Thread.current[:datadog_current_waf_context] = context
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def reset_active_context
|
|
63
|
-
Thread.current[:datadog_current_waf_context] = nil
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
class NoActiveContextError < StandardError; end
|
|
68
|
-
class AlreadyActiveContextError < StandardError; end
|
|
69
|
-
|
|
70
46
|
attr_reader :ruleset_info, :addresses
|
|
71
47
|
|
|
72
48
|
def initialize(ruleset:)
|
|
@@ -83,27 +59,6 @@ module Datadog
|
|
|
83
59
|
!@handle.nil?
|
|
84
60
|
end
|
|
85
61
|
|
|
86
|
-
def new_context
|
|
87
|
-
Context.new(self)
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def activate_context
|
|
91
|
-
existing_active_context = Processor.active_context
|
|
92
|
-
raise AlreadyActiveContextError if existing_active_context
|
|
93
|
-
|
|
94
|
-
context = new_context
|
|
95
|
-
Processor.send(:active_context=, context)
|
|
96
|
-
context
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
def deactivate_context
|
|
100
|
-
context = Processor.active_context
|
|
101
|
-
raise NoActiveContextError unless context
|
|
102
|
-
|
|
103
|
-
Processor.send(:reset_active_context)
|
|
104
|
-
context.finalize
|
|
105
|
-
end
|
|
106
|
-
|
|
107
62
|
def finalize
|
|
108
63
|
@handle.finalize
|
|
109
64
|
end
|
|
@@ -30,6 +30,7 @@ module Datadog
|
|
|
30
30
|
CAP_ASM_REQUEST_BLOCKING,
|
|
31
31
|
CAP_ASM_RESPONSE_BLOCKING,
|
|
32
32
|
CAP_ASM_DD_RULES,
|
|
33
|
+
CAP_ASM_CUSTOM_RULES,
|
|
33
34
|
].freeze
|
|
34
35
|
|
|
35
36
|
ASM_PRODUCTS = [
|
|
@@ -47,6 +48,7 @@ module Datadog
|
|
|
47
48
|
remote_features_enabled? ? ASM_PRODUCTS : []
|
|
48
49
|
end
|
|
49
50
|
|
|
51
|
+
# rubocop:disable Metrics/MethodLength
|
|
50
52
|
def receivers
|
|
51
53
|
return [] unless remote_features_enabled?
|
|
52
54
|
|
|
@@ -57,6 +59,7 @@ module Datadog
|
|
|
57
59
|
end
|
|
58
60
|
|
|
59
61
|
rules = []
|
|
62
|
+
custom_rules = []
|
|
60
63
|
data = []
|
|
61
64
|
overrides = []
|
|
62
65
|
exclusions = []
|
|
@@ -72,6 +75,7 @@ module Datadog
|
|
|
72
75
|
when 'ASM'
|
|
73
76
|
overrides << parsed_content['rules_override'] if parsed_content['rules_override']
|
|
74
77
|
exclusions << parsed_content['exclusions'] if parsed_content['exclusions']
|
|
78
|
+
custom_rules << parsed_content['custom_rules'] if parsed_content['custom_rules']
|
|
75
79
|
end
|
|
76
80
|
end
|
|
77
81
|
|
|
@@ -88,6 +92,7 @@ module Datadog
|
|
|
88
92
|
data: data,
|
|
89
93
|
overrides: overrides,
|
|
90
94
|
exclusions: exclusions,
|
|
95
|
+
custom_rules: custom_rules,
|
|
91
96
|
)
|
|
92
97
|
|
|
93
98
|
Datadog::AppSec.reconfigure(ruleset: ruleset)
|
|
@@ -95,6 +100,7 @@ module Datadog
|
|
|
95
100
|
|
|
96
101
|
[receiver]
|
|
97
102
|
end
|
|
103
|
+
# rubocop:enable Metrics/MethodLength
|
|
98
104
|
|
|
99
105
|
private
|
|
100
106
|
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'processor'
|
|
4
|
+
|
|
5
|
+
module Datadog
|
|
6
|
+
module AppSec
|
|
7
|
+
# Capture context essential to consistently call processor and report via traces
|
|
8
|
+
class Scope
|
|
9
|
+
attr_reader :trace, :service_entry_span, :processor_context
|
|
10
|
+
|
|
11
|
+
def initialize(trace, service_entry_span, processor_context)
|
|
12
|
+
@trace = trace
|
|
13
|
+
@service_entry_span = service_entry_span
|
|
14
|
+
@processor_context = processor_context
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def finalize
|
|
18
|
+
@processor_context.finalize
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class << self
|
|
22
|
+
def activate_scope(trace, service_entry_span, processor)
|
|
23
|
+
raise ActiveScopeError, 'another scope is active, nested scopes are not supported' if active_scope
|
|
24
|
+
|
|
25
|
+
context = Datadog::AppSec::Processor::Context.new(processor)
|
|
26
|
+
|
|
27
|
+
self.active_scope = new(trace, service_entry_span, context)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def deactivate_scope
|
|
31
|
+
raise InactiveScopeError, 'no scope is active, nested scopes are not supported' unless active_scope
|
|
32
|
+
|
|
33
|
+
scope = active_scope
|
|
34
|
+
|
|
35
|
+
reset_active_scope
|
|
36
|
+
|
|
37
|
+
scope.finalize
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def active_scope
|
|
41
|
+
Thread.current[:datadog_appsec_active_scope]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def active_scope=(scope)
|
|
47
|
+
raise ArgumentError, 'not a Datadog::AppSec::Scope' unless scope.instance_of?(Scope)
|
|
48
|
+
|
|
49
|
+
Thread.current[:datadog_appsec_active_scope] = scope
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def reset_active_scope
|
|
53
|
+
Thread.current[:datadog_appsec_active_scope] = nil
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
class InactiveScopeError < StandardError; end
|
|
58
|
+
class ActiveScopeError < StandardError; end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
data/lib/datadog/appsec.rb
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative 'appsec/configuration'
|
|
4
4
|
require_relative 'appsec/extensions'
|
|
5
|
+
require_relative 'appsec/scope'
|
|
6
|
+
require_relative 'appsec/ext'
|
|
5
7
|
|
|
6
8
|
module Datadog
|
|
7
9
|
# Namespace for Datadog AppSec instrumentation
|
|
@@ -13,6 +15,10 @@ module Datadog
|
|
|
13
15
|
Datadog.configuration.appsec.enabled
|
|
14
16
|
end
|
|
15
17
|
|
|
18
|
+
def active_scope
|
|
19
|
+
Datadog::AppSec::Scope.active_scope
|
|
20
|
+
end
|
|
21
|
+
|
|
16
22
|
def processor
|
|
17
23
|
appsec_component = components.appsec
|
|
18
24
|
|
|
@@ -19,6 +19,8 @@ module Datadog
|
|
|
19
19
|
TAG_PROVIDER_NAME = 'ci.provider.name'
|
|
20
20
|
TAG_STAGE_NAME = 'ci.stage.name'
|
|
21
21
|
TAG_WORKSPACE_PATH = 'ci.workspace_path'
|
|
22
|
+
TAG_NODE_LABELS = 'ci.node.labels'
|
|
23
|
+
TAG_NODE_NAME = 'ci.node.name'
|
|
22
24
|
TAG_CI_ENV_VARS = '_dd.ci.env_vars'
|
|
23
25
|
|
|
24
26
|
PROVIDERS = [
|
|
@@ -33,7 +35,8 @@ module Datadog
|
|
|
33
35
|
['JENKINS_URL', :extract_jenkins],
|
|
34
36
|
['TEAMCITY_VERSION', :extract_teamcity],
|
|
35
37
|
['TRAVIS', :extract_travis],
|
|
36
|
-
['BITRISE_BUILD_SLUG', :extract_bitrise]
|
|
38
|
+
['BITRISE_BUILD_SLUG', :extract_bitrise],
|
|
39
|
+
['CF_BUILD_ID', :extract_codefresh]
|
|
37
40
|
].freeze
|
|
38
41
|
|
|
39
42
|
module_function
|
|
@@ -196,7 +199,7 @@ module Datadog
|
|
|
196
199
|
end
|
|
197
200
|
|
|
198
201
|
def extract_buildkite(env)
|
|
199
|
-
{
|
|
202
|
+
tags = {
|
|
200
203
|
Core::Git::Ext::TAG_BRANCH => env['BUILDKITE_BRANCH'],
|
|
201
204
|
Core::Git::Ext::TAG_COMMIT_SHA => env['BUILDKITE_COMMIT'],
|
|
202
205
|
Core::Git::Ext::TAG_REPOSITORY_URL => env['BUILDKITE_REPO'],
|
|
@@ -211,11 +214,21 @@ module Datadog
|
|
|
211
214
|
Core::Git::Ext::TAG_COMMIT_AUTHOR_NAME => env['BUILDKITE_BUILD_AUTHOR'],
|
|
212
215
|
Core::Git::Ext::TAG_COMMIT_AUTHOR_EMAIL => env['BUILDKITE_BUILD_AUTHOR_EMAIL'],
|
|
213
216
|
Core::Git::Ext::TAG_COMMIT_MESSAGE => env['BUILDKITE_MESSAGE'],
|
|
217
|
+
TAG_NODE_NAME => env['BUILDKITE_AGENT_ID'],
|
|
214
218
|
TAG_CI_ENV_VARS => {
|
|
215
219
|
'BUILDKITE_BUILD_ID' => env['BUILDKITE_BUILD_ID'],
|
|
216
220
|
'BUILDKITE_JOB_ID' => env['BUILDKITE_JOB_ID']
|
|
217
221
|
}.to_json
|
|
218
222
|
}
|
|
223
|
+
|
|
224
|
+
extra_tags = env
|
|
225
|
+
.select { |key| key.start_with?('BUILDKITE_AGENT_META_DATA_') }
|
|
226
|
+
.map { |key, value| "#{key.to_s.sub('BUILDKITE_AGENT_META_DATA_', '').downcase}:#{value}" }
|
|
227
|
+
.sort_by(&:length)
|
|
228
|
+
|
|
229
|
+
tags[TAG_NODE_LABELS] = extra_tags.to_json unless extra_tags.empty?
|
|
230
|
+
|
|
231
|
+
tags
|
|
219
232
|
end
|
|
220
233
|
|
|
221
234
|
def extract_circle_ci(env)
|
|
@@ -274,7 +287,6 @@ module Datadog
|
|
|
274
287
|
def extract_gitlab(env)
|
|
275
288
|
commit_author_name, commit_author_email = extract_name_email(env['CI_COMMIT_AUTHOR'])
|
|
276
289
|
|
|
277
|
-
url = env['CI_PIPELINE_URL']
|
|
278
290
|
{
|
|
279
291
|
Core::Git::Ext::TAG_BRANCH => env['CI_COMMIT_REF_NAME'],
|
|
280
292
|
Core::Git::Ext::TAG_COMMIT_SHA => env['CI_COMMIT_SHA'],
|
|
@@ -289,9 +301,11 @@ module Datadog
|
|
|
289
301
|
TAG_PIPELINE_ID => env['CI_PIPELINE_ID'],
|
|
290
302
|
TAG_PIPELINE_NAME => env['CI_PROJECT_PATH'],
|
|
291
303
|
TAG_PIPELINE_NUMBER => env['CI_PIPELINE_IID'],
|
|
292
|
-
TAG_PIPELINE_URL =>
|
|
304
|
+
TAG_PIPELINE_URL => env['CI_PIPELINE_URL'],
|
|
293
305
|
TAG_PROVIDER_NAME => 'gitlab',
|
|
294
306
|
TAG_WORKSPACE_PATH => env['CI_PROJECT_DIR'],
|
|
307
|
+
TAG_NODE_LABELS => env['CI_RUNNER_TAGS'],
|
|
308
|
+
TAG_NODE_NAME => env['CI_RUNNER_ID'],
|
|
295
309
|
Core::Git::Ext::TAG_COMMIT_MESSAGE => env['CI_COMMIT_MESSAGE'],
|
|
296
310
|
TAG_CI_ENV_VARS => {
|
|
297
311
|
'CI_PROJECT_URL' => env['CI_PROJECT_URL'],
|
|
@@ -308,6 +322,9 @@ module Datadog
|
|
|
308
322
|
name = name.gsub("/#{normalize_ref(branch)}", '') if branch
|
|
309
323
|
name = name.split('/').reject { |v| v.nil? || v.include?('=') }.join('/')
|
|
310
324
|
end
|
|
325
|
+
|
|
326
|
+
node_labels = env['NODE_LABELS'].split.to_json unless env['NODE_LABELS'].nil?
|
|
327
|
+
|
|
311
328
|
{
|
|
312
329
|
Core::Git::Ext::TAG_BRANCH => branch,
|
|
313
330
|
Core::Git::Ext::TAG_COMMIT_SHA => env['GIT_COMMIT'],
|
|
@@ -319,6 +336,8 @@ module Datadog
|
|
|
319
336
|
TAG_PIPELINE_URL => env['BUILD_URL'],
|
|
320
337
|
TAG_PROVIDER_NAME => 'jenkins',
|
|
321
338
|
TAG_WORKSPACE_PATH => env['WORKSPACE'],
|
|
339
|
+
TAG_NODE_LABELS => node_labels,
|
|
340
|
+
TAG_NODE_NAME => env['NODE_NAME'],
|
|
322
341
|
TAG_CI_ENV_VARS => {
|
|
323
342
|
'DD_CUSTOM_TRACE_ID' => env['DD_CUSTOM_TRACE_ID']
|
|
324
343
|
}.to_json
|
|
@@ -380,6 +399,23 @@ module Datadog
|
|
|
380
399
|
}
|
|
381
400
|
end
|
|
382
401
|
|
|
402
|
+
def extract_codefresh(env)
|
|
403
|
+
branch, tag = branch_or_tag(env['CF_BRANCH'])
|
|
404
|
+
|
|
405
|
+
{
|
|
406
|
+
TAG_PROVIDER_NAME => 'codefresh',
|
|
407
|
+
TAG_PIPELINE_ID => env['CF_BUILD_ID'],
|
|
408
|
+
TAG_PIPELINE_NAME => env['CF_PIPELINE_NAME'],
|
|
409
|
+
TAG_PIPELINE_URL => env['CF_BUILD_URL'],
|
|
410
|
+
TAG_JOB_NAME => env['CF_STEP_NAME'],
|
|
411
|
+
Core::Git::Ext::TAG_BRANCH => branch,
|
|
412
|
+
Core::Git::Ext::TAG_TAG => tag,
|
|
413
|
+
TAG_CI_ENV_VARS => {
|
|
414
|
+
'CF_BUILD_ID' => env['CF_BUILD_ID'],
|
|
415
|
+
}.to_json
|
|
416
|
+
}
|
|
417
|
+
end
|
|
418
|
+
|
|
383
419
|
def extract_user_defined_git(env)
|
|
384
420
|
{
|
|
385
421
|
Core::Git::Ext::TAG_REPOSITORY_URL => env[Core::Git::Ext::ENV_REPOSITORY_URL],
|
|
@@ -154,6 +154,9 @@ module Datadog
|
|
|
154
154
|
# @default `DD_ENV` environment variable, otherwise `nil`
|
|
155
155
|
# @return [String,nil]
|
|
156
156
|
option :env do |o|
|
|
157
|
+
# DEV-2.0: Remove this conversion for symbol.
|
|
158
|
+
o.setter { |v| v.to_s if v }
|
|
159
|
+
|
|
157
160
|
# NOTE: env also gets set as a side effect of tags. See the WORKAROUND note in #initialize for details.
|
|
158
161
|
o.default { ENV.fetch(Core::Environment::Ext::ENV_ENVIRONMENT, nil) }
|
|
159
162
|
o.lazy
|
|
@@ -202,12 +205,23 @@ module Datadog
|
|
|
202
205
|
|
|
203
206
|
# @public_api
|
|
204
207
|
settings :advanced do
|
|
208
|
+
# @deprecated This setting is ignored when CPU Profiling 2.0 is in use, and will be removed on dd-trace-rb 2.0.
|
|
209
|
+
#
|
|
205
210
|
# This should never be reduced, as it can cause the resulting profiles to become biased.
|
|
206
211
|
# The default should be enough for most services, allowing 16 threads to be sampled around 30 times
|
|
207
212
|
# per second for a 60 second period.
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
213
|
+
option :max_events do |o|
|
|
214
|
+
o.default 32768
|
|
215
|
+
o.on_set do |value|
|
|
216
|
+
if value != 32768
|
|
217
|
+
Datadog.logger.warn(
|
|
218
|
+
'The profiling.advanced.max_events setting has been deprecated for removal. It no longer does ' \
|
|
219
|
+
'anything unless you the `force_enable_legacy_profiler` option is in use. ' \
|
|
220
|
+
'Please remove it from your Datadog.configure block.'
|
|
221
|
+
)
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
end
|
|
211
225
|
|
|
212
226
|
# Controls the maximum number of frames for each thread sampled. Can be tuned to avoid omitted frames in the
|
|
213
227
|
# produced profiles. Increasing this may increase the overhead of profiling.
|
|
@@ -250,28 +264,39 @@ module Datadog
|
|
|
250
264
|
end
|
|
251
265
|
end
|
|
252
266
|
|
|
253
|
-
#
|
|
254
|
-
#
|
|
255
|
-
# Note that setting this to "false" (or not setting it) will not prevent the new profiler from
|
|
256
|
-
# being automatically used.
|
|
257
|
-
# This option will be deprecated for removal once the legacy profiler is removed.
|
|
267
|
+
# @deprecated No longer does anything, and will be removed on dd-trace-rb 2.0.
|
|
258
268
|
#
|
|
259
|
-
#
|
|
269
|
+
# This was used prior to the GA of the new CPU Profiling 2.0 profiler. Using CPU Profiling 2.0 is now the
|
|
270
|
+
# default and this doesn't do anything.
|
|
260
271
|
option :force_enable_new_profiler do |o|
|
|
261
|
-
o.
|
|
262
|
-
|
|
272
|
+
o.on_set do
|
|
273
|
+
Datadog.logger.warn(
|
|
274
|
+
'The profiling.advanced.force_enable_new_profiler setting has been deprecated for removal and no ' \
|
|
275
|
+
'longer does anything. Please remove it from your Datadog.configure block.'
|
|
276
|
+
)
|
|
277
|
+
end
|
|
263
278
|
end
|
|
264
279
|
|
|
265
|
-
#
|
|
280
|
+
# @deprecated Will be removed for dd-trace-rb 2.0.
|
|
266
281
|
#
|
|
267
|
-
#
|
|
282
|
+
# Forces enabling the *legacy* non-CPU Profiling 2.0 profiler.
|
|
268
283
|
# Do not use unless instructed to by support.
|
|
269
|
-
# This option will be deprecated for removal once the legacy profiler is removed.
|
|
270
284
|
#
|
|
271
285
|
# @default `DD_PROFILING_FORCE_ENABLE_LEGACY` environment variable, otherwise `false`
|
|
272
286
|
option :force_enable_legacy_profiler do |o|
|
|
273
287
|
o.default { env_to_bool('DD_PROFILING_FORCE_ENABLE_LEGACY', false) }
|
|
274
288
|
o.lazy
|
|
289
|
+
o.on_set do |value|
|
|
290
|
+
if value
|
|
291
|
+
Datadog.logger.warn(
|
|
292
|
+
'The profiling.advanced.force_enable_legacy_profiler setting has been deprecated for removal. ' \
|
|
293
|
+
'Do not use unless instructed to by support. ' \
|
|
294
|
+
'If you needed to use it due to incompatibilities with the CPU Profiling 2.0 profiler, consider ' \
|
|
295
|
+
'using the profiling.advanced.no_signals_workaround_enabled setting instead. ' \
|
|
296
|
+
'See <https://dtdg.co/ruby-profiler-troubleshooting> for details.'
|
|
297
|
+
)
|
|
298
|
+
end
|
|
299
|
+
end
|
|
275
300
|
end
|
|
276
301
|
|
|
277
302
|
# Forces enabling of profiling of time/resources spent in Garbage Collection.
|
|
@@ -317,6 +342,30 @@ module Datadog
|
|
|
317
342
|
o.default { env_to_bool('DD_PROFILING_SKIP_MYSQL2_CHECK', false) }
|
|
318
343
|
o.lazy
|
|
319
344
|
end
|
|
345
|
+
|
|
346
|
+
# The profiler gathers data by sending `SIGPROF` unix signals to Ruby application threads.
|
|
347
|
+
#
|
|
348
|
+
# Sending `SIGPROF` is a common profiling approach, and may cause system calls from native
|
|
349
|
+
# extensions/libraries to be interrupted with a system
|
|
350
|
+
# [EINTR error code.](https://man7.org/linux/man-pages/man7/signal.7.html#:~:text=Interruption%20of%20system%20calls%20and%20library%20functions%20by%20signal%20handlers)
|
|
351
|
+
# Rarely, native extensions or libraries called by them may have missing or incorrect error handling for the
|
|
352
|
+
# `EINTR` error code.
|
|
353
|
+
#
|
|
354
|
+
# The "no signals" workaround, when enabled, enables an alternative mode for the profiler where it does not
|
|
355
|
+
# send `SIGPROF` unix signals. The downside of this approach is that the profiler data will have lower
|
|
356
|
+
# quality.
|
|
357
|
+
#
|
|
358
|
+
# This workaround is automatically enabled when gems that are known to have issues handling
|
|
359
|
+
# `EINTR` error codes are detected. If you suspect you may be seeing an issue due to the profiler's use of
|
|
360
|
+
# signals, you can try manually enabling this mode as a fallback.
|
|
361
|
+
# Please also report these issues to us on <https://github.com/DataDog/dd-trace-rb/issues/new>, so we can
|
|
362
|
+
# work with the gem authors to fix them!
|
|
363
|
+
#
|
|
364
|
+
# @default `DD_PROFILING_NO_SIGNALS_WORKAROUND_ENABLED` environment variable as a boolean, otherwise `:auto`
|
|
365
|
+
option :no_signals_workaround_enabled do |o|
|
|
366
|
+
o.default { env_to_bool('DD_PROFILING_NO_SIGNALS_WORKAROUND_ENABLED', :auto) }
|
|
367
|
+
o.lazy
|
|
368
|
+
end
|
|
320
369
|
end
|
|
321
370
|
|
|
322
371
|
# @public_api
|
|
@@ -353,6 +402,9 @@ module Datadog
|
|
|
353
402
|
# @default `DD_SERVICE` environment variable, otherwise the program name (e.g. `'ruby'`, `'rails'`, `'pry'`)
|
|
354
403
|
# @return [String]
|
|
355
404
|
option :service do |o|
|
|
405
|
+
# DEV-2.0: Remove this conversion for symbol.
|
|
406
|
+
o.setter { |v| v.to_s if v }
|
|
407
|
+
|
|
356
408
|
# NOTE: service also gets set as a side effect of tags. See the WORKAROUND note in #initialize for details.
|
|
357
409
|
o.default { ENV.fetch(Core::Environment::Ext::ENV_SERVICE, Core::Environment::Ext::FALLBACK_SERVICE_NAME) }
|
|
358
410
|
o.lazy
|