dd-trace 2.31.0 → 2.32.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.
- package/package.json +6 -6
- package/packages/datadog-instrumentations/src/body-parser.js +15 -9
- package/packages/datadog-instrumentations/src/express.js +32 -0
- package/packages/datadog-instrumentations/src/http/server.js +2 -1
- package/packages/datadog-instrumentations/src/playwright.js +3 -0
- package/packages/datadog-plugin-amqp10/src/consumer.js +1 -3
- package/packages/datadog-plugin-amqp10/src/producer.js +1 -3
- package/packages/datadog-plugin-amqplib/src/client.js +4 -3
- package/packages/datadog-plugin-amqplib/src/consumer.js +1 -3
- package/packages/datadog-plugin-amqplib/src/producer.js +1 -3
- package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +4 -3
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -3
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +1 -3
- package/packages/datadog-plugin-http/src/server.js +2 -2
- package/packages/datadog-plugin-http2/src/server.js +0 -5
- package/packages/datadog-plugin-kafkajs/src/consumer.js +1 -4
- package/packages/datadog-plugin-kafkajs/src/producer.js +1 -3
- package/packages/datadog-plugin-rhea/src/consumer.js +1 -3
- package/packages/datadog-plugin-rhea/src/producer.js +1 -5
- package/packages/dd-trace/src/appsec/addresses.js +0 -3
- package/packages/dd-trace/src/appsec/blocked_templates.js +2 -9
- package/packages/dd-trace/src/appsec/blocking.js +1 -1
- package/packages/dd-trace/src/appsec/{gateway/channels.js → channels.js} +4 -4
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -1
- package/packages/dd-trace/src/appsec/index.js +87 -79
- package/packages/dd-trace/src/appsec/recommended.json +448 -121
- package/packages/dd-trace/src/appsec/remote_config/apply_states.js +7 -0
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +2 -0
- package/packages/dd-trace/src/appsec/remote_config/index.js +29 -10
- package/packages/dd-trace/src/appsec/remote_config/manager.js +33 -12
- package/packages/dd-trace/src/appsec/reporter.js +27 -58
- package/packages/dd-trace/src/appsec/rule_manager.js +160 -32
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +4 -12
- package/packages/dd-trace/src/appsec/waf/index.js +75 -0
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +57 -0
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +66 -0
- package/packages/dd-trace/src/config.js +17 -1
- package/packages/dd-trace/src/encode/0.4.js +12 -4
- package/packages/dd-trace/src/plugin_manager.js +2 -0
- package/packages/dd-trace/src/plugins/client.js +3 -2
- package/packages/dd-trace/src/plugins/consumer.js +17 -2
- package/packages/dd-trace/src/plugins/inbound.js +7 -0
- package/packages/dd-trace/src/plugins/{outgoing.js → outbound.js} +2 -2
- package/packages/dd-trace/src/plugins/producer.js +17 -2
- package/packages/dd-trace/src/plugins/server.js +2 -2
- package/packages/dd-trace/src/plugins/tracing.js +11 -0
- package/packages/dd-trace/src/service-naming/index.js +41 -0
- package/packages/dd-trace/src/service-naming/schemas/definition.js +28 -0
- package/packages/dd-trace/src/service-naming/schemas/index.js +6 -0
- package/packages/dd-trace/src/service-naming/schemas/v0.js +66 -0
- package/packages/dd-trace/src/service-naming/schemas/v1.js +58 -0
- package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +0 -137
- package/packages/dd-trace/src/appsec/callbacks/index.js +0 -7
- package/packages/dd-trace/src/appsec/gateway/als.js +0 -6
- package/packages/dd-trace/src/appsec/gateway/engine/engine.js +0 -140
- package/packages/dd-trace/src/appsec/gateway/engine/index.js +0 -51
- package/packages/dd-trace/src/appsec/gateway/engine/runner.js +0 -42
- package/packages/dd-trace/src/plugins/incoming.js +0 -7
|
@@ -3,8 +3,13 @@
|
|
|
3
3
|
const log = require('../log')
|
|
4
4
|
const RuleManager = require('./rule_manager')
|
|
5
5
|
const remoteConfig = require('./remote_config')
|
|
6
|
-
const {
|
|
7
|
-
|
|
6
|
+
const {
|
|
7
|
+
incomingHttpRequestStart,
|
|
8
|
+
incomingHttpRequestEnd,
|
|
9
|
+
bodyParser,
|
|
10
|
+
queryParser
|
|
11
|
+
} = require('./channels')
|
|
12
|
+
const waf = require('./waf')
|
|
8
13
|
const addresses = require('./addresses')
|
|
9
14
|
const Reporter = require('./reporter')
|
|
10
15
|
const web = require('../plugins/util/web')
|
|
@@ -21,39 +26,25 @@ function enable (_config) {
|
|
|
21
26
|
try {
|
|
22
27
|
setTemplates(_config)
|
|
23
28
|
|
|
24
|
-
|
|
25
|
-
enableFromRules(_config, _config.appsec.rules)
|
|
26
|
-
} catch (err) {
|
|
27
|
-
abortEnable(err)
|
|
28
|
-
}
|
|
29
|
-
}
|
|
29
|
+
RuleManager.applyRules(_config.appsec.rules, _config.appsec)
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
RuleManager.applyRules(rules, _config.appsec)
|
|
33
|
-
remoteConfig.enableAsmData(_config.appsec)
|
|
31
|
+
remoteConfig.enableWafUpdate(_config.appsec)
|
|
34
32
|
|
|
35
|
-
|
|
33
|
+
Reporter.setRateLimit(_config.appsec.rateLimit)
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
Gateway.manager.addresses.add(addresses.HTTP_INCOMING_HEADERS)
|
|
42
|
-
Gateway.manager.addresses.add(addresses.HTTP_INCOMING_ENDPOINT)
|
|
43
|
-
Gateway.manager.addresses.add(addresses.HTTP_INCOMING_RESPONSE_HEADERS)
|
|
44
|
-
Gateway.manager.addresses.add(addresses.HTTP_INCOMING_REMOTE_IP)
|
|
45
|
-
|
|
46
|
-
isEnabled = true
|
|
47
|
-
config = _config
|
|
48
|
-
}
|
|
35
|
+
incomingHttpRequestStart.subscribe(incomingHttpStartTranslator)
|
|
36
|
+
incomingHttpRequestEnd.subscribe(incomingHttpEndTranslator)
|
|
37
|
+
bodyParser.subscribe(onRequestBodyParsed)
|
|
38
|
+
queryParser.subscribe(onRequestQueryParsed)
|
|
49
39
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
40
|
+
isEnabled = true
|
|
41
|
+
config = _config
|
|
42
|
+
} catch (err) {
|
|
43
|
+
log.error('Unable to start AppSec')
|
|
44
|
+
log.error(err)
|
|
53
45
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
remoteConfig.disableAsmData()
|
|
46
|
+
disable()
|
|
47
|
+
}
|
|
57
48
|
}
|
|
58
49
|
|
|
59
50
|
function incomingHttpStartTranslator ({ req, res, abortController }) {
|
|
@@ -68,78 +59,92 @@ function incomingHttpStartTranslator ({ req, res, abortController }) {
|
|
|
68
59
|
[HTTP_CLIENT_IP]: clientIp
|
|
69
60
|
})
|
|
70
61
|
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
store.set('req', req)
|
|
74
|
-
store.set('res', res)
|
|
62
|
+
const requestHeaders = Object.assign({}, req.headers)
|
|
63
|
+
delete requestHeaders.cookie
|
|
75
64
|
|
|
76
|
-
const
|
|
65
|
+
const payload = {
|
|
66
|
+
[addresses.HTTP_INCOMING_URL]: req.url,
|
|
67
|
+
[addresses.HTTP_INCOMING_HEADERS]: requestHeaders,
|
|
68
|
+
[addresses.HTTP_INCOMING_METHOD]: req.method
|
|
69
|
+
}
|
|
77
70
|
|
|
78
71
|
if (clientIp) {
|
|
79
|
-
|
|
80
|
-
[addresses.HTTP_CLIENT_IP]: clientIp
|
|
81
|
-
}, context)
|
|
82
|
-
|
|
83
|
-
if (!results || !abortController) return
|
|
84
|
-
|
|
85
|
-
for (const entry of results) {
|
|
86
|
-
if (entry && entry.includes('block')) {
|
|
87
|
-
block(req, res, rootSpan, abortController)
|
|
88
|
-
break
|
|
89
|
-
}
|
|
90
|
-
}
|
|
72
|
+
payload[addresses.HTTP_CLIENT_IP] = clientIp
|
|
91
73
|
}
|
|
92
|
-
}
|
|
93
74
|
|
|
94
|
-
|
|
95
|
-
const context = Gateway.getContext()
|
|
96
|
-
if (!context) return
|
|
75
|
+
const actions = waf.run(payload, req)
|
|
97
76
|
|
|
98
|
-
|
|
99
|
-
|
|
77
|
+
handleResults(actions, req, res, rootSpan, abortController)
|
|
78
|
+
}
|
|
100
79
|
|
|
80
|
+
function incomingHttpEndTranslator ({ req, res }) {
|
|
101
81
|
// TODO: this doesn't support headers sent with res.writeHead()
|
|
102
|
-
const responseHeaders = Object.assign({},
|
|
82
|
+
const responseHeaders = Object.assign({}, res.getHeaders())
|
|
103
83
|
delete responseHeaders['set-cookie']
|
|
104
84
|
|
|
105
85
|
const payload = {
|
|
106
|
-
[addresses.
|
|
107
|
-
[addresses.HTTP_INCOMING_HEADERS]: requestHeaders,
|
|
108
|
-
[addresses.HTTP_INCOMING_METHOD]: data.req.method,
|
|
109
|
-
[addresses.HTTP_INCOMING_REMOTE_IP]: data.req.socket.remoteAddress,
|
|
110
|
-
[addresses.HTTP_INCOMING_REMOTE_PORT]: data.req.socket.remotePort,
|
|
111
|
-
[addresses.HTTP_INCOMING_RESPONSE_CODE]: data.res.statusCode,
|
|
86
|
+
[addresses.HTTP_INCOMING_RESPONSE_CODE]: res.statusCode,
|
|
112
87
|
[addresses.HTTP_INCOMING_RESPONSE_HEADERS]: responseHeaders
|
|
113
88
|
}
|
|
114
89
|
|
|
115
|
-
//
|
|
116
|
-
if
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if (data.req.query && typeof data.req.query === 'object') {
|
|
121
|
-
payload[addresses.HTTP_INCOMING_QUERY] = data.req.query
|
|
90
|
+
// we need to keep this to support other body parsers
|
|
91
|
+
// TODO: no need to analyze it if it was already done by the body-parser hook
|
|
92
|
+
if (req.body !== undefined && req.body !== null) {
|
|
93
|
+
payload[addresses.HTTP_INCOMING_BODY] = req.body
|
|
122
94
|
}
|
|
123
95
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (data.req.params && typeof data.req.params === 'object') {
|
|
129
|
-
payload[addresses.HTTP_INCOMING_PARAMS] = data.req.params
|
|
96
|
+
// TODO: temporary express instrumentation, will use express plugin later
|
|
97
|
+
if (req.params && typeof req.params === 'object') {
|
|
98
|
+
payload[addresses.HTTP_INCOMING_PARAMS] = req.params
|
|
130
99
|
}
|
|
131
100
|
|
|
132
|
-
if (
|
|
101
|
+
if (req.cookies && typeof req.cookies === 'object') {
|
|
133
102
|
payload[addresses.HTTP_INCOMING_COOKIES] = {}
|
|
134
103
|
|
|
135
|
-
for (const k of Object.keys(
|
|
136
|
-
payload[addresses.HTTP_INCOMING_COOKIES][k] = [
|
|
104
|
+
for (const k of Object.keys(req.cookies)) {
|
|
105
|
+
payload[addresses.HTTP_INCOMING_COOKIES][k] = [req.cookies[k]]
|
|
137
106
|
}
|
|
138
107
|
}
|
|
139
108
|
|
|
140
|
-
|
|
109
|
+
waf.run(payload, req)
|
|
110
|
+
|
|
111
|
+
waf.disposeContext(req)
|
|
112
|
+
|
|
113
|
+
Reporter.finishRequest(req, res)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function onRequestBodyParsed ({ req, res, abortController }) {
|
|
117
|
+
const rootSpan = web.root(req)
|
|
118
|
+
if (!rootSpan) return
|
|
119
|
+
|
|
120
|
+
if (req.body === undefined || req.body === null) return
|
|
121
|
+
|
|
122
|
+
const results = waf.run({
|
|
123
|
+
[addresses.HTTP_INCOMING_BODY]: req.body
|
|
124
|
+
}, req)
|
|
141
125
|
|
|
142
|
-
|
|
126
|
+
handleResults(results, req, res, rootSpan, abortController)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function onRequestQueryParsed ({ req, res, abortController }) {
|
|
130
|
+
const rootSpan = web.root(req)
|
|
131
|
+
if (!rootSpan) return
|
|
132
|
+
|
|
133
|
+
if (!req.query || typeof req.query !== 'object') return
|
|
134
|
+
|
|
135
|
+
const results = waf.run({
|
|
136
|
+
[addresses.HTTP_INCOMING_QUERY]: req.query
|
|
137
|
+
}, req)
|
|
138
|
+
|
|
139
|
+
handleResults(results, req, res, rootSpan, abortController)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function handleResults (actions, req, res, rootSpan, abortController) {
|
|
143
|
+
if (!actions || !req || !res || !rootSpan || !abortController) return
|
|
144
|
+
|
|
145
|
+
if (actions.includes('block')) {
|
|
146
|
+
block(req, res, rootSpan, abortController)
|
|
147
|
+
}
|
|
143
148
|
}
|
|
144
149
|
|
|
145
150
|
function disable () {
|
|
@@ -147,11 +152,14 @@ function disable () {
|
|
|
147
152
|
config = null
|
|
148
153
|
|
|
149
154
|
RuleManager.clearAllRules()
|
|
150
|
-
|
|
155
|
+
|
|
156
|
+
remoteConfig.disableWafUpdate()
|
|
151
157
|
|
|
152
158
|
// Channel#unsubscribe() is undefined for non active channels
|
|
153
159
|
if (incomingHttpRequestStart.hasSubscribers) incomingHttpRequestStart.unsubscribe(incomingHttpStartTranslator)
|
|
154
160
|
if (incomingHttpRequestEnd.hasSubscribers) incomingHttpRequestEnd.unsubscribe(incomingHttpEndTranslator)
|
|
161
|
+
if (bodyParser.hasSubscribers) bodyParser.unsubscribe(onRequestBodyParsed)
|
|
162
|
+
if (queryParser.hasSubscribers) queryParser.unsubscribe(onRequestQueryParsed)
|
|
155
163
|
}
|
|
156
164
|
|
|
157
165
|
module.exports = {
|