@newrelic/security-agent 1.0.1 → 1.1.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/CHANGELOG.md +18 -0
- package/README.md +2 -1
- package/THIRD_PARTY_NOTICES.md +48 -1
- package/lib/instrumentation-security/core/route-manager.js +28 -5
- package/lib/instrumentation-security/core/sec-utils.js +3 -3
- package/lib/instrumentation-security/hooks/express/nr-express.js +2 -4
- package/lib/instrumentation-security/hooks/undici/nr-undici.js +139 -0
- package/lib/instrumentation-security/index.js +9 -0
- package/lib/nr-security-agent/lib/core/apiEndpoints.js +29 -0
- package/lib/nr-security-agent/lib/core/commonUtils.js +4 -4
- package/lib/nr-security-agent/lib/core/logging.js +5 -5
- package/lib/nr-security-agent/lib/core/statusUtils.js +2 -2
- package/lib/nr-security-agent/lib/core/websocket-client.js +10 -1
- package/package.json +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
### v1.1.1 (2024-03-21)
|
|
2
|
+
#### Bug fixes
|
|
3
|
+
* Reverted IAST support for gRPC.
|
|
4
|
+
|
|
5
|
+
### v1.1.0 (2024-03-19)
|
|
6
|
+
#### Features
|
|
7
|
+
* IAST support for grpc
|
|
8
|
+
* Functionality to report API endpoints of the application
|
|
9
|
+
* IAST support for undici
|
|
10
|
+
#### Bug fixes
|
|
11
|
+
* Updated permissions for file/directory created by security agent
|
|
12
|
+
#### Miscellaneous chores
|
|
13
|
+
* Bumped follow-redirects from v1.15.2 to v1.15.4
|
|
14
|
+
* Updated axios to v1.6.8
|
|
15
|
+
* Bumped ip from v2.0.0 to v2.0.1
|
|
16
|
+
* Bumped undici from 5.28.2 to v5.28.3
|
|
17
|
+
* Readme update
|
|
18
|
+
|
|
1
19
|
### v1.0.1 (2024-02-07)
|
|
2
20
|
#### Bug fixes
|
|
3
21
|
* Reporting of framework in security event json
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
**Note**: The IAST capability should only be used in pre-production environments as the application is tested for real exploitable vulnerabilities.
|
|
5
5
|
|
|
6
|
-
The New Relic security agent
|
|
6
|
+
The New Relic security agent enables instrumentation of a Node.js application for Interactive Application Security Testing(IAST) and exposes exploitable vulnerabilities.
|
|
7
7
|
|
|
8
8
|
## Installation
|
|
9
9
|
|
|
@@ -67,6 +67,7 @@ The [Developer docs](http://newrelic.github.io/node-newrelic/) for writing instr
|
|
|
67
67
|
- [ldapts](https://www.npmjs.com/package/ldapts)(2.x and above)
|
|
68
68
|
- [xpath](https://www.npmjs.com/package/xpath)(0.0.20 and above)
|
|
69
69
|
- [xpath.js](https://www.npmjs.com/package/xpath.js)(0.0.1 and above)
|
|
70
|
+
- [undici](https://www.npmjs.com/package/undici)(4.7.0 and above)
|
|
70
71
|
|
|
71
72
|
For more information, please see New Relic Node.js agent [compatibility and requirements](https://docs.newrelic.com/docs/apm/agents/nodejs-agent/getting-started/compatibility-requirements-nodejs-agent/).
|
|
72
73
|
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -64,7 +64,9 @@ code, the source code can be found at [https://github.com/newrelic/csec-node-age
|
|
|
64
64
|
* [request](#request)
|
|
65
65
|
* [restify](#restify)
|
|
66
66
|
* [sinon](#sinon)
|
|
67
|
+
* [stream](#stream)
|
|
67
68
|
* [tap](#tap)
|
|
69
|
+
* [undici](#undici)
|
|
68
70
|
* [xmldom](#xmldom)
|
|
69
71
|
* [xpath.js](#xpathjs)
|
|
70
72
|
* [xpath](#xpath)
|
|
@@ -74,7 +76,7 @@ code, the source code can be found at [https://github.com/newrelic/csec-node-age
|
|
|
74
76
|
|
|
75
77
|
### axios
|
|
76
78
|
|
|
77
|
-
This product includes source derived from [axios](https://github.com/axios/axios) ([v1.6.
|
|
79
|
+
This product includes source derived from [axios](https://github.com/axios/axios) ([v1.6.8](https://github.com/axios/axios/tree/v1.6.8)), distributed under the [MIT License](https://github.com/axios/axios/blob/v1.6.8/LICENSE):
|
|
78
80
|
|
|
79
81
|
```
|
|
80
82
|
# Copyright (c) 2014-present Matt Zabriskie & Collaborators
|
|
@@ -2588,6 +2590,22 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
2588
2590
|
|
|
2589
2591
|
```
|
|
2590
2592
|
|
|
2593
|
+
### stream
|
|
2594
|
+
|
|
2595
|
+
This product includes source derived from [stream](https://github.com/juliangruber/stream) ([v0.0.2](https://github.com/juliangruber/stream/tree/v0.0.2)), distributed under the [MIT License](https://github.com/juliangruber/stream/blob/v0.0.2/README.md):
|
|
2596
|
+
|
|
2597
|
+
```
|
|
2598
|
+
MIT License
|
|
2599
|
+
|
|
2600
|
+
Copyright (c) <year> <copyright holders>
|
|
2601
|
+
|
|
2602
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
2603
|
+
|
|
2604
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
2605
|
+
|
|
2606
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
2607
|
+
```
|
|
2608
|
+
|
|
2591
2609
|
### tap
|
|
2592
2610
|
|
|
2593
2611
|
This product includes source derived from [tap](https://github.com/tapjs/node-tap) ([v16.3.7](https://github.com/tapjs/node-tap/tree/v16.3.7)), distributed under the [ISC License](https://github.com/tapjs/node-tap/blob/v16.3.7/LICENSE):
|
|
@@ -2611,6 +2629,35 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
2611
2629
|
|
|
2612
2630
|
```
|
|
2613
2631
|
|
|
2632
|
+
### undici
|
|
2633
|
+
|
|
2634
|
+
This product includes source derived from [undici](https://github.com/nodejs/undici) ([v5.28.3](https://github.com/nodejs/undici/tree/v5.28.3)), distributed under the [MIT License](https://github.com/nodejs/undici/blob/v5.28.3/LICENSE):
|
|
2635
|
+
|
|
2636
|
+
```
|
|
2637
|
+
MIT License
|
|
2638
|
+
|
|
2639
|
+
Copyright (c) Matteo Collina and Undici contributors
|
|
2640
|
+
|
|
2641
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
2642
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
2643
|
+
in the Software without restriction, including without limitation the rights
|
|
2644
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
2645
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
2646
|
+
furnished to do so, subject to the following conditions:
|
|
2647
|
+
|
|
2648
|
+
The above copyright notice and this permission notice shall be included in all
|
|
2649
|
+
copies or substantial portions of the Software.
|
|
2650
|
+
|
|
2651
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
2652
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
2653
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
2654
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
2655
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
2656
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
2657
|
+
SOFTWARE.
|
|
2658
|
+
|
|
2659
|
+
```
|
|
2660
|
+
|
|
2614
2661
|
### xmldom
|
|
2615
2662
|
|
|
2616
2663
|
This product includes source derived from [xmldom](https://github.com/xmldom/xmldom) ([v0.6.0](https://github.com/xmldom/xmldom/tree/v0.6.0)), distributed under the [MIT License](https://github.com/xmldom/xmldom/blob/v0.6.0/LICENSE):
|
|
@@ -10,8 +10,8 @@ const routeMap = new Map();
|
|
|
10
10
|
* @param {*} key
|
|
11
11
|
* @param {*} value
|
|
12
12
|
*/
|
|
13
|
-
function setRoute(key, value){
|
|
14
|
-
routeMap.set(key,value);
|
|
13
|
+
function setRoute(key, value) {
|
|
14
|
+
routeMap.set(key, value);
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -19,12 +19,35 @@ function setRoute(key, value){
|
|
|
19
19
|
* @param {*} key
|
|
20
20
|
* @returns
|
|
21
21
|
*/
|
|
22
|
-
function getRoute(key){
|
|
22
|
+
function getRoute(key) {
|
|
23
23
|
return routeMap.get(key);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Utility to get all api end points
|
|
28
|
+
* @returns all keys from routeMap
|
|
29
|
+
*/
|
|
30
|
+
function getAllAPIEndPoints() {
|
|
31
|
+
let apiEndpoints = [];
|
|
32
|
+
try {
|
|
33
|
+
routeMap.forEach((value, key) => {
|
|
34
|
+
let obj = {};
|
|
35
|
+
let splitted = key.split('@');
|
|
36
|
+
obj.method = splitted[0];
|
|
37
|
+
obj.path = splitted[1];
|
|
38
|
+
obj.handler = routeMap.get(key);
|
|
39
|
+
apiEndpoints.push(obj);
|
|
40
|
+
})
|
|
41
|
+
} catch (error) {
|
|
42
|
+
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return apiEndpoints;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = {
|
|
27
49
|
getRoute,
|
|
28
50
|
setRoute,
|
|
29
|
-
routeMap
|
|
51
|
+
routeMap,
|
|
52
|
+
getAllAPIEndPoints
|
|
30
53
|
}
|
|
@@ -150,11 +150,11 @@ function getExecutionId(){
|
|
|
150
150
|
function createPathIfNotExist (dir) {
|
|
151
151
|
try {
|
|
152
152
|
if (!fs.existsSync(dir)) {
|
|
153
|
-
fs.mkdirSync(dir,
|
|
153
|
+
fs.mkdirSync(dir, 770, { recursive: true });
|
|
154
154
|
logger.info(dir + ' Created');
|
|
155
|
-
fs.chmodSync(dir,
|
|
155
|
+
fs.chmodSync(dir, 0o770);
|
|
156
156
|
} else {
|
|
157
|
-
fs.chmodSync(dir,
|
|
157
|
+
fs.chmodSync(dir, 0o770);
|
|
158
158
|
logger.debug(dir + ' Already Exists');
|
|
159
159
|
}
|
|
160
160
|
} catch (error) {
|
|
@@ -27,9 +27,8 @@ module.exports = function initialize(shim, express, moduleName) {
|
|
|
27
27
|
|
|
28
28
|
if (express.Router.use) {
|
|
29
29
|
wrapExpress4(shim, express)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
}
|
|
30
|
+
}
|
|
31
|
+
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
/**
|
|
@@ -57,7 +56,6 @@ function wrapExpress4(shim, express) {
|
|
|
57
56
|
}
|
|
58
57
|
})
|
|
59
58
|
|
|
60
|
-
|
|
61
59
|
//Wrapper to hook process_params method to extract out path param and query params.
|
|
62
60
|
shim.wrap(express.Router, 'process_params', function wrapParam(shim, fn) {
|
|
63
61
|
if (!shim.isFunction(fn)) {
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2023 New Relic Corporation. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: New Relic Pre-Release
|
|
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 lodash = require('lodash');
|
|
11
|
+
const securityMetaData = require('../../core/security-metadata');
|
|
12
|
+
const { EVENT_TYPE, EVENT_CATEGORY } = require('../../core/event-constants');
|
|
13
|
+
const { NR_CSEC_FUZZ_REQUEST_ID, QUESTION_MARK, EMPTY_STRING, COLON, SLASH } = require('../../core/constants');
|
|
14
|
+
const NRCSECTRACINGDATA = 'NR-CSEC-TRACING-DATA';
|
|
15
|
+
const DOUBLE_SLASH = '//';
|
|
16
|
+
const logger = API.getLogger();
|
|
17
|
+
const url = require('url');
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Entry point undici module instrumentation.
|
|
22
|
+
* @param {*} shim
|
|
23
|
+
* @param {*} mod
|
|
24
|
+
* @param {*} moduleName
|
|
25
|
+
*/
|
|
26
|
+
function initialize(shim, mod, moduleName) {
|
|
27
|
+
logger.info('Instrumenting ' + moduleName);
|
|
28
|
+
fetchHook(shim, mod, "fetch");
|
|
29
|
+
let util = shim.require('./lib/core/util');
|
|
30
|
+
parseOriginHook(shim, util, "parseOrigin")
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Wrapper for util.parseOrigin
|
|
35
|
+
* @param {*} shim
|
|
36
|
+
* @param {*} mod
|
|
37
|
+
* @param {*} methodName
|
|
38
|
+
*/
|
|
39
|
+
function parseOriginHook(shim, mod, methodName) {
|
|
40
|
+
shim.wrap(mod, methodName, function ClientWrapper(shim, fn) {
|
|
41
|
+
logger.debug(`Instrumenting ${methodName}`);
|
|
42
|
+
if (!shim.isFunction(fn)) {
|
|
43
|
+
return fn
|
|
44
|
+
}
|
|
45
|
+
return function wrapper() {
|
|
46
|
+
const request = requestManager.getRequest(shim);
|
|
47
|
+
try {
|
|
48
|
+
if (typeof arguments[0] === 'string') {
|
|
49
|
+
let URLObject = new URL(arguments[0]);
|
|
50
|
+
const data = {};
|
|
51
|
+
data.headers = {};
|
|
52
|
+
data.path = URLObject.pathname ? URLObject.pathname : EMPTY_STRING;
|
|
53
|
+
data.protocol = URLObject.protocol ? URLObject.protocol : 'http:';
|
|
54
|
+
data.headers.host = URLObject.host ? URLObject.host : URLObject.hostname;
|
|
55
|
+
shim.interceptedArgs = data;
|
|
56
|
+
if (request) {
|
|
57
|
+
const traceObject = secUtils.getTraceObject(shim);
|
|
58
|
+
const secMetadata = securityMetaData.getSecurityMetaData(request, data, traceObject, secUtils.getExecutionId(), EVENT_TYPE.HTTP_REQUEST, EVENT_CATEGORY.HTTP)
|
|
59
|
+
this.secEvent = API.generateSecEvent(secMetadata);
|
|
60
|
+
API.sendEvent(this.secEvent);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
} catch (error) {
|
|
64
|
+
|
|
65
|
+
}
|
|
66
|
+
const result = fn.apply(this, arguments);
|
|
67
|
+
if (result && request && request.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
|
|
68
|
+
API.generateExitEvent(this.secEvent);
|
|
69
|
+
delete this.secEvent
|
|
70
|
+
}
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Wrapper to hook undici.fetch()
|
|
78
|
+
* @param {*} shim
|
|
79
|
+
* @param {*} mod
|
|
80
|
+
* @param {*} methodName
|
|
81
|
+
*/
|
|
82
|
+
function fetchHook(shim, mod, methodName) {
|
|
83
|
+
shim.wrap(mod, methodName, function makeWrapper(shim, fn) {
|
|
84
|
+
logger.debug(`Instrumenting ${methodName}`);
|
|
85
|
+
if (!shim.isFunction(fn)) {
|
|
86
|
+
return fn
|
|
87
|
+
}
|
|
88
|
+
return function wrapper() {
|
|
89
|
+
const request = requestManager.getRequest(shim);
|
|
90
|
+
try {
|
|
91
|
+
const completeURL = arguments[0];
|
|
92
|
+
const parsedUrl = url.parse(completeURL);
|
|
93
|
+
const data = {};
|
|
94
|
+
data.headers = {};
|
|
95
|
+
data.method = arguments[0].method ? arguments[0].method : EMPTY_STRING;
|
|
96
|
+
data.path = parsedUrl.pathname ? parsedUrl.pathname : parsedUrl.path;
|
|
97
|
+
data.protocol = parsedUrl.protocol;
|
|
98
|
+
data.headers.host = parsedUrl.host ? parsedUrl.host : parsedUrl.hostname;
|
|
99
|
+
data.port = parsedUrl.port ? parsedUrl.port : parsedUrl.port;
|
|
100
|
+
|
|
101
|
+
shim.interceptedArgs = data;
|
|
102
|
+
if (request && !lodash.isEmpty(data.headers.host) && !lodash.isEmpty(data.path)) {
|
|
103
|
+
const appUUID = API.getSecAgent().applicationInfo.applicationUUID;
|
|
104
|
+
const traceObject = secUtils.getTraceObject(shim);
|
|
105
|
+
const secMetadata = securityMetaData.getSecurityMetaData(request, data, traceObject, secUtils.getExecutionId(), EVENT_TYPE.HTTP_REQUEST, EVENT_CATEGORY.HTTP)
|
|
106
|
+
this.secEvent = API.generateSecEvent(secMetadata);
|
|
107
|
+
API.sendEvent(this.secEvent);
|
|
108
|
+
|
|
109
|
+
let traceHeader = EMPTY_STRING;
|
|
110
|
+
if (request.headers['nr-csec-tracing-data']) {
|
|
111
|
+
traceHeader = request.headers['nr-csec-tracing-data'];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (arguments[1] instanceof Object) {
|
|
115
|
+
if (arguments[1] && arguments[1].headers && request.headers) {
|
|
116
|
+
arguments[1].headers[NRCSECTRACINGDATA] = traceHeader + appUUID + '/' + this.secEvent.apiId + '/' + this.secEvent.id + ';';
|
|
117
|
+
} else {
|
|
118
|
+
arguments[1].headers = {};
|
|
119
|
+
arguments[1].headers[NRCSECTRACINGDATA] = traceHeader + appUUID + '/' + this.secEvent.apiId + '/' + this.secEvent.id + ';';
|
|
120
|
+
}
|
|
121
|
+
if (request && request.headers[NR_CSEC_FUZZ_REQUEST_ID] && arguments[1].headers) {
|
|
122
|
+
arguments[1].headers[NR_CSEC_FUZZ_REQUEST_ID] = request.headers[NR_CSEC_FUZZ_REQUEST_ID];
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
} catch (error) {
|
|
127
|
+
logger.debug("Error while extracting undici fetch args:", error);
|
|
128
|
+
}
|
|
129
|
+
const result = fn.apply(this, arguments);
|
|
130
|
+
|
|
131
|
+
if (result && request && request.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
|
|
132
|
+
API.generateExitEvent(this.secEvent);
|
|
133
|
+
delete this.secEvent
|
|
134
|
+
}
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
|
|
@@ -190,6 +190,15 @@ newrelic.instrumentWebframework({
|
|
|
190
190
|
}
|
|
191
191
|
})
|
|
192
192
|
|
|
193
|
+
newrelic.instrumentWebframework({
|
|
194
|
+
moduleName: 'undici',
|
|
195
|
+
isEsm: true,
|
|
196
|
+
onRequire: require('./hooks/undici/nr-undici'),
|
|
197
|
+
onError: function intrumentErrorHandler(err) {
|
|
198
|
+
logger.error(err.message, err.stack)
|
|
199
|
+
}
|
|
200
|
+
})
|
|
201
|
+
|
|
193
202
|
|
|
194
203
|
|
|
195
204
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2023 New Relic Corporation. All rights reserved.
|
|
4
|
+
* SPDX-License-Identifier: New Relic Software License v1.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { BasicInfo } = require('./event');
|
|
8
|
+
const applicationInfo = require('./applicationinfo').getInstance();
|
|
9
|
+
/**
|
|
10
|
+
* Function Constructor to create object of FuzzFail event
|
|
11
|
+
* @param {*} fuzzHeader
|
|
12
|
+
*/
|
|
13
|
+
function APIEndPoint (apiEndpoints) {
|
|
14
|
+
BasicInfo.call(this);
|
|
15
|
+
this.jsonVersion = applicationInfo.jsonVersion;
|
|
16
|
+
this.jsonName = 'sec-application-url-mapping';
|
|
17
|
+
this.eventType = "sec-application-url-mapping"
|
|
18
|
+
this.applicationUUID = applicationInfo.applicationUUID;
|
|
19
|
+
this.groupName = applicationInfo.groupName;
|
|
20
|
+
this.mappings = apiEndpoints;
|
|
21
|
+
|
|
22
|
+
return this;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
APIEndPoint.prototype.constructor = APIEndPoint;
|
|
26
|
+
|
|
27
|
+
module.exports = {
|
|
28
|
+
APIEndPoint
|
|
29
|
+
};
|
|
@@ -97,11 +97,11 @@ function runtimeSupportsAsyncFunctionGenerators() {
|
|
|
97
97
|
function createPathIfNotExist(dir) {
|
|
98
98
|
try {
|
|
99
99
|
if (!fs.existsSync(dir)) {
|
|
100
|
-
fs.mkdirSync(dir,
|
|
100
|
+
fs.mkdirSync(dir, 770, { recursive: true });
|
|
101
101
|
logger.info(dir + ' Created');
|
|
102
|
-
fs.chmodSync(dir,
|
|
102
|
+
fs.chmodSync(dir, 0o770);
|
|
103
103
|
} else {
|
|
104
|
-
fs.chmodSync(dir,
|
|
104
|
+
fs.chmodSync(dir, 0o770);
|
|
105
105
|
logger.debug(dir + ' Already Exists');
|
|
106
106
|
}
|
|
107
107
|
} catch (error) {
|
|
@@ -139,7 +139,7 @@ function createDirectories() {
|
|
|
139
139
|
createPathIfNotExist(`${CSEC_HOME}${SLASH}nr-security-home${SLASH}tmp${SLASH}language-agent${SLASH}${getUUID()}`);
|
|
140
140
|
createPathIfNotExist(`${CSEC_HOME}${SLASH}nr-security-home${SLASH}tmp${SLASH}language-agent${SLASH}${getUUID()}${SLASH}ds-tmp`);
|
|
141
141
|
try {
|
|
142
|
-
fs.chmodSync(`${CSEC_HOME}${SLASH}nr-security-home`,
|
|
142
|
+
fs.chmodSync(`${CSEC_HOME}${SLASH}nr-security-home`, 0o770);
|
|
143
143
|
} catch (error) {
|
|
144
144
|
}
|
|
145
145
|
}
|
|
@@ -31,11 +31,11 @@ const CSEC_ROOT = `${CSEC_HOME}${sep}nr-security-home${sep}`;
|
|
|
31
31
|
function createLogPathIfNotExist(dir) {
|
|
32
32
|
try {
|
|
33
33
|
if (!fs.existsSync(dir)) {
|
|
34
|
-
fs.mkdirSync(dir,
|
|
35
|
-
fs.chmodSync(dir,
|
|
34
|
+
fs.mkdirSync(dir, 770, { recursive: true });
|
|
35
|
+
fs.chmodSync(dir, 0o770);
|
|
36
36
|
}
|
|
37
37
|
else {
|
|
38
|
-
fs.chmodSync(dir,
|
|
38
|
+
fs.chmodSync(dir, 0o770);
|
|
39
39
|
}
|
|
40
40
|
} catch (error) {
|
|
41
41
|
}
|
|
@@ -168,8 +168,8 @@ function getLogger(applicationUUID = process.env.applicationUUID) {
|
|
|
168
168
|
logger = log4js.getLogger('NR_CSEC');
|
|
169
169
|
const initLogger = getInitLogger();
|
|
170
170
|
try {
|
|
171
|
-
fs.chmodSync(`${logFileName}`,
|
|
172
|
-
fs.chmodSync(`${initLogFileName}`,
|
|
171
|
+
fs.chmodSync(`${logFileName}`, 0o660);
|
|
172
|
+
fs.chmodSync(`${initLogFileName}`, 0o660);
|
|
173
173
|
} catch (error) {
|
|
174
174
|
}
|
|
175
175
|
initLogger.info("[STEP-2] => Generating unique identifier:", applicationUUID)
|
|
@@ -93,7 +93,7 @@ function getFormattedData() {
|
|
|
93
93
|
function writeSnapshot() {
|
|
94
94
|
const snapshot = getFormattedData();
|
|
95
95
|
commonUtils.removeOlderSnapshots();
|
|
96
|
-
fs.writeFile(statusFile, snapshot, { mode:
|
|
96
|
+
fs.writeFile(statusFile, snapshot, { mode: 0o660 }, function (err) {
|
|
97
97
|
if (err) {
|
|
98
98
|
logger.debug(err.message);
|
|
99
99
|
const LogMessage = require('./LogMessage');
|
|
@@ -101,7 +101,7 @@ function writeSnapshot() {
|
|
|
101
101
|
commonUtils.addLogEventtoBuffer(logMessage);
|
|
102
102
|
} else {
|
|
103
103
|
logger.info('Snapshot updated to file: %s', statusFile);
|
|
104
|
-
fs.chmod(statusFile,
|
|
104
|
+
fs.chmod(statusFile, 0o660, (err) => {
|
|
105
105
|
if (err) {
|
|
106
106
|
addErrortoBuffer(err);
|
|
107
107
|
}
|
|
@@ -70,6 +70,15 @@ const initialize = function () {
|
|
|
70
70
|
setTimeout(() => {
|
|
71
71
|
setInterval(sendHC, HC_INTERVAL_MS);
|
|
72
72
|
sendHC();
|
|
73
|
+
try {
|
|
74
|
+
let apiEndpoints = require('../../../instrumentation-security/core/route-manager').getAllAPIEndPoints();
|
|
75
|
+
let data = require('./apiEndpoints').APIEndPoint(apiEndpoints);
|
|
76
|
+
logger.debug("All API end points of the application is:",JSON.stringify(data));
|
|
77
|
+
getDispatcherAndSendEvent(data);
|
|
78
|
+
} catch (error) {
|
|
79
|
+
logger.debug("Error while processing API endpoints",error);
|
|
80
|
+
}
|
|
81
|
+
|
|
73
82
|
try {
|
|
74
83
|
const framework = NRAgent.environment.get('Framework')[0];
|
|
75
84
|
const dispatcher = NRAgent.environment.get('Dispatcher')[0];
|
|
@@ -78,8 +87,8 @@ const initialize = function () {
|
|
|
78
87
|
} catch (error) {
|
|
79
88
|
logger.debug("Error while extracting data from APM environment",error);
|
|
80
89
|
}
|
|
90
|
+
}, 20000);
|
|
81
91
|
|
|
82
|
-
}, 30000);
|
|
83
92
|
|
|
84
93
|
setInterval(commonUtils.logRollOver, 30000);
|
|
85
94
|
initLogger.info("[STEP-5] => Security Agent components started");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@newrelic/security-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "New Relic Security Agent for Node.js",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"jsonVersion": "1.1.1",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"url": "https://github.com/newrelic/csec-node-agent.git"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"axios": "^1.6.
|
|
38
|
+
"axios": "^1.6.8",
|
|
39
39
|
"check-disk-space": "^3.4.0",
|
|
40
40
|
"content-type": "^1.0.5",
|
|
41
41
|
"fast-safe-stringify": "^2.1.1",
|
|
@@ -84,7 +84,9 @@
|
|
|
84
84
|
"request": "^2.88.2",
|
|
85
85
|
"restify": "^11.1.0",
|
|
86
86
|
"sinon": "^15.0.0",
|
|
87
|
+
"stream": "^0.0.2",
|
|
87
88
|
"tap": "^16.3.2",
|
|
89
|
+
"undici": "^5.28.0",
|
|
88
90
|
"xmldom": "^0.6.0",
|
|
89
91
|
"xpath": "^0.0.32",
|
|
90
92
|
"xpath.js": "^1.1.0"
|