@contrast/agent 4.21.1 → 4.22.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/bin/VERSION CHANGED
@@ -1 +1 @@
1
- 2.28.20
1
+ 2.28.22
Binary file
@@ -16,7 +16,6 @@ Copyright: 2022 Contrast Security, Inc
16
16
 
17
17
  const cp = require('child_process');
18
18
  const fs = require('fs');
19
- const os = require('os');
20
19
  const path = require('path');
21
20
  // according to https://nodejs.org/api/process.html#process_process the process
22
21
  // global can be required. We're only doing so here so we can mock it out in tests
@@ -37,6 +36,21 @@ const SuccessConnectionState = require('./success-connection-state');
37
36
 
38
37
  const RESEND_WAIT_MS = 100;
39
38
 
39
+ /**
40
+ * We might have the /bin/* files in /target directory if we're in
41
+ * development. Packaged/installed agents will have the executables in a
42
+ * top-level directory, e.g. /node_modules/@contrast/agent/bin/*
43
+ * @returns {'target' | '.'}
44
+ */
45
+ const maybeTargetDir = () => {
46
+ try {
47
+ fs.statSync(path.resolve(__dirname, '..', '..', '..', 'target'));
48
+ return 'target';
49
+ } catch (error) {
50
+ return '.';
51
+ }
52
+ };
53
+
40
54
  class Speedracer {
41
55
  constructor({ agent, logger }) {
42
56
  this.agent = agent;
@@ -155,7 +169,35 @@ class Speedracer {
155
169
  this.logger.info('starting contrast-service');
156
170
  this.startTime = Date.now();
157
171
 
158
- this.serviceProcess = cp.spawn(this.startCommand, this.startOptions);
172
+ const speedracerPath = path.resolve(
173
+ __dirname,
174
+ '..',
175
+ '..',
176
+ '..',
177
+ maybeTargetDir(),
178
+ 'bin',
179
+ `contrast-service-${process.platform}-${process.arch}`
180
+ );
181
+
182
+ try {
183
+ fs.statSync(speedracerPath);
184
+ } catch (error) {
185
+ this.logger.error(
186
+ 'unable to locate a speedracer binary for the current platform (%s) and architecture (%s)',
187
+ process.platform,
188
+ process.arch
189
+ );
190
+ return Promise.reject();
191
+ }
192
+
193
+ this.serviceProcess = cp.spawn(speedracerPath, {
194
+ env: {
195
+ ...process.env,
196
+ CONTRAST_CONFIG_PATH: this.agent.config.configFile
197
+ },
198
+ stdio: 'ignore',
199
+ windowsHide: true
200
+ });
159
201
 
160
202
  this.serviceProcess.on('error', (err) => {
161
203
  this.serviceProcess = null;
@@ -262,39 +304,6 @@ class Speedracer {
262
304
  }
263
305
  }
264
306
 
265
- /**
266
- * The start command for spawning the speedracer
267
- */
268
- get startCommand() {
269
- return path.resolve(
270
- __dirname,
271
- path.join(
272
- '..',
273
- '..',
274
- '..',
275
- utils.maybeTargetDir(),
276
- 'bin',
277
- utils.getOsDir(),
278
- 'contrast-service'
279
- )
280
- );
281
- }
282
-
283
- /**
284
- * The start options for spawning the speedracer child process. We provide the
285
- * service the location of our config file via environment variable.
286
- */
287
- get startOptions() {
288
- return {
289
- env: {
290
- ...process.env,
291
- CONTRAST_CONFIG_PATH: this.agent.config.configFile
292
- },
293
- stdio: 'ignore',
294
- windowsHide: true
295
- };
296
- }
297
-
298
307
  /**
299
308
  * GRPC is enabled when `agent.service.grpc` is not false, e.g., undefined
300
309
  * defaults to enabled, and `agent.service.socket` is not configured
@@ -314,39 +323,4 @@ class Speedracer {
314
323
  }
315
324
  }
316
325
 
317
- const utils = {
318
- /**
319
- * We might have the /bin/* files in /target directory if we're in
320
- * development. Packaged/installed agents will have the executables in a
321
- * top-level directory, e.g. /node_modules/@contrast/agent/bin/*
322
- * @returns {String}
323
- */
324
- maybeTargetDir() {
325
- try {
326
- fs.statSync(
327
- path.resolve(__dirname, path.join('..', '..', '..', 'target'))
328
- );
329
- return 'target';
330
- } catch (error) {
331
- return '';
332
- }
333
- },
334
- /**
335
- * Map platform values to folder names based on OS. The folder names are
336
- * determined by the packaging of the S-R artifacts and how they unzip.
337
- * @returns {String}
338
- */
339
- getOsDir() {
340
- switch (os.platform()) {
341
- case 'linux':
342
- return 'linux';
343
- case 'darwin':
344
- return 'mac';
345
- case 'win32':
346
- return 'windows';
347
- }
348
- }
349
- };
350
-
351
326
  module.exports = Speedracer;
352
- module.exports.utils = utils;
@@ -12,51 +12,63 @@ Copyright: 2022 Contrast Security, Inc
12
12
  engineered, modified, repackaged, sold, redistributed or otherwise used in a
13
13
  way not consistent with the End User License Agreement.
14
14
  */
15
- const path = require('path');
15
+ 'use strict';
16
+
16
17
  const fs = require('fs');
18
+ const path = require('path');
19
+ const v8 = require('v8');
17
20
  const logger = require('../core/logger')('contrast:heapDump');
18
- const heapUtil = module.exports;
19
- let heapdump;
20
21
 
21
22
  /**
22
- * setup n heap dumps to be created every n seconds after n seconds.
23
+ * @param {string} localPath location from config.path
24
+ */
25
+ const writeHeapSnapshot = function writeHeapSnapshot(localPath) {
26
+ const dumpPath = path.join(process.cwd(), localPath);
27
+
28
+ fs.mkdir(dumpPath, { recursive: true }, (err) => {
29
+ if (err) {
30
+ logger.error('Unable to create directory for heap snapshots: %o', err);
31
+ return;
32
+ }
33
+
34
+ // create dump at ${path}/${time}.heapdump
35
+ const filename = path.format({
36
+ dir: dumpPath,
37
+ name: `${Date.now()}-contrast`,
38
+ ext: '.heapsnapshot',
39
+ });
40
+
41
+ logger.info('Writing heap snapshot at %s', filename);
42
+ v8.writeHeapSnapshot(filename);
43
+ });
44
+ };
45
+
46
+ /**
47
+ * setup x heap dumps to be created every y seconds after z seconds.
23
48
  * @param {Object} config config blob from config/options.js
24
- * must have: window_ms (Number), delay_ms (Number), dumpPath (String), count (Number)
49
+ * @param {boolean} config.enable
50
+ * @param {string} config.path
51
+ * @param {number} config.count x
52
+ * @param {number} config.window_ms y
53
+ * @param {number} config.delay_ms z
25
54
  */
26
- heapUtil.init = function(config) {
55
+ const init = function init(config) {
27
56
  if (!config.enable) return;
28
- // NODE-1200: make this optional based on if config
29
- // bit is flipped
30
- heapdump = require('@contrast/heapdump');
31
57
 
32
58
  setTimeout(() => {
33
59
  let count = 0;
34
- const timeout = setInterval(() => {
60
+
61
+ const interval = setInterval(() => {
35
62
  if (count >= config.count) {
36
- clearInterval(timeout);
63
+ clearInterval(interval);
37
64
  return;
38
65
  }
39
- heapUtil.buildDump(config.path);
66
+
67
+ writeHeapSnapshot(config.path);
40
68
 
41
69
  count++;
42
70
  }, config.window_ms);
43
71
  }, config.delay_ms).unref();
44
72
  };
45
73
 
46
- heapUtil.buildDump = function(dumpPath) {
47
- // create directory in cwd
48
- dumpPath = `${path.join(process.cwd(), dumpPath)}`;
49
- fs.mkdir(dumpPath, (err) => {
50
- if (!err || (err && err.code == 'EEXIST')) {
51
- // create dump at ${path}/${time}.heapdump
52
- const fileName = `${path.join(
53
- dumpPath,
54
- String(Date.now())
55
- )}-contrast.heapsnapshot`;
56
- logger.info(`Building heap snapshot at ${fileName}`);
57
- heapdump.writeSnapshot(fileName);
58
- } else {
59
- logger.error(`Unable to create directory for heap snapshots: ${err}`);
60
- }
61
- });
62
- };
74
+ module.exports = { writeHeapSnapshot, init };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/agent",
3
- "version": "4.21.1",
3
+ "version": "4.22.0",
4
4
  "description": "Node.js security instrumentation by Contrast Security",
5
5
  "keywords": [
6
6
  "security",
@@ -76,11 +76,10 @@
76
76
  "@babel/template": "^7.10.4",
77
77
  "@babel/traverse": "^7.12.1",
78
78
  "@babel/types": "^7.12.1",
79
- "@contrast/agent-lib": "^4.2.0",
79
+ "@contrast/agent-lib": "^4.3.0",
80
80
  "@contrast/distringuish-prebuilt": "^3.2.0",
81
81
  "@contrast/flat": "^4.1.1",
82
- "@contrast/fn-inspect": "^3.0.0",
83
- "@contrast/heapdump": "^1.1.0",
82
+ "@contrast/fn-inspect": "^3.1.0",
84
83
  "@contrast/protobuf-api": "^3.2.5",
85
84
  "@contrast/require-hook": "^3.2.1",
86
85
  "@contrast/synchronous-source-maps": "^1.1.0",