dd-trace 2.4.2 → 2.6.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 +1 -0
- package/ci/init.js +6 -0
- package/ci/jest/env.js +16 -3
- package/ext/exporters.d.ts +2 -1
- package/ext/exporters.js +2 -1
- package/index.d.ts +17 -1
- package/package.json +5 -4
- package/packages/datadog-instrumentations/index.js +1 -0
- package/packages/datadog-instrumentations/src/cypress.js +8 -0
- package/packages/datadog-instrumentations/src/jest.js +170 -0
- package/packages/datadog-plugin-aws-sdk/src/helpers.js +4 -4
- package/packages/datadog-plugin-aws-sdk/src/index.js +1 -1
- package/packages/datadog-plugin-cucumber/src/index.js +16 -16
- package/packages/datadog-plugin-cypress/src/index.js +10 -5
- package/packages/datadog-plugin-cypress/src/plugin.js +18 -17
- package/packages/datadog-plugin-fs/src/index.js +2 -0
- package/packages/datadog-plugin-http/src/server.js +0 -8
- package/packages/datadog-plugin-jest/src/index.js +101 -3
- package/packages/datadog-plugin-jest/src/util.js +1 -29
- package/packages/datadog-plugin-mocha/src/index.js +14 -15
- package/packages/dd-trace/lib/version.js +1 -1
- package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +29 -12
- package/packages/dd-trace/src/appsec/index.js +7 -3
- package/packages/dd-trace/src/appsec/recommended.json +15 -5
- package/packages/dd-trace/src/appsec/reporter.js +29 -3
- package/packages/dd-trace/src/appsec/rule_manager.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +32 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +51 -0
- package/packages/dd-trace/src/config.js +33 -4
- package/packages/dd-trace/src/encode/0.4.js +0 -1
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +193 -0
- package/packages/dd-trace/src/encode/tags-processors.js +116 -0
- package/packages/dd-trace/src/exporter.js +3 -0
- package/packages/dd-trace/src/exporters/agent/index.js +1 -1
- package/packages/dd-trace/src/exporters/agent/writer.js +7 -32
- package/packages/dd-trace/src/exporters/{agent → common}/docker.js +0 -0
- package/packages/dd-trace/src/exporters/common/request.js +83 -0
- package/packages/dd-trace/src/exporters/common/writer.js +36 -0
- package/packages/dd-trace/src/exporters/{agent/scheduler.js → scheduler.js} +0 -0
- package/packages/dd-trace/src/format.js +9 -5
- package/packages/dd-trace/src/instrumenter.js +3 -0
- package/packages/dd-trace/src/pkg.js +11 -6
- package/packages/dd-trace/src/plugins/util/test.js +79 -1
- package/packages/dd-trace/src/plugins/util/web.js +11 -10
- package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/cpu.js +1 -1
- package/packages/dd-trace/src/proxy.js +2 -0
- package/packages/dd-trace/src/span_processor.js +4 -1
- package/packages/dd-trace/src/telemetry.js +187 -0
- package/scripts/install_plugin_modules.js +1 -0
- package/packages/datadog-plugin-jest/src/jest-environment.js +0 -272
- package/packages/datadog-plugin-jest/src/jest-jasmine2.js +0 -185
- package/packages/dd-trace/src/exporters/agent/request.js +0 -86
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
const { SAMPLING_RULE_DECISION } = require('../../dd-trace/src/constants')
|
|
2
|
-
const { SAMPLING_PRIORITY, SPAN_TYPE } = require('../../../ext/tags')
|
|
3
|
-
const { AUTO_KEEP } = require('../../../ext/priority')
|
|
4
|
-
const { TEST_TYPE, TEST_STATUS, getTestParentSpan } = require('../../dd-trace/src/plugins/util/test')
|
|
5
|
-
|
|
6
1
|
/**
|
|
7
2
|
* There are two ways to call `test.each` in `jest`:
|
|
8
3
|
* 1. With an array of arrays: https://jestjs.io/docs/api#1-testeachtablename-fn-timeout
|
|
@@ -38,27 +33,4 @@ function getFormattedJestTestParameters (testParameters) {
|
|
|
38
33
|
return formattedParameters
|
|
39
34
|
}
|
|
40
35
|
|
|
41
|
-
|
|
42
|
-
const childOf = getTestParentSpan(tracer)
|
|
43
|
-
|
|
44
|
-
const commonSpanTags = {
|
|
45
|
-
[TEST_TYPE]: 'test',
|
|
46
|
-
[SAMPLING_RULE_DECISION]: 1,
|
|
47
|
-
[SAMPLING_PRIORITY]: AUTO_KEEP,
|
|
48
|
-
[SPAN_TYPE]: 'test',
|
|
49
|
-
...testEnvironmentMetadata
|
|
50
|
-
}
|
|
51
|
-
return {
|
|
52
|
-
childOf,
|
|
53
|
-
commonSpanTags
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function setSuppressedErrors (suppressedErrors, testSpan) {
|
|
58
|
-
if (suppressedErrors && suppressedErrors.length) {
|
|
59
|
-
testSpan.setTag('error', suppressedErrors[0])
|
|
60
|
-
testSpan.setTag(TEST_STATUS, 'fail')
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
module.exports = { getFormattedJestTestParameters, getTestSpanTags, setSuppressedErrors }
|
|
36
|
+
module.exports = { getFormattedJestTestParameters }
|
|
@@ -5,21 +5,19 @@ const { storage } = require('../../datadog-core')
|
|
|
5
5
|
|
|
6
6
|
const {
|
|
7
7
|
CI_APP_ORIGIN,
|
|
8
|
-
|
|
9
|
-
TEST_NAME,
|
|
8
|
+
TEST_CODE_OWNERS,
|
|
10
9
|
TEST_SUITE,
|
|
11
|
-
TEST_FRAMEWORK_VERSION,
|
|
12
10
|
TEST_STATUS,
|
|
13
11
|
TEST_PARAMETERS,
|
|
14
12
|
finishAllTraceSpans,
|
|
15
13
|
getTestEnvironmentMetadata,
|
|
16
14
|
getTestSuitePath,
|
|
17
15
|
getTestParentSpan,
|
|
18
|
-
getTestParametersString
|
|
16
|
+
getTestParametersString,
|
|
17
|
+
getCodeOwnersFileEntries,
|
|
18
|
+
getCodeOwnersForFilename,
|
|
19
|
+
getTestCommonTags
|
|
19
20
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
20
|
-
const { SPAN_TYPE, RESOURCE_NAME, SAMPLING_PRIORITY } = require('../../../ext/tags')
|
|
21
|
-
const { SAMPLING_RULE_DECISION } = require('../../dd-trace/src/constants')
|
|
22
|
-
const { AUTO_KEEP } = require('../../../ext/priority')
|
|
23
21
|
|
|
24
22
|
const skippedTests = new WeakSet()
|
|
25
23
|
|
|
@@ -30,16 +28,11 @@ function getTestSpanMetadata (tracer, test, sourceRoot) {
|
|
|
30
28
|
const fullTestName = test.fullTitle()
|
|
31
29
|
const testSuite = getTestSuitePath(testSuiteAbsolutePath, sourceRoot)
|
|
32
30
|
|
|
31
|
+
const commonTags = getTestCommonTags(fullTestName, testSuite, tracer._version)
|
|
32
|
+
|
|
33
33
|
return {
|
|
34
34
|
childOf,
|
|
35
|
-
|
|
36
|
-
[TEST_TYPE]: 'test',
|
|
37
|
-
[TEST_NAME]: fullTestName,
|
|
38
|
-
[TEST_SUITE]: testSuite,
|
|
39
|
-
[SAMPLING_RULE_DECISION]: 1,
|
|
40
|
-
[SAMPLING_PRIORITY]: AUTO_KEEP,
|
|
41
|
-
[TEST_FRAMEWORK_VERSION]: tracer._version,
|
|
42
|
-
[RESOURCE_NAME]: `${testSuite}.${fullTestName}`
|
|
35
|
+
...commonTags
|
|
43
36
|
}
|
|
44
37
|
}
|
|
45
38
|
|
|
@@ -54,6 +47,7 @@ class MochaPlugin extends Plugin {
|
|
|
54
47
|
this._testNameToParams = {}
|
|
55
48
|
this.testEnvironmentMetadata = getTestEnvironmentMetadata('mocha', this.config)
|
|
56
49
|
this.sourceRoot = process.cwd()
|
|
50
|
+
this.codeOwnersEntries = getCodeOwnersFileEntries(this.sourceRoot)
|
|
57
51
|
|
|
58
52
|
this.addSub('ci:mocha:test:start', (test) => {
|
|
59
53
|
const store = storage.getStore()
|
|
@@ -139,6 +133,11 @@ class MochaPlugin extends Plugin {
|
|
|
139
133
|
if (testParametersString) {
|
|
140
134
|
testSpanMetadata[TEST_PARAMETERS] = testParametersString
|
|
141
135
|
}
|
|
136
|
+
const codeOwners = getCodeOwnersForFilename(testSpanMetadata[TEST_SUITE], this.codeOwnersEntries)
|
|
137
|
+
|
|
138
|
+
if (codeOwners) {
|
|
139
|
+
testSpanMetadata[TEST_CODE_OWNERS] = codeOwners
|
|
140
|
+
}
|
|
142
141
|
|
|
143
142
|
const testSpan = this.tracer
|
|
144
143
|
.startSpan('mocha.test', {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
module.exports = '2.
|
|
1
|
+
module.exports = '2.6.0'
|
|
@@ -7,16 +7,14 @@ const Reporter = require('../reporter')
|
|
|
7
7
|
|
|
8
8
|
const validAddressSet = new Set(Object.values(addresses))
|
|
9
9
|
|
|
10
|
-
const DEFAULT_MAX_BUDGET = 5e3 // µs
|
|
11
|
-
|
|
12
10
|
// TODO: put reusable code in a base class
|
|
13
11
|
class WAFCallback {
|
|
14
|
-
static loadDDWAF (rules) {
|
|
12
|
+
static loadDDWAF (rules, config) {
|
|
15
13
|
try {
|
|
16
14
|
// require in `try/catch` because this can throw at require time
|
|
17
15
|
const { DDWAF } = require('@datadog/native-appsec')
|
|
18
16
|
|
|
19
|
-
return new DDWAF(rules)
|
|
17
|
+
return new DDWAF(rules, config)
|
|
20
18
|
} catch (err) {
|
|
21
19
|
log.error('AppSec could not load native package. In-app WAF features will not be available.')
|
|
22
20
|
|
|
@@ -24,8 +22,24 @@ class WAFCallback {
|
|
|
24
22
|
}
|
|
25
23
|
}
|
|
26
24
|
|
|
27
|
-
constructor (rules) {
|
|
28
|
-
|
|
25
|
+
constructor (rules, config) {
|
|
26
|
+
const { wafTimeout, obfuscatorKeyRegex, obfuscatorValueRegex } = config
|
|
27
|
+
|
|
28
|
+
this.ddwaf = WAFCallback.loadDDWAF(rules, { obfuscatorKeyRegex, obfuscatorValueRegex })
|
|
29
|
+
|
|
30
|
+
this.wafTimeout = wafTimeout
|
|
31
|
+
|
|
32
|
+
const version = this.ddwaf.constructor.version()
|
|
33
|
+
|
|
34
|
+
Reporter.metricsQueue.set('_dd.appsec.waf.version', `${version.major}.${version.minor}.${version.patch}`)
|
|
35
|
+
|
|
36
|
+
const { loaded, failed } = this.ddwaf.rulesInfo
|
|
37
|
+
|
|
38
|
+
Reporter.metricsQueue.set('_dd.appsec.event_rules.loaded', loaded)
|
|
39
|
+
Reporter.metricsQueue.set('_dd.appsec.event_rules.error_count', failed)
|
|
40
|
+
|
|
41
|
+
Reporter.metricsQueue.set('manual.keep', true)
|
|
42
|
+
|
|
29
43
|
this.wafContextCache = new WeakMap()
|
|
30
44
|
|
|
31
45
|
// closures are faster than binds
|
|
@@ -70,7 +84,7 @@ class WAFCallback {
|
|
|
70
84
|
}
|
|
71
85
|
}
|
|
72
86
|
|
|
73
|
-
if (!wafContext) {
|
|
87
|
+
if (!wafContext || wafContext.disposed) {
|
|
74
88
|
wafContext = this.ddwaf.createContext()
|
|
75
89
|
}
|
|
76
90
|
|
|
@@ -81,23 +95,26 @@ class WAFCallback {
|
|
|
81
95
|
|
|
82
96
|
try {
|
|
83
97
|
// TODO: possible optimizaion: only send params that haven't already been sent to this wafContext
|
|
84
|
-
const result = wafContext.run(params,
|
|
98
|
+
const result = wafContext.run(params, this.wafTimeout)
|
|
85
99
|
|
|
86
100
|
return this.applyResult(result, store)
|
|
87
101
|
} catch (err) {
|
|
88
102
|
log.error('Error while running the AppSec WAF')
|
|
89
103
|
log.error(err)
|
|
104
|
+
} finally {
|
|
105
|
+
wafContext.dispose()
|
|
90
106
|
}
|
|
91
107
|
}
|
|
92
108
|
|
|
93
109
|
applyResult (result, store) {
|
|
110
|
+
Reporter.reportMetrics({
|
|
111
|
+
duration: result.totalRuntime,
|
|
112
|
+
rulesVersion: this.ddwaf.rulesInfo.version
|
|
113
|
+
}, store)
|
|
114
|
+
|
|
94
115
|
if (result.data && result.data !== '[]') {
|
|
95
116
|
Reporter.reportAttack(result.data, store)
|
|
96
117
|
}
|
|
97
|
-
|
|
98
|
-
// TODO: use these values later for budget management
|
|
99
|
-
// result.perfData
|
|
100
|
-
// result.perfTotalRuntime
|
|
101
118
|
}
|
|
102
119
|
|
|
103
120
|
clear () {
|
|
@@ -16,7 +16,7 @@ function enable (config) {
|
|
|
16
16
|
let rules = fs.readFileSync(config.appsec.rules)
|
|
17
17
|
rules = JSON.parse(rules)
|
|
18
18
|
|
|
19
|
-
RuleManager.applyRules(rules)
|
|
19
|
+
RuleManager.applyRules(rules, config.appsec)
|
|
20
20
|
} catch (err) {
|
|
21
21
|
log.error('Unable to start AppSec')
|
|
22
22
|
log.error(err)
|
|
@@ -94,12 +94,16 @@ function incomingHttpEndTranslator (data) {
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
if (data.req.cookies && typeof data.req.cookies === 'object') {
|
|
97
|
-
payload[addresses.HTTP_INCOMING_COOKIES] =
|
|
97
|
+
payload[addresses.HTTP_INCOMING_COOKIES] = {}
|
|
98
|
+
|
|
99
|
+
for (const k of Object.keys(data.req.cookies)) {
|
|
100
|
+
payload[addresses.HTTP_INCOMING_COOKIES][k] = [ data.req.cookies[k] ]
|
|
101
|
+
}
|
|
98
102
|
}
|
|
99
103
|
|
|
100
104
|
Gateway.propagate(payload, context)
|
|
101
105
|
|
|
102
|
-
Reporter.
|
|
106
|
+
Reporter.finishRequest(data.req, context)
|
|
103
107
|
}
|
|
104
108
|
|
|
105
109
|
function disable () {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "2.2",
|
|
3
3
|
"metadata": {
|
|
4
|
-
"rules_version": "1.3.
|
|
4
|
+
"rules_version": "1.3.1"
|
|
5
5
|
},
|
|
6
6
|
"rules": [
|
|
7
7
|
{
|
|
@@ -3040,7 +3040,9 @@
|
|
|
3040
3040
|
"operator": "match_regex"
|
|
3041
3041
|
}
|
|
3042
3042
|
],
|
|
3043
|
-
"transformers": [
|
|
3043
|
+
"transformers": [
|
|
3044
|
+
"keys_only"
|
|
3045
|
+
]
|
|
3044
3046
|
},
|
|
3045
3047
|
{
|
|
3046
3048
|
"id": "crs-942-360",
|
|
@@ -4097,15 +4099,23 @@
|
|
|
4097
4099
|
"parameters": {
|
|
4098
4100
|
"inputs": [
|
|
4099
4101
|
{
|
|
4100
|
-
"address": "server.request.
|
|
4102
|
+
"address": "server.request.query"
|
|
4103
|
+
},
|
|
4104
|
+
{
|
|
4105
|
+
"address": "server.request.body"
|
|
4106
|
+
},
|
|
4107
|
+
{
|
|
4108
|
+
"address": "server.request.path_params"
|
|
4101
4109
|
}
|
|
4102
4110
|
],
|
|
4103
|
-
"regex": "
|
|
4111
|
+
"regex": "^\\$(eq|ne|(l|g)te?|n?in|not|(n|x|)or|and|regex|where|expr|exists)$"
|
|
4104
4112
|
},
|
|
4105
4113
|
"operator": "match_regex"
|
|
4106
4114
|
}
|
|
4107
4115
|
],
|
|
4108
|
-
"transformers": [
|
|
4116
|
+
"transformers": [
|
|
4117
|
+
"keys_only"
|
|
4118
|
+
]
|
|
4109
4119
|
},
|
|
4110
4120
|
{
|
|
4111
4121
|
"id": "sqr-000-008",
|
|
@@ -35,6 +35,8 @@ const RESPONSE_HEADERS_PASSLIST = [
|
|
|
35
35
|
'content-type'
|
|
36
36
|
]
|
|
37
37
|
|
|
38
|
+
const metricsQueue = new Map()
|
|
39
|
+
|
|
38
40
|
function resolveHTTPRequest (context) {
|
|
39
41
|
if (!context) return {}
|
|
40
42
|
|
|
@@ -82,6 +84,20 @@ function formatHeaderName (name) {
|
|
|
82
84
|
.toLowerCase()
|
|
83
85
|
}
|
|
84
86
|
|
|
87
|
+
function reportMetrics (metrics, store) {
|
|
88
|
+
const req = store && store.get('req')
|
|
89
|
+
const topSpan = web.root(req)
|
|
90
|
+
if (!topSpan) return false
|
|
91
|
+
|
|
92
|
+
if (metrics.duration) {
|
|
93
|
+
topSpan.setTag('_dd.appsec.waf.duration', metrics.duration)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (metrics.rulesVersion) {
|
|
97
|
+
topSpan.setTag('_dd.appsec.event_rules.version', metrics.rulesVersion)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
85
101
|
function reportAttack (attackData, store) {
|
|
86
102
|
const req = store && store.get('req')
|
|
87
103
|
const topSpan = web.root(req)
|
|
@@ -129,9 +145,17 @@ function reportAttack (attackData, store) {
|
|
|
129
145
|
topSpan.addTags(newTags)
|
|
130
146
|
}
|
|
131
147
|
|
|
132
|
-
function
|
|
148
|
+
function finishRequest (req, context) {
|
|
133
149
|
const topSpan = web.root(req)
|
|
134
|
-
if (!topSpan
|
|
150
|
+
if (!topSpan) return false
|
|
151
|
+
|
|
152
|
+
if (metricsQueue.size) {
|
|
153
|
+
topSpan.addTags(Object.fromEntries(metricsQueue))
|
|
154
|
+
|
|
155
|
+
metricsQueue.clear()
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (!context || !topSpan.context()._tags['appsec.event']) return false
|
|
135
159
|
|
|
136
160
|
const resolvedResponse = resolveHTTPResponse(context)
|
|
137
161
|
|
|
@@ -149,11 +173,13 @@ function setRateLimit (rateLimit) {
|
|
|
149
173
|
}
|
|
150
174
|
|
|
151
175
|
module.exports = {
|
|
176
|
+
metricsQueue,
|
|
152
177
|
resolveHTTPRequest,
|
|
153
178
|
resolveHTTPResponse,
|
|
154
179
|
filterHeaders,
|
|
155
180
|
formatHeaderName,
|
|
181
|
+
reportMetrics,
|
|
156
182
|
reportAttack,
|
|
157
|
-
|
|
183
|
+
finishRequest,
|
|
158
184
|
setRateLimit
|
|
159
185
|
}
|
|
@@ -4,11 +4,11 @@ const callbacks = require('./callbacks')
|
|
|
4
4
|
|
|
5
5
|
const appliedCallbacks = new Map()
|
|
6
6
|
|
|
7
|
-
function applyRules (rules) {
|
|
7
|
+
function applyRules (rules, config) {
|
|
8
8
|
if (appliedCallbacks.has(rules)) return
|
|
9
9
|
|
|
10
10
|
// for now there is only WAF
|
|
11
|
-
const callback = new callbacks.DDWAF(rules)
|
|
11
|
+
const callback = new callbacks.DDWAF(rules, config)
|
|
12
12
|
|
|
13
13
|
appliedCallbacks.set(rules, callback)
|
|
14
14
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const URL = require('url').URL
|
|
4
|
+
const Writer = require('./writer')
|
|
5
|
+
const Scheduler = require('../../../exporters/scheduler')
|
|
6
|
+
|
|
7
|
+
class AgentlessCiVisibilityExporter {
|
|
8
|
+
constructor (config) {
|
|
9
|
+
const { flushInterval, tags, site, url } = config
|
|
10
|
+
this._url = url || new URL(`https://citestcycle-intake.${site}`)
|
|
11
|
+
this._writer = new Writer({ url: this._url, tags })
|
|
12
|
+
|
|
13
|
+
if (flushInterval > 0) {
|
|
14
|
+
this._scheduler = new Scheduler(() => this._writer.flush(), flushInterval)
|
|
15
|
+
}
|
|
16
|
+
this._scheduler && this._scheduler.start()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export (trace) {
|
|
20
|
+
this._writer.append(trace)
|
|
21
|
+
|
|
22
|
+
if (!this._scheduler) {
|
|
23
|
+
this._writer.flush()
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
flush () {
|
|
28
|
+
this._writer.flush()
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = AgentlessCiVisibilityExporter
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
const request = require('../../../exporters/common/request')
|
|
3
|
+
const log = require('../../../log')
|
|
4
|
+
|
|
5
|
+
const { AgentlessCiVisibilityEncoder } = require('../../../encode/agentless-ci-visibility')
|
|
6
|
+
const BaseWriter = require('../../../exporters/common/writer')
|
|
7
|
+
|
|
8
|
+
class Writer extends BaseWriter {
|
|
9
|
+
constructor ({ url, tags }) {
|
|
10
|
+
super(...arguments)
|
|
11
|
+
const { 'runtime-id': runtimeId, env, service } = tags
|
|
12
|
+
this._url = url
|
|
13
|
+
this._encoder = new AgentlessCiVisibilityEncoder({ runtimeId, env, service })
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
_sendPayload (data, _, done) {
|
|
17
|
+
makeRequest(data, this._url, (err, res) => {
|
|
18
|
+
if (err) {
|
|
19
|
+
log.error(err)
|
|
20
|
+
done()
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
log.debug(`Response from the intake: ${res}`)
|
|
24
|
+
done()
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function makeRequest (data, url, cb) {
|
|
30
|
+
const options = {
|
|
31
|
+
path: '/api/v2/citestcycle',
|
|
32
|
+
method: 'POST',
|
|
33
|
+
headers: {
|
|
34
|
+
'Content-Type': 'application/msgpack',
|
|
35
|
+
'dd-api-key': process.env.DATADOG_API_KEY || process.env.DD_API_KEY
|
|
36
|
+
},
|
|
37
|
+
timeout: 15000
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
options.protocol = url.protocol
|
|
41
|
+
options.hostname = url.hostname
|
|
42
|
+
options.port = url.port
|
|
43
|
+
|
|
44
|
+
log.debug(() => `Request to the intake: ${JSON.stringify(options)}`)
|
|
45
|
+
|
|
46
|
+
request(data, options, false, (err, res) => {
|
|
47
|
+
cb(err, res)
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = Writer
|
|
@@ -66,6 +66,7 @@ class Config {
|
|
|
66
66
|
process.env.DD_TRACE_URL,
|
|
67
67
|
null
|
|
68
68
|
)
|
|
69
|
+
const DD_CIVISIBILITY_AGENTLESS_URL = process.env.DD_CIVISIBILITY_AGENTLESS_URL
|
|
69
70
|
const DD_SERVICE = options.service ||
|
|
70
71
|
process.env.DD_SERVICE ||
|
|
71
72
|
process.env.DD_SERVICE_NAME ||
|
|
@@ -90,6 +91,10 @@ class Config {
|
|
|
90
91
|
process.env.DD_TRACE_STARTUP_LOGS,
|
|
91
92
|
false
|
|
92
93
|
)
|
|
94
|
+
const DD_TRACE_TELEMETRY_ENABLED = coalesce(
|
|
95
|
+
process.env.DD_TRACE_TELEMETRY_ENABLED,
|
|
96
|
+
true
|
|
97
|
+
)
|
|
93
98
|
const DD_TRACE_DEBUG = coalesce(
|
|
94
99
|
process.env.DD_TRACE_DEBUG,
|
|
95
100
|
false
|
|
@@ -145,10 +150,29 @@ class Config {
|
|
|
145
150
|
path.join(__dirname, 'appsec', 'recommended.json')
|
|
146
151
|
)
|
|
147
152
|
const DD_APPSEC_TRACE_RATE_LIMIT = coalesce(
|
|
148
|
-
appsec.rateLimit,
|
|
149
|
-
process.env.DD_APPSEC_TRACE_RATE_LIMIT,
|
|
153
|
+
parseInt(appsec.rateLimit),
|
|
154
|
+
parseInt(process.env.DD_APPSEC_TRACE_RATE_LIMIT),
|
|
150
155
|
100
|
|
151
156
|
)
|
|
157
|
+
const DD_APPSEC_WAF_TIMEOUT = coalesce(
|
|
158
|
+
parseInt(appsec.wafTimeout),
|
|
159
|
+
parseInt(process.env.DD_APPSEC_WAF_TIMEOUT),
|
|
160
|
+
5e3 // µs
|
|
161
|
+
)
|
|
162
|
+
const DD_APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP = coalesce(
|
|
163
|
+
appsec.obfuscatorKeyRegex,
|
|
164
|
+
process.env.DD_APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP,
|
|
165
|
+
`(?i)(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?)key)|token|consumer_?(?:id|key|se\
|
|
166
|
+
cret)|sign(?:ed|ature)|bearer|authorization`
|
|
167
|
+
)
|
|
168
|
+
const DD_APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP = coalesce(
|
|
169
|
+
appsec.obfuscatorValueRegex,
|
|
170
|
+
process.env.DD_APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP,
|
|
171
|
+
`(?i)(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?|access_?|secret_?)key(?:_?id)?|to\
|
|
172
|
+
ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)(?:\\s*=[^;]|"\\s*:\\s*"[^"]+")|bearer\
|
|
173
|
+
\\s+[a-z0-9\\._\\-]+|token:[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L][\\w=-]+\\.ey[I-L][\\w=-]+(?:\\.[\\w.+\\/=-]+)?\
|
|
174
|
+
|[\\-]{5}BEGIN[a-z\\s]+PRIVATE\\sKEY[\\-]{5}[^\\-]+[\\-]{5}END[a-z\\s]+PRIVATE\\sKEY|ssh-rsa\\s*[a-z0-9\\/\\.+]{100,}`
|
|
175
|
+
)
|
|
152
176
|
|
|
153
177
|
const sampler = (options.experimental && options.experimental.sampler) || {}
|
|
154
178
|
const ingestion = options.ingestion || {}
|
|
@@ -171,7 +195,8 @@ class Config {
|
|
|
171
195
|
this.debug = isTrue(DD_TRACE_DEBUG)
|
|
172
196
|
this.logInjection = isTrue(DD_LOGS_INJECTION)
|
|
173
197
|
this.env = DD_ENV
|
|
174
|
-
this.url =
|
|
198
|
+
this.url = DD_CIVISIBILITY_AGENTLESS_URL ? new URL(DD_CIVISIBILITY_AGENTLESS_URL)
|
|
199
|
+
: getAgentUrl(DD_TRACE_AGENT_URL, options)
|
|
175
200
|
this.site = coalesce(options.site, process.env.DD_SITE, 'datadoghq.com')
|
|
176
201
|
this.hostname = DD_AGENT_HOST || (this.url && this.url.hostname)
|
|
177
202
|
this.port = String(DD_TRACE_AGENT_PORT || (this.url && this.url.port))
|
|
@@ -212,11 +237,15 @@ class Config {
|
|
|
212
237
|
}
|
|
213
238
|
this.lookup = options.lookup
|
|
214
239
|
this.startupLogs = isTrue(DD_TRACE_STARTUP_LOGS)
|
|
240
|
+
this.telemetryEnabled = isTrue(DD_TRACE_TELEMETRY_ENABLED)
|
|
215
241
|
this.protocolVersion = DD_TRACE_AGENT_PROTOCOL_VERSION
|
|
216
242
|
this.appsec = {
|
|
217
243
|
enabled: isTrue(DD_APPSEC_ENABLED),
|
|
218
244
|
rules: DD_APPSEC_RULES,
|
|
219
|
-
rateLimit: DD_APPSEC_TRACE_RATE_LIMIT
|
|
245
|
+
rateLimit: DD_APPSEC_TRACE_RATE_LIMIT,
|
|
246
|
+
wafTimeout: DD_APPSEC_WAF_TIMEOUT,
|
|
247
|
+
obfuscatorKeyRegex: DD_APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP,
|
|
248
|
+
obfuscatorValueRegex: DD_APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP
|
|
220
249
|
}
|
|
221
250
|
|
|
222
251
|
tagger.add(this.tags, {
|