dd-trace 1.5.0 → 2.0.0-appsec-beta.1
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 +2 -0
- package/index.d.ts +0 -6
- package/package.json +10 -6
- package/packages/datadog-core/index.js +7 -0
- package/packages/datadog-core/src/storage/async_hooks.js +49 -0
- package/packages/datadog-core/src/storage/async_resource.js +76 -0
- package/packages/datadog-core/src/storage/index.js +14 -0
- package/packages/datadog-plugin-cucumber/src/index.js +2 -0
- package/packages/datadog-plugin-cypress/src/plugin.js +5 -3
- package/packages/datadog-plugin-graphql/src/index.js +16 -10
- package/packages/datadog-plugin-grpc/src/client.js +1 -1
- package/packages/datadog-plugin-http/src/server.js +1 -1
- package/packages/datadog-plugin-jest/src/jest-environment.js +5 -1
- package/packages/datadog-plugin-jest/src/jest-jasmine2.js +11 -2
- package/packages/datadog-plugin-mocha/src/index.js +9 -1
- package/packages/dd-trace/lib/version.js +1 -1
- package/packages/dd-trace/src/appsec/addresses.js +11 -0
- package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +126 -0
- package/packages/dd-trace/src/appsec/callbacks/index.js +7 -0
- package/packages/dd-trace/src/appsec/index.js +97 -2
- package/packages/dd-trace/src/appsec/recommended.json +1 -0
- package/packages/dd-trace/src/appsec/reporter.js +275 -0
- package/packages/dd-trace/src/appsec/rule_manager.js +27 -0
- package/packages/dd-trace/src/config.js +1 -5
- package/packages/dd-trace/src/encode/0.4.js +84 -23
- package/packages/dd-trace/src/encode/chunk.js +12 -14
- package/packages/dd-trace/src/gateway/als.js +5 -0
- package/packages/dd-trace/src/gateway/channels.js +8 -0
- package/packages/dd-trace/src/gateway/dc_block.js +68 -0
- package/packages/dd-trace/src/gateway/engine/engine.js +150 -0
- package/packages/dd-trace/src/gateway/engine/index.js +46 -0
- package/packages/dd-trace/src/gateway/engine/runner.js +40 -0
- package/packages/dd-trace/src/id.js +22 -18
- package/packages/dd-trace/src/instrumenter.js +2 -2
- package/packages/dd-trace/src/noop/scope.js +23 -0
- package/packages/dd-trace/src/noop/span.js +2 -0
- package/packages/dd-trace/src/noop/tracer.js +3 -10
- package/packages/dd-trace/src/opentracing/span.js +2 -0
- package/packages/dd-trace/src/plugins/util/ci-app-spec.json +1 -0
- package/packages/dd-trace/src/plugins/util/ci.js +36 -7
- package/packages/dd-trace/src/plugins/util/git.js +11 -25
- package/packages/dd-trace/src/plugins/util/test.js +14 -2
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +57 -0
- package/packages/dd-trace/src/plugins/util/web.js +15 -2
- package/packages/dd-trace/src/profiling/exporters/agent.js +11 -4
- package/packages/dd-trace/src/profiling/profilers/cpu.js +1 -3
- package/packages/dd-trace/src/proxy.js +1 -1
- package/packages/dd-trace/src/scope.js +212 -18
- package/packages/dd-trace/src/startup-log.js +2 -1
- package/packages/dd-trace/src/tracer.js +4 -19
- package/scripts/version.js +8 -3
- package/NOTICE +0 -4
- package/packages/dd-trace/src/.DS_Store +0 -0
- package/packages/dd-trace/src/scope/async_hooks.js +0 -139
- package/packages/dd-trace/src/scope/async_local_storage.js +0 -29
- package/packages/dd-trace/src/scope/async_resource.js +0 -82
- package/packages/dd-trace/src/scope/base.js +0 -218
- package/packages/dd-trace/src/scope/scope_manager.js +0 -5
- package/packages/dd-trace/src/scope/sync.js +0 -29
- package/packages/dd-trace/src/scope/zone.js +0 -38
package/LICENSE-3rdparty.csv
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
Component,Origin,License,Copyright
|
|
2
|
+
require,@datadog/native-appsec,Apache license 2.0,Copyright 2018 Datadog Inc.
|
|
2
3
|
require,@datadog/native-metrics,Apache license 2.0,Copyright 2018 Datadog Inc.
|
|
3
4
|
require,@datadog/pprof,Apache license 2.0,Copyright 2019 Google Inc.
|
|
4
5
|
require,@datadog/sketches-js,Apache license 2.0,Copyright 2020 Datadog Inc.
|
|
5
6
|
require,@types/node,MIT,Copyright Authors
|
|
6
7
|
require,crypto-randomuuid,MIT,Copyright 2021 Node.js Foundation and contributors
|
|
8
|
+
require,diagnostics_channel,MIT,Copyright 2021 Simon D.
|
|
7
9
|
require,form-data,MIT,Copyright 2012 Felix Geisendörfer and contributors
|
|
8
10
|
require,import-in-the-middle,Apache license 2.0,Copyright 2021 Datadog Inc.
|
|
9
11
|
require,koalas,MIT,Copyright 2013-2017 Brian Woodward
|
package/index.d.ts
CHANGED
|
@@ -285,12 +285,6 @@ export declare interface TracerOptions {
|
|
|
285
285
|
*/
|
|
286
286
|
runtimeMetrics?: boolean
|
|
287
287
|
|
|
288
|
-
/**
|
|
289
|
-
* Whether to track the scope of async functions. This is needed for async/await to work with non-native promises (thenables). Only disable this if you are sure only native promises are used with async/await, or if you are using Node >=14.5 since the issue has been fixed in that version.
|
|
290
|
-
* @default true
|
|
291
|
-
*/
|
|
292
|
-
trackAsyncScope?: boolean
|
|
293
|
-
|
|
294
288
|
/**
|
|
295
289
|
* Custom function for DNS lookups when sending requests to the agent.
|
|
296
290
|
* @default dns.lookup()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-appsec-beta.1",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -16,8 +16,10 @@
|
|
|
16
16
|
"services": "node ./scripts/install_plugin_modules && node packages/dd-trace/test/setup/services",
|
|
17
17
|
"tdd": "node scripts/tdd.js",
|
|
18
18
|
"test": "SERVICES=* yarn services && mocha --exit --expose-gc 'packages/dd-trace/test/setup/node.js' 'packages/*/test/**/*.spec.js'",
|
|
19
|
-
"test:core": "mocha --exit --expose-gc --file packages/dd-trace/test/setup/core.js \"packages/dd-trace/test/**/*.spec.js\"",
|
|
20
|
-
"test:core:ci": "nyc --include \"packages/dd-trace/src/**/*.js\" -- npm run test:core -- --reporter mocha-multi-reporters --reporter-options configFile=mocha-reporter-config.json",
|
|
19
|
+
"test:trace:core": "mocha --exit --expose-gc --file packages/dd-trace/test/setup/core.js \"packages/dd-trace/test/**/*.spec.js\"",
|
|
20
|
+
"test:trace:core:ci": "nyc --include \"packages/dd-trace/src/**/*.js\" -- npm run test:trace:core -- --reporter mocha-multi-reporters --reporter-options configFile=mocha-reporter-config.json",
|
|
21
|
+
"test:core": "mocha --file packages/datadog-core/test/setup.js 'packages/datadog-core/test/**/*.spec.js'",
|
|
22
|
+
"test:core:ci": "nyc --include 'packages/datadog-core/src/**/*.js' -- npm run test:core -- --reporter mocha-multi-reporters --reporter-options configFile=mocha-reporter-config.json",
|
|
21
23
|
"test:plugins": "mocha --exit --file \"packages/dd-trace/test/setup/core.js\" \"packages/datadog-plugin-@($(echo $PLUGINS))/test/**/*.spec.js\"",
|
|
22
24
|
"test:plugins:ci": "yarn services && nyc --include \"packages/datadog-plugin-@($(echo $PLUGINS))/src/**/*.js\" -- npm run test:plugins -- --reporter mocha-multi-reporters --reporter-options configFile=mocha-reporter-config.json",
|
|
23
25
|
"test:plugins:upstream": "node ./packages/dd-trace/test/plugins/suite.js",
|
|
@@ -56,13 +58,15 @@
|
|
|
56
58
|
"node": ">=12"
|
|
57
59
|
},
|
|
58
60
|
"dependencies": {
|
|
59
|
-
"@datadog/native-
|
|
60
|
-
"@datadog/
|
|
61
|
+
"@datadog/native-appsec": "^0.6.0",
|
|
62
|
+
"@datadog/native-metrics": "^1.0.1",
|
|
63
|
+
"@datadog/pprof": "^0.3.0",
|
|
61
64
|
"@datadog/sketches-js": "^1.0.4",
|
|
62
65
|
"@types/node": "^10.12.18",
|
|
63
66
|
"crypto-randomuuid": "^1.0.0",
|
|
67
|
+
"diagnostics_channel": "^1.1.0",
|
|
64
68
|
"form-data": "^3.0.0",
|
|
65
|
-
"import-in-the-middle": "^1.1.
|
|
69
|
+
"import-in-the-middle": "^1.1.2",
|
|
66
70
|
"koalas": "^1.0.2",
|
|
67
71
|
"limiter": "^1.1.4",
|
|
68
72
|
"lodash.kebabcase": "^4.1.1",
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { createHook, executionAsyncId } = require('async_hooks')
|
|
4
|
+
const AsyncResourceStorage = require('./async_resource')
|
|
5
|
+
|
|
6
|
+
class AsyncHooksStorage extends AsyncResourceStorage {
|
|
7
|
+
constructor () {
|
|
8
|
+
super()
|
|
9
|
+
|
|
10
|
+
this._resources = new Map()
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
disable () {
|
|
14
|
+
super.disable()
|
|
15
|
+
|
|
16
|
+
this._resources.clear()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
_createHook () {
|
|
20
|
+
return createHook({
|
|
21
|
+
init: this._init.bind(this),
|
|
22
|
+
destroy: this._destroy.bind(this)
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
_init (asyncId, type, triggerAsyncId, resource) {
|
|
27
|
+
super._init.apply(this, arguments)
|
|
28
|
+
|
|
29
|
+
this._resources.set(asyncId, resource)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
_destroy (asyncId) {
|
|
33
|
+
this._resources.delete(asyncId)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
_executionAsyncResource () {
|
|
37
|
+
const asyncId = executionAsyncId()
|
|
38
|
+
|
|
39
|
+
let resource = this._resources.get(asyncId)
|
|
40
|
+
|
|
41
|
+
if (!resource) {
|
|
42
|
+
this._resources.set(asyncId, resource = {})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return resource
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = AsyncHooksStorage
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { createHook, executionAsyncResource } = require('async_hooks')
|
|
4
|
+
|
|
5
|
+
class AsyncResourceStorage {
|
|
6
|
+
constructor () {
|
|
7
|
+
this._ddResourceStore = Symbol('ddResourceStore')
|
|
8
|
+
this._enabled = false
|
|
9
|
+
this._hook = this._createHook()
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
disable () {
|
|
13
|
+
if (!this._enabled) return
|
|
14
|
+
|
|
15
|
+
this._hook.disable()
|
|
16
|
+
this._enabled = false
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
getStore () {
|
|
20
|
+
if (!this._enabled) return
|
|
21
|
+
|
|
22
|
+
const resource = this._executionAsyncResource()
|
|
23
|
+
|
|
24
|
+
return resource[this._ddResourceStore]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
enterWith (store) {
|
|
28
|
+
this._enable()
|
|
29
|
+
|
|
30
|
+
const resource = this._executionAsyncResource()
|
|
31
|
+
|
|
32
|
+
resource[this._ddResourceStore] = store
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
run (store, callback, ...args) {
|
|
36
|
+
this._enable()
|
|
37
|
+
|
|
38
|
+
const resource = this._executionAsyncResource()
|
|
39
|
+
const oldStore = resource[this._ddResourceStore]
|
|
40
|
+
|
|
41
|
+
resource[this._ddResourceStore] = store
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
return callback(...args)
|
|
45
|
+
} finally {
|
|
46
|
+
resource[this._ddResourceStore] = oldStore
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
_createHook () {
|
|
51
|
+
return createHook({
|
|
52
|
+
init: this._init.bind(this)
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
_enable () {
|
|
57
|
+
if (this._enabled) return
|
|
58
|
+
|
|
59
|
+
this._enabled = true
|
|
60
|
+
this._hook.enable()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
_init (asyncId, type, triggerAsyncId, resource) {
|
|
64
|
+
const currentResource = this._executionAsyncResource()
|
|
65
|
+
|
|
66
|
+
if (Object.prototype.hasOwnProperty.call(currentResource, this._ddResourceStore)) {
|
|
67
|
+
resource[this._ddResourceStore] = currentResource[this._ddResourceStore]
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
_executionAsyncResource () {
|
|
72
|
+
return executionAsyncResource()
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
module.exports = AsyncResourceStorage
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// TODO: default to AsyncLocalStorage when it supports triggerAsyncResource
|
|
4
|
+
|
|
5
|
+
const semver = require('semver')
|
|
6
|
+
|
|
7
|
+
// https://github.com/nodejs/node/pull/33801
|
|
8
|
+
const hasJavaScriptAsyncHooks = semver.satisfies(process.versions.node, '>=14.5 || ^12.19.0')
|
|
9
|
+
|
|
10
|
+
if (hasJavaScriptAsyncHooks) {
|
|
11
|
+
module.exports = require('./async_resource')
|
|
12
|
+
} else {
|
|
13
|
+
module.exports = require('./async_hooks')
|
|
14
|
+
}
|
|
@@ -5,6 +5,7 @@ const {
|
|
|
5
5
|
TEST_NAME,
|
|
6
6
|
TEST_SUITE,
|
|
7
7
|
TEST_STATUS,
|
|
8
|
+
TEST_FRAMEWORK_VERSION,
|
|
8
9
|
TEST_SKIP_REASON,
|
|
9
10
|
CI_APP_ORIGIN,
|
|
10
11
|
ERROR_MESSAGE,
|
|
@@ -52,6 +53,7 @@ function createWrapRun (tracer, testEnvironmentMetadata, sourceRoot, setStatus)
|
|
|
52
53
|
[TEST_NAME]: testName,
|
|
53
54
|
[TEST_SUITE]: testSuite,
|
|
54
55
|
[SAMPLING_RULE_DECISION]: 1,
|
|
56
|
+
[TEST_FRAMEWORK_VERSION]: tracer._version,
|
|
55
57
|
...testEnvironmentMetadata
|
|
56
58
|
}
|
|
57
59
|
|
|
@@ -3,6 +3,7 @@ const {
|
|
|
3
3
|
TEST_NAME,
|
|
4
4
|
TEST_SUITE,
|
|
5
5
|
TEST_STATUS,
|
|
6
|
+
TEST_FRAMEWORK_VERSION,
|
|
6
7
|
getTestEnvironmentMetadata,
|
|
7
8
|
CI_APP_ORIGIN,
|
|
8
9
|
getTestParentSpan
|
|
@@ -19,7 +20,7 @@ const CYPRESS_STATUS_TO_TEST_STATUS = {
|
|
|
19
20
|
skipped: 'skip'
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
function getTestSpanMetadata (tracer, testName, testSuite) {
|
|
23
|
+
function getTestSpanMetadata (tracer, testName, testSuite, cypressConfig) {
|
|
23
24
|
const childOf = getTestParentSpan(tracer)
|
|
24
25
|
|
|
25
26
|
return {
|
|
@@ -29,7 +30,8 @@ function getTestSpanMetadata (tracer, testName, testSuite) {
|
|
|
29
30
|
[TEST_NAME]: testName,
|
|
30
31
|
[TEST_SUITE]: testSuite,
|
|
31
32
|
[SAMPLING_RULE_DECISION]: 1,
|
|
32
|
-
[SAMPLING_PRIORITY]: AUTO_KEEP
|
|
33
|
+
[SAMPLING_PRIORITY]: AUTO_KEEP,
|
|
34
|
+
[TEST_FRAMEWORK_VERSION]: cypressConfig.version
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
37
|
|
|
@@ -50,7 +52,7 @@ module.exports = (on, config) => {
|
|
|
50
52
|
childOf,
|
|
51
53
|
resource,
|
|
52
54
|
...testSpanMetadata
|
|
53
|
-
} = getTestSpanMetadata(tracer, testName, testSuite)
|
|
55
|
+
} = getTestSpanMetadata(tracer, testName, testSuite, config)
|
|
54
56
|
|
|
55
57
|
if (!activeSpan) {
|
|
56
58
|
activeSpan = tracer.startSpan('cypress.test', {
|
|
@@ -9,20 +9,17 @@ let tools
|
|
|
9
9
|
function createWrapExecute (tracer, config, defaultFieldResolver) {
|
|
10
10
|
return function wrapExecute (execute) {
|
|
11
11
|
return function executeWithTrace () {
|
|
12
|
-
const args = normalizeArgs(arguments)
|
|
12
|
+
const args = normalizeArgs(arguments, tracer, config, defaultFieldResolver)
|
|
13
13
|
const schema = args.schema
|
|
14
14
|
const document = args.document
|
|
15
15
|
const source = document && document._datadog_source
|
|
16
|
-
const
|
|
17
|
-
const contextValue = args.contextValue = args.contextValue || {}
|
|
16
|
+
const contextValue = args.contextValue
|
|
18
17
|
const operation = getOperation(document, args.operationName)
|
|
19
18
|
|
|
20
19
|
if (contextValue._datadog_graphql) {
|
|
21
20
|
return execute.apply(this, arguments)
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
args.fieldResolver = wrapResolve(fieldResolver, tracer, config)
|
|
25
|
-
|
|
26
23
|
if (schema) {
|
|
27
24
|
wrapFields(schema._queryType, tracer, config)
|
|
28
25
|
wrapFields(schema._mutationType, tracer, config)
|
|
@@ -32,7 +29,7 @@ function createWrapExecute (tracer, config, defaultFieldResolver) {
|
|
|
32
29
|
|
|
33
30
|
contextValue._datadog_graphql = { source, span, fields: {} }
|
|
34
31
|
|
|
35
|
-
return call(execute, span, this,
|
|
32
|
+
return call(execute, span, this, arguments, (err, res) => {
|
|
36
33
|
finishResolvers(contextValue, config)
|
|
37
34
|
|
|
38
35
|
setError(span, err || (res && res.errors && res.errors[0]))
|
|
@@ -212,10 +209,19 @@ function getField (contextValue, path) {
|
|
|
212
209
|
return contextValue._datadog_graphql.fields[path.join('.')]
|
|
213
210
|
}
|
|
214
211
|
|
|
215
|
-
function normalizeArgs (args) {
|
|
216
|
-
if (args.length
|
|
217
|
-
|
|
218
|
-
}
|
|
212
|
+
function normalizeArgs (args, tracer, config, defaultFieldResolver) {
|
|
213
|
+
if (args.length !== 1) return normalizePositional(args, tracer, config, defaultFieldResolver)
|
|
214
|
+
|
|
215
|
+
args[0].contextValue = args[0].contextValue || {}
|
|
216
|
+
args[0].fieldResolver = wrapResolve(args[0].fieldResolver || defaultFieldResolver, tracer, config)
|
|
217
|
+
|
|
218
|
+
return args[0]
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function normalizePositional (args, tracer, config, defaultFieldResolver) {
|
|
222
|
+
args[3] = args[3] || {} // contextValue
|
|
223
|
+
args[6] = wrapResolve(args[6] || defaultFieldResolver, tracer, config) // fieldResolver
|
|
224
|
+
args.length = Math.max(args.length, 7)
|
|
219
225
|
|
|
220
226
|
return {
|
|
221
227
|
schema: args[0],
|
|
@@ -48,7 +48,7 @@ function createWrapMakeClientConstructor (tracer, config) {
|
|
|
48
48
|
function wrapPackageDefinition (tracer, config, def) {
|
|
49
49
|
for (const name in def) {
|
|
50
50
|
if (def[name].format) continue
|
|
51
|
-
if (def[name].service) {
|
|
51
|
+
if (def[name].service && def[name].prototype) {
|
|
52
52
|
wrapClientConstructor(tracer, config, def[name], def[name].service)
|
|
53
53
|
} else {
|
|
54
54
|
wrapPackageDefinition(tracer, config, def[name])
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const web = require('../../dd-trace/src/plugins/util/web')
|
|
4
|
-
const Scope = require('../../dd-trace/src/scope
|
|
4
|
+
const Scope = require('../../dd-trace/src/scope')
|
|
5
5
|
|
|
6
6
|
function createWrapEmit (tracer, config) {
|
|
7
7
|
config = web.normalizeConfig(config)
|
|
@@ -5,6 +5,8 @@ const {
|
|
|
5
5
|
TEST_NAME,
|
|
6
6
|
TEST_SUITE,
|
|
7
7
|
TEST_STATUS,
|
|
8
|
+
TEST_FRAMEWORK_VERSION,
|
|
9
|
+
JEST_TEST_RUNNER,
|
|
8
10
|
ERROR_MESSAGE,
|
|
9
11
|
ERROR_TYPE,
|
|
10
12
|
TEST_PARAMETERS,
|
|
@@ -138,7 +140,9 @@ function createHandleTestEvent (tracer, testEnvironmentMetadata, instrumenter) {
|
|
|
138
140
|
const spanTags = {
|
|
139
141
|
...commonSpanTags,
|
|
140
142
|
[TEST_NAME]: testName,
|
|
141
|
-
[TEST_SUITE]: this.testSuite
|
|
143
|
+
[TEST_SUITE]: this.testSuite,
|
|
144
|
+
[TEST_FRAMEWORK_VERSION]: tracer._version,
|
|
145
|
+
[JEST_TEST_RUNNER]: 'jest-circus'
|
|
142
146
|
}
|
|
143
147
|
|
|
144
148
|
const testParametersString = getTestParametersString(nameToParams, event.test.name)
|
|
@@ -5,6 +5,8 @@ const {
|
|
|
5
5
|
TEST_NAME,
|
|
6
6
|
TEST_SUITE,
|
|
7
7
|
TEST_STATUS,
|
|
8
|
+
TEST_FRAMEWORK_VERSION,
|
|
9
|
+
JEST_TEST_RUNNER,
|
|
8
10
|
CI_APP_ORIGIN,
|
|
9
11
|
getTestEnvironmentMetadata,
|
|
10
12
|
finishAllTraceSpans,
|
|
@@ -29,7 +31,12 @@ function createWrapIt (tracer, globalConfig, globalInput, testEnvironmentMetadat
|
|
|
29
31
|
{
|
|
30
32
|
type: 'test',
|
|
31
33
|
childOf,
|
|
32
|
-
tags: {
|
|
34
|
+
tags: {
|
|
35
|
+
...commonSpanTags,
|
|
36
|
+
[TEST_SUITE]: testSuite,
|
|
37
|
+
[TEST_FRAMEWORK_VERSION]: tracer._version,
|
|
38
|
+
[JEST_TEST_RUNNER]: 'jest-jasmine2'
|
|
39
|
+
}
|
|
33
40
|
},
|
|
34
41
|
async (done) => {
|
|
35
42
|
const testSpan = tracer.scope().active()
|
|
@@ -124,7 +131,9 @@ function createWrapItSkip (tracer, globalConfig, globalInput, testEnvironmentMet
|
|
|
124
131
|
[RESOURCE_NAME]: resource,
|
|
125
132
|
[TEST_NAME]: testName,
|
|
126
133
|
[TEST_SUITE]: testSuite,
|
|
127
|
-
[TEST_STATUS]: 'skip'
|
|
134
|
+
[TEST_STATUS]: 'skip',
|
|
135
|
+
[TEST_FRAMEWORK_VERSION]: tracer._version,
|
|
136
|
+
[JEST_TEST_RUNNER]: 'jest-jasmine2'
|
|
128
137
|
}
|
|
129
138
|
}
|
|
130
139
|
)
|
|
@@ -9,6 +9,7 @@ const {
|
|
|
9
9
|
TEST_SUITE,
|
|
10
10
|
TEST_STATUS,
|
|
11
11
|
TEST_PARAMETERS,
|
|
12
|
+
TEST_FRAMEWORK_VERSION,
|
|
12
13
|
CI_APP_ORIGIN,
|
|
13
14
|
getTestEnvironmentMetadata,
|
|
14
15
|
getTestParametersString,
|
|
@@ -31,13 +32,20 @@ function getTestSpanMetadata (tracer, test, sourceRoot) {
|
|
|
31
32
|
[TEST_NAME]: fullTestName,
|
|
32
33
|
[TEST_SUITE]: testSuite,
|
|
33
34
|
[SAMPLING_RULE_DECISION]: 1,
|
|
34
|
-
[SAMPLING_PRIORITY]: AUTO_KEEP
|
|
35
|
+
[SAMPLING_PRIORITY]: AUTO_KEEP,
|
|
36
|
+
[TEST_FRAMEWORK_VERSION]: tracer._version
|
|
35
37
|
}
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
function createWrapRunTest (tracer, testEnvironmentMetadata, sourceRoot) {
|
|
39
41
|
return function wrapRunTest (runTest) {
|
|
40
42
|
return async function runTestWithTrace () {
|
|
43
|
+
// `runTest` is rerun when retries are configured through `this.retries` and the test fails.
|
|
44
|
+
// This clause prevents rewrapping `this.test.fn` when it has already been wrapped.
|
|
45
|
+
if (this.test._currentRetry !== undefined && this.test._currentRetry !== 0) {
|
|
46
|
+
return runTest.apply(this, arguments)
|
|
47
|
+
}
|
|
48
|
+
|
|
41
49
|
let specFunction = this.test.fn
|
|
42
50
|
if (specFunction.length) {
|
|
43
51
|
specFunction = promisify(specFunction)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
module.exports = '
|
|
1
|
+
module.exports = '2.0.0-pre'
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
HTTP_INCOMING_URL: 'server.request.uri.raw',
|
|
5
|
+
HTTP_INCOMING_HEADERS: 'server.request.headers.no_cookies',
|
|
6
|
+
HTTP_INCOMING_METHOD: 'server.request.method',
|
|
7
|
+
HTTP_INCOMING_REMOTE_IP: 'server.request.client_ip',
|
|
8
|
+
HTTP_INCOMING_REMOTE_PORT: 'server.request.client_port',
|
|
9
|
+
HTTP_INCOMING_RESPONSE_CODE: 'server.response.status',
|
|
10
|
+
HTTP_INCOMING_RESPONSE_HEADERS: 'server.response.headers.no_cookies'
|
|
11
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const log = require('../../log')
|
|
4
|
+
const addresses = require('../addresses')
|
|
5
|
+
const Gateway = require('../../gateway/engine')
|
|
6
|
+
const Reporter = require('../reporter')
|
|
7
|
+
|
|
8
|
+
let warned = false
|
|
9
|
+
|
|
10
|
+
const validAddressSet = new Set(Object.values(addresses))
|
|
11
|
+
|
|
12
|
+
const DEFAULT_MAX_BUDGET = 5e3 // µs
|
|
13
|
+
|
|
14
|
+
// TODO: put reusable code in a base class
|
|
15
|
+
class WAFCallback {
|
|
16
|
+
static loadDDWAF (rules) {
|
|
17
|
+
try {
|
|
18
|
+
// require in `try/catch` because this can throw at require time
|
|
19
|
+
const { DDWAF } = require('@datadog/native-appsec')
|
|
20
|
+
|
|
21
|
+
return new DDWAF(rules)
|
|
22
|
+
} catch (err) {
|
|
23
|
+
if (!warned) {
|
|
24
|
+
log.warn('AppSec could not load native package. In-app WAF features will not be available.')
|
|
25
|
+
warned = true
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
throw err
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
constructor (rules) {
|
|
33
|
+
this.ddwaf = WAFCallback.loadDDWAF(rules)
|
|
34
|
+
this.wafContextCache = new WeakMap()
|
|
35
|
+
|
|
36
|
+
// closures are faster than binds
|
|
37
|
+
const self = this
|
|
38
|
+
const method = (params, store) => {
|
|
39
|
+
return self.action(params, store)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// might be its own class with more info later
|
|
43
|
+
const callback = { method }
|
|
44
|
+
|
|
45
|
+
const subscribedAddresses = new Set()
|
|
46
|
+
|
|
47
|
+
for (const rule of rules.rules) {
|
|
48
|
+
for (const condition of rule.conditions) {
|
|
49
|
+
for (const input of condition.parameters.inputs) {
|
|
50
|
+
const address = input.address.split(':', 2)[0]
|
|
51
|
+
|
|
52
|
+
if (!validAddressSet.has(address) || subscribedAddresses.has(address)) continue
|
|
53
|
+
|
|
54
|
+
subscribedAddresses.add(address)
|
|
55
|
+
|
|
56
|
+
Gateway.manager.addSubscription({ addresses: [ address ], callback })
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
action (params, store) {
|
|
63
|
+
let wafContext
|
|
64
|
+
|
|
65
|
+
if (store) {
|
|
66
|
+
const key = store.get('context')
|
|
67
|
+
|
|
68
|
+
if (key) {
|
|
69
|
+
if (this.wafContextCache.has(key)) {
|
|
70
|
+
wafContext = this.wafContextCache.get(key)
|
|
71
|
+
} else {
|
|
72
|
+
wafContext = this.ddwaf.createContext()
|
|
73
|
+
this.wafContextCache.set(key, wafContext)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!wafContext) {
|
|
79
|
+
wafContext = this.ddwaf.createContext()
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// TODO: if status code in params, convert it to string
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
// TODO: possible optimizaion: only send params that haven't already been sent to this wafContext
|
|
86
|
+
const result = wafContext.run(params, DEFAULT_MAX_BUDGET)
|
|
87
|
+
|
|
88
|
+
return this.applyResult(result)
|
|
89
|
+
} catch (err) {
|
|
90
|
+
log.warn('Error while running the AppSec WAF')
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
applyResult (result) {
|
|
95
|
+
if (result.action) {
|
|
96
|
+
const data = JSON.parse(result.data)
|
|
97
|
+
|
|
98
|
+
for (let i = 0; i < data.length; ++i) {
|
|
99
|
+
const point = data[i]
|
|
100
|
+
const ruleMatch = point.rule_matches[0]
|
|
101
|
+
|
|
102
|
+
ruleMatch.highlight = []
|
|
103
|
+
|
|
104
|
+
for (const param of ruleMatch.parameters) {
|
|
105
|
+
ruleMatch.highlight = ruleMatch.highlight.concat(param.highlight)
|
|
106
|
+
delete param.highlight
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
Reporter.reportAttack(point.rule, ruleMatch)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// result.perfData
|
|
114
|
+
// result.perfTotalRuntime
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
clear () {
|
|
118
|
+
this.ddwaf.dispose()
|
|
119
|
+
|
|
120
|
+
this.wafContextCache = new WeakMap()
|
|
121
|
+
|
|
122
|
+
Gateway.manager.clear()
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
module.exports = WAFCallback
|