dd-trace 4.51.1 → 4.53.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/LICENSE-3rdparty.csv +8 -2
- package/ci/init.js +16 -0
- package/index.d.ts +31 -13
- package/init.js +4 -66
- package/initialize.mjs +13 -10
- package/loader-hook.mjs +4 -0
- package/package.json +16 -11
- package/packages/datadog-core/src/storage.js +39 -2
- package/packages/datadog-instrumentations/src/aerospike.js +1 -1
- package/packages/datadog-instrumentations/src/azure-functions.js +1 -1
- package/packages/datadog-instrumentations/src/cucumber.js +29 -3
- package/packages/datadog-instrumentations/src/express.js +38 -4
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +3 -3
- package/packages/datadog-instrumentations/src/helpers/hooks.js +0 -1
- package/packages/datadog-instrumentations/src/helpers/register.js +3 -4
- package/packages/datadog-instrumentations/src/http/client.js +1 -1
- package/packages/datadog-instrumentations/src/jest.js +27 -8
- package/packages/datadog-instrumentations/src/mocha/utils.js +2 -1
- package/packages/datadog-instrumentations/src/mysql2.js +13 -8
- package/packages/datadog-instrumentations/src/next.js +7 -4
- package/packages/datadog-instrumentations/src/passport-http.js +2 -14
- package/packages/datadog-instrumentations/src/passport-local.js +2 -14
- package/packages/datadog-instrumentations/src/passport-utils.js +43 -19
- package/packages/datadog-instrumentations/src/pg.js +6 -6
- package/packages/datadog-instrumentations/src/playwright.js +17 -4
- package/packages/datadog-instrumentations/src/router.js +97 -1
- package/packages/datadog-instrumentations/src/sequelize.js +9 -4
- package/packages/datadog-instrumentations/src/url.js +4 -0
- package/packages/datadog-instrumentations/src/vitest.js +27 -2
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +8 -3
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +154 -0
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/s3.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/util.js +92 -0
- package/packages/datadog-plugin-azure-functions/src/index.js +1 -1
- package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +1 -1
- package/packages/datadog-plugin-cucumber/src/index.js +39 -4
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +3 -3
- package/packages/datadog-plugin-grpc/src/client.js +2 -2
- package/packages/datadog-plugin-grpc/src/util.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +39 -4
- package/packages/datadog-plugin-langchain/src/handlers/language_models/chat_model.js +1 -1
- package/packages/datadog-plugin-langchain/src/handlers/language_models/llm.js +1 -1
- package/packages/datadog-plugin-mocha/src/index.js +36 -2
- package/packages/datadog-plugin-oracledb/src/index.js +1 -1
- package/packages/datadog-plugin-vitest/src/index.js +34 -2
- package/packages/datadog-shimmer/src/shimmer.js +8 -4
- package/packages/dd-trace/src/appsec/addresses.js +3 -0
- package/packages/dd-trace/src/appsec/api_security_sampler.js +1 -1
- package/packages/dd-trace/src/appsec/blocked_templates.js +1 -1
- package/packages/dd-trace/src/appsec/blocking.js +1 -1
- package/packages/dd-trace/src/appsec/channels.js +1 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/code-injection-analyzer.js +4 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js +2 -2
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-rules.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secret-rules.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secrets-rules.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/injection-analyzer.js +10 -3
- package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +4 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/template-injection-analyzer.js +4 -0
- package/packages/dd-trace/src/appsec/iast/iast-plugin.js +8 -21
- package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +3 -3
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +2 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +64 -3
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +5 -8
- package/packages/dd-trace/src/appsec/iast/taint-tracking/source-types.js +2 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +7 -11
- package/packages/dd-trace/src/appsec/iast/telemetry/namespaces.js +2 -3
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js +2 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/ldap-sensitive-analyzer.js +2 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +2 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js +2 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +3 -3
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-regex.js +2 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +32 -37
- package/packages/dd-trace/src/appsec/index.js +18 -13
- package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +2 -2
- package/packages/dd-trace/src/appsec/rasp/utils.js +1 -1
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +1 -0
- package/packages/dd-trace/src/appsec/remote_config/index.js +25 -1
- package/packages/dd-trace/src/appsec/remote_config/manager.js +2 -2
- package/packages/dd-trace/src/appsec/reporter.js +3 -1
- package/packages/dd-trace/src/appsec/sdk/set_user.js +2 -2
- package/packages/dd-trace/src/appsec/sdk/track_event.js +37 -24
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +4 -4
- package/packages/dd-trace/src/appsec/telemetry.js +10 -0
- package/packages/dd-trace/src/appsec/user_tracking.js +168 -0
- package/packages/dd-trace/src/appsec/waf/index.js +2 -2
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +2 -3
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +1 -1
- package/packages/dd-trace/src/azure_metadata.js +4 -4
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +5 -4
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +39 -3
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +29 -9
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +4 -2
- package/packages/dd-trace/src/config.js +24 -32
- package/packages/dd-trace/src/constants.js +1 -0
- package/packages/dd-trace/src/crashtracking/crashtracker.js +3 -2
- package/packages/dd-trace/src/datastreams/processor.js +4 -6
- package/packages/dd-trace/src/datastreams/writer.js +6 -5
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +80 -0
- package/packages/dd-trace/src/debugger/devtools_client/config.js +3 -1
- package/packages/dd-trace/src/debugger/devtools_client/defaults.js +6 -0
- package/packages/dd-trace/src/debugger/devtools_client/index.js +63 -8
- package/packages/dd-trace/src/debugger/devtools_client/remote_config.js +10 -67
- package/packages/dd-trace/src/debugger/devtools_client/send.js +2 -1
- package/packages/dd-trace/src/debugger/devtools_client/state.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/status.js +4 -4
- package/packages/dd-trace/src/debugger/index.js +14 -10
- package/packages/dd-trace/src/dogstatsd.js +2 -2
- package/packages/dd-trace/src/encode/0.4.js +23 -78
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +0 -32
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +1 -2
- package/packages/dd-trace/src/encode/span-stats.js +0 -30
- package/packages/dd-trace/src/exporters/agent/writer.js +3 -3
- package/packages/dd-trace/src/exporters/common/request.js +1 -1
- package/packages/dd-trace/src/exporters/span-stats/writer.js +1 -1
- package/packages/dd-trace/src/flare/index.js +1 -1
- package/packages/dd-trace/src/guardrails/index.js +64 -0
- package/packages/dd-trace/src/guardrails/log.js +32 -0
- package/packages/dd-trace/src/guardrails/telemetry.js +78 -0
- package/packages/dd-trace/src/guardrails/util.js +10 -0
- package/packages/dd-trace/src/lambda/runtime/ritm.js +2 -2
- package/packages/dd-trace/src/llmobs/storage.js +2 -3
- package/packages/dd-trace/src/llmobs/writers/base.js +2 -2
- package/packages/dd-trace/src/{encode → msgpack}/chunk.js +8 -5
- package/packages/dd-trace/src/msgpack/encoder.js +309 -0
- package/packages/dd-trace/src/msgpack/index.js +6 -0
- package/packages/dd-trace/src/opentelemetry/context_manager.js +2 -2
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +12 -9
- package/packages/dd-trace/src/opentracing/span.js +1 -1
- package/packages/dd-trace/src/opentracing/tracer.js +2 -2
- package/packages/dd-trace/src/plugin_manager.js +4 -2
- package/packages/dd-trace/src/plugins/ci_plugin.js +47 -4
- package/packages/dd-trace/src/plugins/plugin.js +1 -1
- package/packages/dd-trace/src/plugins/tracing.js +1 -1
- package/packages/dd-trace/src/plugins/util/git.js +7 -7
- package/packages/dd-trace/src/plugins/util/test.js +36 -3
- package/packages/dd-trace/src/plugins/util/web.js +2 -2
- package/packages/dd-trace/src/profiling/config.js +3 -0
- package/packages/dd-trace/src/profiling/exporters/agent.js +9 -68
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +76 -0
- package/packages/dd-trace/src/profiling/exporters/file.js +8 -4
- package/packages/dd-trace/src/profiling/profiler.js +62 -10
- package/packages/dd-trace/src/profiling/profilers/event_plugins/event.js +22 -12
- package/packages/dd-trace/src/profiling/profilers/events.js +47 -8
- package/packages/dd-trace/src/profiling/profilers/wall.js +2 -17
- package/packages/dd-trace/src/profiling/webspan-utils.js +23 -0
- package/packages/dd-trace/src/proxy.js +7 -2
- package/packages/dd-trace/src/runtime_metrics.js +107 -4
- package/packages/dd-trace/src/serverless.js +1 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/serverless.js +1 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/serverless.js +1 -1
- package/packages/dd-trace/src/span_processor.js +10 -10
- package/packages/dd-trace/src/tagger.js +1 -1
- package/packages/dd-trace/src/telemetry/index.js +1 -0
- package/packages/dd-trace/src/telemetry/logs/index.js +2 -2
- package/packages/dd-trace/src/telemetry/logs/log-collector.js +10 -2
- package/packages/dd-trace/src/telemetry/send-data.js +2 -2
- package/packages/dd-trace/src/util.js +5 -16
- package/packages/datadog-instrumentations/src/qs.js +0 -24
- package/packages/dd-trace/src/appsec/iast/iast-log.js +0 -86
- package/packages/dd-trace/src/appsec/passport.js +0 -110
- package/packages/dd-trace/src/telemetry/init-telemetry.js +0 -75
|
@@ -15,7 +15,7 @@ function isUserBlocked (user) {
|
|
|
15
15
|
|
|
16
16
|
function checkUserAndSetUser (tracer, user) {
|
|
17
17
|
if (!user || !user.id) {
|
|
18
|
-
log.warn('Invalid user provided to isUserBlocked')
|
|
18
|
+
log.warn('[ASM] Invalid user provided to isUserBlocked')
|
|
19
19
|
return false
|
|
20
20
|
}
|
|
21
21
|
|
|
@@ -25,7 +25,7 @@ function checkUserAndSetUser (tracer, user) {
|
|
|
25
25
|
setUserTags(user, rootSpan)
|
|
26
26
|
}
|
|
27
27
|
} else {
|
|
28
|
-
log.warn('Root span not available in isUserBlocked')
|
|
28
|
+
log.warn('[ASM] Root span not available in isUserBlocked')
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
return isUserBlocked(user)
|
|
@@ -41,13 +41,13 @@ function blockRequest (tracer, req, res) {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
if (!req || !res) {
|
|
44
|
-
log.warn('Requests or response object not available in blockRequest')
|
|
44
|
+
log.warn('[ASM] Requests or response object not available in blockRequest')
|
|
45
45
|
return false
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
const rootSpan = getRootSpan(tracer)
|
|
49
49
|
if (!rootSpan) {
|
|
50
|
-
log.warn('Root span not available in blockRequest')
|
|
50
|
+
log.warn('[ASM] Root span not available in blockRequest')
|
|
51
51
|
return false
|
|
52
52
|
}
|
|
53
53
|
|
|
@@ -172,6 +172,15 @@ function addRaspRequestMetrics (store, { duration, durationExt }) {
|
|
|
172
172
|
store[DD_TELEMETRY_REQUEST_METRICS].raspEvalCount++
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
+
function incrementMissingUserLoginMetric (framework, eventType) {
|
|
176
|
+
if (!enabled) return
|
|
177
|
+
|
|
178
|
+
appsecMetrics.count('instrum.user_auth.missing_user_login', {
|
|
179
|
+
framework,
|
|
180
|
+
event_type: eventType
|
|
181
|
+
}).inc()
|
|
182
|
+
}
|
|
183
|
+
|
|
175
184
|
function getRequestMetrics (req) {
|
|
176
185
|
if (req) {
|
|
177
186
|
const store = getStore(req)
|
|
@@ -188,6 +197,7 @@ module.exports = {
|
|
|
188
197
|
incrementWafInitMetric,
|
|
189
198
|
incrementWafUpdatesMetric,
|
|
190
199
|
incrementWafRequestsMetric,
|
|
200
|
+
incrementMissingUserLoginMetric,
|
|
191
201
|
|
|
192
202
|
getRequestMetrics
|
|
193
203
|
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const crypto = require('crypto')
|
|
4
|
+
const log = require('../log')
|
|
5
|
+
const telemetry = require('./telemetry')
|
|
6
|
+
const addresses = require('./addresses')
|
|
7
|
+
const { keepTrace } = require('../priority_sampler')
|
|
8
|
+
const { SAMPLING_MECHANISM_APPSEC } = require('../constants')
|
|
9
|
+
const standalone = require('./standalone')
|
|
10
|
+
const waf = require('./waf')
|
|
11
|
+
|
|
12
|
+
// the RFC doesn't include '_id', but it's common in MongoDB
|
|
13
|
+
const USER_ID_FIELDS = ['id', '_id', 'email', 'username', 'login', 'user']
|
|
14
|
+
|
|
15
|
+
let collectionMode
|
|
16
|
+
|
|
17
|
+
function setCollectionMode (mode, overwrite = true) {
|
|
18
|
+
// don't overwrite if already set, only used in appsec/index.js to not overwrite RC values
|
|
19
|
+
if (!overwrite && collectionMode) return
|
|
20
|
+
|
|
21
|
+
/* eslint-disable no-fallthrough */
|
|
22
|
+
switch (mode) {
|
|
23
|
+
case 'safe':
|
|
24
|
+
log.warn('[ASM] Using deprecated value "safe" in config.appsec.eventTracking.mode')
|
|
25
|
+
case 'anon':
|
|
26
|
+
case 'anonymization':
|
|
27
|
+
collectionMode = 'anonymization'
|
|
28
|
+
break
|
|
29
|
+
|
|
30
|
+
case 'extended':
|
|
31
|
+
log.warn('[ASM] Using deprecated value "extended" in config.appsec.eventTracking.mode')
|
|
32
|
+
case 'ident':
|
|
33
|
+
case 'identification':
|
|
34
|
+
collectionMode = 'identification'
|
|
35
|
+
break
|
|
36
|
+
|
|
37
|
+
default:
|
|
38
|
+
collectionMode = 'disabled'
|
|
39
|
+
}
|
|
40
|
+
/* eslint-enable no-fallthrough */
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function obfuscateIfNeeded (str) {
|
|
44
|
+
if (collectionMode === 'anonymization') {
|
|
45
|
+
// get first 16 bytes of sha256 hash in lowercase hex
|
|
46
|
+
return 'anon_' + crypto.createHash('sha256').update(str).digest().toString('hex', 0, 16).toLowerCase()
|
|
47
|
+
} else {
|
|
48
|
+
return str
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// TODO: should we find other ways to get the user ID ?
|
|
53
|
+
function getUserId (user) {
|
|
54
|
+
if (!user) return
|
|
55
|
+
|
|
56
|
+
for (const field of USER_ID_FIELDS) {
|
|
57
|
+
let id = user[field]
|
|
58
|
+
|
|
59
|
+
// try to find a field that can be stringified
|
|
60
|
+
if (id && typeof id.toString === 'function') {
|
|
61
|
+
id = id.toString()
|
|
62
|
+
|
|
63
|
+
if (typeof id !== 'string' || id.startsWith('[object ')) {
|
|
64
|
+
// probably not a usable ID ?
|
|
65
|
+
continue
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return obfuscateIfNeeded(id)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function trackLogin (framework, login, user, success, rootSpan) {
|
|
74
|
+
if (!collectionMode || collectionMode === 'disabled') return
|
|
75
|
+
|
|
76
|
+
if (!rootSpan) {
|
|
77
|
+
log.error('[ASM] No rootSpan found in AppSec trackLogin')
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (typeof login !== 'string') {
|
|
82
|
+
log.error('[ASM] Invalid login provided to AppSec trackLogin')
|
|
83
|
+
|
|
84
|
+
telemetry.incrementMissingUserLoginMetric(framework, success ? 'login_success' : 'login_failure')
|
|
85
|
+
// note:
|
|
86
|
+
// if we start supporting using userId if login is missing, we need to only give up if both are missing, and
|
|
87
|
+
// implement 'appsec.instrum.user_auth.missing_user_id' telemetry too
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
login = obfuscateIfNeeded(login)
|
|
92
|
+
const userId = getUserId(user)
|
|
93
|
+
|
|
94
|
+
let newTags
|
|
95
|
+
|
|
96
|
+
const persistent = {
|
|
97
|
+
[addresses.USER_LOGIN]: login
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const currentTags = rootSpan.context()._tags
|
|
101
|
+
const isSdkCalled = currentTags[`_dd.appsec.events.users.login.${success ? 'success' : 'failure'}.sdk`] === 'true'
|
|
102
|
+
|
|
103
|
+
// used to not overwrite tags set by SDK
|
|
104
|
+
function shouldSetTag (tag) {
|
|
105
|
+
return !(isSdkCalled && currentTags[tag])
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (success) {
|
|
109
|
+
newTags = {
|
|
110
|
+
'appsec.events.users.login.success.track': 'true',
|
|
111
|
+
'_dd.appsec.events.users.login.success.auto.mode': collectionMode,
|
|
112
|
+
'_dd.appsec.usr.login': login
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (shouldSetTag('appsec.events.users.login.success.usr.login')) {
|
|
116
|
+
newTags['appsec.events.users.login.success.usr.login'] = login
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (userId) {
|
|
120
|
+
newTags['_dd.appsec.usr.id'] = userId
|
|
121
|
+
|
|
122
|
+
if (shouldSetTag('usr.id')) {
|
|
123
|
+
newTags['usr.id'] = userId
|
|
124
|
+
persistent[addresses.USER_ID] = userId
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
persistent[addresses.LOGIN_SUCCESS] = null
|
|
129
|
+
} else {
|
|
130
|
+
newTags = {
|
|
131
|
+
'appsec.events.users.login.failure.track': 'true',
|
|
132
|
+
'_dd.appsec.events.users.login.failure.auto.mode': collectionMode,
|
|
133
|
+
'_dd.appsec.usr.login': login
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (shouldSetTag('appsec.events.users.login.failure.usr.login')) {
|
|
137
|
+
newTags['appsec.events.users.login.failure.usr.login'] = login
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (userId) {
|
|
141
|
+
newTags['_dd.appsec.usr.id'] = userId
|
|
142
|
+
|
|
143
|
+
if (shouldSetTag('appsec.events.users.login.failure.usr.id')) {
|
|
144
|
+
newTags['appsec.events.users.login.failure.usr.id'] = userId
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* TODO: if one day we have this info
|
|
149
|
+
if (exists != null && shouldSetTag('appsec.events.users.login.failure.usr.exists')) {
|
|
150
|
+
newTags['appsec.events.users.login.failure.usr.exists'] = exists
|
|
151
|
+
}
|
|
152
|
+
*/
|
|
153
|
+
|
|
154
|
+
persistent[addresses.LOGIN_FAILURE] = null
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
keepTrace(rootSpan, SAMPLING_MECHANISM_APPSEC)
|
|
158
|
+
standalone.sample(rootSpan)
|
|
159
|
+
|
|
160
|
+
rootSpan.addTags(newTags)
|
|
161
|
+
|
|
162
|
+
return waf.run({ persistent })
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
module.exports = {
|
|
166
|
+
setCollectionMode,
|
|
167
|
+
trackLogin
|
|
168
|
+
}
|
|
@@ -41,7 +41,7 @@ function update (newRules) {
|
|
|
41
41
|
try {
|
|
42
42
|
waf.wafManager.update(newRules)
|
|
43
43
|
} catch (err) {
|
|
44
|
-
log.error('Could not apply rules from remote config')
|
|
44
|
+
log.error('[ASM] Could not apply rules from remote config')
|
|
45
45
|
throw err
|
|
46
46
|
}
|
|
47
47
|
}
|
|
@@ -50,7 +50,7 @@ function run (data, req, raspRuleType) {
|
|
|
50
50
|
if (!req) {
|
|
51
51
|
const store = storage.getStore()
|
|
52
52
|
if (!store || !store.req) {
|
|
53
|
-
log.warn('Request object not available in waf.run')
|
|
53
|
+
log.warn('[ASM] Request object not available in waf.run')
|
|
54
54
|
return
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -23,7 +23,7 @@ class WAFContextWrapper {
|
|
|
23
23
|
|
|
24
24
|
run ({ persistent, ephemeral }, raspRuleType) {
|
|
25
25
|
if (this.ddwafContext.disposed) {
|
|
26
|
-
log.warn('Calling run on a disposed context')
|
|
26
|
+
log.warn('[ASM] Calling run on a disposed context')
|
|
27
27
|
return
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -101,8 +101,7 @@ class WAFContextWrapper {
|
|
|
101
101
|
|
|
102
102
|
return result.actions
|
|
103
103
|
} catch (err) {
|
|
104
|
-
log.error('Error while running the AppSec WAF')
|
|
105
|
-
log.error(err)
|
|
104
|
+
log.error('[ASM] Error while running the AppSec WAF', err)
|
|
106
105
|
}
|
|
107
106
|
}
|
|
108
107
|
|
|
@@ -25,7 +25,7 @@ class WAFManager {
|
|
|
25
25
|
const { obfuscatorKeyRegex, obfuscatorValueRegex } = this.config
|
|
26
26
|
return new DDWAF(rules, { obfuscatorKeyRegex, obfuscatorValueRegex })
|
|
27
27
|
} catch (err) {
|
|
28
|
-
log.error('AppSec could not load native package. In-app WAF features will not be available.')
|
|
28
|
+
log.error('[ASM] AppSec could not load native package. In-app WAF features will not be available.')
|
|
29
29
|
|
|
30
30
|
throw err
|
|
31
31
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
// eslint-disable-next-line max-len
|
|
3
|
+
// eslint-disable-next-line @stylistic/js/max-len
|
|
4
4
|
// Modeled after https://github.com/DataDog/libdatadog/blob/f3994857a59bb5679a65967138c5a3aec418a65f/ddcommon/src/azure_app_services.rs
|
|
5
5
|
|
|
6
6
|
const os = require('os')
|
|
@@ -79,7 +79,7 @@ function buildMetadata () {
|
|
|
79
79
|
function getAzureAppMetadata () {
|
|
80
80
|
// DD_AZURE_APP_SERVICES is an environment variable introduced by the .NET APM team and is set automatically for
|
|
81
81
|
// anyone using the Datadog APM Extensions (.NET, Java, or Node) for Windows Azure App Services
|
|
82
|
-
// eslint-disable-next-line max-len
|
|
82
|
+
// eslint-disable-next-line @stylistic/js/max-len
|
|
83
83
|
// See: https://github.com/DataDog/datadog-aas-extension/blob/01f94b5c28b7fa7a9ab264ca28bd4e03be603900/node/src/applicationHost.xdt#L20-L21
|
|
84
84
|
return process.env.DD_AZURE_APP_SERVICES !== undefined ? buildMetadata() : undefined
|
|
85
85
|
}
|
|
@@ -88,9 +88,9 @@ function getAzureFunctionMetadata () {
|
|
|
88
88
|
return getIsAzureFunction() ? buildMetadata() : undefined
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
// eslint-disable-next-line max-len
|
|
91
|
+
// eslint-disable-next-line @stylistic/js/max-len
|
|
92
92
|
// Modeled after https://github.com/DataDog/libdatadog/blob/92272e90a7919f07178f3246ef8f82295513cfed/profiling/src/exporter/mod.rs#L187
|
|
93
|
-
// eslint-disable-next-line max-len
|
|
93
|
+
// eslint-disable-next-line @stylistic/js/max-len
|
|
94
94
|
// and https://github.com/DataDog/libdatadog/blob/f3994857a59bb5679a65967138c5a3aec418a65f/trace-utils/src/trace_utils.rs#L533
|
|
95
95
|
function getAzureTagsFromMetadata (metadata) {
|
|
96
96
|
if (metadata === undefined) {
|
|
@@ -73,8 +73,7 @@ class TestVisDynamicInstrumentation {
|
|
|
73
73
|
// Allow the parent to exit even if the worker is still running
|
|
74
74
|
this.worker.unref()
|
|
75
75
|
|
|
76
|
-
this.breakpointSetChannel.port2.on('message', (
|
|
77
|
-
const { probeId } = message
|
|
76
|
+
this.breakpointSetChannel.port2.on('message', ({ probeId }) => {
|
|
78
77
|
const resolve = probeIdToResolveBreakpointSet.get(probeId)
|
|
79
78
|
if (resolve) {
|
|
80
79
|
resolve()
|
|
@@ -82,8 +81,7 @@ class TestVisDynamicInstrumentation {
|
|
|
82
81
|
}
|
|
83
82
|
}).unref()
|
|
84
83
|
|
|
85
|
-
this.breakpointHitChannel.port2.on('message', (
|
|
86
|
-
const { snapshot } = message
|
|
84
|
+
this.breakpointHitChannel.port2.on('message', ({ snapshot }) => {
|
|
87
85
|
const { probe: { id: probeId } } = snapshot
|
|
88
86
|
const resolve = probeIdToResolveBreakpointHit.get(probeId)
|
|
89
87
|
if (resolve) {
|
|
@@ -91,6 +89,9 @@ class TestVisDynamicInstrumentation {
|
|
|
91
89
|
probeIdToResolveBreakpointHit.delete(probeId)
|
|
92
90
|
}
|
|
93
91
|
}).unref()
|
|
92
|
+
|
|
93
|
+
this.worker.on('error', (err) => log.error('ci-visibility DI worker error', err))
|
|
94
|
+
this.worker.on('messageerror', (err) => log.error('ci-visibility DI worker messageerror', err))
|
|
94
95
|
}
|
|
95
96
|
}
|
|
96
97
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
-
|
|
2
|
+
const sourceMap = require('source-map')
|
|
3
|
+
const path = require('path')
|
|
3
4
|
const { workerData: { breakpointSetChannel, breakpointHitChannel } } = require('worker_threads')
|
|
5
|
+
|
|
4
6
|
// TODO: move debugger/devtools_client/session to common place
|
|
5
7
|
const session = require('../../../debugger/devtools_client/session')
|
|
6
8
|
// TODO: move debugger/devtools_client/snapshot to common place
|
|
@@ -69,14 +71,24 @@ async function addBreakpoint (snapshotId, probe) {
|
|
|
69
71
|
const script = findScriptFromPartialPath(file)
|
|
70
72
|
if (!script) throw new Error(`No loaded script found for ${file}`)
|
|
71
73
|
|
|
72
|
-
const [path, scriptId] = script
|
|
74
|
+
const [path, scriptId, sourceMapURL] = script
|
|
73
75
|
|
|
74
76
|
log.debug(`Adding breakpoint at ${path}:${line}`)
|
|
75
77
|
|
|
78
|
+
let lineNumber = line
|
|
79
|
+
|
|
80
|
+
if (sourceMapURL && sourceMapURL.startsWith('data:')) {
|
|
81
|
+
try {
|
|
82
|
+
lineNumber = await processScriptWithInlineSourceMap({ file, line, sourceMapURL })
|
|
83
|
+
} catch (err) {
|
|
84
|
+
log.error(err)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
76
88
|
const { breakpointId } = await session.post('Debugger.setBreakpoint', {
|
|
77
89
|
location: {
|
|
78
90
|
scriptId,
|
|
79
|
-
lineNumber:
|
|
91
|
+
lineNumber: lineNumber - 1
|
|
80
92
|
}
|
|
81
93
|
})
|
|
82
94
|
|
|
@@ -88,3 +100,27 @@ function start () {
|
|
|
88
100
|
sessionStarted = true
|
|
89
101
|
return session.post('Debugger.enable') // return instead of await to reduce number of promises created
|
|
90
102
|
}
|
|
103
|
+
|
|
104
|
+
async function processScriptWithInlineSourceMap (params) {
|
|
105
|
+
const { file, line, sourceMapURL } = params
|
|
106
|
+
|
|
107
|
+
// Extract the base64-encoded source map
|
|
108
|
+
const base64SourceMap = sourceMapURL.split('base64,')[1]
|
|
109
|
+
|
|
110
|
+
// Decode the base64 source map
|
|
111
|
+
const decodedSourceMap = Buffer.from(base64SourceMap, 'base64').toString('utf8')
|
|
112
|
+
|
|
113
|
+
// Parse the source map
|
|
114
|
+
const consumer = await new sourceMap.SourceMapConsumer(decodedSourceMap)
|
|
115
|
+
|
|
116
|
+
// Map to the generated position
|
|
117
|
+
const generatedPosition = consumer.generatedPositionFor({
|
|
118
|
+
source: path.basename(file), // this needs to be the file, not the filepath
|
|
119
|
+
line,
|
|
120
|
+
column: 0
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
consumer.destroy()
|
|
124
|
+
|
|
125
|
+
return generatedPosition.line
|
|
126
|
+
}
|
|
@@ -73,6 +73,9 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
73
73
|
if (this._coverageWriter) {
|
|
74
74
|
this._coverageWriter.flush()
|
|
75
75
|
}
|
|
76
|
+
if (this._logsWriter) {
|
|
77
|
+
this._logsWriter.flush()
|
|
78
|
+
}
|
|
76
79
|
})
|
|
77
80
|
}
|
|
78
81
|
|
|
@@ -193,7 +196,8 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
193
196
|
isEarlyFlakeDetectionEnabled,
|
|
194
197
|
earlyFlakeDetectionNumRetries,
|
|
195
198
|
earlyFlakeDetectionFaultyThreshold,
|
|
196
|
-
isFlakyTestRetriesEnabled
|
|
199
|
+
isFlakyTestRetriesEnabled,
|
|
200
|
+
isDiEnabled
|
|
197
201
|
} = remoteConfiguration
|
|
198
202
|
return {
|
|
199
203
|
isCodeCoverageEnabled,
|
|
@@ -204,7 +208,8 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
204
208
|
earlyFlakeDetectionNumRetries,
|
|
205
209
|
earlyFlakeDetectionFaultyThreshold,
|
|
206
210
|
isFlakyTestRetriesEnabled: isFlakyTestRetriesEnabled && this._config.isFlakyTestRetriesEnabled,
|
|
207
|
-
flakyTestRetriesCount: this._config.flakyTestRetriesCount
|
|
211
|
+
flakyTestRetriesCount: this._config.flakyTestRetriesCount,
|
|
212
|
+
isDiEnabled: isDiEnabled && this._config.isTestDynamicInstrumentationEnabled
|
|
208
213
|
}
|
|
209
214
|
}
|
|
210
215
|
|
|
@@ -222,7 +227,7 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
222
227
|
repositoryUrl,
|
|
223
228
|
(err) => {
|
|
224
229
|
if (err) {
|
|
225
|
-
log.error(
|
|
230
|
+
log.error('Error uploading git metadata: %s', err.message)
|
|
226
231
|
} else {
|
|
227
232
|
log.debug('Successfully uploaded git metadata')
|
|
228
233
|
}
|
|
@@ -302,13 +307,28 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
302
307
|
if (!this._isInitialized) {
|
|
303
308
|
return done()
|
|
304
309
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
310
|
+
|
|
311
|
+
// TODO: safe to do them at once? Or do we want to do them one by one?
|
|
312
|
+
const writers = [
|
|
313
|
+
this._writer,
|
|
314
|
+
this._coverageWriter,
|
|
315
|
+
this._logsWriter
|
|
316
|
+
].filter(writer => writer)
|
|
317
|
+
|
|
318
|
+
let remaining = writers.length
|
|
319
|
+
|
|
320
|
+
if (remaining === 0) {
|
|
321
|
+
return done()
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const onFlushComplete = () => {
|
|
325
|
+
remaining -= 1
|
|
326
|
+
if (remaining === 0) {
|
|
309
327
|
done()
|
|
310
328
|
}
|
|
311
|
-
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
writers.forEach(writer => writer.flush(onFlushComplete))
|
|
312
332
|
}
|
|
313
333
|
|
|
314
334
|
exportUncodedCoverages () {
|
|
@@ -327,7 +347,7 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
327
347
|
this._writer.setUrl(url)
|
|
328
348
|
this._coverageWriter.setUrl(coverageUrl)
|
|
329
349
|
} catch (e) {
|
|
330
|
-
log.error(e)
|
|
350
|
+
log.error('Error setting CI exporter url', e)
|
|
331
351
|
}
|
|
332
352
|
}
|
|
333
353
|
|
|
@@ -92,7 +92,8 @@ function getLibraryConfiguration ({
|
|
|
92
92
|
itr_enabled: isItrEnabled,
|
|
93
93
|
require_git: requireGit,
|
|
94
94
|
early_flake_detection: earlyFlakeDetectionConfig,
|
|
95
|
-
flaky_test_retries_enabled: isFlakyTestRetriesEnabled
|
|
95
|
+
flaky_test_retries_enabled: isFlakyTestRetriesEnabled,
|
|
96
|
+
di_enabled: isDiEnabled
|
|
96
97
|
}
|
|
97
98
|
}
|
|
98
99
|
} = JSON.parse(res)
|
|
@@ -107,7 +108,8 @@ function getLibraryConfiguration ({
|
|
|
107
108
|
earlyFlakeDetectionConfig?.slow_test_retries?.['5s'] || DEFAULT_EARLY_FLAKE_DETECTION_NUM_RETRIES,
|
|
108
109
|
earlyFlakeDetectionFaultyThreshold:
|
|
109
110
|
earlyFlakeDetectionConfig?.faulty_session_threshold ?? DEFAULT_EARLY_FLAKE_DETECTION_ERROR_THRESHOLD,
|
|
110
|
-
isFlakyTestRetriesEnabled
|
|
111
|
+
isFlakyTestRetriesEnabled,
|
|
112
|
+
isDiEnabled: isDiEnabled && isFlakyTestRetriesEnabled
|
|
111
113
|
}
|
|
112
114
|
|
|
113
115
|
log.debug(() => `Remote settings: ${JSON.stringify(settings)}`)
|