@empire-builder-kit/nx 1.0.0-rc.30 → 1.0.0-rc.32
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/executors.json +8 -3
- package/package.json +14 -7
- package/src/aws/child-environment.d.ts +10 -0
- package/src/aws/child-environment.js +77 -0
- package/src/aws/child-environment.js.map +1 -0
- package/src/aws/identity.d.ts +13 -0
- package/src/aws/identity.js +41 -0
- package/src/aws/identity.js.map +1 -0
- package/src/aws-authority/index.d.ts +1 -0
- package/src/aws-authority/index.js +5 -0
- package/src/aws-authority/index.js.map +1 -0
- package/src/aws-authority/stage-authority.d.ts +240 -0
- package/src/aws-authority/stage-authority.js +2968 -0
- package/src/aws-authority/stage-authority.js.map +1 -0
- package/src/cli/main.d.ts +2 -0
- package/src/cli/main.js +11 -0
- package/src/cli/main.js.map +1 -1
- package/src/developer-agent/generator-planning.js +4 -4
- package/src/developer-agent/generator-planning.js.map +1 -1
- package/src/developer-agent/operation-registry.js +14 -6
- package/src/developer-agent/operation-registry.js.map +1 -1
- package/src/developer-agent/workspace-inspection.js +11 -2
- package/src/developer-agent/workspace-inspection.js.map +1 -1
- package/src/executors/deployment-plan/deployment-plan.js +1 -1
- package/src/executors/deployment-plan/deployment-plan.js.map +1 -1
- package/src/executors/foundation-preflight/foundation-preflight.d.ts +0 -1
- package/src/executors/foundation-preflight/foundation-preflight.js.map +1 -1
- package/src/executors/foundation-preflight/schema.json +0 -5
- package/src/executors/foundation-profile-preflight/foundation-profile-preflight.d.ts +12 -3
- package/src/executors/foundation-profile-preflight/foundation-profile-preflight.js +95 -32
- package/src/executors/foundation-profile-preflight/foundation-profile-preflight.js.map +1 -1
- package/src/executors/foundation-profile-preflight/production-database-safeguard.d.ts +64 -0
- package/src/executors/foundation-profile-preflight/production-database-safeguard.js +221 -0
- package/src/executors/foundation-profile-preflight/production-database-safeguard.js.map +1 -0
- package/src/executors/foundation-profile-preflight/schema.json +1 -6
- package/src/executors/foundation-remove-preflight/foundation-remove-preflight.d.ts +11 -1
- package/src/executors/foundation-remove-preflight/foundation-remove-preflight.js +44 -21
- package/src/executors/foundation-remove-preflight/foundation-remove-preflight.js.map +1 -1
- package/src/executors/foundation-remove-preflight/schema.json +6 -1
- package/src/executors/github-bootstrap/github-bootstrap.d.ts +1 -0
- package/src/executors/github-bootstrap/github-bootstrap.js +1 -0
- package/src/executors/github-bootstrap/github-bootstrap.js.map +1 -1
- package/src/executors/github-bootstrap/schema.json +7 -1
- package/src/executors/infrastructure-plan/infrastructure-plan.d.ts +27 -369
- package/src/executors/infrastructure-plan/infrastructure-plan.js +237 -5470
- package/src/executors/infrastructure-plan/infrastructure-plan.js.map +1 -1
- package/src/executors/infrastructure-plan/schema.json +8 -64
- package/src/executors/local-deploy/federated-credential-transport.d.ts +48 -0
- package/src/executors/local-deploy/federated-credential-transport.js +252 -0
- package/src/executors/local-deploy/federated-credential-transport.js.map +1 -0
- package/src/executors/local-deploy/local-approval.d.ts +4 -9
- package/src/executors/local-deploy/local-approval.js +3 -7
- package/src/executors/local-deploy/local-approval.js.map +1 -1
- package/src/executors/local-deploy/local-deploy.d.ts +60 -43
- package/src/executors/local-deploy/local-deploy.js +955 -804
- package/src/executors/local-deploy/local-deploy.js.map +1 -1
- package/src/executors/local-deploy/schema.json +3 -20
- package/src/executors/refresh/refresh.js +2 -2
- package/src/executors/refresh/refresh.js.map +1 -1
- package/src/executors/remove/remove.js +2 -2
- package/src/executors/remove/remove.js.map +1 -1
- package/src/executors/router-waf-rehearsal/router-waf-rehearsal.d.ts +27 -1
- package/src/executors/router-waf-rehearsal/router-waf-rehearsal.js +907 -22
- package/src/executors/router-waf-rehearsal/router-waf-rehearsal.js.map +1 -1
- package/src/executors/router-waf-rehearsal/schema.json +17 -2
- package/src/executors/secret-initialize/schema.json +42 -0
- package/src/executors/secret-initialize/secret-initialize.d.ts +32 -0
- package/src/executors/secret-initialize/secret-initialize.js +243 -0
- package/src/executors/secret-initialize/secret-initialize.js.map +1 -0
- package/src/executors/secret-metadata/secret-metadata.d.ts +4 -1
- package/src/executors/secret-metadata/secret-metadata.js +76 -29
- package/src/executors/secret-metadata/secret-metadata.js.map +1 -1
- package/src/executors/sst-lifecycle/generated-secret-retirement.d.ts +53 -0
- package/src/executors/sst-lifecycle/generated-secret-retirement.js +192 -0
- package/src/executors/sst-lifecycle/generated-secret-retirement.js.map +1 -0
- package/src/executors/sst-lifecycle/governed-native-operation.d.ts +46 -0
- package/src/executors/sst-lifecycle/governed-native-operation.js +153 -0
- package/src/executors/sst-lifecycle/governed-native-operation.js.map +1 -0
- package/src/executors/sst-lifecycle/run-sst-command.d.ts +27 -7
- package/src/executors/sst-lifecycle/run-sst-command.js +474 -89
- package/src/executors/sst-lifecycle/run-sst-command.js.map +1 -1
- package/src/executors/sst-lifecycle/schema.json +0 -5
- package/src/executors/sst-lifecycle/secret-preflight.d.ts +2 -0
- package/src/executors/sst-lifecycle/secret-preflight.js +13 -7
- package/src/executors/sst-lifecycle/secret-preflight.js.map +1 -1
- package/src/executors/unlock/unlock.js +2 -2
- package/src/executors/unlock/unlock.js.map +1 -1
- package/src/foundation/provision-logical-database.js +2 -0
- package/src/foundation/provision-logical-database.js.map +1 -1
- package/src/foundation/router-waf-rate-rehearsal.d.ts +97 -0
- package/src/foundation/router-waf-rate-rehearsal.js +210 -0
- package/src/foundation/router-waf-rate-rehearsal.js.map +1 -0
- package/src/foundation/router-waf.d.ts +59 -9
- package/src/foundation/router-waf.js +427 -32
- package/src/foundation/router-waf.js.map +1 -1
- package/src/foundation/stages.d.ts +1 -0
- package/src/foundation/stages.js +11 -0
- package/src/foundation/stages.js.map +1 -1
- package/src/generators/formatting.d.ts +8 -0
- package/src/generators/formatting.js +118 -0
- package/src/generators/formatting.js.map +1 -0
- package/src/generators/function/function.js +37 -17
- package/src/generators/function/function.js.map +1 -1
- package/src/generators/post-generation-install.js +2 -2
- package/src/generators/post-generation-install.js.map +1 -1
- package/src/generators/preset/generator.js +28 -8
- package/src/generators/preset/generator.js.map +1 -1
- package/src/generators/preset/schema.d.ts +3 -0
- package/src/generators/preset/schema.json +5 -5
- package/src/generators/preset/workspace-files-developer-agent.js +15 -7
- package/src/generators/preset/workspace-files-developer-agent.js.map +1 -1
- package/src/generators/preset/workspace-files-ecr-inspector.d.ts +18 -0
- package/src/generators/preset/workspace-files-ecr-inspector.js +298 -0
- package/src/generators/preset/workspace-files-ecr-inspector.js.map +1 -0
- package/src/generators/preset/workspace-files-performance-cost.d.ts +2 -2
- package/src/generators/preset/workspace-files-performance-cost.js +8 -8
- package/src/generators/preset/workspace-files-performance-cost.js.map +1 -1
- package/src/generators/preset/workspace-files-performance-load.d.ts +1 -1
- package/src/generators/preset/workspace-files-performance-load.js +29 -24
- package/src/generators/preset/workspace-files-performance-load.js.map +1 -1
- package/src/generators/preset/workspace-files-stage-authority.d.ts +6 -0
- package/src/generators/preset/workspace-files-stage-authority.js +479 -0
- package/src/generators/preset/workspace-files-stage-authority.js.map +1 -0
- package/src/generators/preset/workspace-files-thin-deploy.d.ts +40 -0
- package/src/generators/preset/workspace-files-thin-deploy.js +1500 -0
- package/src/generators/preset/workspace-files-thin-deploy.js.map +1 -0
- package/src/generators/preset/workspace-files-thin-docs.d.ts +5 -0
- package/src/generators/preset/workspace-files-thin-docs.js +240 -0
- package/src/generators/preset/workspace-files-thin-docs.js.map +1 -0
- package/src/generators/preset/workspace-files-thin-release.d.ts +14 -0
- package/src/generators/preset/workspace-files-thin-release.js +26 -0
- package/src/generators/preset/workspace-files-thin-release.js.map +1 -0
- package/src/generators/preset/workspace-files.d.ts +2 -1
- package/src/generators/preset/workspace-files.js +448 -680
- package/src/generators/preset/workspace-files.js.map +1 -1
- package/src/generators/repository-policy/repository-policy.js +149 -19
- package/src/generators/repository-policy/repository-policy.js.map +1 -1
- package/src/generators/repository-policy/schema.d.ts +2 -0
- package/src/generators/repository-policy/schema.json +11 -1
- package/src/generators/repository-policy/tree-policy.d.ts +3 -0
- package/src/generators/repository-policy/tree-policy.js +25 -0
- package/src/generators/repository-policy/tree-policy.js.map +1 -0
- package/src/generators/slice/built-in-plan-api-files.js +1 -0
- package/src/generators/slice/built-in-plan-api-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-async-work-files.js +41 -0
- package/src/generators/slice/built-in-plan-async-work-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-authorization-infrastructure-files.js +6 -0
- package/src/generators/slice/built-in-plan-authorization-infrastructure-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-data-export-infrastructure-files.js +5 -31
- package/src/generators/slice/built-in-plan-data-export-infrastructure-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-data-files.d.ts +1 -1
- package/src/generators/slice/built-in-plan-data-files.js +89 -30
- package/src/generators/slice/built-in-plan-data-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-data-lifecycle-runtime-files.js +19 -0
- package/src/generators/slice/built-in-plan-data-lifecycle-runtime-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-data-retention-launcher-files.js +21 -3
- package/src/generators/slice/built-in-plan-data-retention-launcher-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-database-retirement-rehearsal-files.js +20 -1
- package/src/generators/slice/built-in-plan-database-retirement-rehearsal-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-foundation-files.js +3 -5
- package/src/generators/slice/built-in-plan-foundation-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-frontend-files.js +5 -1
- package/src/generators/slice/built-in-plan-frontend-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-infrastructure-files.d.ts +1 -1
- package/src/generators/slice/built-in-plan-infrastructure-files.js +199 -188
- package/src/generators/slice/built-in-plan-infrastructure-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-metadata-files.js +13 -0
- package/src/generators/slice/built-in-plan-metadata-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-native-runtime-authority-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-native-runtime-authority-files.js +307 -0
- package/src/generators/slice/built-in-plan-native-runtime-authority-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-operations-files.js +65 -51
- package/src/generators/slice/built-in-plan-operations-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-performance-files.js +97 -19
- package/src/generators/slice/built-in-plan-performance-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-project-files.js +9 -68
- package/src/generators/slice/built-in-plan-project-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-secret-runtime-files.d.ts +1 -1
- package/src/generators/slice/built-in-plan-secret-runtime-files.js +87 -76
- package/src/generators/slice/built-in-plan-secret-runtime-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-testing-files.js +94 -47
- package/src/generators/slice/built-in-plan-testing-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-thin-release-files.d.ts +11 -0
- package/src/generators/slice/built-in-plan-thin-release-files.js +129 -0
- package/src/generators/slice/built-in-plan-thin-release-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-verification-files.js +6 -2
- package/src/generators/slice/built-in-plan-verification-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-web-files.js +4 -2
- package/src/generators/slice/built-in-plan-web-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-workload-role-files.js +26 -4
- package/src/generators/slice/built-in-plan-workload-role-files.js.map +1 -1
- package/src/generators/slice/built-in-plan.d.ts +1 -0
- package/src/generators/slice/built-in-plan.js +28 -11
- package/src/generators/slice/built-in-plan.js.map +1 -1
- package/src/generators/slice/slice.js +30 -32
- package/src/generators/slice/slice.js.map +1 -1
- package/src/generators/upgrade/upgrade.d.ts +1 -1
- package/src/generators/upgrade/upgrade.js +200 -48
- package/src/generators/upgrade/upgrade.js.map +1 -1
- package/src/generators/workload/performance-registration.d.ts +1 -0
- package/src/generators/workload/performance-registration.js +9 -11
- package/src/generators/workload/performance-registration.js.map +1 -1
- package/src/generators/workload/service-performance-files.d.ts +1 -0
- package/src/generators/workload/service-performance-files.js +27 -7
- package/src/generators/workload/service-performance-files.js.map +1 -1
- package/src/generators/workload/workload.d.ts +1 -1
- package/src/generators/workload/workload.js +55 -28
- package/src/generators/workload/workload.js.map +1 -1
- package/src/git-policy/github-bootstrap.d.ts +28 -7
- package/src/git-policy/github-bootstrap.js +205 -163
- package/src/git-policy/github-bootstrap.js.map +1 -1
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/index.js.map +1 -1
- package/src/local-dev/private-state.d.ts +3 -0
- package/src/local-dev/private-state.js +17 -5
- package/src/local-dev/private-state.js.map +1 -1
- package/src/local-dev/tls.js +5 -1
- package/src/local-dev/tls.js.map +1 -1
- package/src/performance/cost-collection.d.ts +1 -1
- package/src/performance/cost-collection.js +4 -2
- package/src/performance/cost-collection.js.map +1 -1
- package/src/performance/cost-controls.d.ts +3 -1
- package/src/performance/cost-controls.js +9 -4
- package/src/performance/cost-controls.js.map +1 -1
- package/src/performance/evidence.d.ts +1 -1
- package/src/performance/evidence.js +5 -3
- package/src/performance/evidence.js.map +1 -1
- package/src/performance/load-safety.js +5 -3
- package/src/performance/load-safety.js.map +1 -1
- package/src/performance/model.d.ts +2 -2
- package/src/performance/model.js +4 -3
- package/src/performance/model.js.map +1 -1
- package/src/release/index.d.ts +0 -2
- package/src/release/index.js +0 -2
- package/src/release/index.js.map +1 -1
- package/src/release/source-authority.d.ts +4 -5
- package/src/release/source-authority.js +13 -123
- package/src/release/source-authority.js.map +1 -1
- package/src/repository-policy/aurora-preflight.d.ts +1 -1
- package/src/repository-policy/aurora-preflight.js +4 -1
- package/src/repository-policy/aurora-preflight.js.map +1 -1
- package/src/repository-policy/policy.d.ts +21 -2
- package/src/repository-policy/policy.js +290 -25
- package/src/repository-policy/policy.js.map +1 -1
- package/src/schemas/performance-policy-v1.json +3 -1
- package/src/schemas/repository-policy-v1.json +46 -2
- package/src/secrets/adapters.d.ts +7 -2
- package/src/secrets/adapters.js +34 -3
- package/src/secrets/adapters.js.map +1 -1
- package/src/secrets/aws-control-plane.d.ts +10 -1
- package/src/secrets/aws-control-plane.js +67 -0
- package/src/secrets/aws-control-plane.js.map +1 -1
- package/src/secrets/generated-aws-control-plane.d.ts +23 -0
- package/src/secrets/generated-aws-control-plane.js +259 -0
- package/src/secrets/generated-aws-control-plane.js.map +1 -0
- package/src/secrets/metadata.js +38 -10
- package/src/secrets/metadata.js.map +1 -1
- package/src/secrets/model.d.ts +8 -1
- package/src/secrets/model.js +24 -3
- package/src/secrets/model.js.map +1 -1
- package/src/secrets/operator.d.ts +89 -3
- package/src/secrets/operator.js +422 -9
- package/src/secrets/operator.js.map +1 -1
- package/src/secrets/registry.d.ts +2 -1
- package/src/secrets/registry.js +18 -1
- package/src/secrets/registry.js.map +1 -1
- package/src/secrets/workload-access.js +10 -2
- package/src/secrets/workload-access.js.map +1 -1
- package/src/supply-chain/action-pins.js +61 -7
- package/src/supply-chain/action-pins.js.map +1 -1
- package/src/supply-chain/build-output-bounds.d.ts +2 -0
- package/src/supply-chain/build-output-bounds.js +12 -0
- package/src/supply-chain/build-output-bounds.js.map +1 -0
- package/src/supply-chain/build-output.js +2 -4
- package/src/supply-chain/build-output.js.map +1 -1
- package/src/supply-chain/ecr-scanning.d.ts +5 -3
- package/src/supply-chain/ecr-scanning.js +11 -7
- package/src/supply-chain/ecr-scanning.js.map +1 -1
- package/src/supply-chain/ecs-deployed-image.d.ts +5 -3
- package/src/supply-chain/ecs-deployed-image.js +6 -4
- package/src/supply-chain/ecs-deployed-image.js.map +1 -1
- package/src/supply-chain/generated-container-release-command.js +849 -44
- package/src/supply-chain/generated-container-release-command.js.map +1 -1
- package/src/supply-chain/generated-ecr-collector-command.d.ts +0 -1
- package/src/supply-chain/generated-ecr-collector-command.js +188 -91
- package/src/supply-chain/generated-ecr-collector-command.js.map +1 -1
- package/src/supply-chain/generated-files.js +4 -3
- package/src/supply-chain/generated-files.js.map +1 -1
- package/src/supply-chain/index.d.ts +1 -1
- package/src/supply-chain/index.js +2 -1
- package/src/supply-chain/index.js.map +1 -1
- package/src/workload-roles/index.d.ts +10 -17
- package/src/workload-roles/index.js +5 -18
- package/src/workload-roles/index.js.map +1 -1
- package/src/workspace-deployment/identity.d.ts +3 -0
- package/src/workspace-deployment/identity.js +22 -0
- package/src/workspace-deployment/identity.js.map +1 -0
- package/src/workspace-deployment/index.d.ts +3 -0
- package/src/workspace-deployment/index.js +7 -0
- package/src/workspace-deployment/index.js.map +1 -0
- package/src/workspace-deployment/migration-evidence.d.ts +29 -0
- package/src/workspace-deployment/migration-evidence.js +83 -0
- package/src/workspace-deployment/migration-evidence.js.map +1 -0
- package/src/workspace-deployment/migration.d.ts +27 -0
- package/src/workspace-deployment/migration.js +109 -0
- package/src/workspace-deployment/migration.js.map +1 -0
- package/src/workspace-deployment/ownership.d.ts +81 -0
- package/src/workspace-deployment/ownership.js +381 -0
- package/src/workspace-deployment/ownership.js.map +1 -0
|
@@ -1,25 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ROUTER_WAF_REQUIRED_MANAGED_RULES = exports.ROUTER_WAF_SCHEMA_VERSION = exports.ROUTER_WAF_REHEARSAL_KIND = exports.ROUTER_WAF_POLICY_KIND = void 0;
|
|
3
|
+
exports.ROUTER_WAF_REQUIRED_MANAGED_RULES = exports.ROUTER_WAF_LIVE_EVIDENCE_SCHEMA_VERSION = exports.ROUTER_WAF_REHEARSAL_SCHEMA_VERSION = exports.ROUTER_WAF_CONTRACT_SCHEMA_VERSION = exports.ROUTER_WAF_SCHEMA_VERSION = exports.ROUTER_WAF_REHEARSAL_KIND = exports.ROUTER_WAF_POLICY_KIND = void 0;
|
|
4
4
|
exports.normalizeRouterWafPolicy = normalizeRouterWafPolicy;
|
|
5
5
|
exports.routerWafPolicyDigest = routerWafPolicyDigest;
|
|
6
6
|
exports.normalizeRouterWafBlockingRehearsal = normalizeRouterWafBlockingRehearsal;
|
|
7
|
+
exports.validateRouterWafLiveEvidenceSeed = validateRouterWafLiveEvidenceSeed;
|
|
7
8
|
exports.createRouterWafBlockingRehearsal = createRouterWafBlockingRehearsal;
|
|
8
9
|
exports.reconcileRouterWafBlockingRehearsal = reconcileRouterWafBlockingRehearsal;
|
|
9
10
|
exports.createRouterWafStagePlan = createRouterWafStagePlan;
|
|
10
11
|
exports.createRouterWafRules = createRouterWafRules;
|
|
12
|
+
exports.routerWafContractDigest = routerWafContractDigest;
|
|
11
13
|
const node_crypto_1 = require("node:crypto");
|
|
12
14
|
const node_net_1 = require("node:net");
|
|
13
15
|
const stages_js_1 = require("./stages.js");
|
|
16
|
+
const policy_js_1 = require("../repository-policy/policy.js");
|
|
17
|
+
const router_waf_rate_rehearsal_js_1 = require("./router-waf-rate-rehearsal.js");
|
|
14
18
|
exports.ROUTER_WAF_POLICY_KIND = 'ebk-router-waf-policy';
|
|
15
19
|
exports.ROUTER_WAF_REHEARSAL_KIND = 'ebk-router-waf-blocking-rehearsal';
|
|
16
20
|
exports.ROUTER_WAF_SCHEMA_VERSION = 1;
|
|
21
|
+
exports.ROUTER_WAF_CONTRACT_SCHEMA_VERSION = 1;
|
|
22
|
+
exports.ROUTER_WAF_REHEARSAL_SCHEMA_VERSION = 4;
|
|
23
|
+
exports.ROUTER_WAF_LIVE_EVIDENCE_SCHEMA_VERSION = 4;
|
|
17
24
|
exports.ROUTER_WAF_REQUIRED_MANAGED_RULES = [
|
|
18
25
|
'AWSManagedRulesCommonRuleSet',
|
|
19
26
|
'AWSManagedRulesKnownBadInputsRuleSet',
|
|
20
27
|
'AWSManagedRulesAmazonIpReputationList',
|
|
21
28
|
];
|
|
22
29
|
const POLICY_KEYS = [
|
|
30
|
+
'deploymentProfile',
|
|
23
31
|
'kind',
|
|
24
32
|
'logging',
|
|
25
33
|
'rateLimitPerIp',
|
|
@@ -29,18 +37,24 @@ const POLICY_KEYS = [
|
|
|
29
37
|
const LOGGING_KEYS = ['enabled', 'retention'];
|
|
30
38
|
const STAGE_KEYS = ['access', 'allowedCidrs', 'mode'];
|
|
31
39
|
const REHEARSAL_KEYS = [
|
|
40
|
+
'accountId',
|
|
32
41
|
'completedAt',
|
|
42
|
+
'deploymentRoleArn',
|
|
33
43
|
'evidenceDigest',
|
|
34
44
|
'kind',
|
|
35
45
|
'mode',
|
|
36
46
|
'policyDigest',
|
|
47
|
+
'region',
|
|
37
48
|
'schemaVersion',
|
|
38
49
|
'stage',
|
|
39
50
|
'status',
|
|
51
|
+
'wafContractDigest',
|
|
52
|
+
'workspace',
|
|
40
53
|
];
|
|
41
54
|
const LIVE_EVIDENCE_KEYS = [
|
|
42
55
|
'accountId',
|
|
43
56
|
'completedAt',
|
|
57
|
+
'deploymentRoleArn',
|
|
44
58
|
'distributionId',
|
|
45
59
|
'kind',
|
|
46
60
|
'mode',
|
|
@@ -55,16 +69,57 @@ const LIVE_EVIDENCE_KEYS = [
|
|
|
55
69
|
'startedAt',
|
|
56
70
|
'webAclArn',
|
|
57
71
|
'webAclScope',
|
|
72
|
+
'wafContractDigest',
|
|
73
|
+
'workspace',
|
|
58
74
|
];
|
|
59
75
|
const LIVE_PROBE_KEYS = [
|
|
60
76
|
'allowedRequestStatus',
|
|
61
|
-
'blockedManagedRuleStatus',
|
|
62
|
-
'blockedNonAllowlistedStatus',
|
|
63
|
-
'blockedRateLimitStatus',
|
|
64
77
|
'cloudWatchMetricsObserved',
|
|
65
78
|
'countModeTuningObserved',
|
|
79
|
+
'managedRule',
|
|
80
|
+
'nonAllowlisted',
|
|
81
|
+
'rateLimit',
|
|
66
82
|
'sampledRequestsObserved',
|
|
67
83
|
];
|
|
84
|
+
const OPERATOR_BLOCK_KEYS = [
|
|
85
|
+
'blockedAt',
|
|
86
|
+
'marker',
|
|
87
|
+
'method',
|
|
88
|
+
'path',
|
|
89
|
+
'ruleName',
|
|
90
|
+
'status',
|
|
91
|
+
];
|
|
92
|
+
const RATE_EVIDENCE_KEYS = [
|
|
93
|
+
'blockedAt',
|
|
94
|
+
'blockedRequestStatus',
|
|
95
|
+
'blockedSequence',
|
|
96
|
+
'burstRequests',
|
|
97
|
+
'concurrency',
|
|
98
|
+
'followUpIntervalMs',
|
|
99
|
+
'followUpRequests',
|
|
100
|
+
'maximumRequests',
|
|
101
|
+
'metric',
|
|
102
|
+
'observationPolls',
|
|
103
|
+
'requestsSent',
|
|
104
|
+
'ruleMetricName',
|
|
105
|
+
'ruleName',
|
|
106
|
+
'sample',
|
|
107
|
+
'upstream429Responses',
|
|
108
|
+
];
|
|
109
|
+
const RATE_METRIC_KEYS = [
|
|
110
|
+
'name',
|
|
111
|
+
'namespace',
|
|
112
|
+
'timestamp',
|
|
113
|
+
'value',
|
|
114
|
+
'webAclMetricName',
|
|
115
|
+
];
|
|
116
|
+
const RATE_SAMPLE_KEYS = [
|
|
117
|
+
'action',
|
|
118
|
+
'markerDigest',
|
|
119
|
+
'method',
|
|
120
|
+
'timestamp',
|
|
121
|
+
'uri',
|
|
122
|
+
];
|
|
68
123
|
const DIGEST_PATTERN = /^sha256:[a-f0-9]{64}$/;
|
|
69
124
|
function record(value, label) {
|
|
70
125
|
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
@@ -94,6 +149,119 @@ function canonical(value) {
|
|
|
94
149
|
}
|
|
95
150
|
return encoded;
|
|
96
151
|
}
|
|
152
|
+
function integerInRange(value, minimum, maximum) {
|
|
153
|
+
return (typeof value === 'number' &&
|
|
154
|
+
Number.isSafeInteger(value) &&
|
|
155
|
+
value >= minimum &&
|
|
156
|
+
value <= maximum);
|
|
157
|
+
}
|
|
158
|
+
function sameUtcMinute(left, right) {
|
|
159
|
+
return Math.floor(left / 60_000) === Math.floor(right / 60_000);
|
|
160
|
+
}
|
|
161
|
+
function normalizeRouterWafRateEvidence(input) {
|
|
162
|
+
const candidate = record(input.value, 'Router WAF rate-limit evidence');
|
|
163
|
+
exactKeys(candidate, RATE_EVIDENCE_KEYS, 'Router WAF rate-limit evidence');
|
|
164
|
+
const metric = record(candidate.metric, 'Router WAF rate-limit metric evidence');
|
|
165
|
+
exactKeys(metric, RATE_METRIC_KEYS, 'Router WAF rate-limit metric evidence');
|
|
166
|
+
const sample = record(candidate.sample, 'Router WAF rate-limit sample evidence');
|
|
167
|
+
exactKeys(sample, RATE_SAMPLE_KEYS, 'Router WAF rate-limit sample evidence');
|
|
168
|
+
const blockedAt = typeof candidate.blockedAt === 'string'
|
|
169
|
+
? Date.parse(candidate.blockedAt)
|
|
170
|
+
: Number.NaN;
|
|
171
|
+
const sampleAt = typeof sample.timestamp === 'string'
|
|
172
|
+
? Date.parse(sample.timestamp)
|
|
173
|
+
: Number.NaN;
|
|
174
|
+
const metricAt = typeof metric.timestamp === 'string'
|
|
175
|
+
? Date.parse(metric.timestamp)
|
|
176
|
+
: Number.NaN;
|
|
177
|
+
const expectedRuleMetricName = (0, router_waf_rate_rehearsal_js_1.routerWafRateRuleMetricName)(input.stage);
|
|
178
|
+
const expectedWebAclMetricName = input.webAclName;
|
|
179
|
+
const maximumBurst = Math.min(input.rateLimitPerIp + 160, router_waf_rate_rehearsal_js_1.ROUTER_WAF_RATE_REHEARSAL_MAX_REQUESTS -
|
|
180
|
+
router_waf_rate_rehearsal_js_1.ROUTER_WAF_RATE_REHEARSAL_FOLLOW_UP_REQUESTS);
|
|
181
|
+
if (candidate.blockedRequestStatus !== 403 ||
|
|
182
|
+
!integerInRange(candidate.blockedSequence, 1, router_waf_rate_rehearsal_js_1.ROUTER_WAF_RATE_REHEARSAL_MAX_REQUESTS) ||
|
|
183
|
+
!Number.isFinite(blockedAt) ||
|
|
184
|
+
blockedAt < input.startedAt ||
|
|
185
|
+
blockedAt > input.completedAt ||
|
|
186
|
+
!integerInRange(candidate.burstRequests, 1, maximumBurst) ||
|
|
187
|
+
candidate.concurrency !== router_waf_rate_rehearsal_js_1.ROUTER_WAF_RATE_REHEARSAL_MAX_CONCURRENCY ||
|
|
188
|
+
candidate.followUpIntervalMs !==
|
|
189
|
+
router_waf_rate_rehearsal_js_1.ROUTER_WAF_RATE_REHEARSAL_FOLLOW_UP_INTERVAL_MS ||
|
|
190
|
+
!integerInRange(candidate.followUpRequests, 0, router_waf_rate_rehearsal_js_1.ROUTER_WAF_RATE_REHEARSAL_FOLLOW_UP_REQUESTS) ||
|
|
191
|
+
candidate.maximumRequests !== router_waf_rate_rehearsal_js_1.ROUTER_WAF_RATE_REHEARSAL_MAX_REQUESTS ||
|
|
192
|
+
!integerInRange(candidate.observationPolls, 1, router_waf_rate_rehearsal_js_1.ROUTER_WAF_RATE_REHEARSAL_OBSERVATION_POLLS) ||
|
|
193
|
+
!integerInRange(candidate.requestsSent, 1, router_waf_rate_rehearsal_js_1.ROUTER_WAF_RATE_REHEARSAL_MAX_REQUESTS) ||
|
|
194
|
+
candidate.requestsSent !==
|
|
195
|
+
candidate.burstRequests + candidate.followUpRequests ||
|
|
196
|
+
candidate.blockedSequence > candidate.requestsSent ||
|
|
197
|
+
candidate.ruleName !== router_waf_rate_rehearsal_js_1.ROUTER_WAF_RATE_RULE_NAME ||
|
|
198
|
+
candidate.ruleMetricName !== expectedRuleMetricName ||
|
|
199
|
+
!integerInRange(candidate.upstream429Responses, 0, candidate.requestsSent) ||
|
|
200
|
+
sample.action !== 'BLOCK' ||
|
|
201
|
+
typeof sample.markerDigest !== 'string' ||
|
|
202
|
+
!DIGEST_PATTERN.test(sample.markerDigest) ||
|
|
203
|
+
sample.method !== 'GET' ||
|
|
204
|
+
typeof sample.uri !== 'string' ||
|
|
205
|
+
!/^\/[a-z0-9]+(?:-[a-z0-9]+)*\/api\/health$/.test(sample.uri) ||
|
|
206
|
+
!Number.isFinite(sampleAt) ||
|
|
207
|
+
sampleAt < input.startedAt ||
|
|
208
|
+
sampleAt > input.completedAt ||
|
|
209
|
+
metric.name !== 'BlockedRequests' ||
|
|
210
|
+
metric.namespace !== 'AWS/WAFV2' ||
|
|
211
|
+
typeof expectedWebAclMetricName !== 'string' ||
|
|
212
|
+
metric.webAclMetricName !== expectedWebAclMetricName ||
|
|
213
|
+
typeof metric.value !== 'number' ||
|
|
214
|
+
!Number.isFinite(metric.value) ||
|
|
215
|
+
metric.value <= 0 ||
|
|
216
|
+
!Number.isFinite(metricAt) ||
|
|
217
|
+
!sameUtcMinute(sampleAt, metricAt)) {
|
|
218
|
+
throw new Error('Router WAF rate-limit evidence lacks one bounded exact RateLimitPerIP BLOCK sample and correlated AWS/WAFV2 metric.');
|
|
219
|
+
}
|
|
220
|
+
return candidate;
|
|
221
|
+
}
|
|
222
|
+
function canonicalIpv6(address, prefix) {
|
|
223
|
+
const halves = address.toLowerCase().split('::');
|
|
224
|
+
if (halves.length > 2)
|
|
225
|
+
return null;
|
|
226
|
+
const left = halves[0] ? halves[0].split(':') : [];
|
|
227
|
+
const right = halves[1] ? halves[1].split(':') : [];
|
|
228
|
+
if ([...left, ...right].some((part) => !/^[a-f0-9]{1,4}$/.test(part)) ||
|
|
229
|
+
(halves.length === 1 && left.length !== 8) ||
|
|
230
|
+
(halves.length === 2 && left.length + right.length >= 8)) {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
const groups = [
|
|
234
|
+
...left,
|
|
235
|
+
...Array.from({ length: 8 - left.length - right.length }, () => '0'),
|
|
236
|
+
...right,
|
|
237
|
+
].map((part) => Number.parseInt(part, 16));
|
|
238
|
+
let numeric = groups.reduce((result, group) => (result << 16n) | BigInt(group), 0n);
|
|
239
|
+
numeric &= ((1n << BigInt(prefix)) - 1n) << BigInt(128 - prefix);
|
|
240
|
+
const network = Array.from({ length: 8 }, (_, index) => Number((numeric >> BigInt((7 - index) * 16)) & 0xffffn));
|
|
241
|
+
let bestStart = -1;
|
|
242
|
+
let bestLength = 0;
|
|
243
|
+
for (let index = 0; index < network.length;) {
|
|
244
|
+
if (network[index] !== 0) {
|
|
245
|
+
index += 1;
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
let end = index;
|
|
249
|
+
while (end < network.length && network[end] === 0)
|
|
250
|
+
end += 1;
|
|
251
|
+
if (end - index > bestLength && end - index >= 2) {
|
|
252
|
+
bestStart = index;
|
|
253
|
+
bestLength = end - index;
|
|
254
|
+
}
|
|
255
|
+
index = end;
|
|
256
|
+
}
|
|
257
|
+
const parts = network.map((group) => group.toString(16));
|
|
258
|
+
const rendered = bestStart === -1
|
|
259
|
+
? parts.join(':')
|
|
260
|
+
: `${parts.slice(0, bestStart).join(':')}::${parts
|
|
261
|
+
.slice(bestStart + bestLength)
|
|
262
|
+
.join(':')}`;
|
|
263
|
+
return `${rendered}/${prefix}`;
|
|
264
|
+
}
|
|
97
265
|
function cidr(value, label) {
|
|
98
266
|
if (typeof value !== 'string' || value !== value.trim()) {
|
|
99
267
|
throw new Error(`${label} must be a canonical IPv4 or IPv6 CIDR.`);
|
|
@@ -106,12 +274,29 @@ function cidr(value, label) {
|
|
|
106
274
|
const prefix = Number(match[2]);
|
|
107
275
|
const family = (0, node_net_1.isIP)(address);
|
|
108
276
|
if (family === 0 ||
|
|
277
|
+
prefix === 0 ||
|
|
109
278
|
!Number.isInteger(prefix) ||
|
|
110
279
|
(family === 4 && prefix > 32) ||
|
|
111
280
|
(family === 6 && prefix > 128)) {
|
|
112
281
|
throw new Error(`${label} must be a canonical IPv4 or IPv6 CIDR.`);
|
|
113
282
|
}
|
|
114
|
-
|
|
283
|
+
let canonical = null;
|
|
284
|
+
if (family === 4) {
|
|
285
|
+
const octets = address.split('.').map(Number);
|
|
286
|
+
const numeric = octets.reduce((result, octet) => (result << 8) | octet, 0) >>> 0;
|
|
287
|
+
const mask = prefix === 32 ? 0xffffffff : (0xffffffff << (32 - prefix)) >>> 0;
|
|
288
|
+
const network = (numeric & mask) >>> 0;
|
|
289
|
+
canonical = `${[24, 16, 8, 0]
|
|
290
|
+
.map((shift) => (network >>> shift) & 255)
|
|
291
|
+
.join('.')}/${prefix}`;
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
canonical = canonicalIpv6(address, prefix);
|
|
295
|
+
}
|
|
296
|
+
if (canonical !== value) {
|
|
297
|
+
throw new Error(`${label} must use its canonical network address.`);
|
|
298
|
+
}
|
|
299
|
+
return canonical;
|
|
115
300
|
}
|
|
116
301
|
function stagePolicy(value, stage) {
|
|
117
302
|
const candidate = record(value, `Router WAF ${stage} policy`);
|
|
@@ -145,11 +330,16 @@ function normalizeRouterWafPolicy(value) {
|
|
|
145
330
|
candidate.schemaVersion !== exports.ROUTER_WAF_SCHEMA_VERSION) {
|
|
146
331
|
throw new Error('Router WAF policy kind or schemaVersion is invalid.');
|
|
147
332
|
}
|
|
333
|
+
if (candidate.deploymentProfile !== 'starter' &&
|
|
334
|
+
candidate.deploymentProfile !== 'production-isolated' &&
|
|
335
|
+
candidate.deploymentProfile !== 'fully-isolated') {
|
|
336
|
+
throw new Error('Router WAF deploymentProfile is invalid.');
|
|
337
|
+
}
|
|
148
338
|
if (typeof candidate.rateLimitPerIp !== 'number' ||
|
|
149
339
|
!Number.isSafeInteger(candidate.rateLimitPerIp) ||
|
|
150
340
|
candidate.rateLimitPerIp < 100 ||
|
|
151
|
-
candidate.rateLimitPerIp >
|
|
152
|
-
throw new Error(
|
|
341
|
+
candidate.rateLimitPerIp > router_waf_rate_rehearsal_js_1.ROUTER_WAF_RATE_REHEARSAL_MAX_RATE_LIMIT) {
|
|
342
|
+
throw new Error(`Router WAF rateLimitPerIp must be an integer from 100 through ${router_waf_rate_rehearsal_js_1.ROUTER_WAF_RATE_REHEARSAL_MAX_RATE_LIMIT}, the exact bounded rehearsal maximum.`);
|
|
153
343
|
}
|
|
154
344
|
const logging = record(candidate.logging, 'Router WAF logging policy');
|
|
155
345
|
exactKeys(logging, LOGGING_KEYS, 'Router WAF logging policy');
|
|
@@ -164,8 +354,11 @@ function normalizeRouterWafPolicy(value) {
|
|
|
164
354
|
throw new Error('Router WAF logging retention is invalid or unbounded.');
|
|
165
355
|
}
|
|
166
356
|
const stages = record(candidate.stages, 'Router WAF stages');
|
|
167
|
-
|
|
357
|
+
const deploymentProfile = candidate.deploymentProfile;
|
|
358
|
+
const activeStages = (0, policy_js_1.activeDeploymentStages)(deploymentProfile);
|
|
359
|
+
exactKeys(stages, activeStages, 'Router WAF stages');
|
|
168
360
|
return {
|
|
361
|
+
deploymentProfile,
|
|
169
362
|
kind: exports.ROUTER_WAF_POLICY_KIND,
|
|
170
363
|
logging: {
|
|
171
364
|
enabled: logging.enabled,
|
|
@@ -176,7 +369,9 @@ function normalizeRouterWafPolicy(value) {
|
|
|
176
369
|
stages: {
|
|
177
370
|
development: stagePolicy(stages.development, 'development'),
|
|
178
371
|
production: stagePolicy(stages.production, 'production'),
|
|
179
|
-
|
|
372
|
+
...(activeStages.includes('staging')
|
|
373
|
+
? { staging: stagePolicy(stages.staging, 'staging') }
|
|
374
|
+
: {}),
|
|
180
375
|
},
|
|
181
376
|
};
|
|
182
377
|
}
|
|
@@ -188,33 +383,69 @@ function normalizeRouterWafBlockingRehearsal(value) {
|
|
|
188
383
|
if (candidate.status === 'pending') {
|
|
189
384
|
exactKeys(candidate, ['kind', 'schemaVersion', 'status'], 'Pending Router WAF blocking rehearsal');
|
|
190
385
|
if (candidate.kind !== exports.ROUTER_WAF_REHEARSAL_KIND ||
|
|
191
|
-
candidate.schemaVersion !== exports.
|
|
386
|
+
candidate.schemaVersion !== exports.ROUTER_WAF_REHEARSAL_SCHEMA_VERSION) {
|
|
192
387
|
throw new Error('Pending Router WAF blocking rehearsal kind or schemaVersion is invalid.');
|
|
193
388
|
}
|
|
194
389
|
return null;
|
|
195
390
|
}
|
|
196
391
|
exactKeys(candidate, REHEARSAL_KEYS, 'Router WAF blocking rehearsal');
|
|
197
392
|
if (candidate.kind !== exports.ROUTER_WAF_REHEARSAL_KIND ||
|
|
198
|
-
candidate.schemaVersion !== exports.
|
|
393
|
+
candidate.schemaVersion !== exports.ROUTER_WAF_REHEARSAL_SCHEMA_VERSION ||
|
|
199
394
|
candidate.status !== 'passed' ||
|
|
200
|
-
candidate.stage !== 'staging' ||
|
|
395
|
+
(candidate.stage !== 'development' && candidate.stage !== 'staging') ||
|
|
201
396
|
candidate.mode !== 'block' ||
|
|
397
|
+
typeof candidate.accountId !== 'string' ||
|
|
398
|
+
!/^\d{12}$/.test(candidate.accountId) ||
|
|
399
|
+
typeof candidate.region !== 'string' ||
|
|
400
|
+
!/^[a-z]{2}(?:-gov)?-[a-z]+-\d$/.test(candidate.region) ||
|
|
401
|
+
typeof candidate.deploymentRoleArn !== 'string' ||
|
|
402
|
+
!new RegExp(`^arn:(?:aws|aws-us-gov):iam::${candidate.accountId}:role/[A-Za-z0-9+=,.@_/-]{1,512}$`).test(candidate.deploymentRoleArn) ||
|
|
403
|
+
typeof candidate.workspace !== 'string' ||
|
|
404
|
+
!/^[a-z0-9][a-z0-9-]{0,127}$/.test(candidate.workspace) ||
|
|
202
405
|
typeof candidate.completedAt !== 'string' ||
|
|
203
406
|
!Number.isFinite(Date.parse(candidate.completedAt)) ||
|
|
204
407
|
typeof candidate.evidenceDigest !== 'string' ||
|
|
205
408
|
!DIGEST_PATTERN.test(candidate.evidenceDigest) ||
|
|
206
409
|
typeof candidate.policyDigest !== 'string' ||
|
|
207
|
-
!DIGEST_PATTERN.test(candidate.policyDigest)
|
|
410
|
+
!DIGEST_PATTERN.test(candidate.policyDigest) ||
|
|
411
|
+
typeof candidate.wafContractDigest !== 'string' ||
|
|
412
|
+
!DIGEST_PATTERN.test(candidate.wafContractDigest)) {
|
|
208
413
|
throw new Error('Router WAF blocking rehearsal is invalid.');
|
|
209
414
|
}
|
|
210
415
|
return candidate;
|
|
211
416
|
}
|
|
212
|
-
function
|
|
417
|
+
function operatorBlockEvidence(input) {
|
|
418
|
+
const candidate = record(input.value, `Router WAF ${input.expected} operator evidence`);
|
|
419
|
+
exactKeys(candidate, OPERATOR_BLOCK_KEYS, `Router WAF ${input.expected} operator evidence`);
|
|
420
|
+
const blockedAt = typeof candidate.blockedAt === 'string'
|
|
421
|
+
? Date.parse(candidate.blockedAt)
|
|
422
|
+
: Number.NaN;
|
|
423
|
+
const expectedRule = input.expected === 'nonallowlisted'
|
|
424
|
+
? candidate.ruleName === 'StageIpAllowlist'
|
|
425
|
+
: candidate.ruleName ===
|
|
426
|
+
'AWSManagedRulesCommonRuleSet#NoUserAgent_HEADER';
|
|
427
|
+
if (candidate.status !== 403 ||
|
|
428
|
+
candidate.method !== 'GET' ||
|
|
429
|
+
typeof candidate.path !== 'string' ||
|
|
430
|
+
!/^\/[a-z0-9]+(?:-[a-z0-9]+)*\/api\/health$/.test(candidate.path) ||
|
|
431
|
+
typeof candidate.marker !== 'string' ||
|
|
432
|
+
!/^[a-f0-9]{64}:(?:managed|nonallowlisted)$/.test(candidate.marker) ||
|
|
433
|
+
!candidate.marker.endsWith(`:${input.expected}`) ||
|
|
434
|
+
!expectedRule ||
|
|
435
|
+
!Number.isFinite(blockedAt) ||
|
|
436
|
+
blockedAt < input.startedAt ||
|
|
437
|
+
blockedAt > input.completedAt) {
|
|
438
|
+
throw new Error(`Router WAF ${input.expected} operator evidence is not one bounded exact BLOCK request.`);
|
|
439
|
+
}
|
|
440
|
+
return candidate;
|
|
441
|
+
}
|
|
442
|
+
function validateRouterWafLiveEvidenceSeed(input) {
|
|
213
443
|
const evidence = record(input.evidence, 'Router WAF live evidence');
|
|
214
444
|
exactKeys(evidence, LIVE_EVIDENCE_KEYS, 'Router WAF live evidence');
|
|
215
445
|
const probes = record(evidence.probes, 'Router WAF live evidence probes');
|
|
216
446
|
exactKeys(probes, LIVE_PROBE_KEYS, 'Router WAF live evidence probes');
|
|
217
447
|
const policyDigest = routerWafPolicyDigest(input.policy);
|
|
448
|
+
const wafContractDigest = routerWafContractDigest(input.policy);
|
|
218
449
|
const startedAt = typeof evidence.startedAt === 'string'
|
|
219
450
|
? Date.parse(evidence.startedAt)
|
|
220
451
|
: Number.NaN;
|
|
@@ -226,26 +457,37 @@ function createRouterWafBlockingRehearsal(input) {
|
|
|
226
457
|
'RateLimitPerIP',
|
|
227
458
|
...exports.ROUTER_WAF_REQUIRED_MANAGED_RULES,
|
|
228
459
|
];
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
460
|
+
const rehearsalStage = (0, policy_js_1.productionRehearsalStage)(input.policy.deploymentProfile);
|
|
461
|
+
const rehearsalStagePolicy = input.policy.stages[rehearsalStage];
|
|
462
|
+
const webAclIdentity = typeof evidence.webAclArn === 'string'
|
|
463
|
+
? /^arn:(?:aws|aws-us-gov):wafv2:us-east-1:(\d{12}):global\/webacl\/([A-Za-z0-9_-]{1,128})\/[a-f0-9-]{36}$/.exec(evidence.webAclArn)
|
|
464
|
+
: null;
|
|
465
|
+
if (!rehearsalStagePolicy ||
|
|
466
|
+
rehearsalStagePolicy.mode !== 'block' ||
|
|
467
|
+
rehearsalStagePolicy.access !== 'allowlist' ||
|
|
468
|
+
rehearsalStagePolicy.allowedCidrs.length === 0 ||
|
|
232
469
|
evidence.kind !== 'ebk-router-waf-live-evidence' ||
|
|
233
|
-
evidence.schemaVersion !== exports.
|
|
234
|
-
evidence.stage !==
|
|
470
|
+
evidence.schemaVersion !== exports.ROUTER_WAF_LIVE_EVIDENCE_SCHEMA_VERSION ||
|
|
471
|
+
evidence.stage !== rehearsalStage ||
|
|
235
472
|
evidence.mode !== 'block' ||
|
|
236
473
|
evidence.result !== 'passed' ||
|
|
237
474
|
evidence.webAclScope !== 'CLOUDFRONT' ||
|
|
238
475
|
evidence.policyDigest !== policyDigest ||
|
|
476
|
+
evidence.wafContractDigest !== wafContractDigest ||
|
|
239
477
|
typeof evidence.accountId !== 'string' ||
|
|
240
478
|
!/^\d{12}$/.test(evidence.accountId) ||
|
|
479
|
+
typeof evidence.deploymentRoleArn !== 'string' ||
|
|
480
|
+
!new RegExp(`^arn:(?:aws|aws-us-gov):iam::${evidence.accountId}:role/[A-Za-z0-9+=,.@_/-]{1,512}$`).test(evidence.deploymentRoleArn) ||
|
|
241
481
|
typeof evidence.region !== 'string' ||
|
|
242
482
|
!/^[a-z]{2}(?:-gov)?-[a-z]+-\d$/.test(evidence.region) ||
|
|
243
483
|
typeof evidence.sourceCommit !== 'string' ||
|
|
244
|
-
!/^[a-f0-9]{40}$/.test(evidence.sourceCommit) ||
|
|
484
|
+
!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(evidence.sourceCommit) ||
|
|
485
|
+
typeof evidence.workspace !== 'string' ||
|
|
486
|
+
!/^[a-z0-9][a-z0-9-]{0,127}$/.test(evidence.workspace) ||
|
|
245
487
|
typeof evidence.distributionId !== 'string' ||
|
|
246
488
|
!/^[A-Z0-9]{8,32}$/.test(evidence.distributionId) ||
|
|
247
|
-
|
|
248
|
-
|
|
489
|
+
!webAclIdentity ||
|
|
490
|
+
webAclIdentity[1] !== evidence.accountId ||
|
|
249
491
|
!Number.isFinite(startedAt) ||
|
|
250
492
|
!Number.isFinite(completedAt) ||
|
|
251
493
|
completedAt < startedAt ||
|
|
@@ -255,26 +497,77 @@ function createRouterWafBlockingRehearsal(input) {
|
|
|
255
497
|
typeof probes.allowedRequestStatus !== 'number' ||
|
|
256
498
|
probes.allowedRequestStatus < 200 ||
|
|
257
499
|
probes.allowedRequestStatus > 399 ||
|
|
258
|
-
probes.blockedManagedRuleStatus !== 403 ||
|
|
259
|
-
probes.blockedNonAllowlistedStatus !== 403 ||
|
|
260
|
-
probes.blockedRateLimitStatus !== 403 ||
|
|
261
500
|
probes.cloudWatchMetricsObserved !== true ||
|
|
262
|
-
probes.countModeTuningObserved !==
|
|
501
|
+
typeof probes.countModeTuningObserved !== 'boolean' ||
|
|
263
502
|
probes.sampledRequestsObserved !== true) {
|
|
264
|
-
throw new Error(
|
|
503
|
+
throw new Error(`Router WAF live evidence does not prove the exact ${rehearsalStage} blocking baseline.`);
|
|
265
504
|
}
|
|
505
|
+
operatorBlockEvidence({
|
|
506
|
+
completedAt,
|
|
507
|
+
expected: 'managed',
|
|
508
|
+
startedAt,
|
|
509
|
+
value: probes.managedRule,
|
|
510
|
+
});
|
|
511
|
+
operatorBlockEvidence({
|
|
512
|
+
completedAt,
|
|
513
|
+
expected: 'nonallowlisted',
|
|
514
|
+
startedAt,
|
|
515
|
+
value: probes.nonAllowlisted,
|
|
516
|
+
});
|
|
517
|
+
return {
|
|
518
|
+
accountId: evidence.accountId,
|
|
519
|
+
completedAt,
|
|
520
|
+
deploymentRoleArn: evidence.deploymentRoleArn,
|
|
521
|
+
distributionId: evidence.distributionId,
|
|
522
|
+
probes,
|
|
523
|
+
region: evidence.region,
|
|
524
|
+
stage: rehearsalStage,
|
|
525
|
+
startedAt,
|
|
526
|
+
wafContractDigest,
|
|
527
|
+
webAclArn: evidence.webAclArn,
|
|
528
|
+
webAclName: webAclIdentity[2],
|
|
529
|
+
workspace: evidence.workspace,
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
function createRouterWafBlockingRehearsal(input) {
|
|
533
|
+
const seed = validateRouterWafLiveEvidenceSeed(input);
|
|
534
|
+
const evidence = input.evidence;
|
|
535
|
+
let rateLimitEvidence;
|
|
536
|
+
try {
|
|
537
|
+
rateLimitEvidence = normalizeRouterWafRateEvidence({
|
|
538
|
+
completedAt: seed.completedAt,
|
|
539
|
+
rateLimitPerIp: input.policy.rateLimitPerIp,
|
|
540
|
+
stage: seed.stage,
|
|
541
|
+
startedAt: seed.startedAt,
|
|
542
|
+
value: seed.probes.rateLimit,
|
|
543
|
+
webAclName: seed.webAclName,
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
catch {
|
|
547
|
+
throw new Error(`Router WAF live evidence does not prove the exact ${seed.stage} blocking baseline.`);
|
|
548
|
+
}
|
|
549
|
+
if (rateLimitEvidence.blockedRequestStatus !== 403) {
|
|
550
|
+
throw new Error(`Router WAF live evidence does not prove the exact ${seed.stage} blocking baseline.`);
|
|
551
|
+
}
|
|
552
|
+
const policyDigest = routerWafPolicyDigest(input.policy);
|
|
553
|
+
const authorityEvidence = { ...evidence };
|
|
266
554
|
const evidenceDigest = `sha256:${(0, node_crypto_1.createHash)('sha256')
|
|
267
|
-
.update(canonical(
|
|
555
|
+
.update(canonical(authorityEvidence))
|
|
268
556
|
.digest('hex')}`;
|
|
269
557
|
return {
|
|
558
|
+
accountId: seed.accountId,
|
|
270
559
|
completedAt: evidence.completedAt,
|
|
560
|
+
deploymentRoleArn: seed.deploymentRoleArn,
|
|
271
561
|
evidenceDigest,
|
|
272
562
|
kind: exports.ROUTER_WAF_REHEARSAL_KIND,
|
|
273
563
|
mode: 'block',
|
|
274
564
|
policyDigest,
|
|
275
|
-
|
|
276
|
-
|
|
565
|
+
region: seed.region,
|
|
566
|
+
schemaVersion: exports.ROUTER_WAF_REHEARSAL_SCHEMA_VERSION,
|
|
567
|
+
stage: seed.stage,
|
|
277
568
|
status: 'passed',
|
|
569
|
+
wafContractDigest: seed.wafContractDigest,
|
|
570
|
+
workspace: seed.workspace,
|
|
278
571
|
};
|
|
279
572
|
}
|
|
280
573
|
function reconcileRouterWafBlockingRehearsal(input) {
|
|
@@ -285,6 +578,18 @@ function reconcileRouterWafBlockingRehearsal(input) {
|
|
|
285
578
|
evidence: input.evidence,
|
|
286
579
|
policy: input.policy,
|
|
287
580
|
});
|
|
581
|
+
for (const key of [
|
|
582
|
+
'accountId',
|
|
583
|
+
'deploymentRoleArn',
|
|
584
|
+
'region',
|
|
585
|
+
'stage',
|
|
586
|
+
'wafContractDigest',
|
|
587
|
+
'workspace',
|
|
588
|
+
]) {
|
|
589
|
+
if (observed[key] !== input.expected[key]) {
|
|
590
|
+
throw new Error(`Router WAF blocking rehearsal ${key} does not match committed production reconciliation authority.`);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
288
593
|
if (canonical(retained) !== canonical(observed)) {
|
|
289
594
|
throw new Error('Router WAF blocking rehearsal receipt does not match its exact live evidence.');
|
|
290
595
|
}
|
|
@@ -292,7 +597,13 @@ function reconcileRouterWafBlockingRehearsal(input) {
|
|
|
292
597
|
}
|
|
293
598
|
function createRouterWafStagePlan(input) {
|
|
294
599
|
const stage = (0, stages_js_1.requireFoundationStage)(input.stage);
|
|
600
|
+
if (!(0, policy_js_1.isActiveDeploymentStage)(input.policy.deploymentProfile, stage)) {
|
|
601
|
+
throw new Error(`Router WAF stage ${stage} is inactive for the ${input.policy.deploymentProfile} deployment profile.`);
|
|
602
|
+
}
|
|
295
603
|
const stagePolicy = input.policy.stages[stage];
|
|
604
|
+
if (!stagePolicy) {
|
|
605
|
+
throw new Error(`Router WAF ${stage} policy is missing.`);
|
|
606
|
+
}
|
|
296
607
|
const policyDigest = routerWafPolicyDigest(input.policy);
|
|
297
608
|
if (stagePolicy.access === 'allowlist' &&
|
|
298
609
|
stagePolicy.allowedCidrs.length === 0) {
|
|
@@ -302,8 +613,11 @@ function createRouterWafStagePlan(input) {
|
|
|
302
613
|
if (stagePolicy.mode !== 'block') {
|
|
303
614
|
throw new Error('Production Router WAF must deploy in blocking mode.');
|
|
304
615
|
}
|
|
305
|
-
if (!input.rehearsal ||
|
|
306
|
-
|
|
616
|
+
if (!input.rehearsal ||
|
|
617
|
+
input.rehearsal.policyDigest !== policyDigest ||
|
|
618
|
+
input.rehearsal.wafContractDigest !==
|
|
619
|
+
routerWafContractDigest(input.policy)) {
|
|
620
|
+
throw new Error(`Production Router WAF requires a passed ${(0, policy_js_1.productionRehearsalStage)(input.policy.deploymentProfile)} blocking rehearsal for the exact policy digest.`);
|
|
307
621
|
}
|
|
308
622
|
}
|
|
309
623
|
return {
|
|
@@ -398,4 +712,85 @@ function createRouterWafRules(plan, ipSets) {
|
|
|
398
712
|
}
|
|
399
713
|
return rules;
|
|
400
714
|
}
|
|
715
|
+
function contractStagePlan(policy, stage) {
|
|
716
|
+
const stagePolicy = policy.stages[stage];
|
|
717
|
+
if (!stagePolicy) {
|
|
718
|
+
throw new Error(`Router WAF ${stage} contract policy is missing.`);
|
|
719
|
+
}
|
|
720
|
+
return {
|
|
721
|
+
access: stagePolicy.access,
|
|
722
|
+
ipv4Cidrs: stagePolicy.allowedCidrs.filter((value) => (0, node_net_1.isIP)(value.split('/')[0] ?? '') === 4),
|
|
723
|
+
ipv6Cidrs: stagePolicy.allowedCidrs.filter((value) => (0, node_net_1.isIP)(value.split('/')[0] ?? '') === 6),
|
|
724
|
+
logging: policy.logging.enabled
|
|
725
|
+
? {
|
|
726
|
+
include: 'blocked',
|
|
727
|
+
redact: {
|
|
728
|
+
headers: ['authorization', 'cookie', 'x-api-key'],
|
|
729
|
+
queryString: true,
|
|
730
|
+
},
|
|
731
|
+
retention: policy.logging.retention,
|
|
732
|
+
}
|
|
733
|
+
: false,
|
|
734
|
+
mode: stagePolicy.mode,
|
|
735
|
+
policyDigest: routerWafPolicyDigest(policy),
|
|
736
|
+
rateLimitPerIp: policy.rateLimitPerIp,
|
|
737
|
+
stage,
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
function routerWafContractDigest(policy) {
|
|
741
|
+
const stages = (0, policy_js_1.activeDeploymentStages)(policy.deploymentProfile).map((stage) => {
|
|
742
|
+
const plan = contractStagePlan(policy, stage);
|
|
743
|
+
return {
|
|
744
|
+
plan,
|
|
745
|
+
rules: createRouterWafRules(plan, {
|
|
746
|
+
...(plan.ipv4Cidrs.length > 0
|
|
747
|
+
? { ipv4Arn: `<ipv4-ip-set:${stage}>` }
|
|
748
|
+
: {}),
|
|
749
|
+
...(plan.ipv6Cidrs.length > 0
|
|
750
|
+
? { ipv6Arn: `<ipv6-ip-set:${stage}>` }
|
|
751
|
+
: {}),
|
|
752
|
+
}),
|
|
753
|
+
};
|
|
754
|
+
});
|
|
755
|
+
const implementation = {
|
|
756
|
+
cloudFront: {
|
|
757
|
+
enabled: true,
|
|
758
|
+
identityTags: [
|
|
759
|
+
'ebk:managed-by',
|
|
760
|
+
'ebk:owner',
|
|
761
|
+
'ebk:stage',
|
|
762
|
+
'ebk:workspace',
|
|
763
|
+
],
|
|
764
|
+
staging: false,
|
|
765
|
+
webAclAttachment: 'exact-arn',
|
|
766
|
+
},
|
|
767
|
+
evidenceSchemaVersion: exports.ROUTER_WAF_LIVE_EVIDENCE_SCHEMA_VERSION,
|
|
768
|
+
kind: 'ebk-router-waf-generated-contract',
|
|
769
|
+
receiptSchemaVersion: exports.ROUTER_WAF_REHEARSAL_SCHEMA_VERSION,
|
|
770
|
+
schemaVersion: exports.ROUTER_WAF_CONTRACT_SCHEMA_VERSION,
|
|
771
|
+
stages,
|
|
772
|
+
webAcl: {
|
|
773
|
+
defaultAction: 'allow',
|
|
774
|
+
identityTags: [
|
|
775
|
+
'ebk:managed-by',
|
|
776
|
+
'ebk:owner',
|
|
777
|
+
'ebk:policy-digest',
|
|
778
|
+
'ebk:stage',
|
|
779
|
+
'ebk:workspace',
|
|
780
|
+
],
|
|
781
|
+
ipSetTags: [
|
|
782
|
+
'ebk:managed-by',
|
|
783
|
+
'ebk:owner',
|
|
784
|
+
'ebk:policy-digest',
|
|
785
|
+
'ebk:stage',
|
|
786
|
+
'ebk:workspace',
|
|
787
|
+
],
|
|
788
|
+
logging: policy.logging,
|
|
789
|
+
scope: 'CLOUDFRONT',
|
|
790
|
+
},
|
|
791
|
+
};
|
|
792
|
+
return `sha256:${(0, node_crypto_1.createHash)('sha256')
|
|
793
|
+
.update(canonical({ implementation, policy }))
|
|
794
|
+
.digest('hex')}`;
|
|
795
|
+
}
|
|
401
796
|
//# sourceMappingURL=router-waf.js.map
|