securenow 7.5.1 → 7.6.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/CONSUMING-APPS-GUIDE.md +2 -0
- package/NPM_README.md +201 -237
- package/README.md +73 -26
- package/SKILL-API.md +205 -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 +211 -212
- package/cli/monitor.js +107 -43
- package/cli/security.js +24 -12
- package/cli/utils.js +2 -1
- package/cli.js +72 -40
- 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 +22 -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 +48 -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 = {}) {
|
|
@@ -139,13 +131,13 @@ function registerSecureNow(options = {}) {
|
|
|
139
131
|
|
|
140
132
|
// Detect environment outside try block for error handling
|
|
141
133
|
const isVercel = !!(env('VERCEL') || env('VERCEL_ENV') || env('VERCEL_URL'));
|
|
134
|
+
let deploymentEnvironment = appConfig.resolveDeploymentEnvironment();
|
|
142
135
|
|
|
143
136
|
try {
|
|
144
137
|
console.log('[securenow] Next.js integration loading (pid=%d)', process.pid);
|
|
145
138
|
|
|
146
139
|
// -------- Configuration --------
|
|
147
|
-
// Resolution order: explicit options
|
|
148
|
-
const appConfig = require('./app-config');
|
|
140
|
+
// Resolution order: explicit options -> .securenow/credentials.json -> legacy env fallback -> package.json#name
|
|
149
141
|
const resolvedApp = appConfig.resolveAll();
|
|
150
142
|
|
|
151
143
|
const rawBase = (options.serviceName || resolvedApp.appId || '').trim().replace(/^['"]|['"]$/g, '');
|
|
@@ -154,6 +146,9 @@ function registerSecureNow(options = {}) {
|
|
|
154
146
|
// and the dashboard does exact match). opts.noUuid or SECURENOW_NO_UUID
|
|
155
147
|
// override.
|
|
156
148
|
const noUuid = appConfig.resolveNoUuid({ noUuid: options.noUuid });
|
|
149
|
+
deploymentEnvironment = appConfig.normalizeDeploymentEnvironment(
|
|
150
|
+
options.environment || resolvedApp.deploymentEnvironment || env('VERCEL_ENV')
|
|
151
|
+
);
|
|
157
152
|
|
|
158
153
|
// service.name
|
|
159
154
|
let serviceName;
|
|
@@ -162,29 +157,25 @@ function registerSecureNow(options = {}) {
|
|
|
162
157
|
} else {
|
|
163
158
|
serviceName = `nextjs-app-${randomUUID()}`;
|
|
164
159
|
console.warn('[securenow] ⚠️ No app identity resolved. Using fallback: %s', serviceName);
|
|
165
|
-
console.warn('[securenow]
|
|
160
|
+
console.warn('[securenow] Run `npx securenow login` and `npx securenow init` to write .securenow/credentials.json');
|
|
166
161
|
}
|
|
167
162
|
|
|
168
163
|
// -------- 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`;
|
|
164
|
+
const resolvedEndpoints = appConfig.resolveEndpoints({ endpoint: options.endpoint || resolvedApp.instance });
|
|
165
|
+
const endpointBase = resolvedEndpoints.endpointBase;
|
|
166
|
+
const tracesUrl = resolvedEndpoints.tracesUrl;
|
|
167
|
+
const logsUrl = resolvedEndpoints.logsUrl;
|
|
168
|
+
const headers = resolvedEndpoints.headers;
|
|
179
169
|
|
|
180
170
|
if (!process.env.OTEL_SERVICE_NAME) process.env.OTEL_SERVICE_NAME = serviceName;
|
|
181
171
|
if (!process.env.OTEL_EXPORTER_OTLP_ENDPOINT) process.env.OTEL_EXPORTER_OTLP_ENDPOINT = endpointBase;
|
|
182
172
|
if (!process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT) process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = tracesUrl;
|
|
183
173
|
|
|
184
|
-
console.log('[securenow]
|
|
174
|
+
console.log('[securenow] Next.js App -> service.name=%s', serviceName);
|
|
175
|
+
console.log('[securenow] Environment: %s', deploymentEnvironment);
|
|
185
176
|
|
|
186
177
|
// -------- Body Capture Configuration --------
|
|
187
|
-
// Opt-out default: set
|
|
178
|
+
// Opt-out default: set config.capture.body=false (or options.captureBody=false) to disable.
|
|
188
179
|
const captureBody = options.captureBody ?? !/^(0|false)$/i.test(String(env('SECURENOW_CAPTURE_BODY') ?? ''));
|
|
189
180
|
const maxBodySize = Math.max(1024, parseInt(env('SECURENOW_MAX_BODY_SIZE'), 10) || 10240);
|
|
190
181
|
const customSensitiveFields = (env('SECURENOW_SENSITIVE_FIELDS') || '').split(',').map(s => s.trim()).filter(Boolean);
|
|
@@ -413,7 +404,7 @@ function registerSecureNow(options = {}) {
|
|
|
413
404
|
registerOTel({
|
|
414
405
|
serviceName: serviceName,
|
|
415
406
|
attributes: {
|
|
416
|
-
'deployment.environment':
|
|
407
|
+
'deployment.environment': deploymentEnvironment,
|
|
417
408
|
'service.version': process.env.npm_package_version || process.env.VERCEL_GIT_COMMIT_SHA || undefined,
|
|
418
409
|
'vercel.region': process.env.VERCEL_REGION || undefined,
|
|
419
410
|
},
|
|
@@ -444,7 +435,7 @@ function registerSecureNow(options = {}) {
|
|
|
444
435
|
|
|
445
436
|
const traceExporter = new OTLPTraceExporter({
|
|
446
437
|
url: tracesUrl,
|
|
447
|
-
|
|
438
|
+
headers
|
|
448
439
|
});
|
|
449
440
|
|
|
450
441
|
const sdk = new NodeSDK({
|
|
@@ -453,7 +444,7 @@ function registerSecureNow(options = {}) {
|
|
|
453
444
|
instrumentations: [httpInstrumentation],
|
|
454
445
|
resource: new Resource({
|
|
455
446
|
[SemanticResourceAttributes.SERVICE_NAME]: serviceName,
|
|
456
|
-
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]:
|
|
447
|
+
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: deploymentEnvironment,
|
|
457
448
|
[SemanticResourceAttributes.SERVICE_VERSION]: process.env.npm_package_version || undefined,
|
|
458
449
|
}),
|
|
459
450
|
});
|
|
@@ -462,7 +453,7 @@ function registerSecureNow(options = {}) {
|
|
|
462
453
|
console.log('[securenow] 🎯 Vanilla SDK initialized for self-hosted environment');
|
|
463
454
|
|
|
464
455
|
// -------- Logging (self-hosted only) --------
|
|
465
|
-
// Opt-out default: set
|
|
456
|
+
// Opt-out default: set config.logging.enabled=false to disable.
|
|
466
457
|
const loggingEnabled = !/^(0|false)$/i.test(String(env('SECURENOW_LOGGING_ENABLED') ?? ''));
|
|
467
458
|
if (loggingEnabled) {
|
|
468
459
|
try {
|
|
@@ -471,13 +462,13 @@ function registerSecureNow(options = {}) {
|
|
|
471
462
|
|
|
472
463
|
const logExporter = new OTLPLogExporter({
|
|
473
464
|
url: logsUrl,
|
|
474
|
-
headers
|
|
465
|
+
headers,
|
|
475
466
|
});
|
|
476
467
|
|
|
477
468
|
const loggerProvider = new LoggerProvider({
|
|
478
469
|
resource: new Resource({
|
|
479
470
|
[SemanticResourceAttributes.SERVICE_NAME]: serviceName,
|
|
480
|
-
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]:
|
|
471
|
+
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: deploymentEnvironment,
|
|
481
472
|
}),
|
|
482
473
|
});
|
|
483
474
|
loggerProvider.addLogRecordProcessor(new BatchLogRecordProcessor(logExporter));
|
|
@@ -614,25 +605,28 @@ function registerSecureNow(options = {}) {
|
|
|
614
605
|
}
|
|
615
606
|
|
|
616
607
|
// 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') {
|
|
608
|
+
// Key and environment come from .securenow/credentials.json (written by
|
|
609
|
+
// login/init or credentials runtime), so no .env entry is needed.
|
|
610
|
+
const firewallOptions = appConfig.resolveFirewallOptions();
|
|
611
|
+
if (firewallOptions.apiKey && firewallOptions.enabled) {
|
|
623
612
|
try {
|
|
624
613
|
require('./firewall').init({
|
|
625
|
-
apiKey:
|
|
626
|
-
appKey:
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
614
|
+
apiKey: firewallOptions.apiKey,
|
|
615
|
+
appKey: firewallOptions.appKey,
|
|
616
|
+
environment: deploymentEnvironment || firewallOptions.environment,
|
|
617
|
+
apiUrl: firewallOptions.apiUrl,
|
|
618
|
+
versionCheckInterval: firewallOptions.versionCheckInterval,
|
|
619
|
+
syncInterval: firewallOptions.syncInterval,
|
|
620
|
+
failMode: firewallOptions.failMode,
|
|
621
|
+
statusCode: firewallOptions.statusCode,
|
|
622
|
+
log: firewallOptions.log,
|
|
623
|
+
tcp: firewallOptions.tcp,
|
|
624
|
+
iptables: firewallOptions.iptables,
|
|
625
|
+
cloud: firewallOptions.cloud,
|
|
626
|
+
cloudDryRun: firewallOptions.cloudDryRun,
|
|
627
|
+
cloudflare: firewallOptions.cloudflare,
|
|
628
|
+
aws: firewallOptions.aws,
|
|
629
|
+
gcp: firewallOptions.gcp,
|
|
636
630
|
});
|
|
637
631
|
} catch (e) {
|
|
638
632
|
console.warn('[securenow] Firewall init failed:', e.message);
|
|
@@ -643,4 +637,3 @@ function registerSecureNow(options = {}) {
|
|
|
643
637
|
module.exports = {
|
|
644
638
|
registerSecureNow,
|
|
645
639
|
};
|
|
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
|