securenow 7.5.1 → 7.6.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/CONSUMING-APPS-GUIDE.md +2 -0
- package/NPM_README.md +201 -237
- package/README.md +73 -26
- package/SKILL-API.md +209 -205
- package/SKILL-CLI.md +71 -64
- package/app-config.js +479 -83
- package/cli/apiKey.js +1 -1
- package/cli/apps.js +1 -1
- package/cli/config.js +31 -12
- package/cli/credentials.js +88 -0
- package/cli/diagnostics.js +68 -104
- package/cli/firewall.js +29 -14
- package/cli/init.js +208 -206
- package/cli/monitor.js +107 -43
- package/cli/security.js +24 -12
- package/cli/utils.js +2 -1
- package/cli.js +71 -39
- package/console-instrumentation.js +1 -1
- package/docs/ENVIRONMENT-VARIABLES.md +137 -863
- package/docs/ENVIRONMENTS.md +60 -0
- package/docs/EXPRESS-SETUP-GUIDE.md +3 -0
- package/docs/FIREWALL-GUIDE.md +3 -0
- package/docs/INDEX.md +6 -8
- package/docs/LOGGING-GUIDE.md +3 -0
- package/docs/MCP-GUIDE.md +8 -0
- package/docs/NEXTJS-GUIDE.md +3 -0
- package/docs/NEXTJS-QUICKSTART.md +24 -16
- package/docs/NUXT-GUIDE.md +3 -0
- package/docs/QUICKSTART-BODY-CAPTURE.md +3 -0
- package/docs/REQUEST-BODY-CAPTURE.md +3 -0
- package/firewall-cloud.js +10 -10
- package/firewall-only.js +25 -23
- package/firewall.js +47 -29
- package/free-trial-banner.js +1 -1
- package/mcp/catalog.js +104 -17
- package/nextjs-auto-capture.d.ts +7 -4
- package/nextjs-auto-capture.js +7 -7
- package/nextjs-middleware.js +4 -3
- package/nextjs-wrapper.js +6 -6
- package/nextjs.d.ts +36 -25
- package/nextjs.js +47 -55
- package/nuxt-server-plugin.mjs +35 -51
- package/nuxt.d.ts +29 -23
- package/package.json +1 -1
- package/postinstall.js +27 -61
- package/register.d.ts +19 -33
- package/register.js +8 -8
- package/resolve-ip.js +4 -5
- package/tracing.d.ts +21 -19
- package/tracing.js +34 -42
package/nextjs.js
CHANGED
|
@@ -32,24 +32,15 @@
|
|
|
32
32
|
* registerSecureNow();
|
|
33
33
|
* }
|
|
34
34
|
*
|
|
35
|
-
* 3.
|
|
36
|
-
*
|
|
37
|
-
*
|
|
35
|
+
* 3. Run `npx securenow login` and `npx securenow init`.
|
|
36
|
+
* The SDK reads app identity, collector, firewall, capture, and
|
|
37
|
+
* deploymentEnvironment from .securenow/credentials.json.
|
|
38
38
|
*/
|
|
39
39
|
|
|
40
40
|
const { randomUUID } = require('crypto');
|
|
41
|
+
const appConfig = require('./app-config');
|
|
41
42
|
|
|
42
|
-
const env =
|
|
43
|
-
|
|
44
|
-
const parseHeaders = str => {
|
|
45
|
-
const out = {}; if (!str) return out;
|
|
46
|
-
for (const raw of String(str).split(',')) {
|
|
47
|
-
const s = raw.trim(); if (!s) continue;
|
|
48
|
-
const i = s.indexOf('='); if (i === -1) continue;
|
|
49
|
-
out[s.slice(0, i).trim().toLowerCase()] = s.slice(i + 1).trim();
|
|
50
|
-
}
|
|
51
|
-
return out;
|
|
52
|
-
};
|
|
43
|
+
const env = appConfig.env;
|
|
53
44
|
|
|
54
45
|
let isRegistered = false;
|
|
55
46
|
|
|
@@ -120,8 +111,9 @@ function redactGraphQLQuery(query, sensitiveFields = DEFAULT_SENSITIVE_FIELDS) {
|
|
|
120
111
|
/**
|
|
121
112
|
* Register SecureNow OpenTelemetry for Next.js using @vercel/otel
|
|
122
113
|
* @param {Object} options - Optional configuration
|
|
123
|
-
* @param {string} options.serviceName - Service name (defaults to
|
|
124
|
-
* @param {string} options.endpoint - Traces endpoint (defaults to
|
|
114
|
+
* @param {string} options.serviceName - Service name (defaults to .securenow/credentials.json app.key/app.name)
|
|
115
|
+
* @param {string} options.endpoint - Traces endpoint (defaults to .securenow/credentials.json app.instance)
|
|
116
|
+
* @param {string} options.environment - deployment.environment override (defaults to config.runtime.deploymentEnvironment)
|
|
125
117
|
* @param {boolean} options.noUuid - Don't append UUID to service name
|
|
126
118
|
*/
|
|
127
119
|
function registerSecureNow(options = {}) {
|
|
@@ -144,8 +136,7 @@ function registerSecureNow(options = {}) {
|
|
|
144
136
|
console.log('[securenow] Next.js integration loading (pid=%d)', process.pid);
|
|
145
137
|
|
|
146
138
|
// -------- Configuration --------
|
|
147
|
-
// Resolution order: explicit options
|
|
148
|
-
const appConfig = require('./app-config');
|
|
139
|
+
// Resolution order: explicit options -> .securenow/credentials.json -> legacy env fallback -> package.json#name
|
|
149
140
|
const resolvedApp = appConfig.resolveAll();
|
|
150
141
|
|
|
151
142
|
const rawBase = (options.serviceName || resolvedApp.appId || '').trim().replace(/^['"]|['"]$/g, '');
|
|
@@ -154,6 +145,9 @@ function registerSecureNow(options = {}) {
|
|
|
154
145
|
// and the dashboard does exact match). opts.noUuid or SECURENOW_NO_UUID
|
|
155
146
|
// override.
|
|
156
147
|
const noUuid = appConfig.resolveNoUuid({ noUuid: options.noUuid });
|
|
148
|
+
const deploymentEnvironment = appConfig.normalizeDeploymentEnvironment(
|
|
149
|
+
options.environment || resolvedApp.deploymentEnvironment || env('VERCEL_ENV')
|
|
150
|
+
);
|
|
157
151
|
|
|
158
152
|
// service.name
|
|
159
153
|
let serviceName;
|
|
@@ -162,29 +156,25 @@ function registerSecureNow(options = {}) {
|
|
|
162
156
|
} else {
|
|
163
157
|
serviceName = `nextjs-app-${randomUUID()}`;
|
|
164
158
|
console.warn('[securenow] ⚠️ No app identity resolved. Using fallback: %s', serviceName);
|
|
165
|
-
console.warn('[securenow]
|
|
159
|
+
console.warn('[securenow] Run `npx securenow login` and `npx securenow init` to write .securenow/credentials.json');
|
|
166
160
|
}
|
|
167
161
|
|
|
168
162
|
// -------- Endpoint Configuration --------
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
process.env.OTEL_EXPORTER_OTLP_HEADERS = `x-api-key=${resolvedApp.appKey}`;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const tracesUrl = env('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT') || `${endpointBase}/v1/traces`;
|
|
178
|
-
const logsUrl = env('OTEL_EXPORTER_OTLP_LOGS_ENDPOINT') || `${endpointBase}/v1/logs`;
|
|
163
|
+
const resolvedEndpoints = appConfig.resolveEndpoints({ endpoint: options.endpoint || resolvedApp.instance });
|
|
164
|
+
const endpointBase = resolvedEndpoints.endpointBase;
|
|
165
|
+
const tracesUrl = resolvedEndpoints.tracesUrl;
|
|
166
|
+
const logsUrl = resolvedEndpoints.logsUrl;
|
|
167
|
+
const headers = resolvedEndpoints.headers;
|
|
179
168
|
|
|
180
169
|
if (!process.env.OTEL_SERVICE_NAME) process.env.OTEL_SERVICE_NAME = serviceName;
|
|
181
170
|
if (!process.env.OTEL_EXPORTER_OTLP_ENDPOINT) process.env.OTEL_EXPORTER_OTLP_ENDPOINT = endpointBase;
|
|
182
171
|
if (!process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT) process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = tracesUrl;
|
|
183
172
|
|
|
184
|
-
console.log('[securenow]
|
|
173
|
+
console.log('[securenow] Next.js App -> service.name=%s', serviceName);
|
|
174
|
+
console.log('[securenow] Environment: %s', deploymentEnvironment);
|
|
185
175
|
|
|
186
176
|
// -------- Body Capture Configuration --------
|
|
187
|
-
// Opt-out default: set
|
|
177
|
+
// Opt-out default: set config.capture.body=false (or options.captureBody=false) to disable.
|
|
188
178
|
const captureBody = options.captureBody ?? !/^(0|false)$/i.test(String(env('SECURENOW_CAPTURE_BODY') ?? ''));
|
|
189
179
|
const maxBodySize = Math.max(1024, parseInt(env('SECURENOW_MAX_BODY_SIZE'), 10) || 10240);
|
|
190
180
|
const customSensitiveFields = (env('SECURENOW_SENSITIVE_FIELDS') || '').split(',').map(s => s.trim()).filter(Boolean);
|
|
@@ -413,7 +403,7 @@ function registerSecureNow(options = {}) {
|
|
|
413
403
|
registerOTel({
|
|
414
404
|
serviceName: serviceName,
|
|
415
405
|
attributes: {
|
|
416
|
-
'deployment.environment':
|
|
406
|
+
'deployment.environment': deploymentEnvironment,
|
|
417
407
|
'service.version': process.env.npm_package_version || process.env.VERCEL_GIT_COMMIT_SHA || undefined,
|
|
418
408
|
'vercel.region': process.env.VERCEL_REGION || undefined,
|
|
419
409
|
},
|
|
@@ -444,7 +434,7 @@ function registerSecureNow(options = {}) {
|
|
|
444
434
|
|
|
445
435
|
const traceExporter = new OTLPTraceExporter({
|
|
446
436
|
url: tracesUrl,
|
|
447
|
-
|
|
437
|
+
headers
|
|
448
438
|
});
|
|
449
439
|
|
|
450
440
|
const sdk = new NodeSDK({
|
|
@@ -453,7 +443,7 @@ function registerSecureNow(options = {}) {
|
|
|
453
443
|
instrumentations: [httpInstrumentation],
|
|
454
444
|
resource: new Resource({
|
|
455
445
|
[SemanticResourceAttributes.SERVICE_NAME]: serviceName,
|
|
456
|
-
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]:
|
|
446
|
+
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: deploymentEnvironment,
|
|
457
447
|
[SemanticResourceAttributes.SERVICE_VERSION]: process.env.npm_package_version || undefined,
|
|
458
448
|
}),
|
|
459
449
|
});
|
|
@@ -462,7 +452,7 @@ function registerSecureNow(options = {}) {
|
|
|
462
452
|
console.log('[securenow] 🎯 Vanilla SDK initialized for self-hosted environment');
|
|
463
453
|
|
|
464
454
|
// -------- Logging (self-hosted only) --------
|
|
465
|
-
// Opt-out default: set
|
|
455
|
+
// Opt-out default: set config.logging.enabled=false to disable.
|
|
466
456
|
const loggingEnabled = !/^(0|false)$/i.test(String(env('SECURENOW_LOGGING_ENABLED') ?? ''));
|
|
467
457
|
if (loggingEnabled) {
|
|
468
458
|
try {
|
|
@@ -471,13 +461,13 @@ function registerSecureNow(options = {}) {
|
|
|
471
461
|
|
|
472
462
|
const logExporter = new OTLPLogExporter({
|
|
473
463
|
url: logsUrl,
|
|
474
|
-
headers
|
|
464
|
+
headers,
|
|
475
465
|
});
|
|
476
466
|
|
|
477
467
|
const loggerProvider = new LoggerProvider({
|
|
478
468
|
resource: new Resource({
|
|
479
469
|
[SemanticResourceAttributes.SERVICE_NAME]: serviceName,
|
|
480
|
-
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]:
|
|
470
|
+
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: deploymentEnvironment,
|
|
481
471
|
}),
|
|
482
472
|
});
|
|
483
473
|
loggerProvider.addLogRecordProcessor(new BatchLogRecordProcessor(logExporter));
|
|
@@ -614,25 +604,28 @@ function registerSecureNow(options = {}) {
|
|
|
614
604
|
}
|
|
615
605
|
|
|
616
606
|
// Firewall — runs independently from OTel so it works even if tracing fails.
|
|
617
|
-
// Key
|
|
618
|
-
//
|
|
619
|
-
const
|
|
620
|
-
|
|
621
|
-
const firewallAppKey = appConfig.resolveAppKey();
|
|
622
|
-
if (firewallApiKey && env('SECURENOW_FIREWALL_ENABLED') !== '0') {
|
|
607
|
+
// Key and environment come from .securenow/credentials.json (written by
|
|
608
|
+
// login/init or credentials runtime), so no .env entry is needed.
|
|
609
|
+
const firewallOptions = appConfig.resolveFirewallOptions();
|
|
610
|
+
if (firewallOptions.apiKey && firewallOptions.enabled) {
|
|
623
611
|
try {
|
|
624
612
|
require('./firewall').init({
|
|
625
|
-
apiKey:
|
|
626
|
-
appKey:
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
613
|
+
apiKey: firewallOptions.apiKey,
|
|
614
|
+
appKey: firewallOptions.appKey,
|
|
615
|
+
environment: deploymentEnvironment || firewallOptions.environment,
|
|
616
|
+
apiUrl: firewallOptions.apiUrl,
|
|
617
|
+
versionCheckInterval: firewallOptions.versionCheckInterval,
|
|
618
|
+
syncInterval: firewallOptions.syncInterval,
|
|
619
|
+
failMode: firewallOptions.failMode,
|
|
620
|
+
statusCode: firewallOptions.statusCode,
|
|
621
|
+
log: firewallOptions.log,
|
|
622
|
+
tcp: firewallOptions.tcp,
|
|
623
|
+
iptables: firewallOptions.iptables,
|
|
624
|
+
cloud: firewallOptions.cloud,
|
|
625
|
+
cloudDryRun: firewallOptions.cloudDryRun,
|
|
626
|
+
cloudflare: firewallOptions.cloudflare,
|
|
627
|
+
aws: firewallOptions.aws,
|
|
628
|
+
gcp: firewallOptions.gcp,
|
|
636
629
|
});
|
|
637
630
|
} catch (e) {
|
|
638
631
|
console.warn('[securenow] Firewall init failed:', e.message);
|
|
@@ -643,4 +636,3 @@ function registerSecureNow(options = {}) {
|
|
|
643
636
|
module.exports = {
|
|
644
637
|
registerSecureNow,
|
|
645
638
|
};
|
|
646
|
-
|
package/nuxt-server-plugin.mjs
CHANGED
|
@@ -25,21 +25,7 @@ const appConfig = nodeRequire('./app-config');
|
|
|
25
25
|
|
|
26
26
|
// ── Helpers ──
|
|
27
27
|
|
|
28
|
-
const env =
|
|
29
|
-
process.env[k] ?? process.env[k.toUpperCase()] ?? process.env[k.toLowerCase()];
|
|
30
|
-
|
|
31
|
-
const parseHeaders = (str) => {
|
|
32
|
-
const out = {};
|
|
33
|
-
if (!str) return out;
|
|
34
|
-
for (const raw of String(str).split(',')) {
|
|
35
|
-
const s = raw.trim();
|
|
36
|
-
if (!s) continue;
|
|
37
|
-
const i = s.indexOf('=');
|
|
38
|
-
if (i === -1) continue;
|
|
39
|
-
out[s.slice(0, i).trim().toLowerCase()] = s.slice(i + 1).trim();
|
|
40
|
-
}
|
|
41
|
-
return out;
|
|
42
|
-
};
|
|
28
|
+
const env = appConfig.env;
|
|
43
29
|
|
|
44
30
|
const DEFAULT_SENSITIVE_FIELDS = [
|
|
45
31
|
'password', 'passwd', 'pwd', 'secret', 'token', 'api_key', 'apikey',
|
|
@@ -74,10 +60,10 @@ function getRuntimeOptions() {
|
|
|
74
60
|
|
|
75
61
|
// ── Plugin ──
|
|
76
62
|
|
|
77
|
-
export default defineNitroPlugin((nitroApp) => {
|
|
63
|
+
export default defineNitroPlugin(async (nitroApp) => {
|
|
78
64
|
const opts = getRuntimeOptions();
|
|
79
65
|
|
|
80
|
-
// Resolution order: opts
|
|
66
|
+
// Resolution order: opts -> .securenow/credentials.json -> legacy env fallback -> package.json#name
|
|
81
67
|
const resolvedApp = appConfig.resolveAll();
|
|
82
68
|
|
|
83
69
|
// ── Naming ──
|
|
@@ -85,8 +71,11 @@ export default defineNitroPlugin((nitroApp) => {
|
|
|
85
71
|
const baseName = rawBase || null;
|
|
86
72
|
// Default: auto-disable per-worker suffix when logged in (appId is the
|
|
87
73
|
// routing UUID and the dashboard does exact match). opts.noUuid or
|
|
88
|
-
//
|
|
74
|
+
// config.runtime.noUuid or opts.noUuid override.
|
|
89
75
|
const noUuid = appConfig.resolveNoUuid({ noUuid: opts.noUuid });
|
|
76
|
+
const deploymentEnvironment = appConfig.normalizeDeploymentEnvironment(
|
|
77
|
+
opts.environment || resolvedApp.deploymentEnvironment
|
|
78
|
+
);
|
|
90
79
|
|
|
91
80
|
let serviceName;
|
|
92
81
|
if (baseName) {
|
|
@@ -98,40 +87,31 @@ export default defineNitroPlugin((nitroApp) => {
|
|
|
98
87
|
serviceName,
|
|
99
88
|
);
|
|
100
89
|
console.warn(
|
|
101
|
-
'[securenow]
|
|
90
|
+
'[securenow] Run `npx securenow login` or set app.key in .securenow/credentials.json',
|
|
102
91
|
);
|
|
103
92
|
}
|
|
104
93
|
|
|
105
94
|
const serviceInstanceId = `${baseName || 'securenow'}-${uuidv4()}`;
|
|
106
95
|
|
|
107
96
|
// ── Endpoints ──
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
process.env.OTEL_EXPORTER_OTLP_HEADERS = `x-api-key=${resolvedApp.appKey}`;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const tracesUrl =
|
|
117
|
-
env('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT') || `${endpointBase}/v1/traces`;
|
|
118
|
-
const logsUrl =
|
|
119
|
-
env('OTEL_EXPORTER_OTLP_LOGS_ENDPOINT') || `${endpointBase}/v1/logs`;
|
|
120
|
-
const headers = parseHeaders(env('OTEL_EXPORTER_OTLP_HEADERS'));
|
|
97
|
+
const resolvedEndpoints = appConfig.resolveEndpoints({ endpoint: opts.endpoint || resolvedApp.instance });
|
|
98
|
+
const endpointBase = resolvedEndpoints.endpointBase;
|
|
99
|
+
const tracesUrl = resolvedEndpoints.tracesUrl;
|
|
100
|
+
const logsUrl = resolvedEndpoints.logsUrl;
|
|
101
|
+
const headers = resolvedEndpoints.headers;
|
|
121
102
|
|
|
122
103
|
// ── Resource ──
|
|
123
104
|
const resource = new Resource({
|
|
124
105
|
[SemanticResourceAttributes.SERVICE_NAME]: serviceName,
|
|
125
106
|
[SemanticResourceAttributes.SERVICE_INSTANCE_ID]: serviceInstanceId,
|
|
126
|
-
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]:
|
|
127
|
-
env('NODE_ENV') || 'production',
|
|
107
|
+
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: deploymentEnvironment,
|
|
128
108
|
[SemanticResourceAttributes.SERVICE_VERSION]:
|
|
129
109
|
process.env.npm_package_version || undefined,
|
|
130
110
|
'framework': 'nuxt',
|
|
131
111
|
});
|
|
132
112
|
|
|
133
113
|
// ── Body capture config ──
|
|
134
|
-
// Opt-out default: set
|
|
114
|
+
// Opt-out default: set config.capture.body=false (or opts.captureBody=false) to disable.
|
|
135
115
|
const captureBody =
|
|
136
116
|
opts.captureBody ??
|
|
137
117
|
!/^(0|false)$/i.test(String(env('SECURENOW_CAPTURE_BODY') ?? ''));
|
|
@@ -240,7 +220,7 @@ export default defineNitroPlugin((nitroApp) => {
|
|
|
240
220
|
);
|
|
241
221
|
|
|
242
222
|
// ── Logging ──
|
|
243
|
-
// Opt-out default: set
|
|
223
|
+
// Opt-out default: set config.logging.enabled=false (or opts.logging=false) to disable.
|
|
244
224
|
const loggingEnabled =
|
|
245
225
|
opts.logging ??
|
|
246
226
|
!/^(0|false)$/i.test(String(env('SECURENOW_LOGGING_ENABLED') ?? ''));
|
|
@@ -304,7 +284,7 @@ export default defineNitroPlugin((nitroApp) => {
|
|
|
304
284
|
}
|
|
305
285
|
} else {
|
|
306
286
|
console.log(
|
|
307
|
-
'[securenow]
|
|
287
|
+
'[securenow] Logging: DISABLED (config.logging.enabled=false)',
|
|
308
288
|
);
|
|
309
289
|
}
|
|
310
290
|
|
|
@@ -327,23 +307,27 @@ export default defineNitroPlugin((nitroApp) => {
|
|
|
327
307
|
}
|
|
328
308
|
|
|
329
309
|
// ── Firewall — runs independently from OTel ──
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
if (firewallApiKey && env('SECURENOW_FIREWALL_ENABLED') !== '0') {
|
|
310
|
+
const firewallOptions = appConfig.resolveFirewallOptions();
|
|
311
|
+
if (firewallOptions.apiKey && firewallOptions.enabled) {
|
|
333
312
|
try {
|
|
334
313
|
const { init: fwInit } = await import('./firewall.js');
|
|
335
314
|
fwInit({
|
|
336
|
-
apiKey:
|
|
337
|
-
appKey:
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
315
|
+
apiKey: firewallOptions.apiKey,
|
|
316
|
+
appKey: firewallOptions.appKey,
|
|
317
|
+
environment: deploymentEnvironment || firewallOptions.environment,
|
|
318
|
+
apiUrl: firewallOptions.apiUrl,
|
|
319
|
+
versionCheckInterval: firewallOptions.versionCheckInterval,
|
|
320
|
+
syncInterval: firewallOptions.syncInterval,
|
|
321
|
+
failMode: firewallOptions.failMode,
|
|
322
|
+
statusCode: firewallOptions.statusCode,
|
|
323
|
+
log: firewallOptions.log,
|
|
324
|
+
tcp: firewallOptions.tcp,
|
|
325
|
+
iptables: firewallOptions.iptables,
|
|
326
|
+
cloud: firewallOptions.cloud,
|
|
327
|
+
cloudDryRun: firewallOptions.cloudDryRun,
|
|
328
|
+
cloudflare: firewallOptions.cloudflare,
|
|
329
|
+
aws: firewallOptions.aws,
|
|
330
|
+
gcp: firewallOptions.gcp,
|
|
347
331
|
});
|
|
348
332
|
} catch (e) {
|
|
349
333
|
console.warn('[securenow] Firewall init failed:', e.message);
|
package/nuxt.d.ts
CHANGED
|
@@ -3,17 +3,23 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
export interface SecureNowNuxtOptions {
|
|
6
|
-
/**
|
|
7
|
-
* Service name for OpenTelemetry traces.
|
|
8
|
-
* @default
|
|
9
|
-
*/
|
|
10
|
-
serviceName?: string;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* OTLP endpoint base URL.
|
|
14
|
-
* @default
|
|
15
|
-
*/
|
|
16
|
-
endpoint?: string;
|
|
6
|
+
/**
|
|
7
|
+
* Service name for OpenTelemetry traces.
|
|
8
|
+
* @default .securenow/credentials.json app.key/app.name
|
|
9
|
+
*/
|
|
10
|
+
serviceName?: string;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* OTLP endpoint base URL.
|
|
14
|
+
* @default .securenow/credentials.json app.instance, or https://freetrial.securenow.ai:4318
|
|
15
|
+
*/
|
|
16
|
+
endpoint?: string;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Deployment environment sent as OpenTelemetry deployment.environment.
|
|
20
|
+
* @default .securenow/credentials.json config.runtime.deploymentEnvironment
|
|
21
|
+
*/
|
|
22
|
+
environment?: string;
|
|
17
23
|
|
|
18
24
|
/**
|
|
19
25
|
* Don't append UUID to service name (useful when running a single instance).
|
|
@@ -22,18 +28,18 @@ export interface SecureNowNuxtOptions {
|
|
|
22
28
|
noUuid?: boolean;
|
|
23
29
|
|
|
24
30
|
/**
|
|
25
|
-
* Capture request bodies (POST/PUT/PATCH) on traced spans.
|
|
26
|
-
* Sensitive fields are automatically redacted.
|
|
27
|
-
* @default
|
|
28
|
-
*/
|
|
29
|
-
captureBody?: boolean;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Enable console log forwarding as OTLP log records.
|
|
33
|
-
* @default
|
|
34
|
-
*/
|
|
35
|
-
logging?: boolean;
|
|
36
|
-
}
|
|
31
|
+
* Capture request bodies (POST/PUT/PATCH) on traced spans.
|
|
32
|
+
* Sensitive fields are automatically redacted.
|
|
33
|
+
* @default true from .securenow/credentials.json secure defaults
|
|
34
|
+
*/
|
|
35
|
+
captureBody?: boolean;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Enable console log forwarding as OTLP log records.
|
|
39
|
+
* @default true from .securenow/credentials.json secure defaults
|
|
40
|
+
*/
|
|
41
|
+
logging?: boolean;
|
|
42
|
+
}
|
|
37
43
|
|
|
38
44
|
declare module 'nuxt/schema' {
|
|
39
45
|
interface NuxtConfig {
|
package/package.json
CHANGED
package/postinstall.js
CHANGED
|
@@ -69,23 +69,17 @@ function hasInstrumentationFile() {
|
|
|
69
69
|
|
|
70
70
|
// Create TypeScript instrumentation file
|
|
71
71
|
function createTsInstrumentation(targetPath) {
|
|
72
|
-
const content = `import {
|
|
72
|
+
const content = `import { createRequire } from 'node:module';
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
registerSecureNow();
|
|
76
|
-
}
|
|
74
|
+
const require = createRequire(import.meta.url);
|
|
77
75
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
* SECURENOW_INSTANCE=http://your-otlp-backend:4318
|
|
86
|
-
* OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-key"
|
|
87
|
-
* OTEL_LOG_LEVEL=info
|
|
88
|
-
*/
|
|
76
|
+
export async function register() {
|
|
77
|
+
if (process.env.NEXT_RUNTIME !== 'nodejs') return;
|
|
78
|
+
|
|
79
|
+
const { registerSecureNow } = require('securenow/nextjs');
|
|
80
|
+
registerSecureNow({ captureBody: true });
|
|
81
|
+
require('securenow/nextjs-auto-capture');
|
|
82
|
+
}
|
|
89
83
|
`;
|
|
90
84
|
|
|
91
85
|
fs.writeFileSync(targetPath, content, 'utf8');
|
|
@@ -93,26 +87,17 @@ export function register() {
|
|
|
93
87
|
|
|
94
88
|
// Create JavaScript instrumentation file
|
|
95
89
|
function createJsInstrumentation(targetPath) {
|
|
96
|
-
const content = `
|
|
90
|
+
const content = `import { createRequire } from 'node:module';
|
|
97
91
|
|
|
98
|
-
|
|
99
|
-
registerSecureNow();
|
|
100
|
-
}
|
|
92
|
+
const require = createRequire(import.meta.url);
|
|
101
93
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
* SECURENOW_INSTANCE=http://your-otlp-backend:4318
|
|
110
|
-
* OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-key"
|
|
111
|
-
* OTEL_LOG_LEVEL=info
|
|
112
|
-
*
|
|
113
|
-
* Optional: Disable request body capture (enabled by default)
|
|
114
|
-
* SECURENOW_CAPTURE_BODY=0
|
|
115
|
-
*/
|
|
94
|
+
export async function register() {
|
|
95
|
+
if (process.env.NEXT_RUNTIME !== 'nodejs') return;
|
|
96
|
+
|
|
97
|
+
const { registerSecureNow } = require('securenow/nextjs');
|
|
98
|
+
registerSecureNow({ captureBody: true });
|
|
99
|
+
require('securenow/nextjs-auto-capture');
|
|
100
|
+
}
|
|
116
101
|
`;
|
|
117
102
|
|
|
118
103
|
fs.writeFileSync(targetPath, content, 'utf8');
|
|
@@ -133,12 +118,8 @@ export const config = {
|
|
|
133
118
|
/**
|
|
134
119
|
* Bodies are captured with:
|
|
135
120
|
* - Automatic redaction of passwords, tokens, cards, etc.
|
|
136
|
-
* - Size limits
|
|
121
|
+
* - Size limits from .securenow/credentials.json
|
|
137
122
|
* - JSON, GraphQL, Form data support
|
|
138
|
-
*
|
|
139
|
-
* Configure in .env.local:
|
|
140
|
-
* SECURENOW_MAX_BODY_SIZE=20480
|
|
141
|
-
* SECURENOW_SENSITIVE_FIELDS=email,phone
|
|
142
123
|
*/
|
|
143
124
|
`;
|
|
144
125
|
|
|
@@ -160,38 +141,24 @@ export const config = {
|
|
|
160
141
|
/**
|
|
161
142
|
* Bodies are captured with:
|
|
162
143
|
* - Automatic redaction of passwords, tokens, cards, etc.
|
|
163
|
-
* - Size limits
|
|
144
|
+
* - Size limits from .securenow/credentials.json
|
|
164
145
|
* - JSON, GraphQL, Form data support
|
|
165
|
-
*
|
|
166
|
-
* Configure in .env.local:
|
|
167
|
-
* SECURENOW_MAX_BODY_SIZE=20480
|
|
168
|
-
* SECURENOW_SENSITIVE_FIELDS=email,phone
|
|
169
146
|
*/
|
|
170
147
|
`;
|
|
171
148
|
|
|
172
149
|
fs.writeFileSync(targetPath, content, 'utf8');
|
|
173
150
|
}
|
|
174
151
|
|
|
175
|
-
// Create .
|
|
152
|
+
// Create a credentials-file reminder for old callers that still import this helper.
|
|
176
153
|
function createEnvTemplate(targetPath) {
|
|
177
|
-
const content =
|
|
178
|
-
# Required: Your application identifier
|
|
179
|
-
SECURENOW_APPID=my-nextjs-app
|
|
180
|
-
|
|
181
|
-
# Optional: Your OTLP-compatible backend / collector endpoint
|
|
182
|
-
# Default: https://freetrial.securenow.ai:4318
|
|
183
|
-
SECURENOW_INSTANCE=http://your-otlp-backend:4318
|
|
154
|
+
const content = `SecureNow no longer needs a .env file for local development.
|
|
184
155
|
|
|
185
|
-
|
|
186
|
-
|
|
156
|
+
Run:
|
|
157
|
+
npx securenow login
|
|
158
|
+
npx securenow init
|
|
187
159
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
# Optional: Disable request body capture (enabled by default)
|
|
192
|
-
# SECURENOW_CAPTURE_BODY=0
|
|
193
|
-
# SECURENOW_MAX_BODY_SIZE=10240
|
|
194
|
-
# SECURENOW_SENSITIVE_FIELDS=email,phone
|
|
160
|
+
The CLI writes .securenow/credentials.json with the selected app, firewall key,
|
|
161
|
+
secure defaults, and explanations for each setting.
|
|
195
162
|
`;
|
|
196
163
|
|
|
197
164
|
fs.writeFileSync(targetPath, content, 'utf8');
|
|
@@ -327,4 +294,3 @@ module.exports = { setup };
|
|
|
327
294
|
|
|
328
295
|
|
|
329
296
|
|
|
330
|
-
|
package/register.d.ts
CHANGED
|
@@ -6,27 +6,17 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* - SECURENOW_SENSITIVE_FIELDS=field1,field2 - Additional sensitive fields
|
|
21
|
-
* - SECURENOW_DISABLE_INSTRUMENTATIONS=pkg1,pkg2 - Disable specific instrumentations
|
|
22
|
-
* - OTEL_LOG_LEVEL=info|debug - Logging level
|
|
23
|
-
* - SECURENOW_TEST_SPAN=1 - Create test span on startup
|
|
24
|
-
*
|
|
25
|
-
* Alternative Environment Variables:
|
|
26
|
-
* - OTEL_SERVICE_NAME - Alternative to SECURENOW_APPID
|
|
27
|
-
* - OTEL_EXPORTER_OTLP_ENDPOINT - Alternative to SECURENOW_INSTANCE
|
|
28
|
-
* - OTEL_EXPORTER_OTLP_TRACES_ENDPOINT - Full traces URL
|
|
29
|
-
* - OTEL_EXPORTER_OTLP_HEADERS - Headers for OTLP exporter (k=v,k2=v2)
|
|
9
|
+
* Configuration:
|
|
10
|
+
*
|
|
11
|
+
* Local development reads .securenow/credentials.json. Run
|
|
12
|
+
* `npx securenow login` to choose/create an app, then `npx securenow init`
|
|
13
|
+
* to ensure secure defaults and explanations are present.
|
|
14
|
+
*
|
|
15
|
+
* Production uses the same file shape. Run
|
|
16
|
+
* `npx securenow credentials runtime --env production`, then mount/copy the
|
|
17
|
+
* generated JSON to .securenow/credentials.json in the running app.
|
|
18
|
+
*
|
|
19
|
+
* Legacy env vars are fallback-only for existing installs.
|
|
30
20
|
*/
|
|
31
21
|
|
|
32
22
|
// This module has side effects (initializes OpenTelemetry)
|
|
@@ -49,18 +39,14 @@ export {};
|
|
|
49
39
|
* @example
|
|
50
40
|
* ```javascript
|
|
51
41
|
* // ecosystem.config.js
|
|
52
|
-
* module.exports = {
|
|
53
|
-
* apps: [{
|
|
54
|
-
* name: 'my-app',
|
|
55
|
-
* script: './app.js',
|
|
56
|
-
* node_args: '-r securenow/register',
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* SECURENOW_CAPTURE_BODY: '1',
|
|
61
|
-
* }
|
|
62
|
-
* }]
|
|
63
|
-
* };
|
|
42
|
+
* module.exports = {
|
|
43
|
+
* apps: [{
|
|
44
|
+
* name: 'my-app',
|
|
45
|
+
* script: './app.js',
|
|
46
|
+
* node_args: '-r securenow/register',
|
|
47
|
+
* // Local and production use .securenow/credentials.json.
|
|
48
|
+
* }]
|
|
49
|
+
* };
|
|
64
50
|
* ```
|
|
65
51
|
*
|
|
66
52
|
* @example
|