@newrelic/security-agent 0.5.0 → 0.7.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 +31 -0
- package/README.md +1 -0
- package/THIRD_PARTY_NOTICES.md +1 -211
- package/lib/instrumentation-security/core/sec-utils.js +1 -0
- package/lib/instrumentation-security/hooks/@nestjs/nr-nestjs-core.js +1 -0
- package/lib/instrumentation-security/hooks/express/nr-express.js +2 -0
- package/lib/instrumentation-security/hooks/fastify/nr-fastify.js +1 -0
- package/lib/instrumentation-security/hooks/fs/nr-fs.js +56 -20
- package/lib/instrumentation-security/hooks/hapi/nr-hapi.js +2 -1
- package/lib/instrumentation-security/hooks/http/nr-http.js +96 -4
- package/lib/instrumentation-security/hooks/koa/@koa/nr-@koa-router.js +3 -1
- package/lib/instrumentation-security/hooks/ldap/nr-ldap.js +1 -0
- package/lib/instrumentation-security/hooks/mongodb/common.js +2 -0
- package/lib/instrumentation-security/hooks/mongodb/nr-mongodb.js +1 -1
- package/lib/instrumentation-security/hooks/mysql/nr-mysql.js +5 -2
- package/lib/instrumentation-security/hooks/native/nr-childProcess.js +3 -0
- package/lib/instrumentation-security/hooks/postgres/nr-postgres.js +1 -0
- package/lib/instrumentation-security/hooks/require/nr-require.js +3 -2
- package/lib/instrumentation-security/hooks/restify/nr-restify.js +3 -1
- package/lib/instrumentation-security/hooks/xpath/nr-xpath.js +4 -2
- package/lib/nr-security-agent/index.js +9 -4
- package/lib/nr-security-agent/lib/core/Auth-headers.js +7 -0
- package/lib/nr-security-agent/lib/core/LogMessage.js +40 -14
- package/lib/nr-security-agent/lib/core/commonUtils.js +35 -4
- package/lib/nr-security-agent/lib/core/connections/aws-lambda-client.js +6 -8
- package/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js +21 -6
- package/lib/nr-security-agent/lib/core/connections/websocket/response/index.js +5 -2
- package/lib/nr-security-agent/lib/core/connections/websocket/websocket.js +20 -1
- package/lib/nr-security-agent/lib/core/sec-agent-constants.js +3 -0
- package/lib/nr-security-agent/lib/core/sec-util.js +14 -6
- package/lib/nr-security-agent/lib/core/statusUtils.js +4 -1
- package/lib/nr-security-agent/lib/core/websocket-client.js +19 -8
- package/package.json +4 -5
|
@@ -46,7 +46,7 @@ const CSEC_HOME_TMP = `${CSEC_HOME}/nr-security-home/tmp/language-agent/${proces
|
|
|
46
46
|
* @param {*} moduleName
|
|
47
47
|
*/
|
|
48
48
|
function initialize(shim, mod, moduleName) {
|
|
49
|
-
logger.info(
|
|
49
|
+
logger.info(`Instrumenting ${moduleName}`);
|
|
50
50
|
emitHook(shim, mod, moduleName);
|
|
51
51
|
createServerHook(shim, mod, moduleName);
|
|
52
52
|
outboundHook(shim, mod, 'request', moduleName);
|
|
@@ -87,7 +87,11 @@ function setupRequestMapCleanup() {
|
|
|
87
87
|
* @param {*} moduleName
|
|
88
88
|
*/
|
|
89
89
|
function outboundHook(shim, mod, method, moduleName) {
|
|
90
|
+
logger.debug(`Instrumenting ${moduleName}.${method}`);
|
|
90
91
|
shim.wrap(mod, method, function makeRequestWrapper(shim, fn) {
|
|
92
|
+
if (!shim.isFunction(fn)) {
|
|
93
|
+
return fn
|
|
94
|
+
}
|
|
91
95
|
return function requestWrapper() {
|
|
92
96
|
const request = requestManager.getRequest(shim);
|
|
93
97
|
const data = {};
|
|
@@ -206,6 +210,7 @@ function addRequestData(shim, request) {
|
|
|
206
210
|
const data = Object.assign({});
|
|
207
211
|
const segment = shim.getActiveSegment();
|
|
208
212
|
if (segment && segment.transaction) {
|
|
213
|
+
data.protocol = (request.connection && request.connection.encrypted) ? 'https' : 'http';
|
|
209
214
|
data.body = null;
|
|
210
215
|
data.headers = request.headers;
|
|
211
216
|
data.url = request.url;
|
|
@@ -255,6 +260,10 @@ function addRequestData(shim, request) {
|
|
|
255
260
|
*/
|
|
256
261
|
function emitHook(shim, mod, moduleName) {
|
|
257
262
|
shim.wrap(mod && mod.Server && mod.Server.prototype, 'emit', function makeEmitWrapper(shim, fn) {
|
|
263
|
+
logger.debug(`Instrumenting ${moduleName}.Server.prototype.emit`);
|
|
264
|
+
if (!shim.isFunction(fn)) {
|
|
265
|
+
return fn
|
|
266
|
+
}
|
|
258
267
|
return function emitWrapper() {
|
|
259
268
|
const req = arguments[1];
|
|
260
269
|
const resp = arguments[2];
|
|
@@ -265,6 +274,9 @@ function emitHook(shim, mod, moduleName) {
|
|
|
265
274
|
}
|
|
266
275
|
|
|
267
276
|
shim.wrap(req, 'on', function makeOnWrapper(shim, fn) {
|
|
277
|
+
if (!shim.isFunction(fn)) {
|
|
278
|
+
return fn
|
|
279
|
+
}
|
|
268
280
|
return function OnWrapper() {
|
|
269
281
|
if (!requestManager.getRequest(shim)) {
|
|
270
282
|
addRequestData(shim, req);
|
|
@@ -292,10 +304,17 @@ function emitHook(shim, mod, moduleName) {
|
|
|
292
304
|
* @param {*} shim
|
|
293
305
|
* @param {*} mod
|
|
294
306
|
*/
|
|
295
|
-
function createServerHook(shim, mod) {
|
|
307
|
+
function createServerHook(shim, mod, moduleName) {
|
|
296
308
|
shim.wrap(mod, 'createServer', function createServerWrapper(shim, fn) {
|
|
309
|
+
logger.debug(`Instrumenting ${moduleName}.createServer`);
|
|
310
|
+
if (!shim.isFunction(fn)) {
|
|
311
|
+
return fn
|
|
312
|
+
}
|
|
297
313
|
return function wrappedCreateServer() {
|
|
298
314
|
shim.wrap(arguments, '0', function appWrapper(shim, fn) {
|
|
315
|
+
if (!shim.isFunction(fn)) {
|
|
316
|
+
return fn
|
|
317
|
+
}
|
|
299
318
|
return function wrappedApp() {
|
|
300
319
|
let req = arguments[0];
|
|
301
320
|
if (!requestManager.getRequest(shim)) {
|
|
@@ -316,6 +335,9 @@ function createServerHook(shim, mod) {
|
|
|
316
335
|
*/
|
|
317
336
|
function onDataHook(shim, mod) {
|
|
318
337
|
shim.wrap(mod, '1', function makeOnDataWrapper(shim, fn) {
|
|
338
|
+
if (!shim.isFunction(fn)) {
|
|
339
|
+
return fn
|
|
340
|
+
}
|
|
319
341
|
return function onDataWrapper() {
|
|
320
342
|
const chunk = arguments[0];
|
|
321
343
|
const chunkType = typeof chunk;
|
|
@@ -347,6 +369,9 @@ function responseHook(resp, req, shim) {
|
|
|
347
369
|
resp.res.body = EMPTY_STRING;
|
|
348
370
|
|
|
349
371
|
shim.wrap(resp, 'write', function makeWriteWrapper(shim, fn) {
|
|
372
|
+
if (!shim.isFunction(fn)) {
|
|
373
|
+
return fn
|
|
374
|
+
}
|
|
350
375
|
return function wrappedWrite() {
|
|
351
376
|
const response = this;
|
|
352
377
|
responseBodyCompute(response, arguments);
|
|
@@ -355,6 +380,9 @@ function responseHook(resp, req, shim) {
|
|
|
355
380
|
})
|
|
356
381
|
// wrapper for response.end()
|
|
357
382
|
shim.wrap(resp, 'end', function makeEndWrapper(shim, fn) {
|
|
383
|
+
if (!shim.isFunction(fn)) {
|
|
384
|
+
return fn
|
|
385
|
+
}
|
|
358
386
|
return function wrappedEnd() {
|
|
359
387
|
const response = this;
|
|
360
388
|
responseBodyCompute(response, arguments);
|
|
@@ -362,30 +390,94 @@ function responseHook(resp, req, shim) {
|
|
|
362
390
|
const construct = API.checkForReflectedXSS(request, response.res.body, response.getHeaders());
|
|
363
391
|
const policy = API.getPolicy();
|
|
364
392
|
const dynamicScanningFlag = policy.data ? (policy.data.vulnerabilityScan?.enabled && policy.data.vulnerabilityScan.iastScan.enabled) : false;
|
|
365
|
-
|
|
393
|
+
const type = response.getHeader(CONTENT_TYPE);
|
|
394
|
+
let isUnsupportedType = isUnsupportedContentType(type);
|
|
395
|
+
|
|
396
|
+
if (request && (construct || dynamicScanningFlag) && !isUnsupportedType) {
|
|
366
397
|
const args = [];
|
|
367
398
|
args.push(construct);
|
|
368
399
|
args.push(response.res.body);
|
|
369
400
|
const traceObject = secUtils.getTraceObject(shim);
|
|
370
401
|
const secMetadata = securityMetaData.getSecurityMetaData(request, args, traceObject, secUtils.getExecutionId(), EVENT_TYPE.REFLECTED_XSS, EVENT_CATEGORY.REFLECTED_XSS)
|
|
371
402
|
const secEvent = API.generateSecEvent(secMetadata);
|
|
372
|
-
|
|
403
|
+
secEvent.httpResponse = {};
|
|
404
|
+
secEvent.httpResponse.contentType = response.getHeader(CONTENT_TYPE);
|
|
373
405
|
API.sendEvent(secEvent);
|
|
374
406
|
}
|
|
375
407
|
return fn.apply(this, arguments);
|
|
376
408
|
}
|
|
377
409
|
})
|
|
378
410
|
}
|
|
411
|
+
/**
|
|
412
|
+
* Utility to check unsupported content types
|
|
413
|
+
* @param {*} conType
|
|
414
|
+
* @returns
|
|
415
|
+
*/
|
|
416
|
+
function isUnsupportedContentType(conType) {
|
|
417
|
+
try {
|
|
418
|
+
if (!conType) {
|
|
419
|
+
return true;
|
|
420
|
+
}
|
|
421
|
+
const unsupportedTypes = ["video/",
|
|
422
|
+
"image/",
|
|
423
|
+
"font/",
|
|
424
|
+
"audio/",
|
|
425
|
+
"application/zip",
|
|
426
|
+
"application/epub+zip",
|
|
427
|
+
"application/gzip",
|
|
428
|
+
"application/java-archive",
|
|
429
|
+
"application/msword",
|
|
430
|
+
"application/octet-stream",
|
|
431
|
+
"application/ogg",
|
|
432
|
+
"application/pdf",
|
|
433
|
+
"application/rtf",
|
|
434
|
+
"application/vnd.amazon.ebook",
|
|
435
|
+
"application/vnd.apple.installer+xml",
|
|
436
|
+
"application/vnd.ms-excel",
|
|
437
|
+
"application/vnd.ms-fontobject",
|
|
438
|
+
"application/vnd.ms-powerpoint",
|
|
439
|
+
"application/vnd.oasis.opendocument.presentation",
|
|
440
|
+
"application/vnd.oasis.opendocument.spreadsheet",
|
|
441
|
+
"application/vnd.oasis.opendocument.text",
|
|
442
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
443
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
444
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
445
|
+
"application/vnd.rar",
|
|
446
|
+
"application/vnd.visio",
|
|
447
|
+
"application/x-7z-compressed",
|
|
448
|
+
"application/x-abiword",
|
|
449
|
+
"application/x-bzip",
|
|
450
|
+
"application/x-bzip2",
|
|
451
|
+
"application/x-cdf",
|
|
452
|
+
"application/x-freearc",
|
|
453
|
+
"application/x-tar",
|
|
454
|
+
"application/zip",
|
|
455
|
+
"text/calendar"
|
|
456
|
+
];
|
|
457
|
+
|
|
458
|
+
const startsWithAny = unsupportedTypes.some(prefix => conType.startsWith(prefix));
|
|
459
|
+
return startsWithAny;
|
|
460
|
+
} catch (error) {
|
|
461
|
+
logger.debug("Error while checking unsupported content type");
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
}
|
|
379
465
|
|
|
380
466
|
function responseBodyCompute(response, args) {
|
|
381
467
|
let encoding = UTF8;
|
|
382
468
|
const type = response.getHeader(CONTENT_TYPE);
|
|
469
|
+
let isUnsupportedType = isUnsupportedContentType(type);
|
|
470
|
+
if (isUnsupportedType) {
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
|
|
383
474
|
let contentType = TEXT_HTML;
|
|
384
475
|
if (type) {
|
|
385
476
|
const obj = ConType.parse(type);
|
|
386
477
|
contentType = obj.type;
|
|
387
478
|
encoding = obj.parameters.charset;
|
|
388
479
|
}
|
|
480
|
+
|
|
389
481
|
if (args[0]) {
|
|
390
482
|
switch (contentType) {
|
|
391
483
|
case APPLICATION_JSON:
|
|
@@ -20,7 +20,7 @@ const logger = API.getLogger();
|
|
|
20
20
|
* @param {*} moduleName
|
|
21
21
|
*/
|
|
22
22
|
function initialize(shim, mod, moduleName) {
|
|
23
|
-
logger.info(
|
|
23
|
+
logger.info(`Instrumenting ${moduleName}`);
|
|
24
24
|
const VerbMethods = ['all', 'delete', 'get', 'head', 'opts', 'post', 'put', 'patch'];
|
|
25
25
|
|
|
26
26
|
// RouteMap hooks
|
|
@@ -29,6 +29,7 @@ function initialize(shim, mod, moduleName) {
|
|
|
29
29
|
if (!shim.isFunction(fn)) {
|
|
30
30
|
return fn
|
|
31
31
|
}
|
|
32
|
+
logger.debug(`Instrumenting ${moduleName}.prototype.${fun}`);
|
|
32
33
|
return function wrappedRoute() {
|
|
33
34
|
try {
|
|
34
35
|
const stakTrace = secUtils.traceElementForRoute();
|
|
@@ -59,6 +60,7 @@ function initialize(shim, mod, moduleName) {
|
|
|
59
60
|
*/
|
|
60
61
|
function paramHook(shim, mod, moduleName) {
|
|
61
62
|
shim.wrap(mod && mod.prototype, 'params', function wrapMatch(shim, fn) {
|
|
63
|
+
logger.debug(`Instrumenting ${moduleName}.prototype.params`);
|
|
62
64
|
return function wrappedMatch() {
|
|
63
65
|
const segment = shim.getActiveSegment();
|
|
64
66
|
if (segment && segment.transaction) {
|
|
@@ -35,6 +35,7 @@ function initialize(shim, mod, moduleName){
|
|
|
35
35
|
*/
|
|
36
36
|
function ldapHooks(shim, mod, methodName, moduleName){
|
|
37
37
|
shim.wrap(mod, methodName, function makeWrapper(shim,fn){
|
|
38
|
+
logger.debug(`Instrumenting ${moduleName}.${methodName}`);
|
|
38
39
|
return function wrapper(){
|
|
39
40
|
const param = {};
|
|
40
41
|
param.name = arguments[0];
|
|
@@ -55,6 +55,7 @@ function payloadType(obj) {
|
|
|
55
55
|
|
|
56
56
|
function queryHook(shim, mod, method) {
|
|
57
57
|
shim.wrap(mod, method, function makeQueryWrapper(shim, fn) {
|
|
58
|
+
logger.debug(`Instrumenting mongodb.${method}`);
|
|
58
59
|
return function queryWrapper() {
|
|
59
60
|
const request = requestManager.getRequest(shim);
|
|
60
61
|
if (CURSOR_OPS.includes(method)) {
|
|
@@ -194,6 +195,7 @@ function callbackHook(shim, mod, fun, secEvent) {
|
|
|
194
195
|
|
|
195
196
|
common.queryHookV2 = function queryHookV2(shim, mod, method) {
|
|
196
197
|
shim.wrap(mod, method, function makeQueryWrapper(shim, fn) {
|
|
198
|
+
logger.debug(`Instrumenting mongodb.${method}`);
|
|
197
199
|
return function queryWrapper() {
|
|
198
200
|
const request = requestManager.getRequest(shim);
|
|
199
201
|
if (CURSOR_OPS.includes(method)) {
|
|
@@ -18,7 +18,7 @@ const symbols = {
|
|
|
18
18
|
createPoolCluster: Symbol('createPoolCluster'),
|
|
19
19
|
wrappedPoolConnection: Symbol('wrappedPoolConnection')
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
let modName = '';
|
|
22
22
|
module.exports = initialize;
|
|
23
23
|
|
|
24
24
|
/**
|
|
@@ -28,6 +28,7 @@ module.exports = initialize;
|
|
|
28
28
|
* @param {*} moduleName
|
|
29
29
|
*/
|
|
30
30
|
function initialize(shim, mysql, moduleName) {
|
|
31
|
+
modName = moduleName;
|
|
31
32
|
logger.info("Instrumenting", moduleName);
|
|
32
33
|
if (shim._moduleRoot.includes("mysql2")) {
|
|
33
34
|
promiseInitialize(shim, mysql, moduleName);
|
|
@@ -119,6 +120,7 @@ function wrapGetConnection(shim, connectable) {
|
|
|
119
120
|
|
|
120
121
|
const proto = Object.getPrototypeOf(connectable);
|
|
121
122
|
shim.wrap(proto, "getConnection", function doWrapGetConnection(shim, fn) {
|
|
123
|
+
logger.debug(`Instrumenting ${modName}.getConnection`);
|
|
122
124
|
return function wrappedGetConnection() {
|
|
123
125
|
const args = shim.toArray(arguments);
|
|
124
126
|
const cbIdx = args.length - 1;
|
|
@@ -208,7 +210,7 @@ function extractQueryArgs(shim, args) {
|
|
|
208
210
|
// query(opts [, values], callback)
|
|
209
211
|
rawQuery = args[0].sql;
|
|
210
212
|
try {
|
|
211
|
-
if (args[0].values && typeof args[0].values
|
|
213
|
+
if (args[0].values && typeof args[0].values == 'object') {
|
|
212
214
|
param = Object.values(args[0].values)
|
|
213
215
|
}
|
|
214
216
|
} catch (error) {
|
|
@@ -240,6 +242,7 @@ function extractQueryArgs(shim, args) {
|
|
|
240
242
|
*/
|
|
241
243
|
function queryHook(shim, mod, method, isPoolQuery) {
|
|
242
244
|
shim.wrap(mod, method, function makeQueryWrapper(shim, fn) {
|
|
245
|
+
logger.debug(`Instrumenting ${modName}.${method}`);
|
|
243
246
|
return function queryWrapper() {
|
|
244
247
|
const parameters = extractQueryArgs(shim, arguments);
|
|
245
248
|
shim.interceptedArgs = parameters;
|
|
@@ -26,6 +26,7 @@ function initialize(shim, childProcess, moduleName) {
|
|
|
26
26
|
*/
|
|
27
27
|
function execFileHook(shim, childProcess, moduleName) {
|
|
28
28
|
shim.wrap(childProcess, "execFile", function makeWrapper(shim, fn) {
|
|
29
|
+
logger.debug(`Instrumenting ${moduleName}.execFile`);
|
|
29
30
|
return function wrapper() {
|
|
30
31
|
const interceptedArgs = [arguments[0]];
|
|
31
32
|
shim.interceptedArgs = interceptedArgs;
|
|
@@ -54,6 +55,7 @@ function execFileHook(shim, childProcess, moduleName) {
|
|
|
54
55
|
*/
|
|
55
56
|
function spawnSyncHook(shim, childProcess, moduleName) {
|
|
56
57
|
shim.wrap(childProcess, "spawn", function makeWrapper(shim, fn) {
|
|
58
|
+
logger.debug(`Instrumenting ${moduleName}.spawnSync`);
|
|
57
59
|
return function wrapper() {
|
|
58
60
|
const interceptedArgs = arguments[0].args;
|
|
59
61
|
shim.interceptedArgs = interceptedArgs;
|
|
@@ -83,6 +85,7 @@ function spawnSyncHook(shim, childProcess, moduleName) {
|
|
|
83
85
|
*/
|
|
84
86
|
function spawnHook(shim, childProcess, moduleName) {
|
|
85
87
|
shim.wrap(childProcess, "spawn", function makeWrapper(shim, fn) {
|
|
88
|
+
logger.debug(`Instrumenting ${moduleName}.spawn`);
|
|
86
89
|
return function wrapper() {
|
|
87
90
|
let param = [];
|
|
88
91
|
param.push(arguments[0]);
|
|
@@ -66,6 +66,7 @@ module.exports = function initialize(shim, pgsql, moduleName) {
|
|
|
66
66
|
|
|
67
67
|
function queryHook(shim, mod, method){
|
|
68
68
|
shim.wrap(mod, method, function makeQueryWrapper(shim, fn){
|
|
69
|
+
logger.debug(`Instrumenting pg.${method}`);
|
|
69
70
|
return function queryWrapper(){
|
|
70
71
|
const request = requestManager.getRequest(shim);
|
|
71
72
|
const sqlArgs = [];
|
|
@@ -73,7 +73,8 @@ function requireHook(shim, moduleName, parent) {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
if (request) {
|
|
76
|
-
|
|
76
|
+
let resolvedModulePath = require.resolve(moduleName)
|
|
77
|
+
const interceptedArgs = [resolvedModulePath];
|
|
77
78
|
let traceObject;
|
|
78
79
|
if (!fallback) {
|
|
79
80
|
traceObject = secUtils.getTraceObject(shim);
|
|
@@ -86,7 +87,7 @@ function requireHook(shim, moduleName, parent) {
|
|
|
86
87
|
API.sendEvent(secEvent);
|
|
87
88
|
}
|
|
88
89
|
} catch (error) {
|
|
89
|
-
|
|
90
|
+
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
|
|
@@ -21,12 +21,13 @@ const logger = API.getLogger();
|
|
|
21
21
|
* @param {*} moduleName
|
|
22
22
|
*/
|
|
23
23
|
function initialize(shim, mod, moduleName) {
|
|
24
|
-
logger.info(
|
|
24
|
+
logger.info(`Instrumenting ${moduleName}`);
|
|
25
25
|
try {
|
|
26
26
|
const registryRadix = shim.require("./lib/routerRegistryRadix");
|
|
27
27
|
|
|
28
28
|
//routerRadix hook
|
|
29
29
|
shim.wrap(registryRadix && registryRadix.prototype, 'add', function makeWrapper(shim, fn) {
|
|
30
|
+
logger.info(`Instrumenting registryRadix.prototype.add`);
|
|
30
31
|
return function wrapper() {
|
|
31
32
|
if (arguments[0]) {
|
|
32
33
|
try {
|
|
@@ -47,6 +48,7 @@ function initialize(shim, mod, moduleName) {
|
|
|
47
48
|
const router = shim.require("./lib/router");
|
|
48
49
|
|
|
49
50
|
shim.wrap(router && router.prototype, 'lookup', function lookupWrapper(shim, fn) {
|
|
51
|
+
logger.info(`Instrumenting router.prototype.lookup`);
|
|
50
52
|
return function wrappedLookup() {
|
|
51
53
|
const result = fn.apply(this, arguments);
|
|
52
54
|
extractParams(shim, arguments[0]);
|
|
@@ -27,7 +27,7 @@ function initialize(shim, mod, moduleName){
|
|
|
27
27
|
xpathHooks(shim, mod, 'useNamespaces', moduleName);
|
|
28
28
|
}
|
|
29
29
|
else if(moduleName==='xpath.js'){
|
|
30
|
-
wrappedXPathDotJS(shim, mod);
|
|
30
|
+
wrappedXPathDotJS(shim, mod, moduleName);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
}
|
|
@@ -40,6 +40,7 @@ function initialize(shim, mod, moduleName){
|
|
|
40
40
|
*/
|
|
41
41
|
function xpathHooks(shim, mod, methodName, moduleName){
|
|
42
42
|
shim.wrap(mod, methodName, function makeWrapper(shim,fn){
|
|
43
|
+
logger.debug(`Instrumenting ${moduleName}.${methodName}`);
|
|
43
44
|
return function wrapper(){
|
|
44
45
|
const interceptedArgs = [arguments[0]];
|
|
45
46
|
shim.interceptedArgs = interceptedArgs;
|
|
@@ -67,8 +68,9 @@ function xpathHooks(shim, mod, methodName, moduleName){
|
|
|
67
68
|
* @param {*} shim
|
|
68
69
|
* @param {*} mod
|
|
69
70
|
*/
|
|
70
|
-
function wrappedXPathDotJS(shim, mod){
|
|
71
|
+
function wrappedXPathDotJS(shim, mod, moduleName){
|
|
71
72
|
const wrappedExport = shim.wrapExport(mod, function wrapXpathJSModule(shim, fn) {
|
|
73
|
+
logger.debug(`Instrumenting ${moduleName}`);
|
|
72
74
|
return function wrappedXpathJSModule() {
|
|
73
75
|
const interceptedArgs = [arguments[1]];
|
|
74
76
|
shim.interceptedArgs = interceptedArgs;
|
|
@@ -14,6 +14,9 @@ const agentConfig = require('./resources/config');
|
|
|
14
14
|
const shaSizeUtil = require('./lib/core/sha-size-util');
|
|
15
15
|
const njsAgentConstants = require('./lib/core/sec-agent-constants');
|
|
16
16
|
|
|
17
|
+
const NRLogger = API.newrelic.shim.logger.child({ component: 'security-agent' });
|
|
18
|
+
NRLogger.info("Starting New Relic Node.js Security Agent ");
|
|
19
|
+
|
|
17
20
|
const {
|
|
18
21
|
IS_LAMBDA_ENV,
|
|
19
22
|
AWS_LAMBDA_FUNCTION_NAME_ENV_IDENTIFIER,
|
|
@@ -106,6 +109,7 @@ function initialize() {
|
|
|
106
109
|
initLogger.info("[STEP-3] => Gathering information about the application :", JSON.stringify(applicationInfo));
|
|
107
110
|
if (NRAgent) {
|
|
108
111
|
NRAgent.on('started', () => {
|
|
112
|
+
NRLogger.info("Started New Relic Node.js Security Agent");
|
|
109
113
|
if (NRAgent.config.security.enabled || !NRAgent.config.high_security) {
|
|
110
114
|
wsClient.initialize();
|
|
111
115
|
logger.info('NR Agent started with agent_run_id:', NRAgent.config.run_id, NRAgent.config.account_id);
|
|
@@ -113,7 +117,8 @@ function initialize() {
|
|
|
113
117
|
Agent.setNRAgent(NRAgent);
|
|
114
118
|
}
|
|
115
119
|
else {
|
|
116
|
-
logger.
|
|
120
|
+
logger.warn("security.enabled flag is set to false");
|
|
121
|
+
NRLogger.warn("Failed to Start New Relic Node.js Security Agent. Please check security.enabled and high_security flags");
|
|
117
122
|
}
|
|
118
123
|
});
|
|
119
124
|
}
|
|
@@ -131,9 +136,9 @@ function initialize() {
|
|
|
131
136
|
}
|
|
132
137
|
}
|
|
133
138
|
logger.info(LOG_MESSAGES.AGENT_INFO, applicationInfo.collectorVersion, applicationInfo.jsonVersion, applicationInfo.buildNumber);
|
|
134
|
-
|
|
139
|
+
|
|
135
140
|
applicationInfoModule.addProperty('serverInfo.deployedApplications', applications);
|
|
136
|
-
|
|
141
|
+
|
|
137
142
|
shaSizeUtil.setLogger(logger);
|
|
138
143
|
|
|
139
144
|
// Initialize Agent Status
|
|
@@ -159,7 +164,7 @@ function getProcCMDLineSanitized(applicationInfoModule) {
|
|
|
159
164
|
}
|
|
160
165
|
|
|
161
166
|
(() => {
|
|
162
|
-
if(!NRAgent.config.security.enabled){
|
|
167
|
+
if (!NRAgent.config.security.enabled) {
|
|
163
168
|
logger.warn("security.enabled flag is set to false");
|
|
164
169
|
return;
|
|
165
170
|
}
|
|
@@ -9,6 +9,8 @@ const appInfo = require('./applicationinfo').getInstance();
|
|
|
9
9
|
const logs = require('./logging');
|
|
10
10
|
const logger = logs.getLogger();
|
|
11
11
|
const initLogger = logs.getInitLogger();
|
|
12
|
+
const LinkingMetaData = require('./LinkingMetadata');
|
|
13
|
+
const LogMessage = require('./LogMessage');
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
/* eslint-disable camelcase */
|
|
@@ -20,6 +22,7 @@ function AuthHeaders() {
|
|
|
20
22
|
try {
|
|
21
23
|
const NRAgent = API.getNRAgent();
|
|
22
24
|
authHeaders = {}
|
|
25
|
+
const metadata = LinkingMetaData.getLinkingMetadata();
|
|
23
26
|
authHeaders['NR-CSEC-CONNECTION-TYPE'] = 'LANGUAGE_COLLECTOR';
|
|
24
27
|
authHeaders['NR-AGENT-RUN-TOKEN'] = NRAgent.config.run_id;
|
|
25
28
|
const COLLECTOR_VERSION = appInfo.collectorVersion || '';
|
|
@@ -32,8 +35,12 @@ function AuthHeaders() {
|
|
|
32
35
|
authHeaders['NR-ACCOUNT-ID'] = NRAgent.config.account_id;
|
|
33
36
|
authHeaders['NR-LICENSE-KEY'] = NRAgent ? NRAgent.config.license_key : '';
|
|
34
37
|
authHeaders["NR-CSEC-IAST-DATA-TRANSFER-MODE"] = "PULL";
|
|
38
|
+
authHeaders['NR-CSEC-ENTITY-NAME'] = metadata['entity.name'] ? metadata['entity.name'] : '';
|
|
39
|
+
authHeaders['NR-CSEC-ENTITY-GUID'] = metadata['entity.guid'] ? metadata['entity.guid'] : '';
|
|
35
40
|
} catch (error) {
|
|
36
41
|
logger.error("Exception in preparing auth headers:", error);
|
|
42
|
+
const logMessage = new LogMessage.logMessage("SEVERE", 'Exception in preparing auth headers', __filename, error);
|
|
43
|
+
commonUtils.addLogEventtoBuffer(logMessage);
|
|
37
44
|
}
|
|
38
45
|
|
|
39
46
|
return authHeaders;
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
const LinkingMetaData = require('./LinkingMetadata');
|
|
7
7
|
const API = require('../../../nr-security-api');
|
|
8
8
|
const NRAgent = API.getNRAgent();
|
|
9
|
+
const { BasicInfo } = require('./event');
|
|
10
|
+
const applicationInfo = require('./applicationinfo').getInstance();
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
* constructor function to create LogMessageException object
|
|
@@ -13,10 +15,22 @@ const NRAgent = API.getNRAgent();
|
|
|
13
15
|
* @param {*} cause
|
|
14
16
|
* @param {*} stacktrace
|
|
15
17
|
*/
|
|
16
|
-
function logMessageException
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
function logMessageException(exception) {
|
|
19
|
+
let exceptionObject = {};
|
|
20
|
+
try {
|
|
21
|
+
exceptionObject.message = exception.message ? exception.message : '';
|
|
22
|
+
exceptionObject.cause = null;
|
|
23
|
+
if (exception.stack) {
|
|
24
|
+
let stacktraceInList = exception.stack.split('\n');
|
|
25
|
+
stacktraceInList = stacktraceInList.slice(1);
|
|
26
|
+
exceptionObject.stacktrace = stacktraceInList;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
} catch (error) {
|
|
30
|
+
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return exceptionObject;
|
|
20
34
|
}
|
|
21
35
|
|
|
22
36
|
/**
|
|
@@ -28,17 +42,29 @@ function logMessageException (exception) {
|
|
|
28
42
|
* @param {*} exception
|
|
29
43
|
* @param {*} linkingMetadata
|
|
30
44
|
*/
|
|
31
|
-
function logMessage
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
this.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
this.
|
|
45
|
+
function logMessage(level, message, caller, exception) {
|
|
46
|
+
try {
|
|
47
|
+
BasicInfo.call(this);
|
|
48
|
+
this.jsonVersion = applicationInfo.jsonVersion;
|
|
49
|
+
this.pid = applicationInfo.pid ? applicationInfo.pid : null;
|
|
50
|
+
this.jsonName = 'critical-messages';
|
|
51
|
+
this.applicationUUID = applicationInfo.applicationUUID;
|
|
52
|
+
this.groupName = applicationInfo.groupName;
|
|
53
|
+
this.policyVersion = applicationInfo.policyVersion;
|
|
54
|
+
this.timestamp = Date.now();
|
|
55
|
+
this.level = level ? level : 'SEVERE';
|
|
56
|
+
this.message = message;
|
|
57
|
+
this.caller = caller;
|
|
58
|
+
if (exception) {
|
|
59
|
+
this.exception = logMessageException(exception);
|
|
60
|
+
}
|
|
61
|
+
if (NRAgent) {
|
|
62
|
+
this.linkingMetadata = LinkingMetaData.getLinkingMetadata();
|
|
63
|
+
}
|
|
64
|
+
} catch (error) {
|
|
65
|
+
|
|
41
66
|
}
|
|
67
|
+
|
|
42
68
|
}
|
|
43
69
|
|
|
44
70
|
module.exports = {
|
|
@@ -12,16 +12,19 @@ const OS = require('os');
|
|
|
12
12
|
const path = require('path');
|
|
13
13
|
const checkDiskSpace = require('check-disk-space').default;
|
|
14
14
|
const AgentStatus = require('../core/agent-status');
|
|
15
|
-
const {
|
|
15
|
+
const { CSEC_HOME, SLASH } = require('./sec-agent-constants');
|
|
16
16
|
|
|
17
|
-
const prettyBytes = require('pretty-bytes');
|
|
18
17
|
const njsAgentConstants = require('./sec-agent-constants');
|
|
19
|
-
const LinkingMetaData = require('./LinkingMetadata');
|
|
20
18
|
const API = require('../../../nr-security-api');
|
|
21
19
|
const NRAgent = API.getNRAgent();
|
|
22
20
|
const lodash = require('lodash')
|
|
23
21
|
const backupLogFileRegex = /.log.\d/gm;
|
|
24
22
|
let websocketHealth;
|
|
23
|
+
|
|
24
|
+
const ringBuffer = require('ringbufferjs');
|
|
25
|
+
const bufferedLogEvents = new ringBuffer(10);
|
|
26
|
+
|
|
27
|
+
|
|
25
28
|
/**
|
|
26
29
|
* Utility to generate UUID
|
|
27
30
|
* @returns UUID
|
|
@@ -103,6 +106,9 @@ function createPathIfNotExist(dir) {
|
|
|
103
106
|
}
|
|
104
107
|
} catch (error) {
|
|
105
108
|
logger.debug(dir + ' Not Created', error);
|
|
109
|
+
const LogMessage = require('./LogMessage');
|
|
110
|
+
const logMessage = new LogMessage.logMessage("SEVERE", 'Error in creating directory', __filename, error);
|
|
111
|
+
addLogEventtoBuffer(logMessage);
|
|
106
112
|
}
|
|
107
113
|
}
|
|
108
114
|
|
|
@@ -281,6 +287,9 @@ function removeOlderSnapshots() {
|
|
|
281
287
|
}
|
|
282
288
|
} catch (error) {
|
|
283
289
|
logger.debug(error);
|
|
290
|
+
const LogMessage = require('./LogMessage');
|
|
291
|
+
const logMessage = new LogMessage.logMessage("SEVERE", 'Error in processing snapshot files', __filename, error);
|
|
292
|
+
addLogEventtoBuffer(logMessage);
|
|
284
293
|
}
|
|
285
294
|
}
|
|
286
295
|
/**
|
|
@@ -417,6 +426,26 @@ function getWSHealthStatus() {
|
|
|
417
426
|
}
|
|
418
427
|
}
|
|
419
428
|
|
|
429
|
+
/**
|
|
430
|
+
* return buffered Log Event instance.
|
|
431
|
+
*/
|
|
432
|
+
function getLogEvents() {
|
|
433
|
+
return bufferedLogEvents;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Utility to add error object in error buffer
|
|
439
|
+
* @param {*} error
|
|
440
|
+
*/
|
|
441
|
+
function addLogEventtoBuffer(logMessage) {
|
|
442
|
+
try {
|
|
443
|
+
bufferedLogEvents.enq(logMessage);
|
|
444
|
+
} catch (error) {
|
|
445
|
+
logger.debug(error);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
420
449
|
module.exports = {
|
|
421
450
|
getUUID,
|
|
422
451
|
getKindIdPair,
|
|
@@ -438,5 +467,7 @@ module.exports = {
|
|
|
438
467
|
getCSECmode,
|
|
439
468
|
getPathOfCACert,
|
|
440
469
|
getWSHealthStatus,
|
|
441
|
-
setWSHealthStatus
|
|
470
|
+
setWSHealthStatus,
|
|
471
|
+
addLogEventtoBuffer,
|
|
472
|
+
getLogEvents
|
|
442
473
|
};
|
|
@@ -38,16 +38,14 @@ function invokeLambda (arn, version, data) {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
function init () {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
) {
|
|
45
|
-
|
|
41
|
+
try {
|
|
42
|
+
const { Lambda } = require('@aws-sdk/client-lambda');
|
|
43
|
+
lambdaClient = new Lambda();
|
|
44
|
+
} catch (error) {
|
|
45
|
+
logger.error("Unable to initialize lambda client", error);
|
|
46
46
|
}
|
|
47
|
-
|
|
48
|
-
const { Lambda } = require('@aws-sdk/client-lambda');
|
|
49
|
-
lambdaClient = new Lambda();
|
|
50
47
|
}
|
|
48
|
+
|
|
51
49
|
init();
|
|
52
50
|
|
|
53
51
|
module.exports = {
|