@newrelic/security-agent 2.1.1 → 2.2.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/CHANGELOG.md +9 -0
- package/lib/instrumentation-security/core/event-constants.js +6 -3
- package/lib/instrumentation-security/hooks/crypto/nr-crypto.js +124 -0
- package/lib/instrumentation-security/hooks/express/nr-express.js +71 -3
- package/lib/instrumentation-security/hooks/fastify/nr-fastify.js +4 -7
- package/lib/instrumentation-security/hooks/graphql/nr-graphql.js +75 -0
- package/lib/instrumentation-security/hooks/http/nr-http.js +33 -1
- package/lib/instrumentation-security/index.js +19 -0
- package/lib/nr-security-agent/lib/core/sec-util.js +5 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
### v2.2.0 (2024-12-18)
|
|
2
|
+
#### Features
|
|
3
|
+
* Support for express 5.x
|
|
4
|
+
* IAST support for GraphQL
|
|
5
|
+
* Added support for trustboundary security events
|
|
6
|
+
|
|
7
|
+
#### Bug fixes
|
|
8
|
+
* Fix for empty route in fastify
|
|
9
|
+
|
|
1
10
|
### v2.1.1 (2024-11-07)
|
|
2
11
|
#### Bug fixes
|
|
3
12
|
* Fix for assignment to logger constant
|
|
@@ -14,14 +14,15 @@ const EVENT_TYPE = {
|
|
|
14
14
|
HTTP_REQUEST: 'HTTP_REQUEST',
|
|
15
15
|
CODE_INJECTION: 'CODE_INJECTION',
|
|
16
16
|
XXE: 'XXE',
|
|
17
|
-
CIPHER: 'CIPHER',
|
|
18
17
|
HASH: 'HASH',
|
|
19
18
|
RANDOM: 'RANDOM',
|
|
20
19
|
UNVALIDATED_REDIRECT: 'UNVALIDATED_REDIRECT',
|
|
21
20
|
REFLECTED_XSS: 'REFLECTED_XSS',
|
|
22
21
|
XPATH: 'XPATH',
|
|
23
22
|
LDAP: 'LDAP',
|
|
24
|
-
SECURE_COOKIE: 'SECURE_COOKIE'
|
|
23
|
+
SECURE_COOKIE: 'SECURE_COOKIE',
|
|
24
|
+
TRUSTBOUNDARY: 'TRUSTBOUNDARY',
|
|
25
|
+
CRYPTO: 'CRYPTO',
|
|
25
26
|
}
|
|
26
27
|
const EVENT_CATEGORY = {
|
|
27
28
|
MYSQL: 'MYSQL',
|
|
@@ -42,7 +43,9 @@ const EVENT_CATEGORY = {
|
|
|
42
43
|
REFLECTED_XSS: 'REFLECTED_XSS',
|
|
43
44
|
XPATH: 'XPATH',
|
|
44
45
|
LDAP: 'LDAP',
|
|
45
|
-
SECURE_COOKIE: 'SECURE_COOKIE'
|
|
46
|
+
SECURE_COOKIE: 'SECURE_COOKIE',
|
|
47
|
+
TRUSTBOUNDARY: 'TRUSTBOUNDARY',
|
|
48
|
+
CIPHER: 'CIPHER',
|
|
46
49
|
}
|
|
47
50
|
|
|
48
51
|
module.exports = {
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2023 New Relic Corporation. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: New Relic Software License v1.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
module.exports = initialize
|
|
7
|
+
const requestManager = require('../../core/request-manager');
|
|
8
|
+
const secUtils = require("../../core/sec-utils");
|
|
9
|
+
const API = require("../../../nr-security-api");
|
|
10
|
+
const securityMetaData = require('../../core/security-metadata');
|
|
11
|
+
const { EVENT_TYPE, EVENT_CATEGORY } = require('../../core/event-constants');
|
|
12
|
+
const { NR_CSEC_FUZZ_REQUEST_ID } = require('../../core/constants');
|
|
13
|
+
const logger = API.getLogger();
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Entry point of ldapjs and ldapts module hook
|
|
17
|
+
* @param {*} shim
|
|
18
|
+
* @param {*} mod
|
|
19
|
+
* @param {*} moduleName
|
|
20
|
+
*/
|
|
21
|
+
function initialize(shim, mod, moduleName) {
|
|
22
|
+
logger.info('Instrumenting ' + moduleName)
|
|
23
|
+
cryptoCipherHooks(shim, mod, 'createCipheriv', moduleName);
|
|
24
|
+
cryptoHashHmacHooks(shim, mod, 'createHash', moduleName);
|
|
25
|
+
cryptoHashHmacHooks(shim, mod, 'createHmac', moduleName);
|
|
26
|
+
// cryptoRandomHooks(shim, mod, 'randomInt', moduleName);
|
|
27
|
+
// cryptoRandomHooks(shim, mod, 'randomBytes', moduleName);
|
|
28
|
+
cryptoRandomHooks(shim, Math, 'random', "Math");
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* wrapper to hook crypto cipher methods
|
|
32
|
+
* @param {*} shim
|
|
33
|
+
* @param {*} mod
|
|
34
|
+
* @param {*} methodName
|
|
35
|
+
* @param {*} moduleName
|
|
36
|
+
*/
|
|
37
|
+
function cryptoCipherHooks(shim, mod, methodName, moduleName) {
|
|
38
|
+
shim.wrap(mod, methodName, function makeWrapper(shim, fn) {
|
|
39
|
+
logger.debug(`Instrumenting ${moduleName}.${methodName}`);
|
|
40
|
+
return function wrapper() {
|
|
41
|
+
const interceptedArgs = [arguments[0]];
|
|
42
|
+
shim.interceptedArgs = interceptedArgs;
|
|
43
|
+
const request = requestManager.getRequest(shim);
|
|
44
|
+
if (request) {
|
|
45
|
+
const traceObject = secUtils.getTraceObject(shim);
|
|
46
|
+
const secMetadata = securityMetaData.getSecurityMetaData(request, interceptedArgs, traceObject, secUtils.getExecutionId(), EVENT_TYPE.CRYPTO, EVENT_CATEGORY.CIPHER)
|
|
47
|
+
const secEvent = API.generateSecEvent(secMetadata);
|
|
48
|
+
this.secEvent = secEvent;
|
|
49
|
+
API.sendEvent(secEvent);
|
|
50
|
+
}
|
|
51
|
+
const result = fn.apply(this, arguments);
|
|
52
|
+
|
|
53
|
+
if (result && request && request.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
|
|
54
|
+
API.generateExitEvent(this.secEvent);
|
|
55
|
+
delete this.secEvent
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* wrapper to hook crypto hash and mac methods
|
|
65
|
+
* @param {*} shim
|
|
66
|
+
* @param {*} mod
|
|
67
|
+
* @param {*} methodName
|
|
68
|
+
* @param {*} moduleName
|
|
69
|
+
*/
|
|
70
|
+
function cryptoHashHmacHooks(shim, mod, methodName, moduleName) {
|
|
71
|
+
shim.wrap(mod, methodName, function makeWrapper(shim, fn) {
|
|
72
|
+
logger.debug(`Instrumenting ${moduleName}.${methodName}`);
|
|
73
|
+
return function wrapper() {
|
|
74
|
+
const interceptedArgs = [arguments[0]];
|
|
75
|
+
shim.interceptedArgs = interceptedArgs;
|
|
76
|
+
const request = requestManager.getRequest(shim);
|
|
77
|
+
if (request) {
|
|
78
|
+
const traceObject = secUtils.getTraceObject(shim);
|
|
79
|
+
const secMetadata = securityMetaData.getSecurityMetaData(request, interceptedArgs, traceObject, secUtils.getExecutionId(), EVENT_TYPE.HASH, EVENT_CATEGORY.HASH)
|
|
80
|
+
const secEvent = API.generateSecEvent(secMetadata);
|
|
81
|
+
this.secEvent = secEvent;
|
|
82
|
+
API.sendEvent(secEvent);
|
|
83
|
+
}
|
|
84
|
+
const result = fn.apply(this, arguments);
|
|
85
|
+
if (result && request && request.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
|
|
86
|
+
API.generateExitEvent(this.secEvent);
|
|
87
|
+
delete this.secEvent
|
|
88
|
+
}
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Wrapper for random hooks
|
|
95
|
+
* @param {*} shim
|
|
96
|
+
* @param {*} mod
|
|
97
|
+
* @param {*} methodName
|
|
98
|
+
* @param {*} moduleName
|
|
99
|
+
*/
|
|
100
|
+
function cryptoRandomHooks(shim, mod, methodName, moduleName) {
|
|
101
|
+
shim.wrap(mod, methodName, function makeWrapper(shim, fn) {
|
|
102
|
+
logger.debug(`Instrumenting ${moduleName}.${methodName}`);
|
|
103
|
+
return function wrapper() {
|
|
104
|
+
const interceptedArgs = ["Math.random"];
|
|
105
|
+
shim.interceptedArgs = interceptedArgs;
|
|
106
|
+
const request = requestManager.getRequest(shim);
|
|
107
|
+
if (request && arguments[0]) {
|
|
108
|
+
const traceObject = secUtils.getTraceObject(shim);
|
|
109
|
+
const secMetadata = securityMetaData.getSecurityMetaData(request, interceptedArgs, traceObject, secUtils.getExecutionId(), EVENT_TYPE.RANDOM, EVENT_CATEGORY.WEAKRANDOM)
|
|
110
|
+
const secEvent = API.generateSecEvent(secMetadata);
|
|
111
|
+
this.secEvent = secEvent;
|
|
112
|
+
API.sendEvent(secEvent);
|
|
113
|
+
}
|
|
114
|
+
const result = fn.apply(this, arguments);
|
|
115
|
+
if (result && request && request.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
|
|
116
|
+
API.generateExitEvent(this.secEvent);
|
|
117
|
+
delete this.secEvent
|
|
118
|
+
}
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
@@ -30,12 +30,14 @@ module.exports = function initialize(shim, express) {
|
|
|
30
30
|
|
|
31
31
|
if (express.Router.use) {
|
|
32
32
|
wrapExpress4(shim, express)
|
|
33
|
-
}
|
|
33
|
+
}
|
|
34
|
+
else if (express.Router.prototype) {
|
|
35
|
+
wrapExpress5(shim, express)
|
|
36
|
+
}
|
|
34
37
|
if(API && API.getNRAgent() && !API.getNRAgent().config.security.exclude_from_iast_scan.iast_detection_category.invalid_file_access){
|
|
35
38
|
expressFileHook(shim, express && express.response, 'download')
|
|
36
39
|
expressFileHook(shim, express && express.response, 'sendFile')
|
|
37
40
|
}
|
|
38
|
-
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
/**
|
|
@@ -121,7 +123,7 @@ function extractParams(shim, req) {
|
|
|
121
123
|
* @param {*} mod
|
|
122
124
|
* @param {*} fun
|
|
123
125
|
*/
|
|
124
|
-
function expressFileHook(shim, mod, fun){
|
|
126
|
+
function expressFileHook(shim, mod, fun) {
|
|
125
127
|
shim.wrap(mod, fun, function makeFAWrapper(shim, fn) {
|
|
126
128
|
if (!shim.isFunction(fn)) {
|
|
127
129
|
return fn
|
|
@@ -149,4 +151,70 @@ function expressFileHook(shim, mod, fun){
|
|
|
149
151
|
});
|
|
150
152
|
}
|
|
151
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Wrapper to hook express version 5.x route method
|
|
156
|
+
* @param {*} shim
|
|
157
|
+
* @param {*} express
|
|
158
|
+
*/
|
|
159
|
+
function wrapExpress5(shim, express) {
|
|
160
|
+
shim.wrap(express.Router.prototype, 'route', function wrapRoute(shim, fn) {
|
|
161
|
+
if (!shim.isFunction(fn)) {
|
|
162
|
+
return fn
|
|
163
|
+
}
|
|
164
|
+
logger.debug('Instrumenting express.Router.prototype.route');
|
|
165
|
+
return function wrappedRoute() {
|
|
166
|
+
try {
|
|
167
|
+
const stakTrace = secUtils.traceElementForRoute();
|
|
168
|
+
const splittedStack = stakTrace[0].split(DOUBLE_DOLLAR);
|
|
169
|
+
const key = lodash.upperCase(splittedStack[1]) + ATTHERATE + arguments[0];
|
|
170
|
+
routeManager.setRoute(key, splittedStack[0]);
|
|
171
|
+
} catch (error) {
|
|
172
|
+
|
|
173
|
+
}
|
|
174
|
+
const route = fn.apply(this, arguments)
|
|
175
|
+
return route;
|
|
176
|
+
}
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
module.exports.wrapRouter = function wrapExpress5Router(shim, mod) {
|
|
182
|
+
let layer = shim.require('./lib/layer');
|
|
183
|
+
shim.wrap(layer.prototype, 'match', function wrapParam(shim, fn) {
|
|
184
|
+
if (!shim.isFunction(fn)) {
|
|
185
|
+
return fn
|
|
186
|
+
}
|
|
187
|
+
logger.debug('Instrumenting router.layer.match');
|
|
188
|
+
return function wrappedParam() {
|
|
189
|
+
const route = fn.apply(this, arguments);
|
|
190
|
+
|
|
191
|
+
try {
|
|
192
|
+
const uri = this.route.path;
|
|
193
|
+
const params = this.params;
|
|
194
|
+
const transaction = shim.tracer.getTransaction();
|
|
195
|
+
if (transaction) {
|
|
196
|
+
let request = requestManager.getRequestFromId(transaction.id);
|
|
197
|
+
if (params && request) {
|
|
198
|
+
Object.keys(params).forEach(function (key) {
|
|
199
|
+
if (params[key]) {
|
|
200
|
+
if (!request.parameterMap[key]) {
|
|
201
|
+
request.parameterMap[key] = new Array(params[key].toString());
|
|
202
|
+
requestManager.setRequest(transaction.id, request);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
if (uri && request) {
|
|
208
|
+
request.uri = uri;
|
|
209
|
+
requestManager.setRequest(transaction.id, request);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
} catch (error) {
|
|
213
|
+
logger.debug("Error while getting path params via router module", error);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return route
|
|
217
|
+
}
|
|
218
|
+
})
|
|
219
|
+
}
|
|
152
220
|
|
|
@@ -10,7 +10,6 @@ const { ATTHERATE, DOUBLE_DOLLAR } = require('../../core/constants');
|
|
|
10
10
|
const lodash = require('lodash');
|
|
11
11
|
const routeManager = require('../../core/route-manager');
|
|
12
12
|
const semver = require('semver')
|
|
13
|
-
const url = require('url');
|
|
14
13
|
const API = require("../../../nr-security-api");
|
|
15
14
|
const logger = API.getLogger();
|
|
16
15
|
|
|
@@ -119,12 +118,10 @@ function setupExports(original, wrappedExport) {
|
|
|
119
118
|
*/
|
|
120
119
|
function extractParams(shim, req) {
|
|
121
120
|
try {
|
|
122
|
-
const reqURL = req.url || req.raw.url;
|
|
123
|
-
const parsedURI = url.parse(reqURL).pathname;
|
|
124
121
|
const transaction = shim.tracer.getTransaction();
|
|
125
122
|
if (transaction) {
|
|
126
123
|
let request = requestManager.getRequestFromId(transaction.id);
|
|
127
|
-
if (req.params &&
|
|
124
|
+
if (req.params && request) {
|
|
128
125
|
Object.keys(req.params).forEach(function (key) {
|
|
129
126
|
if (req.params[key]) {
|
|
130
127
|
if (!request.parameterMap[key]) {
|
|
@@ -144,9 +141,9 @@ function extractParams(shim, req) {
|
|
|
144
141
|
}
|
|
145
142
|
});
|
|
146
143
|
}
|
|
147
|
-
|
|
148
|
-
if (
|
|
149
|
-
request.uri =
|
|
144
|
+
const txInfo = lodash.get(req, Object.getOwnPropertySymbols(req).find(symbol => symbol.toString() === 'Symbol(fastify.context)'));
|
|
145
|
+
if (request && txInfo && txInfo.config && txInfo.config.url) {
|
|
146
|
+
request.uri = txInfo.config.url;
|
|
150
147
|
requestManager.setRequest(transaction.id, request);
|
|
151
148
|
}
|
|
152
149
|
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2023 New Relic Corporation. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: New Relic Software License v1.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Express middleware generates traces where middleware are considered siblings
|
|
10
|
+
* (ended on 'next' invocation) and not nested. Middlware are nested below the
|
|
11
|
+
* routers they are mounted to.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const requestManager = require("../../core/request-manager");
|
|
15
|
+
const { QUESTIONMARK } = require('../../core/constants');
|
|
16
|
+
const API = require("../../../nr-security-api");
|
|
17
|
+
const logger = API.getLogger();
|
|
18
|
+
const { APPLICATION_JSON } = require('../../core/constants');
|
|
19
|
+
let querystring = require('querystring');
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
module.exports = function initialize(shim, mod) {
|
|
23
|
+
logger.info("Instrumenting graphql");
|
|
24
|
+
|
|
25
|
+
shim.wrap(mod, 'execute', function wrapExecute(shim, fn) {
|
|
26
|
+
if (!shim.isFunction(fn)) {
|
|
27
|
+
return fn;
|
|
28
|
+
}
|
|
29
|
+
return function wrappedExecute() {
|
|
30
|
+
const segment = shim.getActiveSegment();
|
|
31
|
+
try {
|
|
32
|
+
if (segment && segment.transaction) {
|
|
33
|
+
let request = requestManager.getRequestFromId(segment.transaction.id);
|
|
34
|
+
let customDataType = {};
|
|
35
|
+
//check for query parms
|
|
36
|
+
if (request.headers['x-apollo-operation-name']) {
|
|
37
|
+
const queryString = request.url.split(QUESTIONMARK)[1];
|
|
38
|
+
const parsedQueryString = querystring.parse(queryString);
|
|
39
|
+
let allValues = Object.values(parsedQueryString);
|
|
40
|
+
for (let index = 0; index < allValues.length; index++) {
|
|
41
|
+
const element = allValues[index];
|
|
42
|
+
if (element.startsWith('query')) {
|
|
43
|
+
customDataType['*.query'] = 'GRAPHQL_QUERY';
|
|
44
|
+
}
|
|
45
|
+
if (element.startsWith('variables')) {
|
|
46
|
+
customDataType['*.variables'] = 'GRAPHQL_VARIABLE';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
request.customDataType = customDataType;
|
|
50
|
+
requestManager.setRequest(segment.transaction.id, request);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
//check for body
|
|
54
|
+
if (request.headers['content-type'] === APPLICATION_JSON) {
|
|
55
|
+
const requestBody = JSON.parse(request.body);
|
|
56
|
+
if (requestBody.query) {
|
|
57
|
+
customDataType['*.query'] = 'GRAPHQL_QUERY';
|
|
58
|
+
}
|
|
59
|
+
if (requestBody.variables) {
|
|
60
|
+
customDataType['*.variables'] = 'GRAPHQL_VARIABLE';
|
|
61
|
+
}
|
|
62
|
+
request.customDataType = customDataType;
|
|
63
|
+
requestManager.setRequest(segment.transaction.id, request);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
} catch (error) {
|
|
68
|
+
logger.debug("Error while processing graphql http request", error);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return fn.apply(this, arguments);
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
module.exports = initialize
|
|
7
7
|
const requestManager = require('../../core/request-manager');
|
|
8
|
-
const { NR_CSEC_FUZZ_REQUEST_ID, QUESTION_MARK, EMPTY_STRING, UTF8, CONTENT_TYPE, TEXT_HTML, APPLICATION_JSON, APPLICATION_XML, APPLICATION_XHTML, TEXT_PLAIN, APPLICATION_X_FORM_URLENCODED, MULTIPART_FORM_DATA, COMMA, SEMI_COLON, EQUAL, SECURE, HTTPONLY, SAMESITE, STRICT } = require('../../core/constants');
|
|
8
|
+
const { NR_CSEC_FUZZ_REQUEST_ID, QUESTION_MARK, EMPTY_STRING, UTF8, CONTENT_TYPE, TEXT_HTML, APPLICATION_JSON, APPLICATION_XML, APPLICATION_XHTML, TEXT_PLAIN, APPLICATION_X_FORM_URLENCODED, MULTIPART_FORM_DATA, COMMA, SEMI_COLON, EQUAL, SECURE, HTTPONLY, SAMESITE, STRICT, OBJECT } = require('../../core/constants');
|
|
9
9
|
const ARRAY_TYPE = 'Array';
|
|
10
10
|
const STRING_TYPE = 'string';
|
|
11
11
|
const BUFFER_TYPE = 'Buffer';
|
|
@@ -446,6 +446,9 @@ function responseHook(resp, req, shim) {
|
|
|
446
446
|
}
|
|
447
447
|
try {
|
|
448
448
|
secureCookieCheck(response, shim);
|
|
449
|
+
if (response && response.req && response.req.session) {
|
|
450
|
+
trustBoundaryCheck(response.req.session, shim)
|
|
451
|
+
}
|
|
449
452
|
} catch (error) {
|
|
450
453
|
logger.debug("Error while generating secure cookie event");
|
|
451
454
|
}
|
|
@@ -730,3 +733,32 @@ function truncateStringToBytes(inputString, maxBytes) {
|
|
|
730
733
|
return truncatedString;
|
|
731
734
|
}
|
|
732
735
|
|
|
736
|
+
/**
|
|
737
|
+
* Utility to generate trustboundary events.
|
|
738
|
+
* @param {*} sessionObject
|
|
739
|
+
* @param {*} shim
|
|
740
|
+
*/
|
|
741
|
+
function trustBoundaryCheck(sessionObject, shim) {
|
|
742
|
+
try {
|
|
743
|
+
const request = requestManager.getRequest(shim);
|
|
744
|
+
let params = [];
|
|
745
|
+
Object.keys(sessionObject).forEach(key => {
|
|
746
|
+
if (sessionObject[key] && typeof sessionObject[key] != OBJECT) {
|
|
747
|
+
params.push(String(key));
|
|
748
|
+
params.push(String(sessionObject[key]));
|
|
749
|
+
}
|
|
750
|
+
});
|
|
751
|
+
if (!lodash.isEmpty(params)) {
|
|
752
|
+
const traceObject = secUtils.getTraceObject(shim);
|
|
753
|
+
const secMetadata = securityMetaData.getSecurityMetaData(request, params, traceObject, secUtils.getExecutionId(), EVENT_TYPE.TRUSTBOUNDARY, EVENT_CATEGORY.TRUSTBOUNDARY)
|
|
754
|
+
const secEvent = API.generateSecEvent(secMetadata);
|
|
755
|
+
API.sendEvent(secEvent);
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
} catch (error) {
|
|
759
|
+
logger.debug("Error while processing trustboundary", error);
|
|
760
|
+
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
}
|
|
764
|
+
|
|
@@ -235,3 +235,22 @@ newrelic.instrument({
|
|
|
235
235
|
}
|
|
236
236
|
})
|
|
237
237
|
|
|
238
|
+
newrelic.instrument({
|
|
239
|
+
moduleName: 'graphql/execution/execute',
|
|
240
|
+
isEsm: true,
|
|
241
|
+
onRequire: require('./hooks/graphql/nr-graphql'),
|
|
242
|
+
onError: function intrumentErrorHandler(err) {
|
|
243
|
+
logger.error(err.message, err.stack)
|
|
244
|
+
}
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
newrelic.instrument({
|
|
248
|
+
moduleName: 'router',
|
|
249
|
+
isEsm: true,
|
|
250
|
+
onRequire: require('./hooks/express/nr-express').wrapRouter,
|
|
251
|
+
onError: function intrumentErrorHandler(err) {
|
|
252
|
+
logger.error(err.message, err.stack)
|
|
253
|
+
}
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
|
|
@@ -29,6 +29,10 @@ const initLogger = logs.getInitLogger();
|
|
|
29
29
|
|
|
30
30
|
const NODE_SER = 'node-serialize/lib/serialize.js';
|
|
31
31
|
const SECURE_COOKIE = 'SECURE_COOKIE';
|
|
32
|
+
const TRUSTBOUNDARY = 'TRUSTBOUNDARY';
|
|
33
|
+
const HASH = "HASH";
|
|
34
|
+
const CRYPTO = "CRYPTO";
|
|
35
|
+
const RANDOM = "RANDOM";
|
|
32
36
|
|
|
33
37
|
const insecureSettingApiIdSet = new Set();
|
|
34
38
|
|
|
@@ -110,7 +114,7 @@ function generateSecEvent(securityMetadata) {
|
|
|
110
114
|
|
|
111
115
|
let apiId = shaUtil.getSHA256ForData(traceObject.stacktrace.join('|') + uri);
|
|
112
116
|
apiId = securityMetadata.eventType + HYPHEN + apiId;
|
|
113
|
-
if (securityMetadata.eventType == SECURE_COOKIE) {
|
|
117
|
+
if (securityMetadata.eventType == SECURE_COOKIE || securityMetadata.eventType == CRYPTO || securityMetadata.eventType == HASH || securityMetadata.eventType == RANDOM) {
|
|
114
118
|
if (insecureSettingApiIdSet.has(apiId)) {
|
|
115
119
|
return;
|
|
116
120
|
}
|