@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,173 @@
|
|
|
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 AWS_LAMBDA_NODE_EXEC_ENV_IDENTIFIER = /^AWS_Lambda_nodejs.*$/g;
|
|
9
|
+
const AWS_EXECUTION_ENV_VAR = 'AWS_EXECUTION_ENV';
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const API = require('../../../nr-security-api');
|
|
12
|
+
const NRAgent = API.getNRAgent();
|
|
13
|
+
|
|
14
|
+
let CSEC_HOME = NRAgent && NRAgent.config.newrelic_home ? NRAgent.config.newrelic_home : require('path').join(process.cwd());
|
|
15
|
+
const CSEC_GROUP_NAME = NRAgent ? NRAgent.config.security.mode : 'IAST';
|
|
16
|
+
CSEC_HOME = path.resolve(CSEC_HOME);
|
|
17
|
+
const agentStartTime = new Date().toString();
|
|
18
|
+
|
|
19
|
+
module.exports = {
|
|
20
|
+
CSEC_HOME: CSEC_HOME,
|
|
21
|
+
CSEC_GROUP_NAME: CSEC_GROUP_NAME,
|
|
22
|
+
LOG_DIR: `${CSEC_HOME}/nr-security-home/logs/`,
|
|
23
|
+
CSEC_HOME_TMP: `${CSEC_HOME}/nr-security-home/tmp/language-agent/${process.env.applicationUUID}`,
|
|
24
|
+
AGENT_START_TIME: agentStartTime,
|
|
25
|
+
FRAMEWORK: '',
|
|
26
|
+
STATUS_LOG_FILE: `${CSEC_HOME}/nr-security-home/logs/snapshots/node-security-collector-status-${process.env.applicationUUID}.log`,
|
|
27
|
+
|
|
28
|
+
DB_LIST: {
|
|
29
|
+
MYSQL: 'MYSQL',
|
|
30
|
+
MYSQL2: 'MYSQL',
|
|
31
|
+
POSTGRES: 'POSTGRES',
|
|
32
|
+
MONGODB: 'MONGODB',
|
|
33
|
+
ORACLEDB: 'ORACLEDB',
|
|
34
|
+
MSSQL: 'MSSQL',
|
|
35
|
+
SQLITE3: 'SQLITE3'
|
|
36
|
+
},
|
|
37
|
+
SERVER_COMMAND: {
|
|
38
|
+
SET_LOG_LEVEL: 0,
|
|
39
|
+
SHUTDOWN_LANGUAGE_AGENT: 1,
|
|
40
|
+
SET_DEFAULT_LOG_LEVEL: 2,
|
|
41
|
+
ENABLE_HTTP_REQUEST_PRINTING: 3,
|
|
42
|
+
UPLOAD_LOGS: 4,
|
|
43
|
+
UNSUPPORTED_AGENT: 5,
|
|
44
|
+
VALIDATION_RESPONSE: 6,
|
|
45
|
+
START_VULNERABILITY_SCAN: 8,
|
|
46
|
+
STARTUP_WELCOME_MSG: 10,
|
|
47
|
+
FUZZ_REQUEST: 11,
|
|
48
|
+
COLLECTOR_CONFIG: 100,
|
|
49
|
+
BLOCKING: 101,
|
|
50
|
+
POLICY_ERROR: 102,
|
|
51
|
+
OBEY_WS_RECONNECT:12
|
|
52
|
+
|
|
53
|
+
},
|
|
54
|
+
JSON_NAME: {
|
|
55
|
+
EVENT: 'Event',
|
|
56
|
+
HC: 'LAhealthcheck',
|
|
57
|
+
SD: 'Shutdown',
|
|
58
|
+
APP_INFO: 'ApplicationInfo',
|
|
59
|
+
ICC: 'IntCodeControlCommand',
|
|
60
|
+
CONNSTAT: 'http-connection-stat'
|
|
61
|
+
},
|
|
62
|
+
COLLECTOR_TYPE: 'NODE',
|
|
63
|
+
LANGUAGE: 'JavaScript',
|
|
64
|
+
AWS_LAMBDA_QUALIFIED_ARN_ENV_IDENTIFIER: 'AWS_LAMBDA_ARN',
|
|
65
|
+
AWS_LAMBDA_FUNCTION_NAME_ENV_IDENTIFIER: 'AWS_LAMBDA_FUNCTION_NAME',
|
|
66
|
+
AWS_LAMBDA_FUNCTION_VERSION_ENV_IDENTIFIER: 'AWS_LAMBDA_FUNCTION_VERSION',
|
|
67
|
+
AWS_SESSION_TOKEN_ENV_IDENTIFIER: 'AWS_SESSION_TOKEN',
|
|
68
|
+
LAMBDA_TASK_ROOT_ENV_IDENTIFIER: 'LAMBDA_TASK_ROOT',
|
|
69
|
+
LAMBDA_ENABLE_RESPONSE_BLOCKING: 'LAMBDA_ENABLE_RESPONSE_BLOCKING',
|
|
70
|
+
AWS_LAMBDA_NODE_EXEC_ENV_IDENTIFIER,
|
|
71
|
+
AWS_EXECUTION_ENV_VAR,
|
|
72
|
+
IS_LAMBDA_ENV: Array.isArray(
|
|
73
|
+
(process.env[AWS_EXECUTION_ENV_VAR] || '').match(AWS_LAMBDA_NODE_EXEC_ENV_IDENTIFIER)
|
|
74
|
+
),
|
|
75
|
+
LAMBDA_RUNTIME_DIR_VAR: 'LAMBDA_RUNTIME_DIR',
|
|
76
|
+
CSEC_LAST_FUZZ_REQUEST_TIME: 'CSEC_LAST_FUZZ_REQUEST_TIME',
|
|
77
|
+
NR_CSEC_FUZZ_REQUEST_ID: 'nr-csec-fuzz-request-id',
|
|
78
|
+
EMPTY_APPLICATION_UUID: '--0--',
|
|
79
|
+
QUESTIONMARK: '?',
|
|
80
|
+
PIPE_SEP: '|',
|
|
81
|
+
ATTHERATE: '@',
|
|
82
|
+
EMPTY_STR: '',
|
|
83
|
+
COLON: ':',
|
|
84
|
+
OPEN_PARANTHESIS: '(',
|
|
85
|
+
CLOSE_PARANTHESIS: ')',
|
|
86
|
+
SLASH: '/',
|
|
87
|
+
INCOMING_MSG: 'IncomingMessage',
|
|
88
|
+
OBJECT: 'object',
|
|
89
|
+
STRING: 'string',
|
|
90
|
+
TRIGGER_VIA_RCI: 'triggerViaRCI',
|
|
91
|
+
RCI_METHOD_CALLS: 'rciMethodsCalls',
|
|
92
|
+
VULNERABLE: 'VULNERABLE',
|
|
93
|
+
UTF8: 'utf8',
|
|
94
|
+
CONTENT_TYPE: 'content-type',
|
|
95
|
+
TEXT_HTML: 'text/html',
|
|
96
|
+
APPLICATION_JSON: 'application/json',
|
|
97
|
+
APPLICATION_XML: 'application/xml',
|
|
98
|
+
APPLICATION_XHTML: 'application/xhtml+xml',
|
|
99
|
+
TEXT_PLAIN: 'text/plain',
|
|
100
|
+
APPLICATION_X_FORM_URLENCODED: 'application/x-www-form-urlencoded',
|
|
101
|
+
MULTIPART_FORM_DATA: 'multipart/form-data',
|
|
102
|
+
XFORFOR: 'x-forwarded-for',
|
|
103
|
+
DOUBLE_DOLLAR: '$$',
|
|
104
|
+
LOADING_MODULE: 'Loading module ',
|
|
105
|
+
EXITEVENT: 'exit-event',
|
|
106
|
+
|
|
107
|
+
LOG_MESSAGES: {
|
|
108
|
+
LOADED_CSEC_ENVS_MSG: '[STEP-1][COMPLETE][env] Environment Information Gathering Done.',
|
|
109
|
+
COLLECTOR_INFO: ' CSEC Node version : %s , json version : %s and build number : %s',
|
|
110
|
+
APP_INFO_GATHERING_STARTED: '[STEP-1][BEGIN][APP_INFO] Gathering Application Info For Current Process.',
|
|
111
|
+
DEP_APP_GATHERING_STARTED: '[BEGIN][APP_INFO][DEPLOYED_APP] Gathering deployed application info for current process',
|
|
112
|
+
APP_INFO_DEP_APP: '[APP_INFO][DEPLOYED_APP] Deployed application info generated :%s',
|
|
113
|
+
AGENT_INIT_SUCCESSFUL: '[STEP-3][protection][BEGIN] Node CSEC Agent Attached To Process: PID = %s, With Generated Applicationuid = %s By Static Attachment',
|
|
114
|
+
AGENT_INIT_SUCCESSFUL_COMPLETE: '[STEP-3][PROTECTION][COMPLETE] Protecting new process with PID = %s and UUID = %s',
|
|
115
|
+
AGENT_INIT_FAILED: '[protection] Coudn\'t Initiate CSEC Agent For Process: : Pid = {pid}, With Generated Applicationuid = {application_uuid}.',
|
|
116
|
+
LOG_FILE_INITIATED_MSG: 'Init Log File Initiated.',
|
|
117
|
+
LOG_CONFIGURED_SUCCESSFULLY_MSG: 'Init Logger Configured Successfully With Level: %s And Rollover On Max Size %s.',
|
|
118
|
+
INIT_APPINFO_SEND: '[STEP-9][COMPLETE][APP_INFO][DEPLOYED_APP] Updated ApplicationInfo Will Be Sent To Prevent-web Service',
|
|
119
|
+
AGENT_ATTACH_FAIL: 'CSEC_GROUP_NAME Environment Not Present, Agent Attachment Failed',
|
|
120
|
+
APP_INFO_GENERATED: '[APP_INFO] Application Info Generated: %s ',
|
|
121
|
+
SCHED_SERVICE_START: '[STEP-5][BEGIN][MODULE] Start Threads/pools/scheduler',
|
|
122
|
+
SCHED_SERVICE_START_BEG: '[BEGIN][MODULE] Started Threads/pools/scheduler',
|
|
123
|
+
START_HC: '[BEGIN][MODULE] Starting Healthcheck',
|
|
124
|
+
START_IOM: '[BEGIN][MODULE] Starting Inboundoutboundmonitor.',
|
|
125
|
+
END_HC: '[COMPLETE][MODULE] Started Healthcheck',
|
|
126
|
+
END_IOM: '[COMPLETE][MODULE] Started Inboundoutboundmonitor.',
|
|
127
|
+
START_DIR_WATCH: '[BEGIN][MODULE] Starting DirectoryWatcher',
|
|
128
|
+
STARTED_DIR_WATCH: '[COMPLETE][MODULE] Started DirectoryWatcher',
|
|
129
|
+
NODE_VERSION_MSG: 'Node Version Is %s, Starting Websocket Client In Parent Process',
|
|
130
|
+
NODE_VERSION_MSG_WORKER: 'Node Version Is %s, Starting Websocket Client In Worker Thread',
|
|
131
|
+
MSG_FROM_WORKKER: 'Message From Worker Thread:',
|
|
132
|
+
RECV_POL_DATA: '[STEP-7][BEGIN][POLICY] Received Policy Data From Prevent-web Service:%s',
|
|
133
|
+
RECV_GLOBAL_POL_DATA: 'Received Global Policy Parameters From Prevent-web Service:%s',
|
|
134
|
+
EXP_RAISE_GLOBAL_POL: 'Exception Raised In Global Policy Validation:',
|
|
135
|
+
UNABLE_TO_WRITE_TO_POL_FILE: 'Unable To Write To Policy Yaml File',
|
|
136
|
+
POL_UPDATE_SUCCESS: 'Policy Updated To File Successfully',
|
|
137
|
+
CHANGE_DETECT_POL_FILE: 'Changes Detected In Policy File',
|
|
138
|
+
ERROR_READ_FROM_POL_FILE: 'ERROR In Reading Policy From File',
|
|
139
|
+
POL_UPDATE_RESP: 'Policy Update Response Is:',
|
|
140
|
+
UPDATE_POL_SENT_SERVER: 'Updated Policy Sent To Prevent Web',
|
|
141
|
+
EXP_RAISE_POL: 'Exception Raised In Policy Validation:',
|
|
142
|
+
FALLBACK_TO_CURR_POLICY: 'Fallback To Current Policy!!!:%s',
|
|
143
|
+
POLICY_APPLIED: '[STEP-7][COMPLETE][POLICY] Policy Applied :',
|
|
144
|
+
POL_PULL_INT_IS: 'Policy Pull Interval Is:',
|
|
145
|
+
LOG_LEVEL_UPDATED: 'Log Level Updated To:',
|
|
146
|
+
DEFAULT_POL_SET: 'Default Policy Has Been Set :',
|
|
147
|
+
UNABLE_SET_DEFAULT_POL: 'Unable To Set Default Policy',
|
|
148
|
+
COLLECTOR_INIT_WITH_PROP: 'Collector Is Initialized With Properties:',
|
|
149
|
+
PARSING_EXP_WELCOME_MSG: 'Parsing Exeception In Startup Welcome Command',
|
|
150
|
+
ACCESS_BLOCKED_IP_DETECTED: 'Access By Blocked Ip Address Detected : ',
|
|
151
|
+
FIRST_EVENT_INTERCEPTED: '[BEGIN][EVENT] First event intercepted',
|
|
152
|
+
FIRST_EVENT_PROCESSED: '[EVENT] First event processed :',
|
|
153
|
+
FIRST_EVENT_SENT: '[STEP-8][COMPLETE][EVENT] First Event Sent For Validation',
|
|
154
|
+
DETECTED_BROKEN_CONN: 'Detected Broken Connection. Will Reconnect Now!',
|
|
155
|
+
MAX_WS_RETRY: 'Maximum WS Retry Limit Reached. Unable To Connect To Prevent Web Service!!!',
|
|
156
|
+
EVENT_SENT: 'Event Sent:: ',
|
|
157
|
+
ERROR_WHILE_SEND_EVENT: 'ERROR While Sending Event: {}',
|
|
158
|
+
WS_CONNECTED: '[STEP-4][COMPLETE][WS] Connected To Prevent-web Service',
|
|
159
|
+
SENDING_APPINFO: '[APP_INFO] Sending Application Info To Prevent-web Service: ',
|
|
160
|
+
SENDING_APPINFO_COMPLETE: '[COMPLETE][APP_INFO] Application info sent to Prevent-Web service : {}',
|
|
161
|
+
APPLY_INSTRUMENTATION: '[STEP-6][BEGIN][instrumentation] Applying Instrumentation',
|
|
162
|
+
AVAIL_DISK: 'Available Disk Space Is: ',
|
|
163
|
+
AVAIL_DISK_ERROR: 'Insufficient Disk Space Available To The Location %s Is : %s',
|
|
164
|
+
OBJ_WRAP_MUST_BE_FUNC: 'original object and wrapper must be functions',
|
|
165
|
+
NO_ORIG_FUNC_TO_WRAP: 'no original function %s to wrap',
|
|
166
|
+
NO_WRAPPER_FUNC: 'no wrapper function',
|
|
167
|
+
ERR_IN_INIT_HOOK: 'Error in initial setup of hook',
|
|
168
|
+
ERR_IN_ONSTART: 'Error in execution onStart Hook',
|
|
169
|
+
ERR_IN_ONFINISH: 'Error in execution onFinish Hook',
|
|
170
|
+
COLLECTOR_SHUT_DOWN: 'Collector Is Shutting Down!!!!'
|
|
171
|
+
|
|
172
|
+
}
|
|
173
|
+
};
|
|
@@ -0,0 +1,166 @@
|
|
|
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 { SecEvent } = require('./event');
|
|
9
|
+
const logs = require('./logging');
|
|
10
|
+
const { Agent } = require('./agent');
|
|
11
|
+
const shaUtil = require('./sha-size-util');
|
|
12
|
+
const { LOG_MESSAGES, NR_CSEC_FUZZ_REQUEST_ID, COLON, VULNERABLE, EXITEVENT, EMPTY_STR } = require('./sec-agent-constants');
|
|
13
|
+
const API = require('../../../nr-security-api');
|
|
14
|
+
const NRAgent = API.getNRAgent();
|
|
15
|
+
|
|
16
|
+
const statusUtils = require('./statusUtils');
|
|
17
|
+
|
|
18
|
+
let firstEvent = false;
|
|
19
|
+
let firstEventSent = false;
|
|
20
|
+
|
|
21
|
+
const events = require('events');
|
|
22
|
+
const eventEmitter = undefined;
|
|
23
|
+
|
|
24
|
+
let logger = logs.getLogger();
|
|
25
|
+
const initLogger = logs.getInitLogger();
|
|
26
|
+
|
|
27
|
+
const NODE_SER = 'node-serialize/lib/serialize.js';
|
|
28
|
+
|
|
29
|
+
function getSecEventEmitter() {
|
|
30
|
+
if (eventEmitter) {
|
|
31
|
+
return eventEmitter;
|
|
32
|
+
} else {
|
|
33
|
+
return new events.EventEmitter();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Sets the logger instance.
|
|
40
|
+
*
|
|
41
|
+
* @param {*} loggerInstance
|
|
42
|
+
*/
|
|
43
|
+
const setLogger = loggerInstance => {
|
|
44
|
+
logger = loggerInstance;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
function promisify(thisArg, fn) {
|
|
49
|
+
return (...args) => new Promise((resolve, reject) => {
|
|
50
|
+
args.push((err, data) => {
|
|
51
|
+
if (err) {
|
|
52
|
+
reject(err);
|
|
53
|
+
} else {
|
|
54
|
+
resolve(data);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
fn.apply(thisArg, args);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const sleep = (timeout) => new Promise((resolve) => {
|
|
62
|
+
setTimeout(resolve, timeout);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
function generateSecEvent(securityMetadata) {
|
|
67
|
+
const traceObject = securityMetadata.traceObject;
|
|
68
|
+
const request = securityMetadata.request;
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
let stakTrace = traceObject.stacktrace;
|
|
72
|
+
let uri = EMPTY_STR;
|
|
73
|
+
if (request.uri) {
|
|
74
|
+
uri += request.uri;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let apiId = shaUtil.getSHA256ForData(traceObject.stacktrace.join('|') + uri);
|
|
78
|
+
const agentModule = Agent.getAgent();
|
|
79
|
+
const metaData = {};
|
|
80
|
+
if (traceObject.sourceDetails && traceObject.sourceDetails.evalObj) {
|
|
81
|
+
metaData.triggerViaRCI = true;
|
|
82
|
+
metaData.rciMethodsCalls = traceObject.sourceDetails.evalObj.invokedCalls;
|
|
83
|
+
metaData.rciDetail = traceObject.sourceDetails.evalObj;
|
|
84
|
+
if (traceObject.sourceDetails.evalObj) {
|
|
85
|
+
const evalFile = traceObject.sourceDetails.evalObj.fileName;
|
|
86
|
+
if (evalFile && evalFile.includes(NODE_SER)) {
|
|
87
|
+
metaData.triggerViaDeserialisation = true;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const isClientDetectedFromXFF = false;
|
|
92
|
+
|
|
93
|
+
if (!firstEvent) {
|
|
94
|
+
initLogger.info(LOG_MESSAGES.FIRST_EVENT_INTERCEPTED, securityMetadata.eventCategory, JSON.stringify(request));
|
|
95
|
+
}
|
|
96
|
+
const isAPIBlocked = false;
|
|
97
|
+
|
|
98
|
+
const event = new SecEvent(traceObject.sourceDetails.fileName, traceObject.sourceDetails.funcName, traceObject.sourceDetails.lineNumber, securityMetadata.interceptedArgs, securityMetadata.executionId, agentModule.applicationInfo, securityMetadata.request, securityMetadata.eventType, traceObject.sourceDetails.source, securityMetadata.eventCategory, metaData, stakTrace, apiId, isAPIBlocked);
|
|
99
|
+
event.metaData.isClientDetectedFromXFF = isClientDetectedFromXFF;
|
|
100
|
+
|
|
101
|
+
if (!firstEvent) {
|
|
102
|
+
initLogger.info(LOG_MESSAGES.FIRST_EVENT_PROCESSED, JSON.stringify(event));
|
|
103
|
+
firstEvent = true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return event;
|
|
107
|
+
} catch (e) {
|
|
108
|
+
statusUtils.addErrortoBuffer(e);
|
|
109
|
+
logger.error("Error in generating event:", e);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
*
|
|
116
|
+
* @param {current context} context
|
|
117
|
+
* @param {Sec agent module} agentModule
|
|
118
|
+
* Utility to generate exit events.
|
|
119
|
+
*/
|
|
120
|
+
function generateExitEvent(secEvent) {
|
|
121
|
+
if (secEvent && secEvent.httpRequest && secEvent.httpRequest.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
|
|
122
|
+
try {
|
|
123
|
+
const fuzzHeader = secEvent.httpRequest.headers[NR_CSEC_FUZZ_REQUEST_ID];
|
|
124
|
+
const apiId = fuzzHeader.split(COLON)[0].trim();
|
|
125
|
+
if (fuzzHeader.includes(VULNERABLE) && apiId === secEvent.apiId) {
|
|
126
|
+
const exitEvent = {};
|
|
127
|
+
exitEvent.jsonName = EXITEVENT;
|
|
128
|
+
exitEvent.applicationUUID = secEvent.applicationUUID;
|
|
129
|
+
exitEvent.groupName = secEvent.groupName;
|
|
130
|
+
exitEvent.nodeId = secEvent.nodeId;
|
|
131
|
+
exitEvent.jsonVersion = secEvent.jsonVersion;
|
|
132
|
+
exitEvent.buildNumber = secEvent.buildNumber;
|
|
133
|
+
exitEvent.policyVersion = secEvent.policyVersion;
|
|
134
|
+
exitEvent.executionId = secEvent.id;
|
|
135
|
+
exitEvent.caseType = secEvent.caseType;
|
|
136
|
+
exitEvent.k2RequestIdentifier = secEvent.httpRequest.headers[NR_CSEC_FUZZ_REQUEST_ID];
|
|
137
|
+
sendEvent(exitEvent);
|
|
138
|
+
}
|
|
139
|
+
} catch (error) {
|
|
140
|
+
logger.error('Error in generating exit event', error);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
function sendEvent(secEvent) {
|
|
147
|
+
const agentModule = Agent.getAgent();
|
|
148
|
+
if (agentModule.status.getStatus() === 'active' && NRAgent.config.security.enabled) {
|
|
149
|
+
agentModule.client.dispatcher(secEvent);
|
|
150
|
+
if (!firstEventSent) {
|
|
151
|
+
initLogger.info(LOG_MESSAGES.FIRST_EVENT_SENT, JSON.stringify(secEvent));
|
|
152
|
+
firstEventSent = true;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
module.exports = {
|
|
159
|
+
setLogger,
|
|
160
|
+
getSecEventEmitter: getSecEventEmitter,
|
|
161
|
+
promisify,
|
|
162
|
+
sleep,
|
|
163
|
+
generateSecEvent,
|
|
164
|
+
sendEvent,
|
|
165
|
+
generateExitEvent
|
|
166
|
+
};
|
|
@@ -0,0 +1,338 @@
|
|
|
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 fs = require('fs');
|
|
9
|
+
const hash = require('hash.js');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const async_hooks = require('async_hooks');
|
|
12
|
+
|
|
13
|
+
const INCLUDED_FILE_EXT_REGEX = /(\.)(js|ts|ejs|html|properties|yml|yaml|json|hbs)$/;
|
|
14
|
+
const TWO_PIPES = '||';
|
|
15
|
+
const HEX_DIGEST = 'hex';
|
|
16
|
+
const thresh = 1024;
|
|
17
|
+
const units = ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
|
|
18
|
+
|
|
19
|
+
let logger;
|
|
20
|
+
let CurrentPromise = global.Promise;
|
|
21
|
+
|
|
22
|
+
module.exports = { getApplicationSHAAndSize, getApplicationSHAAndSizeSync, getSHA256ForFile, getSHA256ForFileSync, setPromise, setLogger, getSHA256ForData };
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* This is a utility which is used to calculate
|
|
26
|
+
* sha256 for the complete application context.
|
|
27
|
+
*/
|
|
28
|
+
async function getApplicationSHAAndSize (appPath) {
|
|
29
|
+
if (CurrentPromise) {
|
|
30
|
+
try {
|
|
31
|
+
const shaMap = new Map();
|
|
32
|
+
const shaAndSizeObj = await getSHA256AndSizeForPath(appPath, shaMap);
|
|
33
|
+
return {
|
|
34
|
+
sha256: getSHA256ForData(shaAndSizeObj.shaList.join(TWO_PIPES)),
|
|
35
|
+
size: getHumanReadableSize(shaAndSizeObj.sizeList.reduce((result, value) => {
|
|
36
|
+
return result + value;
|
|
37
|
+
}, 0)),
|
|
38
|
+
shaMap: shaMap
|
|
39
|
+
};
|
|
40
|
+
} catch (err) {
|
|
41
|
+
logger.error('Error while calculating SHA and size for application!');
|
|
42
|
+
logger.debug(err);
|
|
43
|
+
return {};
|
|
44
|
+
}
|
|
45
|
+
} else {
|
|
46
|
+
logger.debug('Promise haven\'t been set!');
|
|
47
|
+
return {};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function getApplicationSHAAndSizeSync (appPath, skipRegex = null) {
|
|
52
|
+
try {
|
|
53
|
+
const shaMap = new Map();
|
|
54
|
+
const shaAndSizeObj = getSHA256AndSizeForPathSync(appPath, shaMap, skipRegex);
|
|
55
|
+
return {
|
|
56
|
+
sha256: getSHA256ForData(shaAndSizeObj.shaList.join(TWO_PIPES)),
|
|
57
|
+
size: getHumanReadableSize(shaAndSizeObj.sizeList.reduce((result, value) => {
|
|
58
|
+
return result + value;
|
|
59
|
+
}, 0)),
|
|
60
|
+
shaMap: shaMap
|
|
61
|
+
};
|
|
62
|
+
} catch (err) {
|
|
63
|
+
logger.error('Error while calculating SHA and size for application!');
|
|
64
|
+
logger.debug(err);
|
|
65
|
+
return {};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Gets sha256 and Size for all the elements of
|
|
71
|
+
* given filePath.
|
|
72
|
+
*
|
|
73
|
+
* @param {String} filePath
|
|
74
|
+
*/
|
|
75
|
+
async function getSHA256AndSizeForPath (filePath, shaMap) {
|
|
76
|
+
const pathStatObject = {};
|
|
77
|
+
pathStatObject.shaList = [];
|
|
78
|
+
pathStatObject.sizeList = [];
|
|
79
|
+
try {
|
|
80
|
+
const stats = await getStats(filePath);
|
|
81
|
+
if (stats.isDirectory()) {
|
|
82
|
+
const fileList = await getSortedDirContent(filePath);
|
|
83
|
+
if (fileList) {
|
|
84
|
+
for (const file of fileList) {
|
|
85
|
+
const calledStateObject = await getSHA256AndSizeForPath(file, shaMap);
|
|
86
|
+
pathStatObject.shaList = pathStatObject.shaList.concat(calledStateObject.shaList);
|
|
87
|
+
pathStatObject.sizeList = pathStatObject.sizeList.concat(calledStateObject.sizeList);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
} else if (filePath.match(INCLUDED_FILE_EXT_REGEX)) {
|
|
91
|
+
const sha = await getSHA256ForFile(filePath);
|
|
92
|
+
const fileSizeInBytes = stats.size;
|
|
93
|
+
if (sha && sha !== null) {
|
|
94
|
+
pathStatObject.shaList.push(sha);
|
|
95
|
+
if (fileSizeInBytes) {
|
|
96
|
+
pathStatObject.sizeList.push(fileSizeInBytes);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
} catch (err) {
|
|
101
|
+
logger.error('Something bad happened while geting sha for ' + filePath);
|
|
102
|
+
logger.debug(err);
|
|
103
|
+
}
|
|
104
|
+
return pathStatObject;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Gets sha256 and Size for all the elements of
|
|
109
|
+
* given filePath Synchronusly.
|
|
110
|
+
*
|
|
111
|
+
* @param {String} filePath
|
|
112
|
+
*/
|
|
113
|
+
function getSHA256AndSizeForPathSync (filePath, shaMap, skipRegex) {
|
|
114
|
+
const pathStatObject = {
|
|
115
|
+
shaList: [],
|
|
116
|
+
sizeList: []
|
|
117
|
+
};
|
|
118
|
+
if (skipRegex && filePath && filePath.match(skipRegex)) {
|
|
119
|
+
return pathStatObject;
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
const stats = getStatsSync(filePath);
|
|
123
|
+
if (stats.isDirectory()) {
|
|
124
|
+
const fileList = getSortedDirContentSync(filePath);
|
|
125
|
+
if (fileList) {
|
|
126
|
+
for (const file of fileList) {
|
|
127
|
+
const calledStateObject = getSHA256AndSizeForPathSync(file, shaMap, skipRegex);
|
|
128
|
+
pathStatObject.shaList = pathStatObject.shaList.concat(calledStateObject.shaList);
|
|
129
|
+
pathStatObject.sizeList = pathStatObject.sizeList.concat(calledStateObject.sizeList);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
} else if (filePath.match(INCLUDED_FILE_EXT_REGEX)) {
|
|
133
|
+
const sha = getSHA256ForFileSync(filePath);
|
|
134
|
+
const fileSizeInBytes = stats.size;
|
|
135
|
+
if (sha && sha !== null) {
|
|
136
|
+
pathStatObject.shaList.push(sha);
|
|
137
|
+
if (fileSizeInBytes) {
|
|
138
|
+
pathStatObject.sizeList.push(fileSizeInBytes);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
} catch (err) {
|
|
143
|
+
logger.error('Something bad happened while geting sha for ' + filePath);
|
|
144
|
+
logger.debug(err);
|
|
145
|
+
}
|
|
146
|
+
return pathStatObject;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Gets all the source and prop files
|
|
151
|
+
* in the passed directory.
|
|
152
|
+
* @param {String} dirPath
|
|
153
|
+
*/
|
|
154
|
+
async function getSortedDirContent (dirPath) {
|
|
155
|
+
return new CurrentPromise(async function (resolve, reject) {
|
|
156
|
+
try {
|
|
157
|
+
const stats = await getStats(dirPath);
|
|
158
|
+
if (stats.isDirectory()) {
|
|
159
|
+
fs.readdir(dirPath, function (err, files) {
|
|
160
|
+
if (err) {
|
|
161
|
+
logger.error('Unable to get directory content: ', dirPath);
|
|
162
|
+
reject(err);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// resolve file paths
|
|
166
|
+
for (let counter = 0; counter < files.length; counter++) {
|
|
167
|
+
files[counter] = path.resolve(dirPath, files[counter]);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// sort
|
|
171
|
+
files = files.sort();
|
|
172
|
+
|
|
173
|
+
resolve(files);
|
|
174
|
+
});
|
|
175
|
+
} else {
|
|
176
|
+
const err = new Error('Not a directory: ' + dirPath);
|
|
177
|
+
logger.error(err);
|
|
178
|
+
reject(err);
|
|
179
|
+
}
|
|
180
|
+
} catch (err) {
|
|
181
|
+
logger.error('Unable to get directory content: ', dirPath);
|
|
182
|
+
reject(err);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Gets all the source and prop files
|
|
189
|
+
* in the passed directory Sync.
|
|
190
|
+
* @param {String} dirPath
|
|
191
|
+
*/
|
|
192
|
+
function getSortedDirContentSync (dirPath) {
|
|
193
|
+
try {
|
|
194
|
+
const stats = getStatsSync(dirPath);
|
|
195
|
+
if (stats.isDirectory()) {
|
|
196
|
+
try {
|
|
197
|
+
let files = fs.readdirSync(dirPath);
|
|
198
|
+
|
|
199
|
+
// resolve file paths
|
|
200
|
+
for (let counter = 0; counter < files.length; counter++) {
|
|
201
|
+
files[counter] = path.resolve(dirPath, files[counter]);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// sort
|
|
205
|
+
files = files.sort();
|
|
206
|
+
|
|
207
|
+
return files;
|
|
208
|
+
} catch (err) {
|
|
209
|
+
logger.error('Unable to get directory content: ', dirPath);
|
|
210
|
+
throw err;
|
|
211
|
+
}
|
|
212
|
+
} else {
|
|
213
|
+
const err = new Error('Not a directory: ' + dirPath);
|
|
214
|
+
logger.error(err);
|
|
215
|
+
throw err;
|
|
216
|
+
}
|
|
217
|
+
} catch (err) {
|
|
218
|
+
logger.error('Unable to get directory content: ', dirPath);
|
|
219
|
+
throw err;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Calculates SHA256 for a file.
|
|
225
|
+
* @param {String} filePath
|
|
226
|
+
*/
|
|
227
|
+
async function getSHA256ForFile (filePath) {
|
|
228
|
+
if (CurrentPromise) {
|
|
229
|
+
return new CurrentPromise((resolve, reject) => {
|
|
230
|
+
if (filePath) {
|
|
231
|
+
} else {
|
|
232
|
+
const err = new Error('Empty FilePath!');
|
|
233
|
+
reject(err);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
} else {
|
|
237
|
+
logger.debug('Promise haven\'t been set!');
|
|
238
|
+
return {};
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Calculates SHA256 for a file synchronously.
|
|
244
|
+
* @param {String} filePath
|
|
245
|
+
*/
|
|
246
|
+
function getSHA256ForFileSync (filePath) {
|
|
247
|
+
if (!filePath) {
|
|
248
|
+
throw new Error('Empty FilePath!');
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
const fd = fs.openSync(filePath);
|
|
252
|
+
const content = fs.readFileSync(fd, { encoding: 'UTF-8' });
|
|
253
|
+
fs.closeSync(fd);
|
|
254
|
+
return getSHA256ForData(content);
|
|
255
|
+
} catch (err) {
|
|
256
|
+
logger.error('Unable to calculate SHA256 for file: ' + filePath);
|
|
257
|
+
throw err;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Generates SHA256 for passed data
|
|
263
|
+
* @param {String} data
|
|
264
|
+
*/
|
|
265
|
+
function getSHA256ForData (data) {
|
|
266
|
+
try {
|
|
267
|
+
if (!process.traceMap) {
|
|
268
|
+
return hash.sha256().update(data).digest(HEX_DIGEST); ;
|
|
269
|
+
}
|
|
270
|
+
const cachedSha = process.traceMap.get(data);
|
|
271
|
+
|
|
272
|
+
if (cachedSha) {
|
|
273
|
+
return cachedSha;
|
|
274
|
+
} else {
|
|
275
|
+
const calSha = hash.sha256().update(data).digest(HEX_DIGEST);
|
|
276
|
+
if (process.traceMap.size < 2000 && (httpreq && httpreq.data)) {
|
|
277
|
+
process.traceMap.set(data, calSha);
|
|
278
|
+
}
|
|
279
|
+
return calSha;
|
|
280
|
+
}
|
|
281
|
+
} catch (err) {
|
|
282
|
+
logger.error('Unable to calculate SHA256 for data.');
|
|
283
|
+
logger.debug(err);
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* returns HumanReadable form of passed Bytes
|
|
290
|
+
* @param {Number} bytes
|
|
291
|
+
*/
|
|
292
|
+
function getHumanReadableSize (bytes) {
|
|
293
|
+
if (Math.abs(bytes) < thresh) {
|
|
294
|
+
return bytes + ' B';
|
|
295
|
+
}
|
|
296
|
+
let u = -1;
|
|
297
|
+
do {
|
|
298
|
+
bytes /= thresh;
|
|
299
|
+
++u;
|
|
300
|
+
} while (Math.abs(bytes) >= thresh && u < units.length - 1);
|
|
301
|
+
return bytes.toFixed(1) + ' ' + units[u];
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Sets logger for this module.
|
|
306
|
+
*/
|
|
307
|
+
function setLogger (logr) {
|
|
308
|
+
logger = logr;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Sets promise for this module.
|
|
313
|
+
*/
|
|
314
|
+
function setPromise (promise) {
|
|
315
|
+
CurrentPromise = promise;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Checks if the given path represents a directory
|
|
320
|
+
*/
|
|
321
|
+
async function getStats (path) {
|
|
322
|
+
return new CurrentPromise((resolve, reject) => {
|
|
323
|
+
fs.lstat(path, function (err, stat) {
|
|
324
|
+
if (err) {
|
|
325
|
+
logger.error('Unable to get stats for: ', path);
|
|
326
|
+
reject(err);
|
|
327
|
+
}
|
|
328
|
+
resolve(stat);
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Checks if the given path represents a directory
|
|
335
|
+
*/
|
|
336
|
+
function getStatsSync (path) {
|
|
337
|
+
return fs.lstatSync(path);
|
|
338
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2023 New Relic Corporation. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { workerData, parentPort } = require('worker_threads');
|
|
7
|
+
const shaSizeUtil = require('./sha-size-util');
|
|
8
|
+
const logs = require('./logging');
|
|
9
|
+
const logger = logs.getLogger(workerData.applicationUUID);
|
|
10
|
+
shaSizeUtil.setLogger(logger);
|
|
11
|
+
const MESSAGE = 'message';
|
|
12
|
+
|
|
13
|
+
async function computeSHA (path) {
|
|
14
|
+
logger.info('Started computing SHA and size in worker thread');
|
|
15
|
+
const data = await shaSizeUtil.getApplicationSHAAndSize(path, global.Promise);
|
|
16
|
+
parentPort.postMessage(data);
|
|
17
|
+
parentPort.unref();
|
|
18
|
+
logger.debug('Terminating SHA worker');
|
|
19
|
+
process.exit(0);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
parentPort.on(MESSAGE, (param) => {
|
|
23
|
+
computeSHA(param);
|
|
24
|
+
});
|