cdk-preflight 1.8.1 → 1.9.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/.jsii +3 -3
- package/README.md +3 -2
- package/docs/rules.md +94 -0
- package/lib/index.js +1 -1
- package/lib/rules.generated.js +1040 -2
- package/package.json +1 -1
package/.jsii
CHANGED
|
@@ -9626,7 +9626,7 @@
|
|
|
9626
9626
|
},
|
|
9627
9627
|
"name": "cdk-preflight",
|
|
9628
9628
|
"readme": {
|
|
9629
|
-
"markdown": "<p align=\"center\">\n <img src=\"https://raw.githubusercontent.com/badmintoncryer/cdk-preflight/main/assets/logo.png\" alt=\"cdk-preflight\" width=\"104\" height=\"104\">\n</p>\n\n<h1 align=\"center\">cdk-preflight</h1>\n\n<p align=\"center\">\n <strong>Catch deploy-time CloudFormation failures at <code>cdk synth</code> time.</strong>\n</p>\n\n<p align=\"center\">\n <a href=\"https://github.com/badmintoncryer/cdk-preflight/actions/workflows/monthly-verify.yml\"><img src=\"https://github.com/badmintoncryer/cdk-preflight/actions/workflows/monthly-verify.yml/badge.svg\" alt=\"monthly real-deploy verification\"></a>\n <a href=\"https://www.npmjs.com/package/cdk-preflight\"><img src=\"https://img.shields.io/npm/v/cdk-preflight.svg\" alt=\"npm version\"></a>\n <a href=\"https://www.npmjs.com/package/cdk-preflight\"><img src=\"https://img.shields.io/npm/dt/cdk-preflight.svg\" alt=\"npm total downloads\"></a>\n <a href=\"docs/rules.md\"><img src=\"https://img.shields.io/badge/rules-3267-blue\" alt=\"3267 bundled rules\"></a>\n</p>\n\nSome CloudFormation constraints are not expressed in resource provider schemas — they live only in documentation, in service API validation, or across multiple properties. Templates that violate them pass `cdk synth`, pass CloudFormation pre-deployment validation, and then fail minutes into a deployment, burning a rollback cycle.\n\ncdk-preflight is a curated [Rego rule pack](docs/rules.md) for exactly those constraints, evaluated with the CloudFormation validation engine that ships inside `aws-cdk-lib` (>= 2.267.0). By default a violation **fails `cdk synth`** — a template that is known to fail at deploy time never leaves your machine.\n\nThe pack aims at **every deploy-time failure, and every post-deploy run that is certain to fail, that no existing CDK mechanism already catches** — nothing narrower. Every bundled rule is backed by a `fail`/`pass` template pair, and the failure has been reproduced against real AWS. The handful of rules that could not be reproduced are marked `doc-only` and report as **warnings**, as does a rule whose remaining false positives cannot be told from the template (a cross-account Lambda layer the owner may have shared): they show up in the validation report but never fail synth. Rules that the built-in validation engine already covers are deliberately **not** duplicated — a test suite enforces this, and a rule the engine catches up with later is skipped on engines that cover it (see [Scope and rule lifecycle](#scope-and-rule-lifecycle)).\n\n> **Requires `aws-cdk-lib` >= 2.267.0** (released 2026-08-27) — the first release that bundles\n> the CloudFormation validation engine. On older versions the rules cannot run at all.\n\n## Quick start\n\n```bash\nnpm i -D cdk-preflight\nnpx cdkpf init # inserts Preflight.apply(app) into your CDK app\n # (`npx cdkpf init` is the same command, shorter)\n```\n\nor add one line yourself:\n\n```ts\nimport { Preflight } from 'cdk-preflight';\n\nconst app = new App();\nPreflight.apply(app);\n```\n\nOn violation, `cdk synth` fails with one error per finding, including the construct trace:\n\n```text\nERROR idle_timeout.timeout_seconds is 5000 but must be between 1 and 4000 seconds (cdk-preflight)\n MyStack/Alb/Resource (Alb16C2F182) aws-cdk-lib.aws_elasticloadbalancingv2.CfnLoadBalancer\n\nSynthesis finished with errors\n```\n\n## What it catches\n\nFour ordinary-looking snippets. All of them pass `cdk synth` and CloudFormation\npre-deployment validation, and all of them fail minutes into a deployment:\n\n```ts\n// 1) pf-iam-inline-policy-size — enumerate buckets, grant each one, blow past 10,240 chars\n// \"Maximum policy size of 10240 bytes exceeded for role IngestRole\"\n// (via role.addToPolicy the CDK auto-splits into managed policies instead,\n// and you hit the 6,144-char limit as pf-iam-managed-policy-size)\nnew iam.Policy(this, 'IngestPolicy', {\n roles: [role],\n statements: [new iam.PolicyStatement({\n actions: ['s3:GetObject', 's3:ListBucket'],\n resources: Array.from({ length: 200 },\n (_, i) => `arn:aws:s3:::data-lake-landing-zone-${i}/year=*/month=*/*`),\n })],\n});\n\n// 2) pf-lambda-env-size — a config blob in the environment, over the 4KB total\n// \"Lambda was unable to configure your environment variables because the\n// environment variables you have provided exceeded the 4KB limit\"\nnew lambda.Function(this, 'Fn', {\n runtime: lambda.Runtime.NODEJS_22_X,\n handler: 'index.handler',\n code: lambda.Code.fromInline('exports.handler = async () => {};'),\n environment: { FEATURE_FLAGS: JSON.stringify(bigFeatureFlagMap) },\n});\n\n// 3) pf-sfn-asl-missing-state (+ pf-sfn-asl-unreachable-state) — a typo in a state name\n// \"Invalid State Machine Definition: 'MISSING_TRANSITION_TARGET: ...'\"\nnew sfn.StateMachine(this, 'Pipeline', {\n definitionBody: sfn.DefinitionBody.fromString(JSON.stringify({\n StartAt: 'Validate',\n States: {\n Validate: { Type: 'Pass', Next: 'Transform' },\n Trasform: { Type: 'Pass', End: true }, // typo: Transform\n },\n })),\n});\n\n// 4) pf-logs-filter-pattern-bracket — a filter pattern opened with '[' and never closed\n// \"If a filter pattern starts with '[' it must end with ']'\"\nnew logs.MetricFilter(this, 'ErrorFilter', {\n logGroup,\n metricNamespace: 'Pipeline',\n metricName: 'Errors',\n filterPattern: logs.FilterPattern.literal('[time, level=ERROR, msg'),\n});\n```\n\nNone of these are type errors, so the L2 constructs accept them; none of them are\nexpressible in a resource schema, so CloudFormation accepts the template. With\n`Preflight.apply(app)` in place they fail `cdk synth` instead.\n\n## Observe-only mode\n\nTo roll the rules out gradually, start with `enforce: false`: findings then surface as synth **warnings** through the CDK built-in validator, with construct traces and per-finding acknowledgement:\n\n```ts\nPreflight.apply(app, { enforce: false });\n```\n\n```text\nWARNING idle_timeout.timeout_seconds is 5000 but must be between 1 and 4000 seconds (CloudFormation Validate)\n MyStack/Alb (Alb) aws-cdk-lib.aws_elasticloadbalancingv2.CfnLoadBalancer\n Acknowledge with 'CloudFormation-Validate::pf-elbv2-lb-idle-timeout-range'\n```\n\n> **Known limitation with stages.** The AWS CDK CLI drops validation findings for stacks nested in a `Stage`\n> before printing them, so in observe-only mode those findings appear **only** in `cdk.out/validation-report.json`\n> and never on the console. Enforce mode is not affected: cdk-preflight reports such findings itself and fails\n> synthesis. This is a CLI-side bug (present since aws-cdk 2.1128.1), not a rule evaluation problem.\n\n> **If the rules cannot run, the build stops.** When the evaluation engine fails on a template (a rule pack that\n> does not compile, an engine bug), enforce mode reports it as a violation named `pf-engine-error` and fails\n> synthesis for that stack instead of passing green with no rule having run. The other stacks keep their rules.\n> `pf-engine-error` is not a bundled rule and cannot be `exclude`d; `enforce: false` unblocks the build if you\n> need one.\n\n| Option | Default | Effect |\n|---|---|---|\n| `enforce` | `true` | Violations of bundled rules fail synthesis; set to `false` to only warn |\n| `strict` | `false` | With `enforce`: also fail on error-class findings (`ERROR`/`FATAL`, e.g. `F3034`) of the built-in validation engine itself, which the CDK currently downgrades to warnings |\n| `exclude` | `[]` | Rule ids to disable |\n| `includeUpstreamPending` | `true` | Include rules already proposed to the upstream engine but not yet merged |\n| `checkQuotas` | `false` | Also check the target account's Service Quotas and current usage (calls AWS at synth time, see below) |\n| `quotaCacheTtl` | 5 minutes | How long `checkQuotas` reuses the usage and deployed-stack state it fetched |\n\nTo opt out of a single rule everywhere, pass its id in `exclude`. To suppress a\nsingle *finding* on one construct, acknowledge it — this works in both modes, the\nid prefix just differs (`cdk-preflight::` when enforcing, `CloudFormation-Validate::`\nin observe-only, as printed in the warning text):\n\n```ts\ncdk.Validations.of(errorFilter).acknowledge({\n id: 'cdk-preflight::pf-logs-filter-pattern-bracket',\n reason: 'log group is written by a legacy producer; pattern is fixed upstream',\n});\n```\n\n## Service quota check (opt-in)\n\nThe rules only read the template, so they never assert a limit an account can raise. `checkQuotas: true` covers that\ngap for the quotas a CDK app runs into most: it adds up what every stack in the app (nested stacks included) is about\nto create in each account and Region, and compares that against the account's applied quota and current usage.\n\n```ts\nPreflight.apply(app, { checkQuotas: true });\n```\n\n| Check | Counts | Against |\n|---|---|---|\n| `pf-quota-vpcs-per-region` | new `AWS::EC2::VPC` | VPCs per Region (`vpc/L-F678F1CE`) |\n| `pf-quota-internet-gateways-per-region` | new `AWS::EC2::InternetGateway` | Internet gateways per Region (`vpc/L-A4707A72`) |\n| `pf-quota-elastic-ips-per-region` | new `AWS::EC2::EIP` (one per NAT gateway in a default `ec2.Vpc`) | EC2-VPC Elastic IPs (`ec2/L-0263D0A3`) |\n| `pf-quota-lambda-unreserved-concurrency` | increase in `ReservedConcurrentExecutions` | Lambda keeps at least 100 concurrent executions unreserved |\n\n- **Only new resources count.** The deployed template of each stack is read with `GetTemplate`; a resource whose\n logical id and type are already deployed is not counted again, so redeploying an unchanged app never trips the\n check. Resources behind a `Condition` and the brief overlap during a replacement are not counted.\n- **A finding fails synth** in enforce mode and is a warning with `enforce: false`. Acknowledge one like any other\n finding (`cdk-preflight::pf-quota-...`; `cdk-preflight-quotas::pf-quota-...` with `enforce: false`). The ids also work in `exclude`, including `pf-quota-check-skipped` to silence the skip warning.\n- **It needs credentials in the app process.** The CDK CLI does not pass `--profile` on to the app, so set\n `AWS_PROFILE` (or `AWS_*` variables) instead. When the credentials are missing, lack permissions, or belong to a\n different account than the stack's, the check is skipped with a `pf-quota-check-skipped` warning and synth goes on.\n- **Permissions:** `servicequotas:GetServiceQuota`, `servicequotas:GetAWSDefaultServiceQuota`, `ec2:DescribeVpcs`,\n `ec2:DescribeInternetGateways`, `ec2:DescribeAddresses`, `lambda:GetAccountSettings`, `cloudformation:GetTemplate`,\n `cloudformation:DescribeStackResource`. All read-only (`ReadOnlyAccess` covers them). The check also calls\n `sts:GetCallerIdentity`, which IAM never denies.\n- **Results are cached** in `cdk.out/.cdk-preflight/quota-cache.json`: usage and deployed templates for\n `quotaCacheTtl` (5 minutes), quota values for 24 hours. Delete the file to force a refetch.\n- Usage can change between synth and deploy (another team deploying to the same account), so a clean check is not a\n guarantee. The reverse also happens: EC2 does not always enforce the Elastic IP quota when CloudFormation\n creates several addresses in parallel (measured 2026-10-16: with 4 of 5 in use, two parallel `AWS::EC2::EIP` both\n succeeded), so a template the check stops may occasionally deploy. The check follows the quota, not the race.\n\n## Bundled rules\n\nSee [docs/rules.md](docs/rules.md) for the generated rule table.\n\n<!-- supported-resources:start -->\n<details>\n<summary><b>417 resource types across 77 services</b> — click to expand</summary>\n\nResource names are relative to `AWS::<Service>::`; the number in parentheses is how many rules target that type.\n\n| Service | Resource types |\n|---|---|\n| **(any resource type)** | `*` (14) |\n| **ApiGateway** | `ApiKey` (1), `Authorizer` (5), `Deployment` (1), `DocumentationPart` (1), `DomainName` (4), `GatewayResponse` (1), `Method` (14), `Model` (3), `Resource` (1), `RestApi` (5), `Stage` (9), `UsagePlan` (5), `VpcLink` (1) |\n| **ApiGatewayV2** | `Api` (5), `Authorizer` (11), `DomainName` (3), `Integration` (15), `IntegrationResponse` (1), `Model` (2), `Route` (6), `RouteResponse` (2), `Stage` (4), `VpcLink` (1) |\n| **ApplicationAutoScaling** | `ScalableTarget` (19), `ScalingPolicy` (30) |\n| **AppSync** | `Api` (7), `ApiCache` (4), `ApiKey` (2), `ChannelNamespace` (5), `DataSource` (15), `DomainName` (1), `FunctionConfiguration` (24), `GraphQLApi` (16), `GraphQLSchema` (12), `Resolver` (32), `SourceApiAssociation` (3) |\n| **APS** | `AnomalyDetector` (9), `ResourcePolicy` (5), `RuleGroupsNamespace` (10), `Workspace` (12) |\n| **Athena** | `DataCatalog` (6), `WorkGroup` (8) |\n| **AutoScaling** | `AutoScalingGroup` (38), `LifecycleHook` (8), `ScalingPolicy` (41), `ScheduledAction` (13), `WarmPool` (4) |\n| **Backup** | `BackupPlan` (12), `BackupSelection` (5), `BackupVault` (3), `Framework` (3), `LogicallyAirGappedBackupVault` (2), `ReportPlan` (2), `RestoreTestingPlan` (5), `RestoreTestingSelection` (3) |\n| **Batch** | `ComputeEnvironment` (40), `ConsumableResource` (2), `JobDefinition` (109), `JobQueue` (18), `SchedulingPolicy` (8), `ServiceEnvironment` (6) |\n| **Bedrock** | `ApplicationInferenceProfile` (2), `AutomatedReasoningPolicy` (3), `Blueprint` (3), `DataAutomationProject` (8), `DataSource` (12), `Flow` (14), `Guardrail` (19), `IntelligentPromptRouter` (5), `KnowledgeBase` (18), `Prompt` (4) |\n| **BedrockAgentCore** | `ApiKeyCredentialProvider` (1), `BrowserCustom` (1), `BrowserProfile` (1), `CapacityProvider` (8), `CodeInterpreterCustom` (1), `ConfigurationBundle` (4), `Dataset` (3), `Evaluator` (4), `Gateway` (16), `GatewayRateLimit` (5), `GatewayRule` (5), `GatewayTarget` (11), `Harness` (2), `HarnessEndpoint` (2), `Memory` (14), `OAuth2CredentialProvider` (5), `OnlineEvaluationConfig` (3), `PaymentCredentialProvider` (1), `PaymentManager` (1), `Policy` (3), `ResourcePolicy` (1), `Runtime` (16), `RuntimeEndpoint` (1) |\n| **Cassandra** | `Keyspace` (2), `Table` (22), `Type` (13) |\n| **CertificateManager** | `Certificate` (4) |\n| **CloudFormation** | `GuardHook` (1), `Stack` (2), `StackSet` (6) |\n| **CloudFront** | `AnycastIpList` (1), `CachePolicy` (7), `ContinuousDeploymentPolicy` (5), `Distribution` (55), `Function` (4), `KeyGroup` (1), `KeyValueStore` (2), `OriginRequestPolicy` (5), `PublicKey` (1), `RealtimeLogConfig` (3), `ResponseHeadersPolicy` (8), `VpcOrigin` (3) |\n| **CloudTrail** | `EventDataStore` (1), `Trail` (19) |\n| **CloudWatch** | `Alarm` (22), `AnomalyDetector` (6), `CompositeAlarm` (7), `Dashboard` (14), `InsightRule` (7), `MetricStream` (6) |\n| **CodeBuild** | `Project` (37), `ReportGroup` (2), `SourceCredential` (4) |\n| **CodeCommit** | `Repository` (11) |\n| **CodeDeploy** | `Application` (7), `DeploymentConfig` (12), `DeploymentGroup` (23) |\n| **CodePipeline** | `CustomActionType` (3), `Pipeline` (25), `Webhook` (2) |\n| **Cognito** | `IdentityPool` (3), `IdentityPoolRoleAttachment` (7), `LogDeliveryConfiguration` (3), `ManagedLoginBranding` (2), `UserPool` (52), `UserPoolClient` (21), `UserPoolDomain` (7), `UserPoolGroup` (1), `UserPoolIdentityProvider` (11), `UserPoolResourceServer` (4), `UserPoolRiskConfigurationAttachment` (6), `UserPoolUICustomizationAttachment` (2) |\n| **Config** | `ConfigRule` (6), `ConfigurationAggregator` (2), `ConfigurationRecorder` (7), `ConformancePack` (1), `RemediationConfiguration` (2) |\n| **DocDB** | `DBCluster` (14), `DBInstance` (1), `DBSubnetGroup` (2), `EventSubscription` (1) |\n| **DocDBElastic** | `Cluster` (7) |\n| **DynamoDB** | `GlobalTable` (25), `Table` (28) |\n| **EC2** | `ClientVpnAuthorizationRule` (1), `ClientVpnEndpoint` (6), `DHCPOptions` (2), `EIPAssociation` (1), `FlowLog` (4), `Instance` (10), `KeyPair` (1), `LaunchTemplate` (12), `NatGateway` (2), `NetworkAclEntry` (1), `NetworkInterface` (2), `PlacementGroup` (3), `PrefixList` (3), `Route` (1), `SecurityGroup` (7), `SecurityGroupEgress` (5), `SecurityGroupIngress` (5), `Subnet` (14), `TrafficMirrorTarget` (1), `TransitGateway` (2), `TransitGatewayRoute` (1), `Volume` (6), `VPC` (2), `VPCCidrBlock` (1), `VPCEndpoint` (4), `VPCGatewayAttachment` (1), `VPNConnection` (5) |\n| **ECR** | `PullThroughCacheRule` (3), `RegistryScanningConfiguration` (1), `ReplicationConfiguration` (1), `Repository` (7), `RepositoryCreationTemplate` (8), `SigningConfiguration` (1) |\n| **ECS** | `CapacityProvider` (3), `Cluster` (5), `Service` (37), `TaskDefinition` (66), `TaskSet` (2) |\n| **EFS** | `AccessPoint` (1), `FileSystem` (7), `MountTarget` (4) |\n| **EKS** | `AccessEntry` (14), `Addon` (5), `Cluster` (21), `FargateProfile` (5), `IdentityProviderConfig` (3), `Nodegroup` (21), `PodIdentityAssociation` (5) |\n| **ElastiCache** | `CacheCluster` (9), `ReplicationGroup` (14), `User` (2), `UserGroup` (1) |\n| **ElasticBeanstalk** | `Application` (2), `ConfigurationTemplate` (37), `Environment` (35) |\n| **ElasticLoadBalancingV2** | `Listener` (57), `ListenerCertificate` (2), `ListenerRule` (38), `LoadBalancer` (37), `TargetGroup` (58), `TrustStore` (1), `TrustStoreRevocation` (1) |\n| **Events** | `ApiDestination` (1), `Archive` (5), `Connection` (1), `Endpoint` (2), `EventBus` (2), `Rule` (27) |\n| **EventSchemas** | `Discoverer` (1), `Registry` (1), `RegistryPolicy` (1), `Schema` (1) |\n| **GlobalAccelerator** | `Accelerator` (1), `EndpointGroup` (5), `Listener` (2) |\n| **Glue** | `Classifier` (6), `Connection` (5), `Crawler` (11), `CustomEntityType` (1), `Database` (1), `DataQualityRuleset` (1), `Job` (15), `MLTransform` (4), `Partition` (1), `Schema` (3), `SecurityConfiguration` (1), `Table` (1), `Trigger` (10), `UserDefinedFunction` (2), `Workflow` (1) |\n| **Grafana** | `Workspace` (7) |\n| **IAM** | `Group` (23), `GroupPolicy` (19), `InstanceProfile` (2), `ManagedPolicy` (31), `OIDCProvider` (2), `Policy` (29), `Role` (44), `RolePolicy` (19), `ServiceLinkedRole` (1), `User` (24), `UserPolicy` (19) |\n| **IoT** | `Authorizer` (3), `Certificate` (1), `CertificateProvider` (1), `Command` (1), `DomainConfiguration` (3), `JobTemplate` (3), `MitigationAction` (1), `Policy` (4), `PolicyPrincipalAttachment` (1), `ProvisioningTemplate` (3), `RoleAlias` (1), `ScheduledAudit` (1), `Thing` (1), `ThingGroup` (2), `TopicRule` (5), `TopicRuleDestination` (2) |\n| **Kinesis** | `ResourcePolicy` (4), `Stream` (5), `StreamConsumer` (2) |\n| **KinesisAnalyticsV2** | `Application` (20), `ApplicationCloudWatchLoggingOption` (1), `ApplicationOutput` (1), `ApplicationReferenceDataSource` (1) |\n| **KinesisFirehose** | `DeliveryStream` (68) |\n| **KMS** | `Alias` (2), `Key` (12), `ReplicaKey` (4) |\n| **Lambda** | `Alias` (7), `CodeSigningConfig` (1), `EventInvokeConfig` (5), `EventSourceMapping` (54), `Function` (48), `LayerVersion` (8), `LayerVersionPermission` (3), `Permission` (8), `Url` (8), `Version` (1) |\n| **Logs** | `AccountPolicy` (6), `DeliveryDestination` (3), `Destination` (1), `LogAnomalyDetector` (2), `LogGroup` (10), `MetricFilter` (7), `QueryDefinition` (1), `ResourcePolicy` (1), `SubscriptionFilter` (6), `Transformer` (3) |\n| **MediaConvert** | `JobTemplate` (9), `Preset` (32), `Queue` (2) |\n| **MemoryDB** | `Cluster` (8), `User` (1) |\n| **MSK** | `BatchScramSecret` (2), `Cluster` (31), `ClusterPolicy` (1), `Configuration` (4), `Replicator` (10), `ServerlessCluster` (4) |\n| **Neptune** | `DBCluster` (11), `DBClusterParameterGroup` (1), `DBInstance` (3), `DBSubnetGroup` (1), `GlobalCluster` (1) |\n| **NeptuneGraph** | `Graph` (2), `PrivateGraphEndpoint` (1) |\n| **NetworkFirewall** | `FirewallPolicy` (18), `RuleGroup` (34), `TLSInspectionConfiguration` (7) |\n| **OpenSearchServerless** | `AccessPolicy` (7), `Collection` (2), `CollectionGroup` (3), `LifecyclePolicy` (4), `SecurityConfig` (5), `SecurityPolicy` (14) |\n| **OpenSearchService** | `Domain` (65) |\n| **Pipes** | `Pipe` (9) |\n| **RDS** | `DBCluster` (19), `DBInstance` (33), `DBParameterGroup` (2), `DBProxy` (4), `DBProxyTargetGroup` (2), `DBShardGroup` (1), `DBSubnetGroup` (3), `EventSubscription` (3), `OptionGroup` (1) |\n| **Redshift** | `Cluster` (20), `EventSubscription` (1), `ScheduledAction` (2) |\n| **RedshiftServerless** | `Namespace` (5), `Workgroup` (6) |\n| **Route53** | `CidrCollection` (11), `DNSSEC` (3), `HealthCheck` (30), `HostedZone` (14), `KeySigningKey` (9), `RecordSet` (74), `RecordSetGroup` (76) |\n| **Route53Profiles** | `ProfileAssociation` (1), `ProfileResourceAssociation` (6) |\n| **Route53Resolver** | `FirewallDomainList` (3), `FirewallRuleGroup` (18), `FirewallRuleGroupAssociation` (4), `ResolverDNSSECConfig` (1), `ResolverEndpoint` (18), `ResolverQueryLoggingConfig` (1), `ResolverQueryLoggingConfigAssociation` (1), `ResolverRule` (15), `ResolverRuleAssociation` (1) |\n| **S3** | `AccessPoint` (1), `Bucket` (54), `BucketPolicy` (4), `StorageLens` (5), `StorageLensGroup` (3) |\n| **S3Express** | `AccessPoint` (3), `DirectoryBucket` (11) |\n| **Scheduler** | `Schedule` (12), `ScheduleGroup` (1) |\n| **SecretsManager** | `RotationSchedule` (4), `Secret` (5), `SecretTargetAttachment` (1) |\n| **ServiceDiscovery** | `HttpNamespace` (3), `Instance` (19), `PrivateDnsNamespace` (4), `PublicDnsNamespace` (4), `Service` (13) |\n| **SES** | `ConfigurationSetEventDestination` (8), `ContactList` (1), `EmailIdentity` (6), `ReceiptRule` (6), `ReceiptRuleSet` (1), `Template` (1) |\n| **SNS** | `Subscription` (10), `Topic` (14), `TopicPolicy` (1) |\n| **SQS** | `Queue` (10), `QueuePolicy` (1) |\n| **SSM** | `Association` (4), `Document` (3), `MaintenanceWindow` (2), `MaintenanceWindowTarget` (1), `MaintenanceWindowTask` (1), `Parameter` (5) |\n| **StepFunctions** | `Activity` (3), `StateMachine` (26) |\n| **Synthetics** | `Canary` (16) |\n| **VerifiedPermissions** | `IdentitySource` (3), `Policy` (26), `PolicyStore` (23), `PolicyStoreAlias` (1), `PolicyTemplate` (29) |\n| **WAFv2** | `IPSet` (3), `LoggingConfiguration` (3), `RegexPatternSet` (3), `RuleGroup` (18), `WebACL` (23), `WebACLAssociation` (2) |\n| **XRay** | `Group` (1), `ResourcePolicy` (3), `SamplingRule` (6) |\n\n</details>\n<!-- supported-resources:end -->\n\nHighlights:\n\n- **ELBv2**: `idle_timeout` / `deregistration_delay` / `slow_start` attribute ranges (stringly-typed Key/Value attributes are invisible to schema validation)\n- **IAM**: managed (6,144 chars) and inline (role/group/user) policy document size limits\n- **CloudFront**: `MinTTL <= DefaultTTL <= MaxTTL` ordering, ACM certificates must live in `us-east-1`\n- **Step Functions**: `Next`/`Default`/`Choices` must reference defined states (a dangling `StartAt` is already caught by the engine's built-in `E3601`)\n- **EC2**: security group TCP/UDP port ranges and `FromPort <= ToPort`\n\n## For AI agents\n\nTo add cdk-preflight to a CDK app:\n\n1. `npm i -D cdk-preflight`\n2. `npx cdk-preflight init` — or the shorter alias `npx cdkpf init` (finds the entry point via `cdk.json` and inserts `Preflight.apply(app)`; use `--dry-run` to preview)\n3. Run `cdk synth`. Violations fail the synth with a validation report; each finding carries a rule id, the actual value, and a suggested fix\n4. To fix a finding, prefer correcting the resource. To opt out instead: `exclude: ['<rule-id>']` disables one rule, `enforce: false` switches to warn-only reporting\n\nThe machine-readable findings are written to `cdk.out/validation-report.json` when synthesizing with `-c @aws-cdk/core:validationReportJson=true`.\n\n### Report missed deploy errors\n\ncdk-preflight only knows the failure modes it has benched. When a deploy fails on a constraint the pack should have caught, that report is how new rules get added — but at that moment cdk-preflight is out of the loop (it passed the synth), so the instruction has to already sit in your agent's context. Paste this into your repository's `AGENTS.md` (or `CLAUDE.md`):\n\n```markdown\n## cdk-preflight: report missed deploy errors\n\nIf `cdk deploy` fails even though `cdk synth` (with cdk-preflight enabled) passed,\nand the failure is a service-side validation rejection — CREATE_FAILED/UPDATE_FAILED\nwith a 400-class message such as \"Invalid request provided: ...\" — cdk-preflight is\nmissing a rule. Report it:\n\n1. Qualify first. NOT reportable: AccessDenied / permissions, service quotas\n (those belong to the opt-in `checkQuotas`; open a regular issue if it missed one),\n throttling, name conflicts with existing resources, stabilization timeouts.\n2. Redact account-specific data (account IDs -> 123456789012, real ARNs/domains\n -> placeholders).\n3. Search existing issues: https://github.com/badmintoncryer/cdk-preflight/issues\n4. With your user's approval, open a \"Missed deploy error\" issue with the verbatim\n error message, the resource type, a minimal template snippet, and your\n aws-cdk-lib / cdk-preflight versions.\n```\n\n## Scope and rule lifecycle\n\nA constraint belongs in the pack when violating it makes a real deployment fail, or lets the deployment succeed and then makes every run of the deployed resource fail (an SSM Automation association that targets several tags, for example), *and* no layer that sees the same synthesized template already blocks it. There is no further \"is this worth a rule\" question — if the gap is real, it gets a rule.\n\nCDK L2 construct validation is deliberately **not** one of those layers. `CfnXxx` usage, escape hatches, `addPropertyOverride`, `cloudformation-include` and migrated templates all bypass L2, so an L2 guard covering the same mistake neither disqualifies a rule nor retires one.\n\nThat makes growth the normal state, and it has a consequence worth knowing before you upgrade: **new rules land in minor releases, so a minor upgrade can newly fail a `cdk synth` that passed yesterday.** That is intended, not a regression. If you need a frozen rule set, pin the version; to drop a single rule, `exclude: ['<rule-id>']`; to see everything without failing the build, `enforce: false`.\n\nRules move the other way too. Once the validation engine bundled in `aws-cdk-lib` starts blocking a constraint, the rule records the engine version that covers it and stops being evaluated on that engine or later — but only where that changes nothing about whether synth fails: with `enforce: false`, with `strict: true`, or when your app sets the context `@aws-cdk/core:validateAgainstDefaultRules: true`. In the default enforce mode the CDK reports its own engine's errors as warnings, so the rule keeps running and you may see both. Users on an older `aws-cdk-lib` keep the rule either way; it is deleted only once the minimum supported `aws-cdk-lib` bundles an engine that covers it.\n\n## How it works\n\n`Preflight.apply()` evaluates the rules with the [cloudformation-validate](https://github.com/aws-cloudformation/cloudformation-validate) Rust/WASM engine that ships inside `aws-cdk-lib` — no extra binaries, and no network access at synth time unless you opt in to `checkQuotas`, which calls AWS from a child process. In the default enforce mode the engine is invoked through a dedicated CDK validation plugin so that violations fail synthesis; with `enforce: false` the rules are instead injected into the CDK built-in `CloudFormationValidatePlugin` and reported as warnings.\n\nConstraints that *can* be expressed in schemas or generic engine rules also make good upstream PRs to that engine, but nothing here waits on one — the upstream release cycle is deliberately slower than this pack's. Each rule's `meta.yaml` tracks its upstream status so that retirement stays bookkeeping.\n\n## Requirements\n\n- `aws-cdk-lib` >= 2.267.0, released 2026-08-27 (the first release that bundles the built-in CloudFormation validator). This is a recent release — an existing CDK app may need an upgrade before cdk-preflight can run.\n\n## Contributing\n\nRule authoring, the verification gates (including real-deploy reproduction), and the test layout are documented in [AGENTS.md](AGENTS.md) — written for AI coding agents and humans alike.\n\n## License\n\nApache-2.0\n"
|
|
9629
|
+
"markdown": "<p align=\"center\">\n <img src=\"https://raw.githubusercontent.com/badmintoncryer/cdk-preflight/main/assets/logo.png\" alt=\"cdk-preflight\" width=\"104\" height=\"104\">\n</p>\n\n<h1 align=\"center\">cdk-preflight</h1>\n\n<p align=\"center\">\n <strong>Catch deploy-time CloudFormation failures at <code>cdk synth</code> time.</strong>\n</p>\n\n<p align=\"center\">\n <a href=\"https://github.com/badmintoncryer/cdk-preflight/actions/workflows/monthly-verify.yml\"><img src=\"https://github.com/badmintoncryer/cdk-preflight/actions/workflows/monthly-verify.yml/badge.svg\" alt=\"monthly real-deploy verification\"></a>\n <a href=\"https://www.npmjs.com/package/cdk-preflight\"><img src=\"https://img.shields.io/npm/v/cdk-preflight.svg\" alt=\"npm version\"></a>\n <a href=\"https://www.npmjs.com/package/cdk-preflight\"><img src=\"https://img.shields.io/npm/dt/cdk-preflight.svg\" alt=\"npm total downloads\"></a>\n <a href=\"docs/rules.md\"><img src=\"https://img.shields.io/badge/rules-3361-blue\" alt=\"3361 bundled rules\"></a>\n</p>\n\nSome CloudFormation constraints are not expressed in resource provider schemas — they live only in documentation, in service API validation, or across multiple properties. Templates that violate them pass `cdk synth`, pass CloudFormation pre-deployment validation, and then fail minutes into a deployment, burning a rollback cycle.\n\ncdk-preflight is a curated [Rego rule pack](docs/rules.md) for exactly those constraints, evaluated with the CloudFormation validation engine that ships inside `aws-cdk-lib` (>= 2.267.0). By default a violation **fails `cdk synth`** — a template that is known to fail at deploy time never leaves your machine.\n\nThe pack aims at **every deploy-time failure, and every post-deploy run that is certain to fail, that no existing CDK mechanism already catches** — nothing narrower. Every bundled rule is backed by a `fail`/`pass` template pair, and the failure has been reproduced against real AWS. The handful of rules that could not be reproduced are marked `doc-only` and report as **warnings**, as does a rule whose remaining false positives cannot be told from the template (a cross-account Lambda layer the owner may have shared): they show up in the validation report but never fail synth. Rules that the built-in validation engine already covers are deliberately **not** duplicated — a test suite enforces this, and a rule the engine catches up with later is skipped on engines that cover it (see [Scope and rule lifecycle](#scope-and-rule-lifecycle)).\n\n> **Requires `aws-cdk-lib` >= 2.267.0** (released 2026-08-27) — the first release that bundles\n> the CloudFormation validation engine. On older versions the rules cannot run at all.\n\n## Quick start\n\n```bash\nnpm i -D cdk-preflight\nnpx cdkpf init # inserts Preflight.apply(app) into your CDK app\n # (`npx cdkpf init` is the same command, shorter)\n```\n\nor add one line yourself:\n\n```ts\nimport { Preflight } from 'cdk-preflight';\n\nconst app = new App();\nPreflight.apply(app);\n```\n\nOn violation, `cdk synth` fails with one error per finding, including the construct trace:\n\n```text\nERROR idle_timeout.timeout_seconds is 5000 but must be between 1 and 4000 seconds (cdk-preflight)\n MyStack/Alb/Resource (Alb16C2F182) aws-cdk-lib.aws_elasticloadbalancingv2.CfnLoadBalancer\n\nSynthesis finished with errors\n```\n\n## What it catches\n\nFour ordinary-looking snippets. All of them pass `cdk synth` and CloudFormation\npre-deployment validation, and all of them fail minutes into a deployment:\n\n```ts\n// 1) pf-iam-inline-policy-size — enumerate buckets, grant each one, blow past 10,240 chars\n// \"Maximum policy size of 10240 bytes exceeded for role IngestRole\"\n// (via role.addToPolicy the CDK auto-splits into managed policies instead,\n// and you hit the 6,144-char limit as pf-iam-managed-policy-size)\nnew iam.Policy(this, 'IngestPolicy', {\n roles: [role],\n statements: [new iam.PolicyStatement({\n actions: ['s3:GetObject', 's3:ListBucket'],\n resources: Array.from({ length: 200 },\n (_, i) => `arn:aws:s3:::data-lake-landing-zone-${i}/year=*/month=*/*`),\n })],\n});\n\n// 2) pf-lambda-env-size — a config blob in the environment, over the 4KB total\n// \"Lambda was unable to configure your environment variables because the\n// environment variables you have provided exceeded the 4KB limit\"\nnew lambda.Function(this, 'Fn', {\n runtime: lambda.Runtime.NODEJS_22_X,\n handler: 'index.handler',\n code: lambda.Code.fromInline('exports.handler = async () => {};'),\n environment: { FEATURE_FLAGS: JSON.stringify(bigFeatureFlagMap) },\n});\n\n// 3) pf-sfn-asl-missing-state (+ pf-sfn-asl-unreachable-state) — a typo in a state name\n// \"Invalid State Machine Definition: 'MISSING_TRANSITION_TARGET: ...'\"\nnew sfn.StateMachine(this, 'Pipeline', {\n definitionBody: sfn.DefinitionBody.fromString(JSON.stringify({\n StartAt: 'Validate',\n States: {\n Validate: { Type: 'Pass', Next: 'Transform' },\n Trasform: { Type: 'Pass', End: true }, // typo: Transform\n },\n })),\n});\n\n// 4) pf-logs-filter-pattern-bracket — a filter pattern opened with '[' and never closed\n// \"If a filter pattern starts with '[' it must end with ']'\"\nnew logs.MetricFilter(this, 'ErrorFilter', {\n logGroup,\n metricNamespace: 'Pipeline',\n metricName: 'Errors',\n filterPattern: logs.FilterPattern.literal('[time, level=ERROR, msg'),\n});\n```\n\nNone of these are type errors, so the L2 constructs accept them; none of them are\nexpressible in a resource schema, so CloudFormation accepts the template. With\n`Preflight.apply(app)` in place they fail `cdk synth` instead.\n\n## Observe-only mode\n\nTo roll the rules out gradually, start with `enforce: false`: findings then surface as synth **warnings** through the CDK built-in validator, with construct traces and per-finding acknowledgement:\n\n```ts\nPreflight.apply(app, { enforce: false });\n```\n\n```text\nWARNING idle_timeout.timeout_seconds is 5000 but must be between 1 and 4000 seconds (CloudFormation Validate)\n MyStack/Alb (Alb) aws-cdk-lib.aws_elasticloadbalancingv2.CfnLoadBalancer\n Acknowledge with 'CloudFormation-Validate::pf-elbv2-lb-idle-timeout-range'\n```\n\n> **Known limitation with stages.** The AWS CDK CLI drops validation findings for stacks nested in a `Stage`\n> before printing them, so in observe-only mode those findings appear **only** in `cdk.out/validation-report.json`\n> and never on the console. Enforce mode is not affected: cdk-preflight reports such findings itself and fails\n> synthesis. This is a CLI-side bug (present since aws-cdk 2.1128.1), not a rule evaluation problem.\n\n> **If the rules cannot run, the build stops.** When the evaluation engine fails on a template (a rule pack that\n> does not compile, an engine bug), enforce mode reports it as a violation named `pf-engine-error` and fails\n> synthesis for that stack instead of passing green with no rule having run. The other stacks keep their rules.\n> `pf-engine-error` is not a bundled rule and cannot be `exclude`d; `enforce: false` unblocks the build if you\n> need one.\n\n| Option | Default | Effect |\n|---|---|---|\n| `enforce` | `true` | Violations of bundled rules fail synthesis; set to `false` to only warn |\n| `strict` | `false` | With `enforce`: also fail on error-class findings (`ERROR`/`FATAL`, e.g. `F3034`) of the built-in validation engine itself, which the CDK currently downgrades to warnings |\n| `exclude` | `[]` | Rule ids to disable |\n| `includeUpstreamPending` | `true` | Include rules already proposed to the upstream engine but not yet merged |\n| `checkQuotas` | `false` | Also check the target account's Service Quotas and current usage (calls AWS at synth time, see below) |\n| `quotaCacheTtl` | 5 minutes | How long `checkQuotas` reuses the usage and deployed-stack state it fetched |\n\nTo opt out of a single rule everywhere, pass its id in `exclude`. To suppress a\nsingle *finding* on one construct, acknowledge it — this works in both modes, the\nid prefix just differs (`cdk-preflight::` when enforcing, `CloudFormation-Validate::`\nin observe-only, as printed in the warning text):\n\n```ts\ncdk.Validations.of(errorFilter).acknowledge({\n id: 'cdk-preflight::pf-logs-filter-pattern-bracket',\n reason: 'log group is written by a legacy producer; pattern is fixed upstream',\n});\n```\n\n## Service quota check (opt-in)\n\nThe rules only read the template, so they never assert a limit an account can raise. `checkQuotas: true` covers that\ngap for the quotas a CDK app runs into most: it adds up what every stack in the app (nested stacks included) is about\nto create in each account and Region, and compares that against the account's applied quota and current usage.\n\n```ts\nPreflight.apply(app, { checkQuotas: true });\n```\n\n| Check | Counts | Against |\n|---|---|---|\n| `pf-quota-vpcs-per-region` | new `AWS::EC2::VPC` | VPCs per Region (`vpc/L-F678F1CE`) |\n| `pf-quota-internet-gateways-per-region` | new `AWS::EC2::InternetGateway` | Internet gateways per Region (`vpc/L-A4707A72`) |\n| `pf-quota-elastic-ips-per-region` | new `AWS::EC2::EIP` (one per NAT gateway in a default `ec2.Vpc`) | EC2-VPC Elastic IPs (`ec2/L-0263D0A3`) |\n| `pf-quota-lambda-unreserved-concurrency` | increase in `ReservedConcurrentExecutions` | Lambda keeps at least 100 concurrent executions unreserved |\n\n- **Only new resources count.** The deployed template of each stack is read with `GetTemplate`; a resource whose\n logical id and type are already deployed is not counted again, so redeploying an unchanged app never trips the\n check. Resources behind a `Condition` and the brief overlap during a replacement are not counted.\n- **A finding fails synth** in enforce mode and is a warning with `enforce: false`. Acknowledge one like any other\n finding (`cdk-preflight::pf-quota-...`; `cdk-preflight-quotas::pf-quota-...` with `enforce: false`). The ids also work in `exclude`, including `pf-quota-check-skipped` to silence the skip warning.\n- **It needs credentials in the app process.** The CDK CLI does not pass `--profile` on to the app, so set\n `AWS_PROFILE` (or `AWS_*` variables) instead. When the credentials are missing, lack permissions, or belong to a\n different account than the stack's, the check is skipped with a `pf-quota-check-skipped` warning and synth goes on.\n- **Permissions:** `servicequotas:GetServiceQuota`, `servicequotas:GetAWSDefaultServiceQuota`, `ec2:DescribeVpcs`,\n `ec2:DescribeInternetGateways`, `ec2:DescribeAddresses`, `lambda:GetAccountSettings`, `cloudformation:GetTemplate`,\n `cloudformation:DescribeStackResource`. All read-only (`ReadOnlyAccess` covers them). The check also calls\n `sts:GetCallerIdentity`, which IAM never denies.\n- **Results are cached** in `cdk.out/.cdk-preflight/quota-cache.json`: usage and deployed templates for\n `quotaCacheTtl` (5 minutes), quota values for 24 hours. Delete the file to force a refetch.\n- Usage can change between synth and deploy (another team deploying to the same account), so a clean check is not a\n guarantee. The reverse also happens: EC2 does not always enforce the Elastic IP quota when CloudFormation\n creates several addresses in parallel (measured 2026-10-16: with 4 of 5 in use, two parallel `AWS::EC2::EIP` both\n succeeded), so a template the check stops may occasionally deploy. The check follows the quota, not the race.\n\n## Bundled rules\n\nSee [docs/rules.md](docs/rules.md) for the generated rule table.\n\n<!-- supported-resources:start -->\n<details>\n<summary><b>431 resource types across 78 services</b> — click to expand</summary>\n\nResource names are relative to `AWS::<Service>::`; the number in parentheses is how many rules target that type.\n\n| Service | Resource types |\n|---|---|\n| **(any resource type)** | `*` (14) |\n| **ApiGateway** | `ApiKey` (1), `Authorizer` (5), `Deployment` (1), `DocumentationPart` (1), `DomainName` (4), `GatewayResponse` (1), `Method` (14), `Model` (3), `Resource` (1), `RestApi` (5), `Stage` (9), `UsagePlan` (5), `VpcLink` (1) |\n| **ApiGatewayV2** | `Api` (5), `Authorizer` (11), `DomainName` (3), `Integration` (15), `IntegrationResponse` (1), `Model` (2), `Route` (6), `RouteResponse` (2), `Stage` (4), `VpcLink` (1) |\n| **ApplicationAutoScaling** | `ScalableTarget` (19), `ScalingPolicy` (30) |\n| **AppSync** | `Api` (7), `ApiCache` (4), `ApiKey` (2), `ChannelNamespace` (5), `DataSource` (15), `DomainName` (1), `FunctionConfiguration` (24), `GraphQLApi` (16), `GraphQLSchema` (12), `Resolver` (32), `SourceApiAssociation` (3) |\n| **APS** | `AnomalyDetector` (9), `ResourcePolicy` (5), `RuleGroupsNamespace` (10), `Workspace` (12) |\n| **Athena** | `DataCatalog` (6), `WorkGroup` (8) |\n| **AutoScaling** | `AutoScalingGroup` (38), `LifecycleHook` (8), `ScalingPolicy` (41), `ScheduledAction` (13), `WarmPool` (4) |\n| **Backup** | `BackupPlan` (12), `BackupSelection` (5), `BackupVault` (3), `Framework` (3), `LogicallyAirGappedBackupVault` (2), `ReportPlan` (2), `RestoreTestingPlan` (5), `RestoreTestingSelection` (3) |\n| **Batch** | `ComputeEnvironment` (40), `ConsumableResource` (2), `JobDefinition` (109), `JobQueue` (18), `SchedulingPolicy` (8), `ServiceEnvironment` (6) |\n| **Bedrock** | `ApplicationInferenceProfile` (2), `AutomatedReasoningPolicy` (3), `Blueprint` (3), `DataAutomationProject` (8), `DataSource` (12), `Flow` (14), `Guardrail` (19), `IntelligentPromptRouter` (5), `KnowledgeBase` (18), `Prompt` (4) |\n| **BedrockAgentCore** | `ApiKeyCredentialProvider` (1), `BrowserCustom` (1), `BrowserProfile` (1), `CapacityProvider` (8), `CodeInterpreterCustom` (1), `ConfigurationBundle` (4), `Dataset` (3), `Evaluator` (4), `Gateway` (16), `GatewayRateLimit` (5), `GatewayRule` (5), `GatewayTarget` (11), `Harness` (2), `HarnessEndpoint` (2), `Memory` (14), `OAuth2CredentialProvider` (5), `OnlineEvaluationConfig` (3), `PaymentCredentialProvider` (1), `PaymentManager` (1), `Policy` (3), `ResourcePolicy` (1), `Runtime` (16), `RuntimeEndpoint` (1) |\n| **Cassandra** | `Keyspace` (2), `Table` (22), `Type` (13) |\n| **CertificateManager** | `Certificate` (4) |\n| **CloudFormation** | `GuardHook` (1), `Stack` (2), `StackSet` (6) |\n| **CloudFront** | `AnycastIpList` (1), `CachePolicy` (7), `ContinuousDeploymentPolicy` (5), `Distribution` (55), `Function` (4), `KeyGroup` (1), `KeyValueStore` (2), `OriginRequestPolicy` (5), `PublicKey` (1), `RealtimeLogConfig` (3), `ResponseHeadersPolicy` (8), `VpcOrigin` (3) |\n| **CloudTrail** | `EventDataStore` (1), `Trail` (19) |\n| **CloudWatch** | `Alarm` (22), `AnomalyDetector` (6), `CompositeAlarm` (7), `Dashboard` (14), `InsightRule` (7), `MetricStream` (6) |\n| **CodeBuild** | `Project` (37), `ReportGroup` (2), `SourceCredential` (4) |\n| **CodeCommit** | `Repository` (11) |\n| **CodeDeploy** | `Application` (7), `DeploymentConfig` (12), `DeploymentGroup` (23) |\n| **CodePipeline** | `CustomActionType` (3), `Pipeline` (25), `Webhook` (2) |\n| **Cognito** | `IdentityPool` (3), `IdentityPoolRoleAttachment` (7), `LogDeliveryConfiguration` (3), `ManagedLoginBranding` (2), `UserPool` (52), `UserPoolClient` (21), `UserPoolDomain` (7), `UserPoolGroup` (1), `UserPoolIdentityProvider` (11), `UserPoolResourceServer` (4), `UserPoolRiskConfigurationAttachment` (6), `UserPoolUICustomizationAttachment` (2) |\n| **Config** | `ConfigRule` (6), `ConfigurationAggregator` (2), `ConfigurationRecorder` (7), `ConformancePack` (1), `RemediationConfiguration` (2) |\n| **DocDB** | `DBCluster` (14), `DBInstance` (1), `DBSubnetGroup` (2), `EventSubscription` (1) |\n| **DocDBElastic** | `Cluster` (7) |\n| **DynamoDB** | `GlobalTable` (25), `Table` (28) |\n| **EC2** | `ClientVpnAuthorizationRule` (1), `ClientVpnEndpoint` (6), `DHCPOptions` (2), `EIPAssociation` (1), `FlowLog` (4), `Instance` (10), `KeyPair` (1), `LaunchTemplate` (12), `NatGateway` (2), `NetworkAclEntry` (1), `NetworkInterface` (2), `PlacementGroup` (3), `PrefixList` (3), `Route` (1), `SecurityGroup` (7), `SecurityGroupEgress` (5), `SecurityGroupIngress` (5), `Subnet` (14), `TrafficMirrorTarget` (1), `TransitGateway` (2), `TransitGatewayRoute` (1), `Volume` (6), `VPC` (2), `VPCCidrBlock` (1), `VPCEndpoint` (4), `VPCGatewayAttachment` (1), `VPNConnection` (5) |\n| **ECR** | `PullThroughCacheRule` (3), `RegistryScanningConfiguration` (1), `ReplicationConfiguration` (1), `Repository` (7), `RepositoryCreationTemplate` (8), `SigningConfiguration` (1) |\n| **ECS** | `CapacityProvider` (3), `Cluster` (5), `Service` (37), `TaskDefinition` (66), `TaskSet` (2) |\n| **EFS** | `AccessPoint` (1), `FileSystem` (7), `MountTarget` (4) |\n| **EKS** | `AccessEntry` (14), `Addon` (5), `Cluster` (21), `FargateProfile` (5), `IdentityProviderConfig` (3), `Nodegroup` (21), `PodIdentityAssociation` (5) |\n| **ElastiCache** | `CacheCluster` (9), `ReplicationGroup` (14), `User` (2), `UserGroup` (1) |\n| **ElasticBeanstalk** | `Application` (2), `ConfigurationTemplate` (37), `Environment` (35) |\n| **ElasticLoadBalancingV2** | `Listener` (57), `ListenerCertificate` (2), `ListenerRule` (38), `LoadBalancer` (37), `TargetGroup` (58), `TrustStore` (1), `TrustStoreRevocation` (1) |\n| **Events** | `ApiDestination` (1), `Archive` (5), `Connection` (1), `Endpoint` (2), `EventBus` (2), `Rule` (27) |\n| **EventSchemas** | `Discoverer` (1), `Registry` (1), `RegistryPolicy` (1), `Schema` (1) |\n| **GlobalAccelerator** | `Accelerator` (1), `EndpointGroup` (5), `Listener` (2) |\n| **Glue** | `Classifier` (6), `Connection` (5), `Crawler` (11), `CustomEntityType` (1), `Database` (1), `DataQualityRuleset` (1), `Job` (15), `MLTransform` (4), `Partition` (1), `Schema` (3), `SecurityConfiguration` (1), `Table` (1), `Trigger` (10), `UserDefinedFunction` (2), `Workflow` (1) |\n| **Grafana** | `Workspace` (7) |\n| **IAM** | `Group` (23), `GroupPolicy` (19), `InstanceProfile` (2), `ManagedPolicy` (31), `OIDCProvider` (2), `Policy` (29), `Role` (44), `RolePolicy` (19), `ServiceLinkedRole` (1), `User` (24), `UserPolicy` (19) |\n| **IoT** | `Authorizer` (3), `Certificate` (1), `CertificateProvider` (1), `Command` (1), `DomainConfiguration` (3), `JobTemplate` (3), `MitigationAction` (1), `Policy` (4), `PolicyPrincipalAttachment` (1), `ProvisioningTemplate` (3), `RoleAlias` (1), `ScheduledAudit` (1), `Thing` (1), `ThingGroup` (2), `TopicRule` (5), `TopicRuleDestination` (2) |\n| **Kinesis** | `ResourcePolicy` (4), `Stream` (5), `StreamConsumer` (2) |\n| **KinesisAnalyticsV2** | `Application` (20), `ApplicationCloudWatchLoggingOption` (1), `ApplicationOutput` (1), `ApplicationReferenceDataSource` (1) |\n| **KinesisFirehose** | `DeliveryStream` (68) |\n| **KMS** | `Alias` (2), `Key` (12), `ReplicaKey` (4) |\n| **Lambda** | `Alias` (7), `CodeSigningConfig` (1), `EventInvokeConfig` (5), `EventSourceMapping` (54), `Function` (48), `LayerVersion` (8), `LayerVersionPermission` (3), `Permission` (8), `Url` (8), `Version` (1) |\n| **Logs** | `AccountPolicy` (6), `DeliveryDestination` (3), `Destination` (1), `LogAnomalyDetector` (2), `LogGroup` (10), `MetricFilter` (7), `QueryDefinition` (1), `ResourcePolicy` (1), `SubscriptionFilter` (6), `Transformer` (3) |\n| **MediaConvert** | `JobTemplate` (9), `Preset` (32), `Queue` (2) |\n| **MemoryDB** | `Cluster` (8), `User` (1) |\n| **MSK** | `BatchScramSecret` (2), `Cluster` (31), `ClusterPolicy` (1), `Configuration` (4), `Replicator` (10), `ServerlessCluster` (4) |\n| **Neptune** | `DBCluster` (11), `DBClusterParameterGroup` (1), `DBInstance` (3), `DBSubnetGroup` (1), `GlobalCluster` (1) |\n| **NeptuneGraph** | `Graph` (2), `PrivateGraphEndpoint` (1) |\n| **NetworkFirewall** | `FirewallPolicy` (18), `RuleGroup` (34), `TLSInspectionConfiguration` (7) |\n| **OpenSearchServerless** | `AccessPolicy` (7), `Collection` (2), `CollectionGroup` (3), `LifecyclePolicy` (4), `SecurityConfig` (5), `SecurityPolicy` (14) |\n| **OpenSearchService** | `Domain` (65) |\n| **Pipes** | `Pipe` (9) |\n| **RDS** | `DBCluster` (19), `DBInstance` (33), `DBParameterGroup` (2), `DBProxy` (4), `DBProxyTargetGroup` (2), `DBShardGroup` (1), `DBSubnetGroup` (3), `EventSubscription` (3), `OptionGroup` (1) |\n| **Redshift** | `Cluster` (20), `EventSubscription` (1), `ScheduledAction` (2) |\n| **RedshiftServerless** | `Namespace` (5), `Workgroup` (6) |\n| **Route53** | `CidrCollection` (11), `DNSSEC` (3), `HealthCheck` (30), `HostedZone` (14), `KeySigningKey` (9), `RecordSet` (74), `RecordSetGroup` (76) |\n| **Route53Profiles** | `ProfileAssociation` (1), `ProfileResourceAssociation` (6) |\n| **Route53Resolver** | `FirewallDomainList` (3), `FirewallRuleGroup` (18), `FirewallRuleGroupAssociation` (4), `ResolverDNSSECConfig` (1), `ResolverEndpoint` (18), `ResolverQueryLoggingConfig` (1), `ResolverQueryLoggingConfigAssociation` (1), `ResolverRule` (15), `ResolverRuleAssociation` (1) |\n| **S3** | `AccessPoint` (1), `Bucket` (54), `BucketPolicy` (4), `StorageLens` (5), `StorageLensGroup` (3) |\n| **S3Express** | `AccessPoint` (3), `DirectoryBucket` (11) |\n| **Scheduler** | `Schedule` (12), `ScheduleGroup` (1) |\n| **SecretsManager** | `RotationSchedule` (4), `Secret` (5), `SecretTargetAttachment` (1) |\n| **ServiceDiscovery** | `HttpNamespace` (3), `Instance` (19), `PrivateDnsNamespace` (4), `PublicDnsNamespace` (4), `Service` (13) |\n| **SES** | `ConfigurationSetEventDestination` (8), `ContactList` (1), `EmailIdentity` (6), `ReceiptRule` (6), `ReceiptRuleSet` (1), `Template` (1) |\n| **SNS** | `Subscription` (10), `Topic` (14), `TopicPolicy` (1) |\n| **SQS** | `Queue` (10), `QueuePolicy` (1) |\n| **SSM** | `Association` (4), `Document` (3), `MaintenanceWindow` (2), `MaintenanceWindowTarget` (1), `MaintenanceWindowTask` (1), `Parameter` (5) |\n| **StepFunctions** | `Activity` (3), `StateMachine` (26) |\n| **Synthetics** | `Canary` (16) |\n| **VerifiedPermissions** | `IdentitySource` (3), `Policy` (26), `PolicyStore` (23), `PolicyStoreAlias` (1), `PolicyTemplate` (29) |\n| **VpcLattice** | `AccessLogSubscription` (3), `AuthPolicy` (3), `DomainVerification` (1), `Listener` (12), `ResourceConfiguration` (30), `ResourceGateway` (6), `ResourcePolicy` (1), `Rule` (7), `Service` (2), `ServiceNetwork` (1), `ServiceNetworkResourceAssociation` (3), `ServiceNetworkServiceAssociation` (3), `ServiceNetworkVpcAssociation` (8), `TargetGroup` (14) |\n| **WAFv2** | `IPSet` (3), `LoggingConfiguration` (3), `RegexPatternSet` (3), `RuleGroup` (18), `WebACL` (23), `WebACLAssociation` (2) |\n| **XRay** | `Group` (1), `ResourcePolicy` (3), `SamplingRule` (6) |\n\n</details>\n<!-- supported-resources:end -->\n\nHighlights:\n\n- **ELBv2**: `idle_timeout` / `deregistration_delay` / `slow_start` attribute ranges (stringly-typed Key/Value attributes are invisible to schema validation)\n- **IAM**: managed (6,144 chars) and inline (role/group/user) policy document size limits\n- **CloudFront**: `MinTTL <= DefaultTTL <= MaxTTL` ordering, ACM certificates must live in `us-east-1`\n- **Step Functions**: `Next`/`Default`/`Choices` must reference defined states (a dangling `StartAt` is already caught by the engine's built-in `E3601`)\n- **EC2**: security group TCP/UDP port ranges and `FromPort <= ToPort`\n\n## For AI agents\n\nTo add cdk-preflight to a CDK app:\n\n1. `npm i -D cdk-preflight`\n2. `npx cdk-preflight init` — or the shorter alias `npx cdkpf init` (finds the entry point via `cdk.json` and inserts `Preflight.apply(app)`; use `--dry-run` to preview)\n3. Run `cdk synth`. Violations fail the synth with a validation report; each finding carries a rule id, the actual value, and a suggested fix\n4. To fix a finding, prefer correcting the resource. To opt out instead: `exclude: ['<rule-id>']` disables one rule, `enforce: false` switches to warn-only reporting\n\nThe machine-readable findings are written to `cdk.out/validation-report.json` when synthesizing with `-c @aws-cdk/core:validationReportJson=true`.\n\n### Report missed deploy errors\n\ncdk-preflight only knows the failure modes it has benched. When a deploy fails on a constraint the pack should have caught, that report is how new rules get added — but at that moment cdk-preflight is out of the loop (it passed the synth), so the instruction has to already sit in your agent's context. Paste this into your repository's `AGENTS.md` (or `CLAUDE.md`):\n\n```markdown\n## cdk-preflight: report missed deploy errors\n\nIf `cdk deploy` fails even though `cdk synth` (with cdk-preflight enabled) passed,\nand the failure is a service-side validation rejection — CREATE_FAILED/UPDATE_FAILED\nwith a 400-class message such as \"Invalid request provided: ...\" — cdk-preflight is\nmissing a rule. Report it:\n\n1. Qualify first. NOT reportable: AccessDenied / permissions, service quotas\n (those belong to the opt-in `checkQuotas`; open a regular issue if it missed one),\n throttling, name conflicts with existing resources, stabilization timeouts.\n2. Redact account-specific data (account IDs -> 123456789012, real ARNs/domains\n -> placeholders).\n3. Search existing issues: https://github.com/badmintoncryer/cdk-preflight/issues\n4. With your user's approval, open a \"Missed deploy error\" issue with the verbatim\n error message, the resource type, a minimal template snippet, and your\n aws-cdk-lib / cdk-preflight versions.\n```\n\n## Scope and rule lifecycle\n\nA constraint belongs in the pack when violating it makes a real deployment fail, or lets the deployment succeed and then makes every run of the deployed resource fail (an SSM Automation association that targets several tags, for example), *and* no layer that sees the same synthesized template already blocks it. There is no further \"is this worth a rule\" question — if the gap is real, it gets a rule.\n\nCDK L2 construct validation is deliberately **not** one of those layers. `CfnXxx` usage, escape hatches, `addPropertyOverride`, `cloudformation-include` and migrated templates all bypass L2, so an L2 guard covering the same mistake neither disqualifies a rule nor retires one.\n\nThat makes growth the normal state, and it has a consequence worth knowing before you upgrade: **new rules land in minor releases, so a minor upgrade can newly fail a `cdk synth` that passed yesterday.** That is intended, not a regression. If you need a frozen rule set, pin the version; to drop a single rule, `exclude: ['<rule-id>']`; to see everything without failing the build, `enforce: false`.\n\nRules move the other way too. Once the validation engine bundled in `aws-cdk-lib` starts blocking a constraint, the rule records the engine version that covers it and stops being evaluated on that engine or later — but only where that changes nothing about whether synth fails: with `enforce: false`, with `strict: true`, or when your app sets the context `@aws-cdk/core:validateAgainstDefaultRules: true`. In the default enforce mode the CDK reports its own engine's errors as warnings, so the rule keeps running and you may see both. Users on an older `aws-cdk-lib` keep the rule either way; it is deleted only once the minimum supported `aws-cdk-lib` bundles an engine that covers it.\n\n## How it works\n\n`Preflight.apply()` evaluates the rules with the [cloudformation-validate](https://github.com/aws-cloudformation/cloudformation-validate) Rust/WASM engine that ships inside `aws-cdk-lib` — no extra binaries, and no network access at synth time unless you opt in to `checkQuotas`, which calls AWS from a child process. In the default enforce mode the engine is invoked through a dedicated CDK validation plugin so that violations fail synthesis; with `enforce: false` the rules are instead injected into the CDK built-in `CloudFormationValidatePlugin` and reported as warnings.\n\nConstraints that *can* be expressed in schemas or generic engine rules also make good upstream PRs to that engine, but nothing here waits on one — the upstream release cycle is deliberately slower than this pack's. Each rule's `meta.yaml` tracks its upstream status so that retirement stays bookkeeping.\n\n## Requirements\n\n- `aws-cdk-lib` >= 2.267.0, released 2026-08-27 (the first release that bundles the built-in CloudFormation validator). This is a recent release — an existing CDK app may need an upgrade before cdk-preflight can run.\n\n## Contributing\n\nRule authoring, the verification gates (including real-deploy reproduction), and the test layout are documented in [AGENTS.md](AGENTS.md) — written for AI coding agents and humans alike.\n\n## License\n\nApache-2.0\n"
|
|
9630
9630
|
},
|
|
9631
9631
|
"repository": {
|
|
9632
9632
|
"type": "git",
|
|
@@ -9847,6 +9847,6 @@
|
|
|
9847
9847
|
"symbolId": "src/index:PreflightOptions"
|
|
9848
9848
|
}
|
|
9849
9849
|
},
|
|
9850
|
-
"version": "1.
|
|
9851
|
-
"fingerprint": "
|
|
9850
|
+
"version": "1.9.1",
|
|
9851
|
+
"fingerprint": "9Q7SSSFRy76VsUZDenjigLImbtiAKjqiNU4ye+GkXHU="
|
|
9852
9852
|
}
|
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<a href="https://github.com/badmintoncryer/cdk-preflight/actions/workflows/monthly-verify.yml"><img src="https://github.com/badmintoncryer/cdk-preflight/actions/workflows/monthly-verify.yml/badge.svg" alt="monthly real-deploy verification"></a>
|
|
13
13
|
<a href="https://www.npmjs.com/package/cdk-preflight"><img src="https://img.shields.io/npm/v/cdk-preflight.svg" alt="npm version"></a>
|
|
14
14
|
<a href="https://www.npmjs.com/package/cdk-preflight"><img src="https://img.shields.io/npm/dt/cdk-preflight.svg" alt="npm total downloads"></a>
|
|
15
|
-
<a href="docs/rules.md"><img src="https://img.shields.io/badge/rules-
|
|
15
|
+
<a href="docs/rules.md"><img src="https://img.shields.io/badge/rules-3361-blue" alt="3361 bundled rules"></a>
|
|
16
16
|
</p>
|
|
17
17
|
|
|
18
18
|
Some CloudFormation constraints are not expressed in resource provider schemas — they live only in documentation, in service API validation, or across multiple properties. Templates that violate them pass `cdk synth`, pass CloudFormation pre-deployment validation, and then fail minutes into a deployment, burning a rollback cycle.
|
|
@@ -193,7 +193,7 @@ See [docs/rules.md](docs/rules.md) for the generated rule table.
|
|
|
193
193
|
|
|
194
194
|
<!-- supported-resources:start -->
|
|
195
195
|
<details>
|
|
196
|
-
<summary><b>
|
|
196
|
+
<summary><b>431 resource types across 78 services</b> — click to expand</summary>
|
|
197
197
|
|
|
198
198
|
Resource names are relative to `AWS::<Service>::`; the number in parentheses is how many rules target that type.
|
|
199
199
|
|
|
@@ -274,6 +274,7 @@ Resource names are relative to `AWS::<Service>::`; the number in parentheses is
|
|
|
274
274
|
| **StepFunctions** | `Activity` (3), `StateMachine` (26) |
|
|
275
275
|
| **Synthetics** | `Canary` (16) |
|
|
276
276
|
| **VerifiedPermissions** | `IdentitySource` (3), `Policy` (26), `PolicyStore` (23), `PolicyStoreAlias` (1), `PolicyTemplate` (29) |
|
|
277
|
+
| **VpcLattice** | `AccessLogSubscription` (3), `AuthPolicy` (3), `DomainVerification` (1), `Listener` (12), `ResourceConfiguration` (30), `ResourceGateway` (6), `ResourcePolicy` (1), `Rule` (7), `Service` (2), `ServiceNetwork` (1), `ServiceNetworkResourceAssociation` (3), `ServiceNetworkServiceAssociation` (3), `ServiceNetworkVpcAssociation` (8), `TargetGroup` (14) |
|
|
277
278
|
| **WAFv2** | `IPSet` (3), `LoggingConfiguration` (3), `RegexPatternSet` (3), `RuleGroup` (18), `WebACL` (23), `WebACLAssociation` (2) |
|
|
278
279
|
| **XRay** | `Group` (1), `ResourcePolicy` (3), `SamplingRule` (6) |
|
|
279
280
|
|
package/docs/rules.md
CHANGED
|
@@ -3232,6 +3232,100 @@
|
|
|
3232
3232
|
| `pf-avp-template-placeholder-in-scope-only` | AWS::VerifiedPermissions::PolicyTemplate | A placeholder appears only in the policy scope | ERROR | none |
|
|
3233
3233
|
| `pf-avp-template-placeholder-slot-match` | AWS::VerifiedPermissions::PolicyTemplate | ?principal sits in the principal element, ?resource in the resource element | ERROR | none |
|
|
3234
3234
|
| `pf-avp-template-requires-placeholder` | AWS::VerifiedPermissions::PolicyTemplate | A policy template uses at least one placeholder | ERROR | none |
|
|
3235
|
+
| `pf-vpclattice-als-arn-region` | AWS::VpcLattice::AccessLogSubscription | An access log subscription must target a resource in the deploy region | ERROR | none |
|
|
3236
|
+
| `pf-vpclattice-als-destination-region` | AWS::VpcLattice::AccessLogSubscription | An access log destination must be in the deploy region | ERROR | none |
|
|
3237
|
+
| `pf-vpclattice-als-destination-service` | AWS::VpcLattice::AccessLogSubscription | An access log subscription delivers only to CloudWatch Logs, S3 or Firehose | ERROR | none |
|
|
3238
|
+
| `pf-vpclattice-authpolicy-action-prefix` | AWS::VpcLattice::AuthPolicy | Auth policy actions must use the vpc-lattice-svcs prefix | ERROR | none |
|
|
3239
|
+
| `pf-vpclattice-authpolicy-arn-region` | AWS::VpcLattice::AuthPolicy | An auth policy must target a service or service network in the deploy region | ERROR | none |
|
|
3240
|
+
| `pf-vpclattice-authpolicy-size` | AWS::VpcLattice::AuthPolicy | An auth policy must not exceed 10240 bytes | ERROR | none |
|
|
3241
|
+
| `pf-vpclattice-domainverification-domain-format` | AWS::VpcLattice::DomainVerification | A domain verification DomainName must be plain ASCII without spaces | ERROR | none |
|
|
3242
|
+
| `pf-vpclattice-listener-default-action-empty` | AWS::VpcLattice::Listener | A listener DefaultAction must not be an empty object | ERROR | none |
|
|
3243
|
+
| `pf-vpclattice-listener-forward-weight-required` | AWS::VpcLattice::Listener | A listener forward action with more than one target group needs a Weight on each | ERROR | none |
|
|
3244
|
+
| `pf-vpclattice-listener-grpc-requires-https` | AWS::VpcLattice::Listener | A GRPC target group can be used only behind an HTTPS listener | ERROR | none |
|
|
3245
|
+
| `pf-vpclattice-listener-http-tg-tcp` | AWS::VpcLattice::Listener | An HTTP or HTTPS listener cannot forward to a TCP target group | ERROR | none |
|
|
3246
|
+
| `pf-vpclattice-listener-http2-requires-https` | AWS::VpcLattice::Listener | A HTTP2 target group can be used only behind an HTTPS listener | ERROR | none |
|
|
3247
|
+
| `pf-vpclattice-listener-name-duplicate` | AWS::VpcLattice::Listener | Listener name must be unique within its service | ERROR | none |
|
|
3248
|
+
| `pf-vpclattice-listener-port-duplicate` | AWS::VpcLattice::Listener | Listener Port must be unique within its service | ERROR | none |
|
|
3249
|
+
| `pf-vpclattice-listener-tg-arn-region` | AWS::VpcLattice::Listener | A listener forward target group ARN must be in the deploy region | ERROR | none |
|
|
3250
|
+
| `pf-vpclattice-listener-tg-shared-across-services` | AWS::VpcLattice::Listener | A target group can serve listeners of only one service | ERROR | none |
|
|
3251
|
+
| `pf-vpclattice-listener-tls-fixed-response` | AWS::VpcLattice::Listener | A TLS_PASSTHROUGH listener default action must be Forward | ERROR | none |
|
|
3252
|
+
| `pf-vpclattice-listener-tls-service-custom-domain` | AWS::VpcLattice::Listener | A TLS_PASSTHROUGH listener needs a service with a CustomDomainName | ERROR | none |
|
|
3253
|
+
| `pf-vpclattice-listener-tls-tg-protocol` | AWS::VpcLattice::Listener | A TLS_PASSTHROUGH listener forwards only to a TCP target group | ERROR | none |
|
|
3254
|
+
| `pf-vpclattice-rc-allow-sharable-child` | AWS::VpcLattice::ResourceConfiguration | A CHILD resource configuration must not set AllowAssociationToSharableServiceNetwork | ERROR | none |
|
|
3255
|
+
| `pf-vpclattice-rc-arn-definition-type` | AWS::VpcLattice::ResourceConfiguration | An ARN resource configuration is defined by ArnResource only | ERROR | none |
|
|
3256
|
+
| `pf-vpclattice-rc-arn-gateway-in-vpc` | AWS::VpcLattice::ResourceConfiguration | An ARN resource configuration cannot use a resource gateway with IN_VPC DNS resolution | ERROR | none |
|
|
3257
|
+
| `pf-vpclattice-rc-arn-port-ranges` | AWS::VpcLattice::ResourceConfiguration | An ARN resource configuration must not set PortRanges | ERROR | none |
|
|
3258
|
+
| `pf-vpclattice-rc-arn-rds-only` | AWS::VpcLattice::ResourceConfiguration | An ARN resource configuration supports RDS ARNs only | ERROR | none |
|
|
3259
|
+
| `pf-vpclattice-rc-child-domain-subdomain` | AWS::VpcLattice::ResourceConfiguration | A CHILD's CustomDomainName must be under its GROUP's GroupDomain | ERROR | none |
|
|
3260
|
+
| `pf-vpclattice-rc-child-gateway` | AWS::VpcLattice::ResourceConfiguration | A CHILD resource configuration must not set ResourceGatewayId | ERROR | none |
|
|
3261
|
+
| `pf-vpclattice-rc-child-requires-group` | AWS::VpcLattice::ResourceConfiguration | A CHILD resource configuration needs ResourceConfigurationGroupId | ERROR | none |
|
|
3262
|
+
| `pf-vpclattice-rc-cidr-custom-domain` | AWS::VpcLattice::ResourceConfiguration | A CIDR resource configuration must not set CustomDomainName | ERROR | none |
|
|
3263
|
+
| `pf-vpclattice-rc-cidr-definition-type` | AWS::VpcLattice::ResourceConfiguration | A CIDR resource configuration is defined by CidrResource only | ERROR | none |
|
|
3264
|
+
| `pf-vpclattice-rc-cidr-format` | AWS::VpcLattice::ResourceConfiguration | CidrRanges prefix lengths must be at most 32 | ERROR | none |
|
|
3265
|
+
| `pf-vpclattice-rc-cidr-gateway-public` | AWS::VpcLattice::ResourceConfiguration | A CIDR resource configuration needs a resource gateway with IN_VPC DNS resolution | ERROR | none |
|
|
3266
|
+
| `pf-vpclattice-rc-custom-domain-format` | AWS::VpcLattice::ResourceConfiguration | A resource configuration's CustomDomainName must be an ASCII hostname | ERROR | none |
|
|
3267
|
+
| `pf-vpclattice-rc-dns-domain-format` | AWS::VpcLattice::ResourceConfiguration | DnsResource.DomainName must be an ASCII hostname | ERROR | none |
|
|
3268
|
+
| `pf-vpclattice-rc-dns-dualstack` | AWS::VpcLattice::ResourceConfiguration | DnsResource.IpAddressType must be IPV4 or IPV6 | ERROR | none |
|
|
3269
|
+
| `pf-vpclattice-rc-gateway-id-format` | AWS::VpcLattice::ResourceConfiguration | ResourceGatewayId must be a resource gateway id or ARN | ERROR | none |
|
|
3270
|
+
| `pf-vpclattice-rc-gateway-required` | AWS::VpcLattice::ResourceConfiguration | A SINGLE, GROUP or ARN resource configuration needs ResourceGatewayId | ERROR | none |
|
|
3271
|
+
| `pf-vpclattice-rc-group-domain-format` | AWS::VpcLattice::ResourceConfiguration | GroupDomain must be an ASCII hostname | ERROR | none |
|
|
3272
|
+
| `pf-vpclattice-rc-group-domain-non-group` | AWS::VpcLattice::ResourceConfiguration | Only a GROUP resource configuration takes GroupDomain | ERROR | none |
|
|
3273
|
+
| `pf-vpclattice-rc-group-id-non-child` | AWS::VpcLattice::ResourceConfiguration | Only a CHILD resource configuration takes ResourceConfigurationGroupId | ERROR | none |
|
|
3274
|
+
| `pf-vpclattice-rc-group-no-definition` | AWS::VpcLattice::ResourceConfiguration | A GROUP resource configuration must not set ResourceConfigurationDefinition | ERROR | none |
|
|
3275
|
+
| `pf-vpclattice-rc-ip-format` | AWS::VpcLattice::ResourceConfiguration | IpResource must be a valid IP address | ERROR | none |
|
|
3276
|
+
| `pf-vpclattice-rc-ip-private-range` | AWS::VpcLattice::ResourceConfiguration | An IPv4 IpResource must be in 10/8, 100.64/10, 172.16/12 or 192.168/16 | ERROR | none |
|
|
3277
|
+
| `pf-vpclattice-rc-port-range-max` | AWS::VpcLattice::ResourceConfiguration | Ports in PortRanges must be at most 65535 | ERROR | none |
|
|
3278
|
+
| `pf-vpclattice-rc-port-range-order` | AWS::VpcLattice::ResourceConfiguration | A port range must not start above its end | ERROR | none |
|
|
3279
|
+
| `pf-vpclattice-rc-port-range-zero` | AWS::VpcLattice::ResourceConfiguration | Ports in PortRanges must be at least 1 | ERROR | none |
|
|
3280
|
+
| `pf-vpclattice-rc-protocol-child-arn` | AWS::VpcLattice::ResourceConfiguration | Only SINGLE and GROUP resource configurations take ProtocolType | ERROR | none |
|
|
3281
|
+
| `pf-vpclattice-rc-single-arn-definition` | AWS::VpcLattice::ResourceConfiguration | A SINGLE resource configuration cannot use ArnResource | ERROR | none |
|
|
3282
|
+
| `pf-vpclattice-rc-single-definition-required` | AWS::VpcLattice::ResourceConfiguration | A SINGLE resource configuration needs ResourceConfigurationDefinition | ERROR | none |
|
|
3283
|
+
| `pf-vpclattice-resourceconfiguration-name-duplicate` | AWS::VpcLattice::ResourceConfiguration | Resource configuration names must be unique in the account and region | ERROR | none |
|
|
3284
|
+
| `pf-vpclattice-resourcepolicy-principal-required` | AWS::VpcLattice::ResourcePolicy | Every resource policy statement needs a Principal | ERROR | none |
|
|
3285
|
+
| `pf-vpclattice-rgw-in-vpc-ipv6` | AWS::VpcLattice::ResourceGateway | An IPV6 resource gateway cannot resolve DNS IN_VPC | ERROR | none |
|
|
3286
|
+
| `pf-vpclattice-rgw-ipv4-per-eni-ipv6` | AWS::VpcLattice::ResourceGateway | An IPV6 resource gateway must not set Ipv4AddressesPerEni | ERROR | none |
|
|
3287
|
+
| `pf-vpclattice-rgw-ipv6-subnet-family` | AWS::VpcLattice::ResourceGateway | An IPV6 or DUALSTACK resource gateway needs subnets with IPv6 blocks | ERROR | none |
|
|
3288
|
+
| `pf-vpclattice-rgw-sg-other-vpc` | AWS::VpcLattice::ResourceGateway | A resource gateway's security groups must be in its VPC | ERROR | none |
|
|
3289
|
+
| `pf-vpclattice-rgw-subnet-id-format` | AWS::VpcLattice::ResourceGateway | ResourceGateway SubnetIds must be subnet ids | ERROR | none |
|
|
3290
|
+
| `pf-vpclattice-rgw-subnet-other-vpc` | AWS::VpcLattice::ResourceGateway | A resource gateway's subnets must be in its VPC | ERROR | none |
|
|
3291
|
+
| `pf-vpclattice-rule-action-empty` | AWS::VpcLattice::Rule | A rule Action must not be an empty object | ERROR | none |
|
|
3292
|
+
| `pf-vpclattice-rule-forward-weight-required` | AWS::VpcLattice::Rule | A rule forward action with more than one target group needs a Weight on each | ERROR | none |
|
|
3293
|
+
| `pf-vpclattice-rule-http-match-empty` | AWS::VpcLattice::Rule | A rule Match.HttpMatch must not be an empty object | ERROR | none |
|
|
3294
|
+
| `pf-vpclattice-rule-name-duplicate` | AWS::VpcLattice::Rule | Rule name must be unique within its listener | ERROR | none |
|
|
3295
|
+
| `pf-vpclattice-rule-on-tls-listener` | AWS::VpcLattice::Rule | A TLS_PASSTHROUGH listener takes no rules besides its default action | ERROR | none |
|
|
3296
|
+
| `pf-vpclattice-rule-path-match-empty` | AWS::VpcLattice::Rule | A rule PathMatch.Match must not be an empty object | ERROR | none |
|
|
3297
|
+
| `pf-vpclattice-rule-priority-duplicate` | AWS::VpcLattice::Rule | Rule Priority must be unique within its listener | ERROR | none |
|
|
3298
|
+
| `pf-vpclattice-service-custom-domain-duplicate-in-sn` | AWS::VpcLattice::ServiceNetworkServiceAssociation | Two services with the same CustomDomainName cannot join one service network | ERROR | none |
|
|
3299
|
+
| `pf-vpclattice-service-custom-domain-format` | AWS::VpcLattice::Service | A service CustomDomainName must be plain ASCII without spaces | ERROR | none |
|
|
3300
|
+
| `pf-vpclattice-service-name-duplicate` | AWS::VpcLattice::Service | Service names must be unique within the account and region | ERROR | none |
|
|
3301
|
+
| `pf-vpclattice-servicenetwork-name-duplicate` | AWS::VpcLattice::ServiceNetwork | Service network names must be unique within the account and region | ERROR | none |
|
|
3302
|
+
| `pf-vpclattice-snra-child-rc` | AWS::VpcLattice::ServiceNetworkResourceAssociation | A CHILD resource configuration cannot be associated with a service network | ERROR | none |
|
|
3303
|
+
| `pf-vpclattice-snra-duplicate` | AWS::VpcLattice::ServiceNetworkResourceAssociation | A resource configuration can be associated with a service network only once | ERROR | none |
|
|
3304
|
+
| `pf-vpclattice-snra-sharable-sn` | AWS::VpcLattice::ServiceNetworkResourceAssociation | A resource configuration that disallows sharable service networks cannot be associated with one | ERROR | none |
|
|
3305
|
+
| `pf-vpclattice-snsa-arn-region` | AWS::VpcLattice::ServiceNetworkServiceAssociation | A service network service association must name a service network in the deploy region | ERROR | none |
|
|
3306
|
+
| `pf-vpclattice-snsa-duplicate` | AWS::VpcLattice::ServiceNetworkServiceAssociation | A service can be associated with a service network only once | ERROR | none |
|
|
3307
|
+
| `pf-vpclattice-snva-arn-region` | AWS::VpcLattice::ServiceNetworkVpcAssociation | A service network VPC association must name a service network in the deploy region | ERROR | none |
|
|
3308
|
+
| `pf-vpclattice-snva-dns-options-requires-private-dns` | AWS::VpcLattice::ServiceNetworkVpcAssociation | DnsOptions needs PrivateDnsEnabled true | ERROR | none |
|
|
3309
|
+
| `pf-vpclattice-snva-security-groups-max` | AWS::VpcLattice::ServiceNetworkVpcAssociation | A service network VPC association takes at most 5 security groups | ERROR | none |
|
|
3310
|
+
| `pf-vpclattice-snva-sg-other-vpc` | AWS::VpcLattice::ServiceNetworkVpcAssociation | Association security groups must belong to the associated VPC | ERROR | none |
|
|
3311
|
+
| `pf-vpclattice-snva-specified-domain-format` | AWS::VpcLattice::ServiceNetworkVpcAssociation | PrivateDnsSpecifiedDomains entries must be host names | ERROR | none |
|
|
3312
|
+
| `pf-vpclattice-snva-specified-domains-preference` | AWS::VpcLattice::ServiceNetworkVpcAssociation | PrivateDnsSpecifiedDomains needs a *_SPECIFIED_DOMAINS* preference | ERROR | none |
|
|
3313
|
+
| `pf-vpclattice-snva-specified-only-requires-domains` | AWS::VpcLattice::ServiceNetworkVpcAssociation | A *_SPECIFIED_DOMAINS* preference needs PrivateDnsSpecifiedDomains | ERROR | none |
|
|
3314
|
+
| `pf-vpclattice-snva-vpc-duplicate` | AWS::VpcLattice::ServiceNetworkVpcAssociation | A VPC can be associated with only one service network | ERROR | none |
|
|
3315
|
+
| `pf-vpclattice-targetgroup-name-duplicate` | AWS::VpcLattice::TargetGroup | Target group names must be unique within the account and region | ERROR | none |
|
|
3316
|
+
| `pf-vpclattice-tg-alb-health-check` | AWS::VpcLattice::TargetGroup | An ALB target group cannot carry a health check config | ERROR | none |
|
|
3317
|
+
| `pf-vpclattice-tg-alb-single-target` | AWS::VpcLattice::TargetGroup | An ALB target group takes a single target | ERROR | none |
|
|
3318
|
+
| `pf-vpclattice-tg-alb-target-account-region` | AWS::VpcLattice::TargetGroup | An ALB target group target must be a load balancer of the deploy account and region | ERROR | none |
|
|
3319
|
+
| `pf-vpclattice-tg-health-check-timeout-interval` | AWS::VpcLattice::TargetGroup | A target group health check timeout must not exceed its interval | ERROR | none |
|
|
3320
|
+
| `pf-vpclattice-tg-lambda-config-port` | AWS::VpcLattice::TargetGroup | A LAMBDA target group Config accepts only LambdaEventStructureVersion | ERROR | none |
|
|
3321
|
+
| `pf-vpclattice-tg-lambda-event-version-non-lambda` | AWS::VpcLattice::TargetGroup | LambdaEventStructureVersion applies only to a LAMBDA target group | ERROR | none |
|
|
3322
|
+
| `pf-vpclattice-tg-lambda-single-target` | AWS::VpcLattice::TargetGroup | A LAMBDA target group takes a single target | ERROR | none |
|
|
3323
|
+
| `pf-vpclattice-tg-lambda-target-region` | AWS::VpcLattice::TargetGroup | A LAMBDA target group target must be a function in the deploy region | ERROR | none |
|
|
3324
|
+
| `pf-vpclattice-tg-target-id-type` | AWS::VpcLattice::TargetGroup | An INSTANCE target group target Id must be an EC2 instance ID | ERROR | none |
|
|
3325
|
+
| `pf-vpclattice-tg-target-ip-family` | AWS::VpcLattice::TargetGroup | An IP target group target must match the group IpAddressType | ERROR | none |
|
|
3326
|
+
| `pf-vpclattice-tg-target-ip-outside-vpc` | AWS::VpcLattice::TargetGroup | An IP target group target must lie in the VPC CIDR | ERROR | none |
|
|
3327
|
+
| `pf-vpclattice-tg-tcp-health-check-protocol` | AWS::VpcLattice::TargetGroup | An enabled health check on a TCP target group needs HealthCheck.Protocol | ERROR | none |
|
|
3328
|
+
| `pf-vpclattice-tg-vpc-required` | AWS::VpcLattice::TargetGroup | An INSTANCE, IP or ALB target group needs Config.VpcIdentifier | ERROR | none |
|
|
3235
3329
|
| `pf-wafv2-association-config-scope` | AWS::WAFv2::WebACL | AssociationConfig.RequestBody keys must match the web ACL Scope | ERROR | none |
|
|
3236
3330
|
| `pf-wafv2-association-resource-arn` | AWS::WAFv2::WebACLAssociation | ResourceArn must be a supported protected-resource ARN in the deploy account and region | ERROR | none |
|
|
3237
3331
|
| `pf-wafv2-association-webacl-arn` | AWS::WAFv2::WebACLAssociation | WebACLArn must be the ARN of a web ACL in the deploy region | ERROR | none |
|
package/lib/index.js
CHANGED
|
@@ -18,7 +18,7 @@ const rules_generated_1 = require("./rules.generated");
|
|
|
18
18
|
* Preflight.apply(app);
|
|
19
19
|
*/
|
|
20
20
|
class Preflight {
|
|
21
|
-
static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-preflight.Preflight", version: "1.
|
|
21
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-preflight.Preflight", version: "1.9.1" };
|
|
22
22
|
/**
|
|
23
23
|
* Register the cdk-preflight rules on an App or Stage.
|
|
24
24
|
*/
|