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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "2.2",
|
|
3
3
|
"metadata": {
|
|
4
|
-
"rules_version": "1.
|
|
4
|
+
"rules_version": "1.7.0"
|
|
5
5
|
},
|
|
6
6
|
"rules": [
|
|
7
7
|
{
|
|
@@ -24,96 +24,51 @@
|
|
|
24
24
|
}
|
|
25
25
|
],
|
|
26
26
|
"list": [
|
|
27
|
-
"",
|
|
28
27
|
"(hydra)",
|
|
29
|
-
".nasl",
|
|
30
28
|
"absinthe",
|
|
31
|
-
"advanced email extractor",
|
|
32
|
-
"arachni/",
|
|
33
29
|
"autogetcontent",
|
|
34
30
|
"bilbo",
|
|
35
31
|
"bfac",
|
|
36
|
-
"brutus",
|
|
37
|
-
"brutus/aet",
|
|
38
|
-
"bsqlbf",
|
|
39
|
-
"cgichk",
|
|
40
32
|
"cisco-torch",
|
|
41
|
-
"commix",
|
|
42
33
|
"core-project/1.0",
|
|
43
34
|
"crimscanner/",
|
|
44
35
|
"datacha0s",
|
|
45
|
-
"detectify",
|
|
46
|
-
"dirbuster",
|
|
47
36
|
"domino hunter",
|
|
48
37
|
"dotdotpwn",
|
|
49
38
|
"email extractor",
|
|
50
39
|
"fhscan core 1.",
|
|
51
40
|
"floodgate",
|
|
52
|
-
"fuzz faster u fool",
|
|
53
41
|
"f-secure radar",
|
|
54
42
|
"get-minimal",
|
|
55
|
-
"gobuster",
|
|
56
43
|
"gootkit auto-rooter scanner",
|
|
57
44
|
"grabber",
|
|
58
45
|
"grendel-scan",
|
|
59
|
-
"havij",
|
|
60
46
|
"inspath",
|
|
61
47
|
"internet ninja",
|
|
62
|
-
"jaascois",
|
|
63
|
-
"jorgee",
|
|
64
48
|
"masscan",
|
|
65
|
-
"metis",
|
|
66
49
|
"morfeus fucking scanner",
|
|
67
50
|
"mysqloit",
|
|
68
|
-
"n-stealth",
|
|
69
|
-
"nessus",
|
|
70
|
-
"netsparker",
|
|
71
|
-
"nikto",
|
|
72
|
-
"nmap nse",
|
|
73
|
-
"nmap scripting engine",
|
|
74
|
-
"nmap-nse",
|
|
75
|
-
"nsauditor",
|
|
76
|
-
"nuclei",
|
|
77
|
-
"openvas",
|
|
78
|
-
"pangolin",
|
|
79
|
-
"paros",
|
|
80
|
-
"pmafind",
|
|
81
51
|
"prog.customcrawler",
|
|
82
52
|
"qqgamehall",
|
|
83
|
-
"qualys was",
|
|
84
53
|
"s.t.a.l.k.e.r.",
|
|
85
|
-
"security scan",
|
|
86
54
|
"springenwerk",
|
|
87
55
|
"sql power injector",
|
|
88
|
-
"sqlmap",
|
|
89
|
-
"sqlninja",
|
|
90
56
|
"struts-pwn",
|
|
91
57
|
"sysscan",
|
|
92
58
|
"tbi-webscanner",
|
|
93
59
|
"teh forest lobster",
|
|
94
|
-
"this is an exploit",
|
|
95
60
|
"toata dragostea",
|
|
96
|
-
"toata dragostea mea pentru diavola",
|
|
97
61
|
"uil2pn",
|
|
98
62
|
"user-agent:",
|
|
99
63
|
"vega/",
|
|
100
64
|
"voideye",
|
|
101
|
-
"w3af.sf.net",
|
|
102
|
-
"w3af.sourceforge.net",
|
|
103
|
-
"w3af.org",
|
|
104
65
|
"webbandit",
|
|
105
|
-
"webinspect",
|
|
106
66
|
"webshag",
|
|
107
|
-
"webtrends security analyzer",
|
|
108
67
|
"webvulnscan",
|
|
109
|
-
"wfuzz",
|
|
110
68
|
"whatweb",
|
|
111
69
|
"whcc/",
|
|
112
70
|
"wordpress hash grabber",
|
|
113
|
-
"
|
|
114
|
-
"xmlrpc exploit",
|
|
115
|
-
"zgrab",
|
|
116
|
-
"zmeu"
|
|
71
|
+
"xmlrpc exploit"
|
|
117
72
|
]
|
|
118
73
|
},
|
|
119
74
|
"operator": "phrase_match"
|
|
@@ -116,7 +116,7 @@ module Datadog
|
|
|
116
116
|
}.freeze
|
|
117
117
|
|
|
118
118
|
# Struct constant whisker cast for Steep
|
|
119
|
-
Integration = _ = Struct.new(:integration
|
|
119
|
+
Integration = _ = Struct.new(:integration) # rubocop:disable Naming/ConstantName
|
|
120
120
|
|
|
121
121
|
def initialize
|
|
122
122
|
@integrations = []
|
|
@@ -181,14 +181,6 @@ module Datadog
|
|
|
181
181
|
_ = @options[:obfuscator_value_regex]
|
|
182
182
|
end
|
|
183
183
|
|
|
184
|
-
def [](integration_name)
|
|
185
|
-
integration = Datadog::AppSec::Contrib::Integration.registry[integration_name]
|
|
186
|
-
|
|
187
|
-
raise ArgumentError, "'#{integration_name}' is not a valid integration." unless integration
|
|
188
|
-
|
|
189
|
-
integration.options
|
|
190
|
-
end
|
|
191
|
-
|
|
192
184
|
def merge(dsl)
|
|
193
185
|
dsl.options.each do |k, v|
|
|
194
186
|
unless v.nil?
|
|
@@ -203,7 +195,7 @@ module Datadog
|
|
|
203
195
|
dsl.instruments.each do |instrument|
|
|
204
196
|
# TODO: error handling
|
|
205
197
|
registered_integration = Datadog::AppSec::Contrib::Integration.registry[instrument.name]
|
|
206
|
-
@integrations << Integration.new(registered_integration
|
|
198
|
+
@integrations << Integration.new(registered_integration)
|
|
207
199
|
|
|
208
200
|
# TODO: move to a separate apply step
|
|
209
201
|
klass = registered_integration.klass
|
|
@@ -15,7 +15,7 @@ module Datadog
|
|
|
15
15
|
# Configuration DSL implementation
|
|
16
16
|
class DSL
|
|
17
17
|
# Struct constant whisker cast for Steep
|
|
18
|
-
Instrument = _ = Struct.new(:name
|
|
18
|
+
Instrument = _ = Struct.new(:name) # rubocop:disable Naming/ConstantName
|
|
19
19
|
|
|
20
20
|
def initialize
|
|
21
21
|
@instruments = []
|
|
@@ -24,8 +24,8 @@ module Datadog
|
|
|
24
24
|
|
|
25
25
|
attr_reader :instruments, :options
|
|
26
26
|
|
|
27
|
-
def instrument(name
|
|
28
|
-
@instruments << Instrument.new(name
|
|
27
|
+
def instrument(name)
|
|
28
|
+
@instruments << Instrument.new(name)
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def enabled=(value)
|
|
@@ -64,12 +64,6 @@ module Datadog
|
|
|
64
64
|
def obfuscator_value_regex=(value)
|
|
65
65
|
options[:obfuscator_value_regex] = value
|
|
66
66
|
end
|
|
67
|
-
|
|
68
|
-
def [](key)
|
|
69
|
-
found = @instruments.find { |e| e.name == key }
|
|
70
|
-
|
|
71
|
-
found.options if found
|
|
72
|
-
end
|
|
73
67
|
end
|
|
74
68
|
|
|
75
69
|
# class-level methods for Configuration
|
|
@@ -33,6 +33,10 @@ module Datadog
|
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
def method
|
|
37
|
+
request.request_method
|
|
38
|
+
end
|
|
39
|
+
|
|
36
40
|
def headers
|
|
37
41
|
request.env.each_with_object({}) do |(k, v), h|
|
|
38
42
|
h[k.gsub(/^HTTP_/, '').downcase.tr('_', '-')] = v if k =~ /^HTTP_/
|
|
@@ -47,6 +51,14 @@ module Datadog
|
|
|
47
51
|
request.url
|
|
48
52
|
end
|
|
49
53
|
|
|
54
|
+
def fullpath
|
|
55
|
+
request.fullpath
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def path
|
|
59
|
+
request.path
|
|
60
|
+
end
|
|
61
|
+
|
|
50
62
|
def cookies
|
|
51
63
|
request.cookies
|
|
52
64
|
end
|
|
@@ -9,14 +9,14 @@ module Datadog
|
|
|
9
9
|
module Gateway
|
|
10
10
|
# Gateway Response argument.
|
|
11
11
|
class Response < Instrumentation::Gateway::Argument
|
|
12
|
-
attr_reader :body, :status, :headers, :
|
|
12
|
+
attr_reader :body, :status, :headers, :scope
|
|
13
13
|
|
|
14
|
-
def initialize(body, status, headers,
|
|
14
|
+
def initialize(body, status, headers, scope:)
|
|
15
15
|
super()
|
|
16
16
|
@body = body
|
|
17
17
|
@status = status
|
|
18
18
|
@headers = headers.each_with_object({}) { |(k, v), h| h[k.downcase] = v }
|
|
19
|
-
@
|
|
19
|
+
@scope = scope
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def response
|
|
@@ -25,13 +25,13 @@ module Datadog
|
|
|
25
25
|
gateway.watch('rack.request', :appsec) do |stack, gateway_request|
|
|
26
26
|
block = false
|
|
27
27
|
event = nil
|
|
28
|
-
|
|
28
|
+
scope = gateway_request.env[Datadog::AppSec::Ext::SCOPE_KEY]
|
|
29
29
|
|
|
30
30
|
AppSec::Reactive::Operation.new('rack.request') do |op|
|
|
31
31
|
trace = active_trace
|
|
32
32
|
span = active_span
|
|
33
33
|
|
|
34
|
-
Rack::Reactive::Request.subscribe(op,
|
|
34
|
+
Rack::Reactive::Request.subscribe(op, scope.processor_context) do |result, _block|
|
|
35
35
|
if result.status == :match
|
|
36
36
|
# TODO: should this hash be an Event instance instead?
|
|
37
37
|
event = {
|
|
@@ -44,7 +44,7 @@ module Datadog
|
|
|
44
44
|
|
|
45
45
|
span.set_tag('appsec.event', 'true') if span
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
scope.processor_context.events << event
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
50
|
|
|
@@ -68,13 +68,13 @@ module Datadog
|
|
|
68
68
|
gateway.watch('rack.response', :appsec) do |stack, gateway_response|
|
|
69
69
|
block = false
|
|
70
70
|
event = nil
|
|
71
|
-
|
|
71
|
+
scope = gateway_response.scope
|
|
72
72
|
|
|
73
73
|
AppSec::Reactive::Operation.new('rack.response') do |op|
|
|
74
74
|
trace = active_trace
|
|
75
75
|
span = active_span
|
|
76
76
|
|
|
77
|
-
Rack::Reactive::Response.subscribe(op,
|
|
77
|
+
Rack::Reactive::Response.subscribe(op, scope.processor_context) do |result, _block|
|
|
78
78
|
if result.status == :match
|
|
79
79
|
# TODO: should this hash be an Event instance instead?
|
|
80
80
|
event = {
|
|
@@ -87,7 +87,7 @@ module Datadog
|
|
|
87
87
|
|
|
88
88
|
span.set_tag('appsec.event', 'true') if span
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
scope.processor_context.events << event
|
|
91
91
|
end
|
|
92
92
|
end
|
|
93
93
|
|
|
@@ -111,13 +111,13 @@ module Datadog
|
|
|
111
111
|
gateway.watch('rack.request.body', :appsec) do |stack, gateway_request|
|
|
112
112
|
block = false
|
|
113
113
|
event = nil
|
|
114
|
-
|
|
114
|
+
scope = gateway_request.env[Datadog::AppSec::Ext::SCOPE_KEY]
|
|
115
115
|
|
|
116
116
|
AppSec::Reactive::Operation.new('rack.request.body') do |op|
|
|
117
117
|
trace = active_trace
|
|
118
118
|
span = active_span
|
|
119
119
|
|
|
120
|
-
Rack::Reactive::RequestBody.subscribe(op,
|
|
120
|
+
Rack::Reactive::RequestBody.subscribe(op, scope.processor_context) do |result, _block|
|
|
121
121
|
if result.status == :match
|
|
122
122
|
# TODO: should this hash be an Event instance instead?
|
|
123
123
|
event = {
|
|
@@ -130,7 +130,7 @@ module Datadog
|
|
|
130
130
|
|
|
131
131
|
span.set_tag('appsec.event', 'true') if span
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
scope.processor_context.events << event
|
|
134
134
|
end
|
|
135
135
|
end
|
|
136
136
|
|
|
@@ -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
|
require_relative 'request_body_middleware'
|
|
@@ -33,10 +32,6 @@ module Datadog
|
|
|
33
32
|
false
|
|
34
33
|
end
|
|
35
34
|
|
|
36
|
-
def default_configuration
|
|
37
|
-
Configuration::Settings.new
|
|
38
|
-
end
|
|
39
|
-
|
|
40
35
|
def patcher
|
|
41
36
|
Patcher
|
|
42
37
|
end
|
|
@@ -13,6 +13,7 @@ module Datadog
|
|
|
13
13
|
'request.query',
|
|
14
14
|
'request.cookies',
|
|
15
15
|
'request.client_ip',
|
|
16
|
+
'server.request.method'
|
|
16
17
|
].freeze
|
|
17
18
|
private_constant :ADDRESSES
|
|
18
19
|
|
|
@@ -20,14 +21,16 @@ module Datadog
|
|
|
20
21
|
catch(:block) do
|
|
21
22
|
op.publish('request.query', gateway_request.query)
|
|
22
23
|
op.publish('request.headers', gateway_request.headers)
|
|
23
|
-
op.publish('request.uri.raw', gateway_request.
|
|
24
|
+
op.publish('request.uri.raw', gateway_request.fullpath)
|
|
24
25
|
op.publish('request.cookies', gateway_request.cookies)
|
|
25
26
|
op.publish('request.client_ip', gateway_request.client_ip)
|
|
27
|
+
op.publish('server.request.method', gateway_request.method)
|
|
26
28
|
|
|
27
29
|
nil
|
|
28
30
|
end
|
|
29
31
|
end
|
|
30
32
|
|
|
33
|
+
# rubocop:disable Metrics/MethodLength
|
|
31
34
|
def self.subscribe(op, waf_context)
|
|
32
35
|
op.subscribe(*ADDRESSES) do |*values|
|
|
33
36
|
Datadog.logger.debug { "reacted to #{ADDRESSES.inspect}: #{values.inspect}" }
|
|
@@ -37,6 +40,7 @@ module Datadog
|
|
|
37
40
|
query = values[2]
|
|
38
41
|
cookies = values[3]
|
|
39
42
|
client_ip = values[4]
|
|
43
|
+
request_method = values[5]
|
|
40
44
|
|
|
41
45
|
waf_args = {
|
|
42
46
|
'server.request.cookies' => cookies,
|
|
@@ -45,6 +49,7 @@ module Datadog
|
|
|
45
49
|
'server.request.headers' => headers,
|
|
46
50
|
'server.request.headers.no_cookies' => headers_no_cookies,
|
|
47
51
|
'http.client_ip' => client_ip,
|
|
52
|
+
'server.request.method' => request_method,
|
|
48
53
|
}
|
|
49
54
|
|
|
50
55
|
waf_timeout = Datadog::AppSec.settings.waf_timeout
|
|
@@ -71,6 +76,7 @@ module Datadog
|
|
|
71
76
|
Datadog.logger.debug { "WAF UNKNOWN: #{result.status.inspect} #{result.inspect}" }
|
|
72
77
|
end
|
|
73
78
|
end
|
|
79
|
+
# rubocop:enable Metrics/MethodLength
|
|
74
80
|
end
|
|
75
81
|
end
|
|
76
82
|
end
|
|
@@ -2,7 +2,6 @@ require 'json'
|
|
|
2
2
|
|
|
3
3
|
require_relative 'gateway/request'
|
|
4
4
|
require_relative 'gateway/response'
|
|
5
|
-
require_relative '../../ext'
|
|
6
5
|
require_relative '../../instrumentation/gateway'
|
|
7
6
|
require_relative '../../processor'
|
|
8
7
|
require_relative '../../response'
|
|
@@ -23,7 +22,7 @@ module Datadog
|
|
|
23
22
|
@oneshot_tags_sent = false
|
|
24
23
|
end
|
|
25
24
|
|
|
26
|
-
# rubocop:disable Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity,Metrics/MethodLength
|
|
25
|
+
# rubocop:disable Metrics/AbcSize,Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity,Metrics/MethodLength
|
|
27
26
|
def call(env)
|
|
28
27
|
return @app.call(env) unless Datadog::AppSec.enabled?
|
|
29
28
|
|
|
@@ -31,14 +30,19 @@ module Datadog
|
|
|
31
30
|
|
|
32
31
|
processor = nil
|
|
33
32
|
ready = false
|
|
34
|
-
|
|
33
|
+
scope = nil
|
|
34
|
+
|
|
35
|
+
# For a given request, keep using the first Rack stack scope for
|
|
36
|
+
# nested apps. Don't set `context` local variable so that on popping
|
|
37
|
+
# out of this nested stack we don't finalize the parent's context
|
|
38
|
+
return @app.call(env) if active_scope(env)
|
|
35
39
|
|
|
36
40
|
Datadog::AppSec.reconfigure_lock do
|
|
37
41
|
processor = Datadog::AppSec.processor
|
|
38
42
|
|
|
39
43
|
if !processor.nil? && processor.ready?
|
|
40
|
-
|
|
41
|
-
env[
|
|
44
|
+
scope = Datadog::AppSec::Scope.activate_scope(active_trace, active_span, processor)
|
|
45
|
+
env[Datadog::AppSec::Ext::SCOPE_KEY] = scope
|
|
42
46
|
ready = true
|
|
43
47
|
end
|
|
44
48
|
end
|
|
@@ -65,17 +69,17 @@ module Datadog
|
|
|
65
69
|
request_return[2],
|
|
66
70
|
request_return[0],
|
|
67
71
|
request_return[1],
|
|
68
|
-
|
|
72
|
+
scope: scope
|
|
69
73
|
)
|
|
70
74
|
|
|
71
75
|
_response_return, response_response = Instrumentation.gateway.push('rack.response', gateway_response)
|
|
72
76
|
|
|
73
|
-
|
|
77
|
+
scope.processor_context.events.each do |e|
|
|
74
78
|
e[:response] ||= gateway_response
|
|
75
79
|
e[:request] ||= gateway_request
|
|
76
80
|
end
|
|
77
81
|
|
|
78
|
-
AppSec::Event.record(*
|
|
82
|
+
AppSec::Event.record(active_span, *scope.processor_context.events)
|
|
79
83
|
|
|
80
84
|
if response_response && response_response.any? { |action, _event| action == :block }
|
|
81
85
|
request_return = AppSec::Response.negotiate(env).to_rack
|
|
@@ -83,15 +87,19 @@ module Datadog
|
|
|
83
87
|
|
|
84
88
|
request_return
|
|
85
89
|
ensure
|
|
86
|
-
if
|
|
87
|
-
add_waf_runtime_tags(
|
|
88
|
-
|
|
90
|
+
if scope
|
|
91
|
+
add_waf_runtime_tags(active_span, scope.processor_context)
|
|
92
|
+
Datadog::AppSec::Scope.deactivate_scope
|
|
89
93
|
end
|
|
90
94
|
end
|
|
91
|
-
# rubocop:enable Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity,Metrics/MethodLength
|
|
95
|
+
# rubocop:enable Metrics/AbcSize,Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity,Metrics/MethodLength
|
|
92
96
|
|
|
93
97
|
private
|
|
94
98
|
|
|
99
|
+
def active_scope(env)
|
|
100
|
+
env[Datadog::AppSec::Ext::SCOPE_KEY]
|
|
101
|
+
end
|
|
102
|
+
|
|
95
103
|
def active_trace
|
|
96
104
|
# TODO: factor out tracing availability detection
|
|
97
105
|
|
|
@@ -111,9 +119,9 @@ module Datadog
|
|
|
111
119
|
def add_appsec_tags(processor, trace, span, env)
|
|
112
120
|
return unless trace
|
|
113
121
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
122
|
+
span.set_tag('_dd.appsec.enabled', 1)
|
|
123
|
+
span.set_tag('_dd.runtime_family', 'ruby')
|
|
124
|
+
span.set_tag('_dd.appsec.waf.version', Datadog::AppSec::WAF::VERSION::BASE_STRING)
|
|
117
125
|
|
|
118
126
|
if span && span.get_tag(Tracing::Metadata::Ext::HTTP::TAG_CLIENT_IP).nil?
|
|
119
127
|
request_header_collection = Datadog::Tracing::Contrib::Rack::Header::RequestHeaderCollection.new(env)
|
|
@@ -127,17 +135,17 @@ module Datadog
|
|
|
127
135
|
end
|
|
128
136
|
|
|
129
137
|
if processor.ruleset_info
|
|
130
|
-
|
|
138
|
+
span.set_tag('_dd.appsec.event_rules.version', processor.ruleset_info[:version])
|
|
131
139
|
|
|
132
140
|
unless @oneshot_tags_sent
|
|
133
141
|
# Small race condition, but it's inoccuous: worst case the tags
|
|
134
142
|
# are sent a couple of times more than expected
|
|
135
143
|
@oneshot_tags_sent = true
|
|
136
144
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
145
|
+
span.set_tag('_dd.appsec.event_rules.loaded', processor.ruleset_info[:loaded].to_f)
|
|
146
|
+
span.set_tag('_dd.appsec.event_rules.error_count', processor.ruleset_info[:failed].to_f)
|
|
147
|
+
span.set_tag('_dd.appsec.event_rules.errors', JSON.dump(processor.ruleset_info[:errors]))
|
|
148
|
+
span.set_tag('_dd.appsec.event_rules.addresses', JSON.dump(processor.addresses))
|
|
141
149
|
|
|
142
150
|
# Ensure these tags reach the backend
|
|
143
151
|
trace.keep!
|
|
@@ -149,15 +157,15 @@ module Datadog
|
|
|
149
157
|
end
|
|
150
158
|
end
|
|
151
159
|
|
|
152
|
-
def add_waf_runtime_tags(
|
|
153
|
-
return unless
|
|
160
|
+
def add_waf_runtime_tags(span, context)
|
|
161
|
+
return unless span
|
|
154
162
|
return unless context
|
|
155
163
|
|
|
156
|
-
|
|
164
|
+
span.set_tag('_dd.appsec.waf.timeouts', context.timeouts)
|
|
157
165
|
|
|
158
166
|
# these tags expect time in us
|
|
159
|
-
|
|
160
|
-
|
|
167
|
+
span.set_tag('_dd.appsec.waf.duration', context.time_ns / 1000.0)
|
|
168
|
+
span.set_tag('_dd.appsec.waf.duration_ext', context.time_ext_ns / 1000.0)
|
|
161
169
|
end
|
|
162
170
|
end
|
|
163
171
|
end
|
|
@@ -8,21 +8,9 @@ module Datadog
|
|
|
8
8
|
module Framework
|
|
9
9
|
def self.setup
|
|
10
10
|
Datadog::AppSec.configure do |datadog_config|
|
|
11
|
-
|
|
12
|
-
activate_rack!(datadog_config, rails_config)
|
|
11
|
+
datadog_config.instrument(:rack)
|
|
13
12
|
end
|
|
14
13
|
end
|
|
15
|
-
|
|
16
|
-
def self.config_with_defaults(datadog_config)
|
|
17
|
-
datadog_config[:rails]
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# Apply relevant configuration from Sinatra to Rack
|
|
21
|
-
def self.activate_rack!(datadog_config, sinatra_config)
|
|
22
|
-
datadog_config.instrument(
|
|
23
|
-
:rack,
|
|
24
|
-
)
|
|
25
|
-
end
|
|
26
14
|
end
|
|
27
15
|
end
|
|
28
16
|
end
|
|
@@ -21,13 +21,13 @@ module Datadog
|
|
|
21
21
|
gateway.watch('rails.request.action', :appsec) do |stack, gateway_request|
|
|
22
22
|
block = false
|
|
23
23
|
event = nil
|
|
24
|
-
|
|
24
|
+
scope = gateway_request.env[Datadog::AppSec::Ext::SCOPE_KEY]
|
|
25
25
|
|
|
26
26
|
AppSec::Reactive::Operation.new('rails.request.action') do |op|
|
|
27
27
|
trace = active_trace
|
|
28
28
|
span = active_span
|
|
29
29
|
|
|
30
|
-
Rails::Reactive::Action.subscribe(op,
|
|
30
|
+
Rails::Reactive::Action.subscribe(op, scope.processor_context) do |result, _block|
|
|
31
31
|
if result.status == :match
|
|
32
32
|
# TODO: should this hash be an Event instance instead?
|
|
33
33
|
event = {
|
|
@@ -40,7 +40,7 @@ module Datadog
|
|
|
40
40
|
|
|
41
41
|
span.set_tag('appsec.event', 'true') if span
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
scope.processor_context.events << event
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
46
|
|
|
@@ -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
|
|
@@ -12,21 +12,9 @@ module Datadog
|
|
|
12
12
|
# Configure Rack from Sinatra, but only if Rack has not been configured manually beforehand
|
|
13
13
|
def self.setup
|
|
14
14
|
Datadog::AppSec.configure do |datadog_config|
|
|
15
|
-
|
|
16
|
-
activate_rack!(datadog_config, sinatra_config)
|
|
15
|
+
datadog_config.instrument(:rack)
|
|
17
16
|
end
|
|
18
17
|
end
|
|
19
|
-
|
|
20
|
-
def self.config_with_defaults(datadog_config)
|
|
21
|
-
datadog_config[:sinatra]
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# Apply relevant configuration from Sinatra to Rack
|
|
25
|
-
def self.activate_rack!(datadog_config, sinatra_config)
|
|
26
|
-
datadog_config.instrument(
|
|
27
|
-
:rack,
|
|
28
|
-
)
|
|
29
|
-
end
|
|
30
18
|
end
|
|
31
19
|
end
|
|
32
20
|
end
|