@newrelic/security-agent 0.0.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 +0 -0
- package/CONTRIBUTING.md +23 -0
- package/LICENSE +43 -0
- package/README.md +98 -0
- package/THIRD_PARTY_NOTICES.md +2909 -0
- package/index.js +24 -0
- package/lib/instrumentation-security/core/constants.js +66 -0
- package/lib/instrumentation-security/core/event-constants.js +49 -0
- package/lib/instrumentation-security/core/request-manager.js +73 -0
- package/lib/instrumentation-security/core/route-manager.js +30 -0
- package/lib/instrumentation-security/core/sec-trace.js +134 -0
- package/lib/instrumentation-security/core/sec-utils.js +212 -0
- package/lib/instrumentation-security/core/security-metadata.js +34 -0
- package/lib/instrumentation-security/core/stack-trace.js +156 -0
- package/lib/instrumentation-security/hooks/director/nr-director.js +98 -0
- package/lib/instrumentation-security/hooks/express/nr-express.js +106 -0
- package/lib/instrumentation-security/hooks/fastify/nr-fastify.js +155 -0
- package/lib/instrumentation-security/hooks/fs/nr-fs.js +391 -0
- package/lib/instrumentation-security/hooks/hapi/nr-hapi.js +131 -0
- package/lib/instrumentation-security/hooks/http/nr-http.js +461 -0
- package/lib/instrumentation-security/hooks/koa/@koa/nr-@koa-router.js +110 -0
- package/lib/instrumentation-security/hooks/ldap/nr-ldap.js +81 -0
- package/lib/instrumentation-security/hooks/mongodb/common.js +239 -0
- package/lib/instrumentation-security/hooks/mongodb/constants.js +91 -0
- package/lib/instrumentation-security/hooks/mongodb/nr-mongodb.js +49 -0
- package/lib/instrumentation-security/hooks/mongodb/v2-mongo.js +91 -0
- package/lib/instrumentation-security/hooks/mongodb/v3-mongo.js +36 -0
- package/lib/instrumentation-security/hooks/mongodb/v4-mongo.js +17 -0
- package/lib/instrumentation-security/hooks/mysql/nr-mysql.js +232 -0
- package/lib/instrumentation-security/hooks/native/nr-childProcess.js +131 -0
- package/lib/instrumentation-security/hooks/postgres/nr-postgres.js +131 -0
- package/lib/instrumentation-security/hooks/require/nr-require.js +93 -0
- package/lib/instrumentation-security/hooks/restify/nr-restify.js +104 -0
- package/lib/instrumentation-security/hooks/xpath/nr-xpath.js +91 -0
- package/lib/instrumentation-security/index.js +171 -0
- package/lib/nr-security-agent/index.js +170 -0
- package/lib/nr-security-agent/lib/core/Auth-headers.js +58 -0
- package/lib/nr-security-agent/lib/core/ContainerProperties.js +42 -0
- package/lib/nr-security-agent/lib/core/ECSProperties.js +34 -0
- package/lib/nr-security-agent/lib/core/FuzzFailEvent.js +27 -0
- package/lib/nr-security-agent/lib/core/LinkingMetadata.js +21 -0
- package/lib/nr-security-agent/lib/core/LogMessage.js +47 -0
- package/lib/nr-security-agent/lib/core/PodProperties.js +36 -0
- package/lib/nr-security-agent/lib/core/Policy.js +105 -0
- package/lib/nr-security-agent/lib/core/agent-status.js +56 -0
- package/lib/nr-security-agent/lib/core/agent.js +146 -0
- package/lib/nr-security-agent/lib/core/applicationinfo.js +634 -0
- package/lib/nr-security-agent/lib/core/commonUtils.js +411 -0
- package/lib/nr-security-agent/lib/core/connections/aws-lambda-client.js +55 -0
- package/lib/nr-security-agent/lib/core/connections/restclient.js +20 -0
- package/lib/nr-security-agent/lib/core/connections/websocket/index.js +25 -0
- package/lib/nr-security-agent/lib/core/connections/websocket/response/collecotor-policy-error-handler.js +18 -0
- package/lib/nr-security-agent/lib/core/connections/websocket/response/collector-policy-handler.js +20 -0
- package/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js +171 -0
- package/lib/nr-security-agent/lib/core/connections/websocket/response/index.js +47 -0
- package/lib/nr-security-agent/lib/core/connections/websocket/response/no-op-handler.js +12 -0
- package/lib/nr-security-agent/lib/core/connections/websocket/response/startup-handshake-handler.js +27 -0
- package/lib/nr-security-agent/lib/core/connections/websocket/response/unsupported-agent-handler.js +18 -0
- package/lib/nr-security-agent/lib/core/connections/websocket/response/ws-reconnect.js +14 -0
- package/lib/nr-security-agent/lib/core/connections/websocket/websocket.js +443 -0
- package/lib/nr-security-agent/lib/core/event.js +186 -0
- package/lib/nr-security-agent/lib/core/health-check.js +159 -0
- package/lib/nr-security-agent/lib/core/json-file-handler.js +66 -0
- package/lib/nr-security-agent/lib/core/jsonValidator.js +149 -0
- package/lib/nr-security-agent/lib/core/lambda-delegated-task-service.js +90 -0
- package/lib/nr-security-agent/lib/core/logging.js +176 -0
- package/lib/nr-security-agent/lib/core/sec-agent-constants.js +173 -0
- package/lib/nr-security-agent/lib/core/sec-util.js +166 -0
- package/lib/nr-security-agent/lib/core/sha-size-util.js +338 -0
- package/lib/nr-security-agent/lib/core/sha_worker.js +24 -0
- package/lib/nr-security-agent/lib/core/startup-config.js +29 -0
- package/lib/nr-security-agent/lib/core/statusUtils.js +157 -0
- package/lib/nr-security-agent/lib/core/timeunit.js +44 -0
- package/lib/nr-security-agent/lib/core/websocket-client.js +335 -0
- package/lib/nr-security-agent/lib/core/worker-entities.js +82 -0
- package/lib/nr-security-agent/lib/core/worker.js +148 -0
- package/lib/nr-security-agent/lib/core/xss-utils.js +297 -0
- package/lib/nr-security-agent/lib/models/lambda-delegated-task/constants.js +12 -0
- package/lib/nr-security-agent/lib/models/lambda-delegated-task/index.js +15 -0
- package/lib/nr-security-agent/lib/models/lambda-delegated-task/lambda-delegated-sha-calculation.js +37 -0
- package/lib/nr-security-agent/lib/models/lambda-delegated-task/lambda-delegated-task-base.js +50 -0
- package/lib/nr-security-agent/lib/models/lambda-delegated-task/lambda-delegated-task-type.js +17 -0
- package/lib/nr-security-agent/resources/cert.pem +31 -0
- package/lib/nr-security-agent/resources/config.js +19 -0
- package/lib/nr-security-agent/resources/default-policy.yaml +36 -0
- package/lib/nr-security-api/index.js +111 -0
- package/package.json +95 -0
|
@@ -0,0 +1,634 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2023 New Relic Corporation. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const { BasicInfo } = require('./event');
|
|
9
|
+
const { JsonHandler } = require('./json-file-handler');
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const shaSizeUtil = require('./sha-size-util');
|
|
12
|
+
const _ = require('lodash');
|
|
13
|
+
const OS = require('os');
|
|
14
|
+
const { Agent } = require('./agent');
|
|
15
|
+
const commonUtils = require('./commonUtils');
|
|
16
|
+
|
|
17
|
+
const events = require('events');
|
|
18
|
+
const eventEmitter = new events.EventEmitter();
|
|
19
|
+
|
|
20
|
+
const LOG_MESSAGES = require('./sec-agent-constants').LOG_MESSAGES;
|
|
21
|
+
const {
|
|
22
|
+
IS_LAMBDA_ENV,
|
|
23
|
+
AWS_LAMBDA_QUALIFIED_ARN_ENV_IDENTIFIER,
|
|
24
|
+
AWS_LAMBDA_FUNCTION_NAME_ENV_IDENTIFIER,
|
|
25
|
+
AWS_LAMBDA_FUNCTION_VERSION_ENV_IDENTIFIER,
|
|
26
|
+
AWS_SESSION_TOKEN_ENV_IDENTIFIER,
|
|
27
|
+
EMPTY_APPLICATION_UUID,
|
|
28
|
+
SLASH
|
|
29
|
+
} = require('./sec-agent-constants');
|
|
30
|
+
const API = require('../../../nr-security-api');
|
|
31
|
+
const NRAgent = API.getNRAgent();
|
|
32
|
+
|
|
33
|
+
const SELF_PROC_DIR = '/proc/self';
|
|
34
|
+
const CGROUP_FILE_NAME = '/proc/self/cgroup';
|
|
35
|
+
const STAT = '/stat';
|
|
36
|
+
const CMD_LINE_FILE = '/cmdline';
|
|
37
|
+
const DIR_IDENTIFIER = '/';
|
|
38
|
+
const NEW_LINE_SEPERATOR = '\n';
|
|
39
|
+
const CGROUP_FILE = '/cgroup';
|
|
40
|
+
const ESCAPED_DOT = '.';
|
|
41
|
+
const FINALIZED_KEYWORD = 'finalized';
|
|
42
|
+
const APPLICATION_INFO_KEYWORD = 'applicationinfo';
|
|
43
|
+
const MODULE_INTERNAL = 'module';
|
|
44
|
+
const STATIC_ATTACHMENT_TYPE = 'STATIC';
|
|
45
|
+
const SERVER_INFO_NAME = 'Node.js';
|
|
46
|
+
const DOCKER_IDENTIFIER = 'docker/';
|
|
47
|
+
const DOCKER_IDENTIFIER_1_13 = '/docker-';
|
|
48
|
+
const KUBPODS_IDENTIFIER = 'kubepods/';
|
|
49
|
+
const ECS_DIR = 'ecs/';
|
|
50
|
+
const LXC_IDENTIFIER = 'lxc/';
|
|
51
|
+
const SCOPE_IDENTIFIER = '.scope';
|
|
52
|
+
const SPACE_CHARACTER = ' ';
|
|
53
|
+
const PACKAGE_JSON_FILE = 'package.json';
|
|
54
|
+
const EMPTY_STRING = '';
|
|
55
|
+
const LIBPOD = '/libpod-';
|
|
56
|
+
const DOCKER_CONTAINER = '/docker/containers/';
|
|
57
|
+
const PROC_SELF_MOUNTINFO = '/proc/self/mountinfo';
|
|
58
|
+
|
|
59
|
+
let applicationInfo;
|
|
60
|
+
let isFinalized = false;
|
|
61
|
+
|
|
62
|
+
const SPACE_SEPERATOR_REGEX = /\s+/g;
|
|
63
|
+
const logs = require('./logging');
|
|
64
|
+
const logger = logs.getLogger();
|
|
65
|
+
const initLogger = logs.getInitLogger();
|
|
66
|
+
|
|
67
|
+
function localIpAddress () {
|
|
68
|
+
try {
|
|
69
|
+
const interfaces = Object.values(OS.networkInterfaces());
|
|
70
|
+
for (const iface of interfaces) {
|
|
71
|
+
for (const alias of iface) {
|
|
72
|
+
if ((alias.family === "IPv4" || alias.family === 4) && alias.address !== "127.0.0.1" && !alias.internal) {
|
|
73
|
+
return alias.address;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
} catch (error) {
|
|
78
|
+
|
|
79
|
+
}
|
|
80
|
+
return "0.0.0.0";
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Constructs the applicationinfo object
|
|
85
|
+
*/
|
|
86
|
+
function ApplicationInfo () {
|
|
87
|
+
BasicInfo.apply(this);
|
|
88
|
+
|
|
89
|
+
const containerId = getContainerID();
|
|
90
|
+
const k8sHost = isK8S();
|
|
91
|
+
const ECSEnv = isECSEnv();
|
|
92
|
+
const isLambda = IS_LAMBDA_ENV;
|
|
93
|
+
|
|
94
|
+
this.jsonName = APPLICATION_INFO_KEYWORD;
|
|
95
|
+
if (NRAgent && NRAgent.config) {
|
|
96
|
+
this.entityGuid = NRAgent.config.entity_guid;
|
|
97
|
+
}
|
|
98
|
+
this.eventType = 'sec_appinfo';
|
|
99
|
+
this.startTime = Date.now();
|
|
100
|
+
this.binaryPath = process.execPath;
|
|
101
|
+
this.binaryName = process.title;
|
|
102
|
+
this.binaryVersion = process.versions.node;
|
|
103
|
+
this.libraryPath = require(MODULE_INTERNAL).globalPaths;
|
|
104
|
+
this.applicationUUID = commonUtils.getUUID();
|
|
105
|
+
this.osArch = process.arch;
|
|
106
|
+
this.osName = process.platform;
|
|
107
|
+
this.pid = process.pid;
|
|
108
|
+
this.userDir = process.env.PWD;
|
|
109
|
+
this.user = process.env.USER;
|
|
110
|
+
this.agentAttachmentType = STATIC_ATTACHMENT_TYPE;
|
|
111
|
+
this.identifier = {};
|
|
112
|
+
|
|
113
|
+
this.identifier = buildIdentifier(this.identifier);
|
|
114
|
+
this.identifier.envInfo = {};
|
|
115
|
+
this.identifier.envInfo.name = getHostName();
|
|
116
|
+
this.identifier.envInfo.ipaddress = localIpAddress();
|
|
117
|
+
|
|
118
|
+
if (!_.isEmpty(containerId)) {
|
|
119
|
+
this.identifier.id = containerId;
|
|
120
|
+
this.identifier.kind = "CONTAINER";
|
|
121
|
+
const containerProps = setContainerProperties(this.identifier);
|
|
122
|
+
this.identifier.envInfo = containerProps;
|
|
123
|
+
if (k8sHost) {
|
|
124
|
+
this.identifier.kind = "POD";
|
|
125
|
+
this.identifier.envInfo = setPodProperties(this.identifier, containerProps);
|
|
126
|
+
}
|
|
127
|
+
if (ECSEnv) {
|
|
128
|
+
this.identifier.kind = "ECS";
|
|
129
|
+
this.identifier.envInfo = setECSProperties(this.identifier);
|
|
130
|
+
}
|
|
131
|
+
} else if (isLambda) {
|
|
132
|
+
const lambdaARN = process.env[AWS_LAMBDA_QUALIFIED_ARN_ENV_IDENTIFIER];
|
|
133
|
+
const lambdaVersion = process.env[AWS_LAMBDA_FUNCTION_VERSION_ENV_IDENTIFIER];
|
|
134
|
+
this.applicationUUID = _.isEmpty(lambdaARN) ? ApplicationInfo.Constants.EMPTY_UUID : `${lambdaARN}:${lambdaVersion}`;
|
|
135
|
+
this.identifier.isHost = true;
|
|
136
|
+
this.identifier.isLambda = isLambda;
|
|
137
|
+
this.identifier.lambdaFunctionARN = _.isEmpty(lambdaARN)
|
|
138
|
+
? `${process.env[AWS_LAMBDA_FUNCTION_NAME_ENV_IDENTIFIER]}:${lambdaVersion}`
|
|
139
|
+
: `${lambdaARN}:${lambdaVersion}`;
|
|
140
|
+
this.identifier.lambdaAWSSessionToken = process.env[AWS_SESSION_TOKEN_ENV_IDENTIFIER];
|
|
141
|
+
|
|
142
|
+
} else {
|
|
143
|
+
this.identifier.kind = "HOST";
|
|
144
|
+
this.identifier.envInfo = setHostProperties();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
this.serverInfo = {};
|
|
149
|
+
this.serverInfo.name = SERVER_INFO_NAME;
|
|
150
|
+
this.runCommand = getRunCommand();
|
|
151
|
+
this.cmdline = process.argv;
|
|
152
|
+
const procStartTime = getProcStartTime(this.pid);
|
|
153
|
+
this.procStartTime = procStartTime || null;
|
|
154
|
+
}
|
|
155
|
+
ApplicationInfo.prototype = Object.create(BasicInfo.prototype);
|
|
156
|
+
ApplicationInfo.prototype.constructor = ApplicationInfo;
|
|
157
|
+
|
|
158
|
+
ApplicationInfo.prototype.getLambdaFunctioninfo = function getLambdaFunctioninfo () {
|
|
159
|
+
return {
|
|
160
|
+
isLambda: this.identifier.isLambda,
|
|
161
|
+
lambdaFunctionARN: this.identifier.lambdaFunctionARN,
|
|
162
|
+
lambdaAWSSessionToken: this.identifier.lambdaAWSSessionToken
|
|
163
|
+
};
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
ApplicationInfo.prototype.setUUID = function setUUID (uuid) {
|
|
167
|
+
this.applicationUUID = uuid;
|
|
168
|
+
Agent.getAgent().setApplicationInfo(this);
|
|
169
|
+
Agent.eventEmitter.emit(Agent.EVENTS.RECONNECT_WS_EVENT);
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
ApplicationInfo.prototype.getIdentifier = function getIdentifier () {
|
|
173
|
+
return this.identifier;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
ApplicationInfo.prototype.setIdentifier = function setIdentifier (identifierJSON) {
|
|
177
|
+
this.identifier = identifierJSON;
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
ApplicationInfo.prototype.updateSHAAndSize = async function updateSHAAndSize (GlobalPromise) {
|
|
181
|
+
const applicationInfo = this;
|
|
182
|
+
const deployedApplications = applicationInfo && applicationInfo.serverInfo && applicationInfo.serverInfo.deployedApplications;
|
|
183
|
+
|
|
184
|
+
// set Promise object for module
|
|
185
|
+
shaSizeUtil.setPromise(GlobalPromise);
|
|
186
|
+
|
|
187
|
+
// if there are no applications detected
|
|
188
|
+
if (!deployedApplications) return;
|
|
189
|
+
|
|
190
|
+
// calculate and add sha and size info
|
|
191
|
+
const [application] = deployedApplications;
|
|
192
|
+
|
|
193
|
+
// For lambda we would want to skip the
|
|
194
|
+
// sha calculation on application files
|
|
195
|
+
if (IS_LAMBDA_ENV) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// add sha256 of binary.
|
|
200
|
+
applicationInfo.sha256 = await shaSizeUtil.getSHA256ForFile(process.argv[0]);
|
|
201
|
+
|
|
202
|
+
let stat = {};
|
|
203
|
+
if (process.hasWorker) {
|
|
204
|
+
stat = await getApplicationSHAAndSizeFromWorker(applicationInfo, application.deployedPath);
|
|
205
|
+
} else {
|
|
206
|
+
stat = await shaSizeUtil.getApplicationSHAAndSize(application.deployedPath, GlobalPromise);
|
|
207
|
+
}
|
|
208
|
+
application.sha256 = stat.sha256;
|
|
209
|
+
application.size = stat.size;
|
|
210
|
+
application.contextPath = '/';
|
|
211
|
+
application.isEmbedded = true;
|
|
212
|
+
process.serverPort = process.serverPort || process.env.PORT ;
|
|
213
|
+
application.ports = [process.serverPort || 0];
|
|
214
|
+
// emit finalization of application info
|
|
215
|
+
if (Agent.getAgent()) {
|
|
216
|
+
Agent.getAgent().setApplicationInfo(applicationInfo);
|
|
217
|
+
initLogger.info(LOG_MESSAGES.APP_INFO_GENERATED, JSON.stringify(applicationInfo));
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
ApplicationInfo.Constants = {
|
|
222
|
+
EMPTY_UUID: EMPTY_APPLICATION_UUID
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Adds the given property and its value to
|
|
227
|
+
* the applicationinfo object.
|
|
228
|
+
*
|
|
229
|
+
* @param {string} property
|
|
230
|
+
* @param {*} value
|
|
231
|
+
* @throws error if property value exists.
|
|
232
|
+
* @throws error if applicationinfo is finalized.
|
|
233
|
+
*
|
|
234
|
+
* @returns {boolean} success
|
|
235
|
+
*/
|
|
236
|
+
function addProperty (property, value) {
|
|
237
|
+
if (!isFinalized && applicationInfo) {
|
|
238
|
+
let currentObject = applicationInfo;
|
|
239
|
+
const properties = property.split(ESCAPED_DOT);
|
|
240
|
+
for (let index = 0; index < properties.length - 1; index++) {
|
|
241
|
+
if (currentObject[properties[index]]) {
|
|
242
|
+
if (typeof currentObject[properties[index]] === 'object') {
|
|
243
|
+
currentObject = currentObject[properties[index]];
|
|
244
|
+
} else {
|
|
245
|
+
throw new Error('CSEC-Agent: Unable to add the given property to ApplicationInfo, property value already exists!');
|
|
246
|
+
}
|
|
247
|
+
} else {
|
|
248
|
+
currentObject[properties[index]] = {};
|
|
249
|
+
currentObject = currentObject[properties[index]];
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
currentObject[properties[properties.length - 1]] = value;
|
|
253
|
+
return true;
|
|
254
|
+
} else {
|
|
255
|
+
throw new Error('CSEC-Agent: Cannot update property when ApplicationInfo is finalized or empty!');
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Returns the current instanceof applicationinfo,
|
|
261
|
+
* creates one if not already created.
|
|
262
|
+
*
|
|
263
|
+
* @returns {ApplicationInfo} instance
|
|
264
|
+
*/
|
|
265
|
+
function getInstance () {
|
|
266
|
+
if (!applicationInfo) {
|
|
267
|
+
applicationInfo = new ApplicationInfo();
|
|
268
|
+
}
|
|
269
|
+
return applicationInfo;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Marks the applicationinfo as finalized.
|
|
274
|
+
*/
|
|
275
|
+
function finalize () {
|
|
276
|
+
if (!isFinalized) {
|
|
277
|
+
isFinalized = true;
|
|
278
|
+
eventEmitter.emit(FINALIZED_KEYWORD);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Checks if the current application info is finalized.
|
|
284
|
+
*
|
|
285
|
+
* @returns {boolean} isFinalized
|
|
286
|
+
*/
|
|
287
|
+
function finalized () {
|
|
288
|
+
return isFinalized;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Retrives the container ID in which the current process
|
|
293
|
+
* is running.
|
|
294
|
+
*
|
|
295
|
+
* @returns {string} ContainerID if found, false otherwise.
|
|
296
|
+
*/
|
|
297
|
+
function getContainerID () {
|
|
298
|
+
let lines, index;
|
|
299
|
+
|
|
300
|
+
// code to get containerId from /proc/self/mountinfo file
|
|
301
|
+
try {
|
|
302
|
+
const mountinfoFile = fs.readFileSync(PROC_SELF_MOUNTINFO);
|
|
303
|
+
lines = mountinfoFile.toString().split(NEW_LINE_SEPERATOR);
|
|
304
|
+
for (const st of lines) {
|
|
305
|
+
index = st.indexOf(DOCKER_CONTAINER);
|
|
306
|
+
if (index > -1) {
|
|
307
|
+
const splitted = st.split(DOCKER_CONTAINER);
|
|
308
|
+
return splitted[splitted.length - 1].split(SLASH)[0];
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
} catch (error) {
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// code to get containerId from /proc/self/cgroup file
|
|
315
|
+
try {
|
|
316
|
+
const cgroupFile = fs.readFileSync(SELF_PROC_DIR + CGROUP_FILE);
|
|
317
|
+
lines = cgroupFile.toString().split(NEW_LINE_SEPERATOR);
|
|
318
|
+
} catch (err) {
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
for (const st of lines) {
|
|
322
|
+
index = st.lastIndexOf(DOCKER_IDENTIFIER);
|
|
323
|
+
if (index > -1) {
|
|
324
|
+
return st.substring(index + 7);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
index = st.lastIndexOf(ECS_DIR);
|
|
328
|
+
if (index > -1) {
|
|
329
|
+
return st.substring(st.lastIndexOf(DIR_IDENTIFIER) + 1);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
index = st.indexOf(KUBPODS_IDENTIFIER);
|
|
333
|
+
if (index > -1) {
|
|
334
|
+
return st.substring(st.lastIndexOf(DIR_IDENTIFIER) + 1);
|
|
335
|
+
}
|
|
336
|
+
// To support docker older versions
|
|
337
|
+
index = st.lastIndexOf(LXC_IDENTIFIER);
|
|
338
|
+
if (index > -1) {
|
|
339
|
+
return st.substring(index + 4);
|
|
340
|
+
}
|
|
341
|
+
// docker version 1.13.1
|
|
342
|
+
index = st.lastIndexOf(DOCKER_IDENTIFIER_1_13);
|
|
343
|
+
const indexEnd = st.lastIndexOf(SCOPE_IDENTIFIER);
|
|
344
|
+
if (index > -1 && indexEnd > -1) {
|
|
345
|
+
return st.substring(index + 8, indexEnd);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// podman
|
|
349
|
+
if (st.indexOf(LIBPOD) > -1 && st.indexOf(SCOPE_IDENTIFIER) > -1) {
|
|
350
|
+
const containerId = st.split(LIBPOD).pop().split(SCOPE_IDENTIFIER)[0];
|
|
351
|
+
if (!_.isEmpty(containerId)) {
|
|
352
|
+
return containerId;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Extracts cmdline from proc.
|
|
361
|
+
*
|
|
362
|
+
*/
|
|
363
|
+
function getCmdLine () {
|
|
364
|
+
try {
|
|
365
|
+
const cmdlineFile = fs.readFileSync(SELF_PROC_DIR + CMD_LINE_FILE);
|
|
366
|
+
if (!cmdlineFile) {
|
|
367
|
+
return EMPTY_STRING;
|
|
368
|
+
}
|
|
369
|
+
const lines = cmdlineFile.toString().split(NEW_LINE_SEPERATOR);
|
|
370
|
+
const cmdline = lines[0];
|
|
371
|
+
if (cmdline) {
|
|
372
|
+
return cmdline;
|
|
373
|
+
}
|
|
374
|
+
} catch (err) {
|
|
375
|
+
return EMPTY_STRING;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Extracts runCommand from process var.
|
|
381
|
+
*
|
|
382
|
+
*/
|
|
383
|
+
function getRunCommand () {
|
|
384
|
+
const argvs = Array.prototype.slice.call(process.argv, 0, process.argv.length);
|
|
385
|
+
const execArgv = Array.prototype.slice.call(process.execArgv, 0, process.execArgv.length);
|
|
386
|
+
const runCommand = [];
|
|
387
|
+
runCommand.push(argvs.shift());
|
|
388
|
+
let element = null;
|
|
389
|
+
while ((element = execArgv.shift())) {
|
|
390
|
+
runCommand.push(element);
|
|
391
|
+
}
|
|
392
|
+
while ((element = argvs.shift())) {
|
|
393
|
+
runCommand.push(element);
|
|
394
|
+
}
|
|
395
|
+
return runCommand.join(SPACE_CHARACTER);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Extracts process start from proc.
|
|
400
|
+
*
|
|
401
|
+
*/
|
|
402
|
+
function getProcStartTime () {
|
|
403
|
+
try {
|
|
404
|
+
const statFile = fs.readFileSync(SELF_PROC_DIR + STAT);
|
|
405
|
+
if (!statFile) {
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
408
|
+
const lines = statFile.toString().split(NEW_LINE_SEPERATOR);
|
|
409
|
+
const statData = lines[0];
|
|
410
|
+
if (statData) {
|
|
411
|
+
const statArray = statData.split(SPACE_SEPERATOR_REGEX);
|
|
412
|
+
if (statArray.length >= 21) {
|
|
413
|
+
return statArray[21];
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
} catch (err) {
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Sets version of current build
|
|
422
|
+
*
|
|
423
|
+
* @param {String} agentDir
|
|
424
|
+
* @param {ApplicationInfo} applicationInfo
|
|
425
|
+
*/
|
|
426
|
+
function setBuildDetails (agentDir, applicationInfo) {
|
|
427
|
+
const jsonFileHandler = new JsonHandler(PACKAGE_JSON_FILE, agentDir);
|
|
428
|
+
const pkg = jsonFileHandler.getJSON();
|
|
429
|
+
process.env.collectorVersion = pkg.collectorVersion;
|
|
430
|
+
applicationInfo.collectorVersion = pkg.collectorVersion;
|
|
431
|
+
applicationInfo.jsonVersion = pkg.jsonVersion;
|
|
432
|
+
applicationInfo.buildNumber = pkg.buildNumber;
|
|
433
|
+
process.env.buildNumber = pkg.buildNumber;
|
|
434
|
+
process.env.jsonVersion = applicationInfo.jsonVersion;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
function isK8S () {
|
|
438
|
+
const k8sHost = process.env.KUBERNETES_SERVICE_HOST;
|
|
439
|
+
if (k8sHost) {
|
|
440
|
+
return k8sHost;
|
|
441
|
+
}
|
|
442
|
+
return false;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function getHostName () {
|
|
446
|
+
try {
|
|
447
|
+
// const hostFile = fs.readFileSync("/etc/hostname");
|
|
448
|
+
// return hostFile.toString().trim();
|
|
449
|
+
return OS.hostname();
|
|
450
|
+
} catch (err) {
|
|
451
|
+
return EMPTY_STRING;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
function getPodNameSpace () {
|
|
457
|
+
try {
|
|
458
|
+
const namespaceFile = fs.readFileSync('/var/run/secrets/kubernetes.io/serviceaccount/namespace');
|
|
459
|
+
return namespaceFile.toString('utf-8');
|
|
460
|
+
} catch (err) {
|
|
461
|
+
return EMPTY_STRING;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
function isECSEnv () {
|
|
466
|
+
if (process.env.AWS_EXECUTION_ENV === 'AWS_ECS_FARGATE') {
|
|
467
|
+
return true;
|
|
468
|
+
}
|
|
469
|
+
return false;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
function getECSTaskId () {
|
|
473
|
+
let lines, index;
|
|
474
|
+
try {
|
|
475
|
+
const cgroupFile = fs.readFileSync(CGROUP_FILE_NAME);
|
|
476
|
+
lines = cgroupFile.toString().split(NEW_LINE_SEPERATOR);
|
|
477
|
+
for (const st of lines) {
|
|
478
|
+
index = st.lastIndexOf(ECS_DIR);
|
|
479
|
+
if (index > -1) {
|
|
480
|
+
return st.substring(index + 4, st.lastIndexOf(DIR_IDENTIFIER));
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
} catch (err) {
|
|
484
|
+
return EMPTY_STRING;
|
|
485
|
+
}
|
|
486
|
+
return EMPTY_STRING;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
function populateECSInfo (ecsObj) {
|
|
490
|
+
ecsObj.ecsTaskId = getECSTaskId();
|
|
491
|
+
const ecsData = getECSInfo();
|
|
492
|
+
if (!_.isEmpty(ecsData)) {
|
|
493
|
+
const imageId = ecsData.ImageID;
|
|
494
|
+
const imageName = ecsData.Image;
|
|
495
|
+
|
|
496
|
+
ecsObj.imageId = imageId;
|
|
497
|
+
ecsObj.imageName = imageName;
|
|
498
|
+
|
|
499
|
+
const labels = ecsData.Labels;
|
|
500
|
+
|
|
501
|
+
if (!_.isEmpty(labels)) {
|
|
502
|
+
const containerName = labels['com.amazonaws.ecs.container-name'];
|
|
503
|
+
const ecsTaskDefinitionFamily = labels['com.amazonaws.ecs.task-definition-family'];
|
|
504
|
+
const ecsTaskDefinitionVersion = labels['com.amazonaws.ecs.task-definition-version'];
|
|
505
|
+
|
|
506
|
+
ecsObj.containerName = containerName;
|
|
507
|
+
if (ecsTaskDefinitionFamily && ecsTaskDefinitionVersion) {
|
|
508
|
+
ecsObj.ecsTaskDefinition = ecsTaskDefinitionFamily + ':' + ecsTaskDefinitionVersion;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return ecsObj;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
function getECSInfo () {
|
|
516
|
+
const url = process.env.ECS_CONTAINER_METADATA_URI;
|
|
517
|
+
let json = {};
|
|
518
|
+
const request = require('sync-request');
|
|
519
|
+
try {
|
|
520
|
+
const res = request('GET', url);
|
|
521
|
+
const body = res.getBody();
|
|
522
|
+
json = JSON.parse(body);
|
|
523
|
+
} catch (error) {
|
|
524
|
+
}
|
|
525
|
+
return json;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
function getApplicationSHAAndSizeFromWorker (applicationInfo, applicationPath) {
|
|
529
|
+
const { Worker } = require('worker_threads');
|
|
530
|
+
return new Promise((resolve, reject) => {
|
|
531
|
+
const worker = new Worker(
|
|
532
|
+
__dirname + '/sha_worker.js', { workerData: applicationInfo });
|
|
533
|
+
worker.on('message', resolve);
|
|
534
|
+
worker.postMessage(applicationPath);
|
|
535
|
+
worker.on('error', reject);
|
|
536
|
+
worker.on('exit', (code) => {
|
|
537
|
+
if (code !== 0) {
|
|
538
|
+
reject(new Error(
|
|
539
|
+
`Stopped the Worker Thread of SHA256 with the exit code: ${code}`));
|
|
540
|
+
}
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
function buildIdentifier (identifier) {
|
|
546
|
+
try {
|
|
547
|
+
identifier.nodeId = EMPTY_STRING;
|
|
548
|
+
identifier.id = EMPTY_STRING;
|
|
549
|
+
identifier.nodeIp = EMPTY_STRING;
|
|
550
|
+
identifier.nodeName = NRAgent ? NRAgent.config.process_host.display_name: EMPTY_STRING;
|
|
551
|
+
identifier.collectorIp = localIpAddress();
|
|
552
|
+
} catch (e) {
|
|
553
|
+
logger.error(e);
|
|
554
|
+
}
|
|
555
|
+
return identifier;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
function setHostProperties () {
|
|
559
|
+
const hostProp = {};
|
|
560
|
+
try {
|
|
561
|
+
hostProp.name = getHostName();
|
|
562
|
+
hostProp.creationTimestamp = new Date().getTime();
|
|
563
|
+
hostProp.state = "Running";
|
|
564
|
+
hostProp.os = process.platform;
|
|
565
|
+
hostProp.arch = process.arch;
|
|
566
|
+
hostProp.version = OS.release();
|
|
567
|
+
hostProp.buildNumber = OS.release();
|
|
568
|
+
hostProp.ipAddress = localIpAddress();
|
|
569
|
+
} catch (e) {
|
|
570
|
+
logger.error(e);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
return hostProp;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
function setContainerProperties (identifier) {
|
|
577
|
+
const containerProp = require("./ContainerProperties").getInstance();
|
|
578
|
+
try {
|
|
579
|
+
containerProp.id = identifier.id;
|
|
580
|
+
containerProp.name = getHostName();
|
|
581
|
+
containerProp.ipAddress = identifier.collectorIp;
|
|
582
|
+
containerProp.creationTimestamp = new Date().getTime();
|
|
583
|
+
logger.debug("containerProp", containerProp);
|
|
584
|
+
} catch (e) {
|
|
585
|
+
logger.error(e);
|
|
586
|
+
}
|
|
587
|
+
return containerProp;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
function setPodProperties (identifier, containerProp) {
|
|
591
|
+
const podProp = require("./PodProperties").getInstance();
|
|
592
|
+
try {
|
|
593
|
+
podProp.id = identifier.id;
|
|
594
|
+
podProp.ipAddress = identifier.collectorIp;
|
|
595
|
+
podProp.namespace = getPodNameSpace();
|
|
596
|
+
podProp.name = getHostName();
|
|
597
|
+
podProp.creationTimestamp = new Date().getTime();
|
|
598
|
+
podProp.ContainerProperties.push(containerProp);
|
|
599
|
+
logger.debug("podProp:", podProp);
|
|
600
|
+
} catch (e) {
|
|
601
|
+
logger.error(e);
|
|
602
|
+
}
|
|
603
|
+
return podProp;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
function setECSProperties (identifier) {
|
|
607
|
+
let ecsObj = {};
|
|
608
|
+
const ecsProp = require('./ECSProperties').getInstance();
|
|
609
|
+
ecsObj = populateECSInfo(ecsObj);
|
|
610
|
+
try {
|
|
611
|
+
ecsProp.id = ecsObj.ecsTaskId;
|
|
612
|
+
ecsProp.ipAddress = identifier.collectorIp;
|
|
613
|
+
ecsProp.creationTimestamp = new Date().getTime();
|
|
614
|
+
ecsProp.imageId = ecsObj.imageId;
|
|
615
|
+
ecsProp.imageName = ecsObj.imageName;
|
|
616
|
+
ecsProp.containerName = ecsObj.containerName;
|
|
617
|
+
ecsProp.containerId = '';
|
|
618
|
+
ecsProp.ecsTaskDefinition = ecsObj.ecsTaskDefinition;
|
|
619
|
+
} catch (e) {
|
|
620
|
+
logger.error(e);
|
|
621
|
+
}
|
|
622
|
+
return ecsProp;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
module.exports = {
|
|
626
|
+
getInstance,
|
|
627
|
+
addProperty,
|
|
628
|
+
eventEmitter,
|
|
629
|
+
finalize,
|
|
630
|
+
finalized,
|
|
631
|
+
setBuildDetails,
|
|
632
|
+
getCmdLine
|
|
633
|
+
}
|
|
634
|
+
;
|