securenow 7.7.14 → 7.7.16
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/NPM_README.md +65 -121
- package/README.md +19 -24
- package/SKILL-API.md +491 -490
- package/SKILL-CLI.md +8 -8
- package/app-config.js +146 -43
- package/cli/apps.js +589 -597
- package/cli/auth.js +1 -3
- package/cli/config.js +37 -9
- package/cli/credentials.js +1 -1
- package/cli/diagnostics.js +40 -10
- package/cli/init.js +1 -0
- package/firewall-only.js +1 -0
- package/firewall.js +62 -10
- package/free-trial-banner.js +2 -2
- package/mcp/catalog.js +2 -2
- package/nextjs.d.ts +67 -63
- package/nextjs.js +93 -52
- package/nuxt-server-plugin.mjs +7 -11
- package/nuxt.d.ts +42 -38
- package/nuxt.mjs +1 -1
- package/package.json +1 -1
- package/tracing.d.ts +2 -1
- package/tracing.js +75 -57
- package/web-vite.mjs +105 -15
package/SKILL-CLI.md
CHANGED
|
@@ -35,13 +35,13 @@ securenow login --token <JWT> # headless / CI login (get token from dashboard
|
|
|
35
35
|
securenow whoami # verify session (shows email, app, auth source)
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
**Zero-config flow (v7+):** the browser step lets the user pick (or create) an app. The CLI stores the app's **key (UUID)
|
|
38
|
+
**Zero-config flow (v7+):** the browser step lets the user pick (or create) an app. The CLI stores the app's **key (UUID)** and **name** in `.securenow/credentials.json`. The SDK sends traces/logs to the default SecureNow ingestion gateway, which routes by app key — **no env vars or per-instance collector URLs required for local dev or production**.
|
|
39
39
|
|
|
40
40
|
**Default-on security (v7.5.1+):** after picking or creating the app, `securenow login` turns on that app's firewall toggle, mints an API key with `firewall:read + blocklist:read + allowlist:read` scopes, and writes it into `.securenow/credentials.json`. Traces, logs, POST body capture, multipart metadata capture, and the firewall are enabled by default. No `SECURENOW_API_KEY` env var is needed. To add or rotate a key later without re-running login, use `securenow api-key set snk_live_...` (see [API Key Management](#api-key-management) below).
|
|
41
41
|
|
|
42
|
-
Credentials resolve in order: project `.securenow/credentials.json` -> project named runtime credentials in the fixed staging/production/preview/local/test/development/dev/prod order -> global `~/.securenow/credentials.json` -> global named runtime credentials in the same fixed order.
|
|
42
|
+
Credentials resolve in order: project `.securenow/credentials.json` -> project named runtime credentials in the fixed staging/production/preview/local/test/development/dev/prod order -> global `~/.securenow/credentials.json` -> global named runtime credentials in the same fixed order. Runtime config is credentials-json based; legacy env fallbacks are disabled unless `SECURENOW_ENABLE_LEGACY_ENV=1` is set and never choose the credentials filename.
|
|
43
43
|
|
|
44
|
-
The **firewall API key** should live in the same credentials file as `apiKey`.
|
|
44
|
+
The **firewall API key** should live in the same credentials file as `apiKey`.
|
|
45
45
|
|
|
46
46
|
For CI / Docker / production, use `securenow credentials runtime --env production` to generate a tokenless runtime file, then mount/copy it as `.securenow/credentials.json`. Since v7.7.2, mounting the generated `.securenow/credentials.production.json` filename directly also works when `credentials.json` is absent.
|
|
47
47
|
|
|
@@ -83,7 +83,7 @@ Config lives in `~/.securenow/` (global) and optionally `.securenow/` (per-proje
|
|
|
83
83
|
| `.securenow/credentials.json` | `token`, `email`, `expiresAt`, `apiKey`, `app`, `config`, `_securenow.explanations` (project-local default) |
|
|
84
84
|
| `.securenow/credentials.<environment>.json` | Tokenless runtime credentials generated by `securenow credentials runtime --env <environment>`; read in a fixed order, not selected from env vars |
|
|
85
85
|
|
|
86
|
-
**Credential resolution order:** `.securenow/credentials.json` (project) -> project named runtime credentials in the fixed staging/production/preview/local/test/development/dev/prod order -> `~/.securenow/credentials.json` (global) -> global named runtime credentials in the same fixed order. Legacy env
|
|
86
|
+
**Credential resolution order:** `.securenow/credentials.json` (project) -> project named runtime credentials in the fixed staging/production/preview/local/test/development/dev/prod order -> `~/.securenow/credentials.json` (global) -> global named runtime credentials in the same fixed order. Legacy env fallbacks are disabled unless `SECURENOW_ENABLE_LEGACY_ENV=1` is set.
|
|
87
87
|
|
|
88
88
|
**Firewall API key resolution (v7.5.1+):** project `.securenow/credentials.json` -> project named runtime credentials in the fixed staging/production/preview/local/test/development/dev/prod order -> global `~/.securenow/credentials.json` -> global named runtime credentials in the same fixed order. Use `securenow login` for default setup or `securenow api-key set` to rotate a key without touching env vars.
|
|
89
89
|
|
|
@@ -95,7 +95,7 @@ securenow config get defaultApp # show one
|
|
|
95
95
|
securenow config path # print file paths + active auth source
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
Legacy CLI overrides still exist for
|
|
98
|
+
Legacy CLI overrides still exist for operator automation, but runtime SDK config should stay in the credentials file.
|
|
99
99
|
|
|
100
100
|
## Global Flags
|
|
101
101
|
|
|
@@ -172,7 +172,7 @@ securenow init [--env local] [--key <API_KEY>]
|
|
|
172
172
|
```
|
|
173
173
|
|
|
174
174
|
Auto-detects framework (Next.js, Nuxt, Express, Fastify, Koa, Hapi, Node) from `package.json`. Then:
|
|
175
|
-
- **Credentials**: ensures `.securenow/credentials.json` exists, has secure defaults/explanations, and `.securenow/`
|
|
175
|
+
- **Credentials**: ensures `.securenow/credentials.json` exists, has secure defaults/explanations, and local credential JSON files are gitignored without ignoring the whole `.securenow/` directory
|
|
176
176
|
- **Next.js**: creates `instrumentation.ts/js` with `securenow/nextjs` + `securenow/nextjs-auto-capture`, and adds `serverExternalPackages: ['securenow']` plus `outputFileTracingIncludes` when the config can be patched safely
|
|
177
177
|
- **Existing Next.js files**: prints a Codex/Claude-ready merge prompt when instrumentation or config already exists or is too custom to safely patch
|
|
178
178
|
- **Nuxt**: tells you to add `securenow/nuxt` to modules
|
|
@@ -473,7 +473,7 @@ securenow test-span
|
|
|
473
473
|
securenow test-span "ci.smoke-test" # custom span name
|
|
474
474
|
```
|
|
475
475
|
|
|
476
|
-
Both commands use the
|
|
476
|
+
Both commands use the default SecureNow ingestion gateway plus optional advanced `config.otel.*` overrides from `.securenow/credentials.json`, and return non-zero on HTTP errors so CI/cron can detect failures.
|
|
477
477
|
|
|
478
478
|
### Utilities — Redaction, CIDR, Diagnostics
|
|
479
479
|
|
|
@@ -497,7 +497,7 @@ securenow doctor # exits 0 if healthy, 1 otherwise
|
|
|
497
497
|
securenow doctor --json
|
|
498
498
|
```
|
|
499
499
|
|
|
500
|
-
The `redact` command accepts a JSON string or `@path/to/file.json
|
|
500
|
+
The `redact` command accepts a JSON string or `@path/to/file.json` and layers your `--fields` flag on top of `DEFAULT_SENSITIVE_FIELDS`. Exit code from `cidr match` is `0` if the IP matches the list, `2` otherwise — scriptable.
|
|
501
501
|
|
|
502
502
|
---
|
|
503
503
|
|
package/app-config.js
CHANGED
|
@@ -8,17 +8,19 @@
|
|
|
8
8
|
* ./.securenow/credentials.production.json are also accepted when the
|
|
9
9
|
* canonical file is not present. Filename selection is deterministic and does
|
|
10
10
|
* not read environment variables.
|
|
11
|
-
* Legacy environment
|
|
12
|
-
*
|
|
13
|
-
* files.
|
|
11
|
+
* Legacy environment fallbacks are disabled by default; every SDK setting has
|
|
12
|
+
* a file-backed equivalent so customers do not need .env files.
|
|
14
13
|
*/
|
|
15
14
|
|
|
16
15
|
const fs = require('fs');
|
|
17
16
|
const path = require('path');
|
|
18
17
|
const os = require('os');
|
|
19
18
|
|
|
20
|
-
const FREE_TRIAL_INSTANCE = 'https://
|
|
19
|
+
const FREE_TRIAL_INSTANCE = 'https://ingest.securenow.ai';
|
|
21
20
|
const DEFAULT_API_URL = 'https://api.securenow.ai';
|
|
21
|
+
const DEFAULT_FIREWALL_API_URL = FREE_TRIAL_INSTANCE;
|
|
22
|
+
const LEGACY_SECURENOW_GATEWAY = 'https://api.securenow.ai/api/otlp';
|
|
23
|
+
const LEGACY_ENV_FALLBACK_FLAG = 'SECURENOW_ENABLE_LEGACY_ENV';
|
|
22
24
|
const CONFIG_SCHEMA_VERSION = 2;
|
|
23
25
|
const CREDENTIAL_FILE_ENVIRONMENTS = Object.freeze([
|
|
24
26
|
'staging',
|
|
@@ -92,13 +94,13 @@ const CONFIG_EXPLANATIONS = Object.freeze({
|
|
|
92
94
|
'apiKey': 'Scoped firewall API key (`snk_live_...`) minted by login or `securenow api-key set`. Secret: do not commit.',
|
|
93
95
|
'app.key': 'SecureNow application routing UUID. The SDK uses this as OTel service.name so dashboard queries match exactly.',
|
|
94
96
|
'app.name': 'Human-readable app label shown in CLI output.',
|
|
95
|
-
'app.
|
|
97
|
+
'app.routing': 'Telemetry uses the default SecureNow ingestion gateway and routes by app.key; runtime credentials do not expose per-instance collector URLs.',
|
|
96
98
|
'config.logging.enabled': 'Secure default: console log forwarding is on. Set false to disable OTLP logs.',
|
|
97
99
|
'config.capture.body': 'Secure default: JSON, GraphQL, and form request bodies are captured with redaction.',
|
|
98
100
|
'config.capture.multipart': 'Secure default: multipart text fields and file metadata are captured. File content is never buffered.',
|
|
99
101
|
'config.capture.maxBodySize': 'Maximum body bytes captured per request. Default 10KB limits memory and sensitive data exposure.',
|
|
100
102
|
'config.capture.sensitiveFields': 'Extra field-name fragments to redact in addition to SecureNow built-ins.',
|
|
101
|
-
'config.otel.endpoint': 'Optional OTLP base endpoint override
|
|
103
|
+
'config.otel.endpoint': 'Optional OTLP base endpoint override for advanced/self-hosted collectors. Leave null for the SecureNow ingestion gateway.',
|
|
102
104
|
'config.otel.tracesEndpoint': 'Optional full traces endpoint override, for split collectors.',
|
|
103
105
|
'config.otel.logsEndpoint': 'Optional full logs endpoint override, for split collectors.',
|
|
104
106
|
'config.otel.headers': 'Optional OTLP headers. The SDK auto-adds x-api-key from app.key when missing.',
|
|
@@ -110,7 +112,7 @@ const CONFIG_EXPLANATIONS = Object.freeze({
|
|
|
110
112
|
'config.runtime.testSpan': 'If true, emit a startup smoke span. Prefer `npx securenow test-span` for manual checks.',
|
|
111
113
|
'config.runtime.hideBanner': 'Hide the free-trial response banner when using the managed free-trial collector.',
|
|
112
114
|
'config.firewall.enabled': 'Secure default: app firewall enforcement starts when apiKey is present and the dashboard toggle is on.',
|
|
113
|
-
'config.firewall.apiUrl': 'SecureNow
|
|
115
|
+
'config.firewall.apiUrl': 'Optional SecureNow firewall control-plane base URL. Leave unset/default so hosted SDKs sync through the SecureNow ingest gateway.',
|
|
114
116
|
'config.firewall.versionCheckInterval': 'Seconds between lightweight firewall version/ETag checks.',
|
|
115
117
|
'config.firewall.syncInterval': 'Seconds between safety-net full firewall blocklist syncs.',
|
|
116
118
|
'config.firewall.failMode': 'open allows traffic if SecureNow is temporarily unreachable; closed blocks all on sync failure.',
|
|
@@ -392,11 +394,14 @@ function mergeCredentials(globalCredentials, localCredentials) {
|
|
|
392
394
|
function withCredentialDefaults(credentials) {
|
|
393
395
|
if (!credentials || typeof credentials !== 'object') return null;
|
|
394
396
|
const out = clone(credentials);
|
|
397
|
+
if (out.app && typeof out.app === 'object' && !Array.isArray(out.app)) {
|
|
398
|
+
delete out.app.instance;
|
|
399
|
+
}
|
|
395
400
|
out.config = mergeMissing(out.config, DEFAULT_CONFIG);
|
|
396
401
|
out._securenow = mergeMissing(out._securenow, {
|
|
397
402
|
schemaVersion: CONFIG_SCHEMA_VERSION,
|
|
398
403
|
note: 'Local SecureNow credentials and secure SDK defaults. This file may contain secrets; keep .securenow/ in .gitignore.',
|
|
399
|
-
precedence:
|
|
404
|
+
precedence: `The same credentials file works in local development and production. SDK runtime config is read from credentials JSON. Legacy environment fallbacks are disabled unless ${LEGACY_ENV_FALLBACK_FLAG}=1 is set.`,
|
|
400
405
|
explanations: CONFIG_EXPLANATIONS,
|
|
401
406
|
});
|
|
402
407
|
return out;
|
|
@@ -412,10 +417,82 @@ function getPath(obj, dotted) {
|
|
|
412
417
|
return cur;
|
|
413
418
|
}
|
|
414
419
|
|
|
420
|
+
function legacyEnvFallbackEnabled() {
|
|
421
|
+
const raw =
|
|
422
|
+
process.env[LEGACY_ENV_FALLBACK_FLAG] ??
|
|
423
|
+
process.env.SECURENOW_ALLOW_ENV_CONFIG ??
|
|
424
|
+
process.env.SECURENOW_LEGACY_ENV;
|
|
425
|
+
return /^(1|true|yes)$/i.test(String(raw || '').trim());
|
|
426
|
+
}
|
|
427
|
+
|
|
415
428
|
function rawEnv(key) {
|
|
429
|
+
if (!legacyEnvFallbackEnabled()) return undefined;
|
|
416
430
|
return process.env[key] ?? process.env[key.toUpperCase()] ?? process.env[key.toLowerCase()];
|
|
417
431
|
}
|
|
418
432
|
|
|
433
|
+
function normalizeInstanceEndpoint(value) {
|
|
434
|
+
if (value === undefined || value === null || value === '') return value;
|
|
435
|
+
const endpoint = String(value).trim().replace(/\/$/, '');
|
|
436
|
+
if (!endpoint) return endpoint;
|
|
437
|
+
if (endpoint === LEGACY_SECURENOW_GATEWAY) return FREE_TRIAL_INSTANCE;
|
|
438
|
+
|
|
439
|
+
try {
|
|
440
|
+
const parseable = /^[a-z][a-z0-9+.-]*:\/\//i.test(endpoint) ? endpoint : `https://${endpoint}`;
|
|
441
|
+
const url = new URL(parseable);
|
|
442
|
+
if (url.port === '4318' && url.hostname.toLowerCase().endsWith('.securenow.ai')) {
|
|
443
|
+
return FREE_TRIAL_INSTANCE;
|
|
444
|
+
}
|
|
445
|
+
} catch {}
|
|
446
|
+
|
|
447
|
+
return endpoint;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
function normalizeSignalEndpoint(value, signalType) {
|
|
451
|
+
if (value === undefined || value === null || value === '') return value;
|
|
452
|
+
const endpoint = String(value).trim().replace(/\/$/, '');
|
|
453
|
+
const signalPath = `/v1/${signalType}`;
|
|
454
|
+
if (endpoint.endsWith(signalPath)) {
|
|
455
|
+
const base = normalizeInstanceEndpoint(endpoint.slice(0, -signalPath.length));
|
|
456
|
+
return `${base}${signalPath}`;
|
|
457
|
+
}
|
|
458
|
+
return endpoint;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
function normalizeFirewallApiUrl(value) {
|
|
462
|
+
const raw = pick(value);
|
|
463
|
+
if (raw == null) return DEFAULT_FIREWALL_API_URL;
|
|
464
|
+
const endpoint = normalizeInstanceEndpoint(raw);
|
|
465
|
+
if (!endpoint) return DEFAULT_FIREWALL_API_URL;
|
|
466
|
+
const trimmed = String(endpoint).trim().replace(/\/$/, '').replace(/\/api(?:\/v1)?$/i, '');
|
|
467
|
+
|
|
468
|
+
// api.securenow.ai was the historical SDK default. Hosted runtime sync now
|
|
469
|
+
// shares the ingest gateway so telemetry and firewall state fail or recover
|
|
470
|
+
// together, and so customer apps need only one public SecureNow egress host.
|
|
471
|
+
if (trimmed === DEFAULT_API_URL || trimmed === LEGACY_SECURENOW_GATEWAY) {
|
|
472
|
+
return DEFAULT_FIREWALL_API_URL;
|
|
473
|
+
}
|
|
474
|
+
if (trimmed === DEFAULT_FIREWALL_API_URL) return DEFAULT_FIREWALL_API_URL;
|
|
475
|
+
|
|
476
|
+
return trimmed;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
function resolveFirewallApiUrl() {
|
|
480
|
+
return normalizeFirewallApiUrl(configValue('firewall.apiUrl', DEFAULT_API_URL));
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
function resolveFirewallApiFallbacks(primary = resolveFirewallApiUrl()) {
|
|
484
|
+
const normalizedPrimary = normalizeFirewallApiUrl(primary);
|
|
485
|
+
const fallbacks = [];
|
|
486
|
+
|
|
487
|
+
if (normalizedPrimary === DEFAULT_FIREWALL_API_URL) {
|
|
488
|
+
fallbacks.push(DEFAULT_API_URL);
|
|
489
|
+
} else if (normalizedPrimary === DEFAULT_API_URL) {
|
|
490
|
+
fallbacks.push(DEFAULT_FIREWALL_API_URL);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
return uniq(fallbacks.filter((url) => url && url !== normalizedPrimary));
|
|
494
|
+
}
|
|
495
|
+
|
|
419
496
|
function pick(value) {
|
|
420
497
|
if (value === undefined || value === null) return null;
|
|
421
498
|
if (typeof value === 'string') {
|
|
@@ -514,6 +591,22 @@ function resolveConfigPath(configPath, envKeys = [], fallback) {
|
|
|
514
591
|
return fallback;
|
|
515
592
|
}
|
|
516
593
|
|
|
594
|
+
function configValue(configPath, fallback) {
|
|
595
|
+
return resolveConfigPath(configPath, [], fallback);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
function boolConfig(configPath, fallback = false) {
|
|
599
|
+
return parseBool(configValue(configPath), fallback);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
function numberConfig(configPath, fallback, min) {
|
|
603
|
+
return parseNumber(configValue(configPath), fallback, min);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
function listConfig(configPath) {
|
|
607
|
+
return parseList(configValue(configPath));
|
|
608
|
+
}
|
|
609
|
+
|
|
517
610
|
function resolveAppKey() {
|
|
518
611
|
const creds = loadCredentials();
|
|
519
612
|
if (creds && creds.app && pick(creds.app.key)) return String(pick(creds.app.key));
|
|
@@ -559,18 +652,13 @@ function resolveApiKey() {
|
|
|
559
652
|
|
|
560
653
|
function resolveInstance() {
|
|
561
654
|
const fromConfig = pick(resolveConfigPath('otel.endpoint'));
|
|
562
|
-
if (fromConfig) return
|
|
563
|
-
|
|
564
|
-
const creds = loadCredentials();
|
|
565
|
-
if (creds && creds.app && pick(creds.app.instance)) {
|
|
566
|
-
return String(pick(creds.app.instance)).replace(/\/$/, '');
|
|
567
|
-
}
|
|
655
|
+
if (fromConfig) return normalizeInstanceEndpoint(fromConfig);
|
|
568
656
|
|
|
569
657
|
const fromEnv =
|
|
570
658
|
pick(rawEnv('SECURENOW_INSTANCE')) ||
|
|
571
659
|
pick(rawEnv('securenow_instance')) ||
|
|
572
660
|
pick(rawEnv('OTEL_EXPORTER_OTLP_ENDPOINT'));
|
|
573
|
-
if (fromEnv) return
|
|
661
|
+
if (fromEnv) return normalizeInstanceEndpoint(fromEnv);
|
|
574
662
|
|
|
575
663
|
return FREE_TRIAL_INSTANCE;
|
|
576
664
|
}
|
|
@@ -587,13 +675,7 @@ function resolveAll() {
|
|
|
587
675
|
}
|
|
588
676
|
|
|
589
677
|
function resolveDeploymentEnvironment() {
|
|
590
|
-
return normalizeDeploymentEnvironment(
|
|
591
|
-
resolveConfigPath('runtime.deploymentEnvironment', [
|
|
592
|
-
'SECURENOW_ENVIRONMENT',
|
|
593
|
-
'SECURENOW_DEPLOYMENT_ENVIRONMENT',
|
|
594
|
-
'NODE_ENV',
|
|
595
|
-
])
|
|
596
|
-
);
|
|
678
|
+
return normalizeDeploymentEnvironment(resolveConfigPath('runtime.deploymentEnvironment'));
|
|
597
679
|
}
|
|
598
680
|
|
|
599
681
|
function resolveNoUuid(opts = {}) {
|
|
@@ -643,11 +725,15 @@ function listEnv(key) {
|
|
|
643
725
|
}
|
|
644
726
|
|
|
645
727
|
function resolveOtlpHeaders() {
|
|
646
|
-
const headers = parseHeaders(
|
|
728
|
+
const headers = parseHeaders(configValue('otel.headers', {}));
|
|
647
729
|
const appKey = resolveAppKey();
|
|
648
730
|
if (appKey && !headers['x-api-key']) {
|
|
649
731
|
headers['x-api-key'] = appKey;
|
|
650
732
|
}
|
|
733
|
+
const deploymentEnvironment = resolveDeploymentEnvironment();
|
|
734
|
+
if (deploymentEnvironment && !headers['x-securenow-environment']) {
|
|
735
|
+
headers['x-securenow-environment'] = deploymentEnvironment;
|
|
736
|
+
}
|
|
651
737
|
return headers;
|
|
652
738
|
}
|
|
653
739
|
|
|
@@ -656,11 +742,13 @@ function resolveOtlpHeaderString() {
|
|
|
656
742
|
}
|
|
657
743
|
|
|
658
744
|
function resolveEndpoints(options = {}) {
|
|
659
|
-
const endpointBase = String(options.endpoint || resolveInstance()).replace(/\/$/, '');
|
|
745
|
+
const endpointBase = String(normalizeInstanceEndpoint(options.endpoint || resolveInstance())).replace(/\/$/, '');
|
|
746
|
+
const tracesOverride = configValue('otel.tracesEndpoint');
|
|
747
|
+
const logsOverride = configValue('otel.logsEndpoint');
|
|
660
748
|
return {
|
|
661
749
|
endpointBase,
|
|
662
|
-
tracesUrl:
|
|
663
|
-
logsUrl:
|
|
750
|
+
tracesUrl: normalizeSignalEndpoint(tracesOverride, 'traces') || `${endpointBase}/v1/traces`,
|
|
751
|
+
logsUrl: normalizeSignalEndpoint(logsOverride, 'logs') || `${endpointBase}/v1/logs`,
|
|
664
752
|
headers: resolveOtlpHeaders(),
|
|
665
753
|
};
|
|
666
754
|
}
|
|
@@ -673,33 +761,35 @@ function resolveFirewallEnabled() {
|
|
|
673
761
|
}
|
|
674
762
|
|
|
675
763
|
function resolveFirewallOptions() {
|
|
764
|
+
const apiUrl = resolveFirewallApiUrl();
|
|
676
765
|
return {
|
|
677
766
|
apiKey: resolveApiKey(),
|
|
678
767
|
appKey: resolveAppKey() || null,
|
|
679
768
|
environment: resolveDeploymentEnvironment(),
|
|
680
769
|
enabled: resolveFirewallEnabled(),
|
|
681
|
-
apiUrl
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
770
|
+
apiUrl,
|
|
771
|
+
apiUrlFallbacks: resolveFirewallApiFallbacks(apiUrl),
|
|
772
|
+
versionCheckInterval: numberConfig('firewall.versionCheckInterval', 10, 1),
|
|
773
|
+
syncInterval: numberConfig('firewall.syncInterval', 3600, 1),
|
|
774
|
+
failMode: configValue('firewall.failMode', 'open') || 'open',
|
|
775
|
+
statusCode: numberConfig('firewall.statusCode', 403, 100),
|
|
776
|
+
log: boolConfig('firewall.log', true),
|
|
777
|
+
tcp: boolConfig('firewall.tcp', false),
|
|
778
|
+
iptables: boolConfig('firewall.iptables', false),
|
|
779
|
+
cloud: configValue('firewall.cloud', null) || null,
|
|
780
|
+
cloudDryRun: boolConfig('firewall.cloudDryRun', false),
|
|
691
781
|
cloudflare: {
|
|
692
|
-
apiToken:
|
|
693
|
-
accountId:
|
|
782
|
+
apiToken: resolveConfigPath('firewall.cloudflare.apiToken', [], null) || null,
|
|
783
|
+
accountId: resolveConfigPath('firewall.cloudflare.accountId', [], null) || null,
|
|
694
784
|
},
|
|
695
785
|
aws: {
|
|
696
|
-
wafIpSetId:
|
|
697
|
-
wafIpSetName:
|
|
698
|
-
wafScope:
|
|
786
|
+
wafIpSetId: resolveConfigPath('firewall.aws.wafIpSetId', [], null) || null,
|
|
787
|
+
wafIpSetName: resolveConfigPath('firewall.aws.wafIpSetName', [], 'securenow-blocklist') || 'securenow-blocklist',
|
|
788
|
+
wafScope: resolveConfigPath('firewall.aws.wafScope', [], 'REGIONAL') || 'REGIONAL',
|
|
699
789
|
},
|
|
700
790
|
gcp: {
|
|
701
|
-
projectId:
|
|
702
|
-
securityPolicy:
|
|
791
|
+
projectId: resolveConfigPath('firewall.gcp.projectId', [], null) || null,
|
|
792
|
+
securityPolicy: resolveConfigPath('firewall.gcp.securityPolicy', [], null) || null,
|
|
703
793
|
},
|
|
704
794
|
};
|
|
705
795
|
}
|
|
@@ -707,6 +797,9 @@ function resolveFirewallOptions() {
|
|
|
707
797
|
module.exports = {
|
|
708
798
|
FREE_TRIAL_INSTANCE,
|
|
709
799
|
DEFAULT_API_URL,
|
|
800
|
+
DEFAULT_FIREWALL_API_URL,
|
|
801
|
+
LEGACY_SECURENOW_GATEWAY,
|
|
802
|
+
LEGACY_ENV_FALLBACK_FLAG,
|
|
710
803
|
CONFIG_SCHEMA_VERSION,
|
|
711
804
|
CREDENTIAL_FILE_ENVIRONMENTS,
|
|
712
805
|
DEFAULT_CONFIG,
|
|
@@ -715,12 +808,17 @@ module.exports = {
|
|
|
715
808
|
withCredentialDefaults,
|
|
716
809
|
mergeCredentials,
|
|
717
810
|
resolveConfigPath,
|
|
811
|
+
configValue,
|
|
812
|
+
boolConfig,
|
|
813
|
+
numberConfig,
|
|
814
|
+
listConfig,
|
|
718
815
|
resolveAppKey,
|
|
719
816
|
resolveAppName,
|
|
720
817
|
resolveAppId,
|
|
721
818
|
resolveApiKey,
|
|
722
819
|
resolveInstance,
|
|
723
820
|
normalizeDeploymentEnvironment,
|
|
821
|
+
legacyEnvFallbackEnabled,
|
|
724
822
|
resolveDeploymentEnvironment,
|
|
725
823
|
resolveAll,
|
|
726
824
|
resolveNoUuid,
|
|
@@ -728,12 +826,17 @@ module.exports = {
|
|
|
728
826
|
resolveOtlpHeaderString,
|
|
729
827
|
resolveEndpoints,
|
|
730
828
|
resolveFirewallEnabled,
|
|
829
|
+
normalizeFirewallApiUrl,
|
|
830
|
+
resolveFirewallApiUrl,
|
|
831
|
+
resolveFirewallApiFallbacks,
|
|
731
832
|
resolveFirewallOptions,
|
|
732
833
|
env,
|
|
733
834
|
boolEnv,
|
|
734
835
|
numberEnv,
|
|
735
836
|
listEnv,
|
|
736
837
|
parseHeaders,
|
|
838
|
+
normalizeInstanceEndpoint,
|
|
839
|
+
normalizeSignalEndpoint,
|
|
737
840
|
headersToString,
|
|
738
841
|
credentialRelativePaths,
|
|
739
842
|
resolveLocalCredentialsFile,
|