securenow 7.5.0 → 7.5.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/cli/diagnostics.js +21 -2
- package/cli/init.js +94 -51
- package/cli/ui.js +22 -12
- package/package.json +1 -1
package/cli/diagnostics.js
CHANGED
|
@@ -39,6 +39,7 @@ function resolvedConfig() {
|
|
|
39
39
|
const apiUrl = config.getApiUrl();
|
|
40
40
|
const loggingEnabled = !/^(0|false)$/i.test(String(process.env.SECURENOW_LOGGING_ENABLED ?? ''));
|
|
41
41
|
const captureBody = !/^(0|false)$/i.test(String(process.env.SECURENOW_CAPTURE_BODY ?? ''));
|
|
42
|
+
const captureMultipart = !/^(0|false)$/i.test(String(process.env.SECURENOW_CAPTURE_MULTIPART ?? ''));
|
|
42
43
|
const firewallEnabled =
|
|
43
44
|
!!apiKey && process.env.SECURENOW_FIREWALL_ENABLED !== '0';
|
|
44
45
|
|
|
@@ -52,6 +53,7 @@ function resolvedConfig() {
|
|
|
52
53
|
apiUrl,
|
|
53
54
|
loggingEnabled,
|
|
54
55
|
captureBody,
|
|
56
|
+
captureMultipart,
|
|
55
57
|
firewallEnabled,
|
|
56
58
|
firewallLayers: {
|
|
57
59
|
http: firewallEnabled,
|
|
@@ -62,6 +64,21 @@ function resolvedConfig() {
|
|
|
62
64
|
};
|
|
63
65
|
}
|
|
64
66
|
|
|
67
|
+
function maskSecret(value) {
|
|
68
|
+
if (!value) return '';
|
|
69
|
+
const text = String(value);
|
|
70
|
+
if (text.length <= 12) return '***';
|
|
71
|
+
return `${text.slice(0, 12)}...${text.slice(-4)}`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function redactConfig(cfg) {
|
|
75
|
+
return {
|
|
76
|
+
...cfg,
|
|
77
|
+
headers: cfg.headers ? '***' : '',
|
|
78
|
+
apiKey: cfg.apiKey ? maskSecret(cfg.apiKey) : '',
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
65
82
|
function parseHeaders(str) {
|
|
66
83
|
const out = {};
|
|
67
84
|
if (!str) return out;
|
|
@@ -305,6 +322,7 @@ function env(_args, flags) {
|
|
|
305
322
|
SECURENOW_API_URL: cfg.apiUrl,
|
|
306
323
|
SECURENOW_LOGGING_ENABLED: cfg.loggingEnabled ? '1' : '0',
|
|
307
324
|
SECURENOW_CAPTURE_BODY: cfg.captureBody ? '1' : '0',
|
|
325
|
+
SECURENOW_CAPTURE_MULTIPART: cfg.captureMultipart ? '1' : '0',
|
|
308
326
|
SECURENOW_NO_UUID: process.env.SECURENOW_NO_UUID || `(auto: ${require('../app-config').resolveNoUuid() ? '1' : '0'})`,
|
|
309
327
|
SECURENOW_FIREWALL_TCP: process.env.SECURENOW_FIREWALL_TCP || '0',
|
|
310
328
|
SECURENOW_FIREWALL_IPTABLES: process.env.SECURENOW_FIREWALL_IPTABLES || '0',
|
|
@@ -313,7 +331,7 @@ function env(_args, flags) {
|
|
|
313
331
|
};
|
|
314
332
|
|
|
315
333
|
if (flags.json) {
|
|
316
|
-
ui.json({ resolved: cfg, env: vars });
|
|
334
|
+
ui.json({ resolved: redactConfig(cfg), env: vars });
|
|
317
335
|
return;
|
|
318
336
|
}
|
|
319
337
|
|
|
@@ -324,6 +342,7 @@ function env(_args, flags) {
|
|
|
324
342
|
['Logs endpoint', cfg.logsEndpoint],
|
|
325
343
|
['Logging', cfg.loggingEnabled ? ui.c.green('enabled') : ui.c.dim('disabled')],
|
|
326
344
|
['Body capture', cfg.captureBody ? ui.c.green('enabled') : ui.c.dim('disabled')],
|
|
345
|
+
['Multipart capture', cfg.captureMultipart ? ui.c.green('enabled') : ui.c.dim('disabled')],
|
|
327
346
|
['Firewall', cfg.firewallEnabled ? ui.c.green('enabled') : ui.c.dim('disabled (no API key)')],
|
|
328
347
|
]);
|
|
329
348
|
|
|
@@ -377,7 +396,7 @@ async function doctor(_args, flags) {
|
|
|
377
396
|
const ok = checks.every((c) => c.ok);
|
|
378
397
|
|
|
379
398
|
if (flags.json) {
|
|
380
|
-
ui.json({ ok, resolved: cfg, checks, warnings });
|
|
399
|
+
ui.json({ ok, resolved: redactConfig(cfg), checks, warnings });
|
|
381
400
|
process.exit(ok ? 0 : 1);
|
|
382
401
|
}
|
|
383
402
|
|
package/cli/init.js
CHANGED
|
@@ -1,24 +1,52 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const ui = require('./ui');
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const ui = require('./ui');
|
|
6
|
+
const config = require('./config');
|
|
7
|
+
|
|
8
|
+
const DEFAULT_ENV = {
|
|
9
|
+
SECURENOW_LOGGING_ENABLED: '1',
|
|
10
|
+
SECURENOW_CAPTURE_BODY: '1',
|
|
11
|
+
SECURENOW_CAPTURE_MULTIPART: '1',
|
|
12
|
+
SECURENOW_FIREWALL_ENABLED: '1',
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const INSTRUMENTATION_JS = `import { createRequire } from 'node:module';
|
|
16
|
+
|
|
17
|
+
const require = createRequire(import.meta.url);
|
|
18
|
+
|
|
19
|
+
export async function register() {
|
|
20
|
+
if (process.env.NEXT_RUNTIME !== 'nodejs') return;
|
|
21
|
+
|
|
22
|
+
process.env.SECURENOW_LOGGING_ENABLED ??= '1';
|
|
23
|
+
process.env.SECURENOW_CAPTURE_BODY ??= '1';
|
|
24
|
+
process.env.SECURENOW_CAPTURE_MULTIPART ??= '1';
|
|
25
|
+
process.env.SECURENOW_FIREWALL_ENABLED ??= '1';
|
|
26
|
+
|
|
27
|
+
const { registerSecureNow } = require('securenow/nextjs');
|
|
28
|
+
registerSecureNow({ captureBody: true });
|
|
29
|
+
require('securenow/nextjs-auto-capture');
|
|
30
|
+
}
|
|
31
|
+
`;
|
|
32
|
+
|
|
33
|
+
const INSTRUMENTATION_TS = `import { createRequire } from 'node:module';
|
|
34
|
+
|
|
35
|
+
const require = createRequire(import.meta.url);
|
|
36
|
+
|
|
37
|
+
export async function register() {
|
|
38
|
+
if (process.env.NEXT_RUNTIME !== 'nodejs') return;
|
|
39
|
+
|
|
40
|
+
process.env.SECURENOW_LOGGING_ENABLED ??= '1';
|
|
41
|
+
process.env.SECURENOW_CAPTURE_BODY ??= '1';
|
|
42
|
+
process.env.SECURENOW_CAPTURE_MULTIPART ??= '1';
|
|
43
|
+
process.env.SECURENOW_FIREWALL_ENABLED ??= '1';
|
|
44
|
+
|
|
45
|
+
const { registerSecureNow } = require('securenow/nextjs');
|
|
46
|
+
registerSecureNow({ captureBody: true });
|
|
47
|
+
require('securenow/nextjs-auto-capture');
|
|
48
|
+
}
|
|
49
|
+
`;
|
|
22
50
|
|
|
23
51
|
function detectProject(dir) {
|
|
24
52
|
const pkgPath = path.join(dir, 'package.json');
|
|
@@ -165,37 +193,52 @@ function initNode(dir, project) {
|
|
|
165
193
|
}
|
|
166
194
|
}
|
|
167
195
|
|
|
168
|
-
function initEnv(dir, flags) {
|
|
169
|
-
const envFiles = ['.env', '.env.local'];
|
|
170
|
-
let envPath = null;
|
|
171
|
-
|
|
172
|
-
for (const f of envFiles) {
|
|
173
|
-
const p = path.join(dir, f);
|
|
174
|
-
if (fs.existsSync(p)) {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
|
|
196
|
+
function initEnv(dir, flags) {
|
|
197
|
+
const envFiles = ['.env', '.env.local'];
|
|
198
|
+
let envPath = null;
|
|
199
|
+
|
|
200
|
+
for (const f of envFiles) {
|
|
201
|
+
const p = path.join(dir, f);
|
|
202
|
+
if (fs.existsSync(p)) {
|
|
203
|
+
envPath = p;
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (!envPath) envPath = path.join(dir, '.env.local');
|
|
209
|
+
|
|
210
|
+
const existing = fs.existsSync(envPath) ? fs.readFileSync(envPath, 'utf8') : '';
|
|
211
|
+
const additions = [];
|
|
212
|
+
for (const [key, value] of Object.entries(DEFAULT_ENV)) {
|
|
213
|
+
if (!hasEnvKey(existing, key)) additions.push(`${key}=${value}`);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const explicitApiKey = flags.key || flags['api-key'] || '';
|
|
217
|
+
const hasApiKey = hasEnvKey(existing, 'SECURENOW_API_KEY');
|
|
218
|
+
if (explicitApiKey && !hasApiKey) additions.push(`SECURENOW_API_KEY=${explicitApiKey}`);
|
|
219
|
+
|
|
220
|
+
if (additions.length > 0) {
|
|
221
|
+
const sep = existing && !existing.endsWith('\n') ? '\n' : '';
|
|
222
|
+
fs.appendFileSync(envPath, `${sep}${additions.join('\n')}\n`, 'utf8');
|
|
223
|
+
ui.success(`Updated ${path.basename(envPath)} with SecureNow defaults`);
|
|
224
|
+
} else {
|
|
225
|
+
ui.info(`${path.basename(envPath)} already contains SecureNow defaults`);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (hasApiKey || explicitApiKey) {
|
|
229
|
+
ui.info(`SECURENOW_API_KEY is set in ${path.basename(envPath)}`);
|
|
230
|
+
} else if (config.getApiKey()) {
|
|
231
|
+
ui.info('Using firewall API key from project .securenow/credentials.json');
|
|
232
|
+
} else {
|
|
233
|
+
ui.warn(`Add your API key to ${path.basename(envPath)}:`);
|
|
234
|
+
console.log('');
|
|
235
|
+
console.log(' SECURENOW_API_KEY=snk_live_...');
|
|
236
|
+
console.log('');
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function hasEnvKey(content, key) {
|
|
241
|
+
return new RegExp(`^\\s*${key}\\s*=`, 'm').test(content || '');
|
|
242
|
+
}
|
|
200
243
|
|
|
201
244
|
module.exports = { init };
|
package/cli/ui.js
CHANGED
|
@@ -111,13 +111,21 @@ function keyValue(pairs) {
|
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
function heading(text) {
|
|
115
|
-
console.log(`\n${c.bold(c.cyan(text))}`);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function
|
|
119
|
-
|
|
120
|
-
}
|
|
114
|
+
function heading(text) {
|
|
115
|
+
console.log(`\n${c.bold(c.cyan(text))}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function header(text) {
|
|
119
|
+
heading(text);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function bold(text) {
|
|
123
|
+
return c.bold(text);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function subheading(text) {
|
|
127
|
+
console.log(`\n ${c.bold(text)}`);
|
|
128
|
+
}
|
|
121
129
|
|
|
122
130
|
function success(msg) {
|
|
123
131
|
console.log(`${c.green('✓')} ${msg}`);
|
|
@@ -361,11 +369,13 @@ function durationColor(ms) {
|
|
|
361
369
|
module.exports = {
|
|
362
370
|
c,
|
|
363
371
|
NO_COLOR,
|
|
364
|
-
stripAnsi,
|
|
365
|
-
table,
|
|
366
|
-
keyValue,
|
|
367
|
-
heading,
|
|
368
|
-
|
|
372
|
+
stripAnsi,
|
|
373
|
+
table,
|
|
374
|
+
keyValue,
|
|
375
|
+
heading,
|
|
376
|
+
header,
|
|
377
|
+
bold,
|
|
378
|
+
subheading,
|
|
369
379
|
success,
|
|
370
380
|
error,
|
|
371
381
|
warn,
|
package/package.json
CHANGED