@intentius/chant-lexicon-aws 0.46.0 → 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/read-client.d.ts +10 -2
- package/dist/api/read-client.d.ts.map +1 -1
- package/dist/codegen/generate-lexicon.d.ts +5 -0
- package/dist/codegen/generate-lexicon.d.ts.map +1 -1
- package/dist/components/host-delivery.d.ts +4 -3
- package/dist/components/host-delivery.d.ts.map +1 -1
- package/dist/composites/agentcore-agent.d.ts +26 -1
- package/dist/composites/agentcore-agent.d.ts.map +1 -1
- package/dist/composites/bucket-deployment.d.ts +82 -0
- package/dist/composites/bucket-deployment.d.ts.map +1 -0
- package/dist/composites/dynamodb-table.d.ts +45 -0
- package/dist/composites/dynamodb-table.d.ts.map +1 -0
- package/dist/composites/ec2-instance-bundle.d.ts +61 -0
- package/dist/composites/ec2-instance-bundle.d.ts.map +1 -0
- package/dist/composites/ecr-repository.d.ts +49 -0
- package/dist/composites/ecr-repository.d.ts.map +1 -0
- package/dist/composites/fargate-service.d.ts +16 -0
- package/dist/composites/fargate-service.d.ts.map +1 -1
- package/dist/composites/index.d.ts +16 -2
- package/dist/composites/index.d.ts.map +1 -1
- package/dist/composites/monitoring-stack.d.ts +99 -0
- package/dist/composites/monitoring-stack.d.ts.map +1 -0
- package/dist/composites/nlb-service.d.ts +48 -0
- package/dist/composites/nlb-service.d.ts.map +1 -0
- package/dist/composites/step-functions-workflow.d.ts +36 -0
- package/dist/composites/step-functions-workflow.d.ts.map +1 -0
- package/dist/deep-observe.d.ts +45 -0
- package/dist/deep-observe.d.ts.map +1 -1
- package/dist/deep-topology.d.ts +104 -0
- package/dist/deep-topology.d.ts.map +1 -0
- package/dist/effect-receipt-row.d.ts +92 -0
- package/dist/effect-receipt-row.d.ts.map +1 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/integrity.json +14 -6
- package/dist/lint/audit-catalog.d.ts.map +1 -1
- package/dist/lint/post-synth/cf-refs.d.ts +17 -0
- package/dist/lint/post-synth/cf-refs.d.ts.map +1 -1
- package/dist/lint/post-synth/index.d.ts.map +1 -1
- package/dist/lint/post-synth/waw016.d.ts +10 -2
- package/dist/lint/post-synth/waw016.d.ts.map +1 -1
- package/dist/lint/post-synth/waw061.d.ts +19 -0
- package/dist/lint/post-synth/waw061.d.ts.map +1 -0
- package/dist/lint/post-synth/waw062.d.ts +19 -0
- package/dist/lint/post-synth/waw062.d.ts.map +1 -0
- package/dist/lint/post-synth/waw063.d.ts +35 -0
- package/dist/lint/post-synth/waw063.d.ts.map +1 -0
- package/dist/lint/post-synth/waw064.d.ts +17 -0
- package/dist/lint/post-synth/waw064.d.ts.map +1 -0
- package/dist/lint/post-synth/waw065.d.ts +23 -0
- package/dist/lint/post-synth/waw065.d.ts.map +1 -0
- package/dist/lint/post-synth/waw066.d.ts +25 -0
- package/dist/lint/post-synth/waw066.d.ts.map +1 -0
- package/dist/lint/post-synth/waw067.d.ts +24 -0
- package/dist/lint/post-synth/waw067.d.ts.map +1 -0
- package/dist/lint/post-synth/waw068.d.ts +20 -0
- package/dist/lint/post-synth/waw068.d.ts.map +1 -0
- package/dist/manifest.json +1 -1
- package/dist/meta.json +34 -0
- package/dist/okf/index.md +8 -0
- package/dist/okf/rules/WAW061.md +17 -0
- package/dist/okf/rules/WAW062.md +27 -0
- package/dist/okf/rules/WAW063.md +19 -0
- package/dist/okf/rules/WAW064.md +18 -0
- package/dist/okf/rules/WAW065.md +25 -0
- package/dist/okf/rules/WAW066.md +22 -0
- package/dist/okf/rules/WAW067.md +20 -0
- package/dist/okf/rules/WAW068.md +19 -0
- package/dist/okf/types/Action.md +1 -0
- package/dist/okf/types/AutoScalingGroup.md +1 -0
- package/dist/okf/types/Bucket.md +1 -0
- package/dist/okf/types/EC2Route.md +2 -0
- package/dist/okf/types/ECRRepository.md +1 -0
- package/dist/okf/types/Function.md +1 -0
- package/dist/okf/types/IamPolicy.md +1 -0
- package/dist/okf/types/InternetGateway.md +4 -0
- package/dist/okf/types/LaunchTemplate.md +1 -0
- package/dist/okf/types/LoadBalancer.md +1 -0
- package/dist/okf/types/ManagedPolicy.md +2 -0
- package/dist/okf/types/Map.md +5 -0
- package/dist/okf/types/NatGateway.md +4 -0
- package/dist/okf/types/Role.md +2 -0
- package/dist/okf/types/RouteTable.md +4 -0
- package/dist/okf/types/SecurityGroup.md +1 -0
- package/dist/okf/types/StateMachine.md +4 -0
- package/dist/okf/types/Subnet.md +6 -0
- package/dist/okf/types/SubnetRouteTableAssociation.md +5 -0
- package/dist/okf/types/Table.md +4 -0
- package/dist/okf/types/TransitGateway.md +6 -0
- package/dist/okf/types/TransitGatewayAttachment.md +4 -0
- package/dist/okf/types/TransitGatewayPeeringAttachment.md +4 -0
- package/dist/okf/types/TransitGatewayRoute.md +5 -0
- package/dist/okf/types/TransitGatewayRouteTable.md +4 -0
- package/dist/okf/types/TransitGatewayRouteTableAssociation.md +4 -0
- package/dist/okf/types/TransitGatewayRouteTablePropagation.md +4 -0
- package/dist/okf/types/TransitGatewayVpcAttachment.md +4 -0
- package/dist/okf/types/Type.md +8 -0
- package/dist/okf/types/VPNConnection.md +4 -0
- package/dist/okf/types/VPNGateway.md +4 -0
- package/dist/okf/types/Vpc.md +1 -0
- package/dist/op/activities/index.d.ts +6 -0
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/builders.d.ts +47 -0
- package/dist/op/builders.d.ts.map +1 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/receipt-store.d.ts +109 -0
- package/dist/receipt-store.d.ts.map +1 -0
- package/dist/rules/cf-refs.ts +40 -0
- package/dist/rules/waw016.ts +37 -16
- package/dist/rules/waw061.ts +67 -0
- package/dist/rules/waw062.ts +0 -0
- package/dist/rules/waw063.ts +0 -0
- package/dist/rules/waw064.ts +52 -0
- package/dist/rules/waw065.ts +110 -0
- package/dist/rules/waw066.ts +155 -0
- package/dist/rules/waw067.ts +114 -0
- package/dist/rules/waw068.ts +78 -0
- package/dist/serializer.d.ts.map +1 -1
- package/dist/skills/chant-aws-carve-terraform.md +26 -23
- package/dist/spec/parse.d.ts +7 -0
- package/dist/spec/parse.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/api/read-client.test.ts +9 -0
- package/src/api/read-client.ts +15 -2
- package/src/codegen/fallback.ts +1 -0
- package/src/codegen/generate-lexicon.ts +6 -0
- package/src/codegen/sam.ts +9 -0
- package/src/components/host-delivery.ts +4 -3
- package/src/composites/agentcore-agent.ts +35 -13
- package/src/composites/bucket-deployment.test.ts +84 -0
- package/src/composites/bucket-deployment.ts +153 -0
- package/src/composites/composites.test.ts +325 -0
- package/src/composites/dynamodb-table.test.ts +154 -0
- package/src/composites/dynamodb-table.ts +124 -0
- package/src/composites/ec2-instance-bundle.ts +134 -0
- package/src/composites/ecr-repository.test.ts +118 -0
- package/src/composites/ecr-repository.ts +117 -0
- package/src/composites/fargate-service.ts +19 -3
- package/src/composites/index.ts +21 -2
- package/src/composites/monitoring-stack.test.ts +130 -0
- package/src/composites/monitoring-stack.ts +164 -0
- package/src/composites/nlb-service.ts +117 -0
- package/src/composites/step-functions-workflow.ts +127 -0
- package/src/deep-observe.test.ts +201 -1
- package/src/deep-observe.ts +204 -0
- package/src/deep-topology.test.ts +392 -0
- package/src/deep-topology.ts +237 -0
- package/src/effect-receipt-row.test.ts +164 -0
- package/src/effect-receipt-row.ts +147 -0
- package/src/generated/lexicon-aws.json +34 -0
- package/src/index.ts +36 -7
- package/src/lint/audit-catalog.ts +16 -0
- package/src/lint/post-synth/cf-refs.ts +40 -0
- package/src/lint/post-synth/index.ts +16 -0
- package/src/lint/post-synth/waw016.test.ts +61 -4
- package/src/lint/post-synth/waw016.ts +37 -16
- package/src/lint/post-synth/waw061.test.ts +99 -0
- package/src/lint/post-synth/waw061.ts +67 -0
- package/src/lint/post-synth/waw062.test.ts +109 -0
- package/src/lint/post-synth/waw062.ts +0 -0
- package/src/lint/post-synth/waw063.test.ts +220 -0
- package/src/lint/post-synth/waw063.ts +0 -0
- package/src/lint/post-synth/waw064.test.ts +79 -0
- package/src/lint/post-synth/waw064.ts +52 -0
- package/src/lint/post-synth/waw065.test.ts +90 -0
- package/src/lint/post-synth/waw065.ts +110 -0
- package/src/lint/post-synth/waw066.test.ts +108 -0
- package/src/lint/post-synth/waw066.ts +155 -0
- package/src/lint/post-synth/waw067.test.ts +79 -0
- package/src/lint/post-synth/waw067.ts +114 -0
- package/src/lint/post-synth/waw068.test.ts +74 -0
- package/src/lint/post-synth/waw068.ts +78 -0
- package/src/lsp/hover.ts +17 -2
- package/src/op/activities/index.ts +15 -0
- package/src/op/builders.test.ts +61 -0
- package/src/op/builders.ts +72 -0
- package/src/plugin.ts +41 -10
- package/src/receipt-store.test.ts +204 -0
- package/src/receipt-store.ts +315 -0
- package/src/serializer.ts +105 -2
- package/src/skills/chant-aws-carve-terraform.md +26 -23
- package/src/spec/parse.test.ts +74 -0
- package/src/spec/parse.ts +26 -6
package/dist/okf/types/Table.md
CHANGED
|
@@ -43,3 +43,7 @@ resource_type: AWS::DynamoDB::Table
|
|
|
43
43
|
- [WAW027](/rules/WAW027.md): DynamoDB table does not have point-in-time recovery enabled
|
|
44
44
|
- [WAW030](/rules/WAW030.md): Missing DependsOn for known CloudFormation ordering patterns
|
|
45
45
|
- [WAW059](/rules/WAW059.md): Wildcard Resource where the declared graph enumerates the touched set — tighten to the consumers' declared Arns
|
|
46
|
+
- [WAW062](/rules/WAW062.md): Duplicate export name or explicit resource name within a template — fails at deploy time
|
|
47
|
+
- [WAW064](/rules/WAW064.md): Transit Gateway route table declares a Blackhole route — confirm the traffic drop is intentional, not an accident
|
|
48
|
+
- [WAW065](/rules/WAW065.md): Transit Gateway route table has associations but no propagations, or an attachment wired into no route table
|
|
49
|
+
- [WAW066](/rules/WAW066.md): Private subnet's route table has no default route, or its default route targets a gateway that does not exist in the template
|
|
@@ -33,3 +33,9 @@ resource_type: AWS::EC2::TransitGateway
|
|
|
33
33
|
- `EncryptionSupportState`
|
|
34
34
|
- `Id`
|
|
35
35
|
- `TransitGatewayArn`
|
|
36
|
+
|
|
37
|
+
## Governed by
|
|
38
|
+
|
|
39
|
+
- [WAW064](/rules/WAW064.md): Transit Gateway route table declares a Blackhole route — confirm the traffic drop is intentional, not an accident
|
|
40
|
+
- [WAW065](/rules/WAW065.md): Transit Gateway route table has associations but no propagations, or an attachment wired into no route table
|
|
41
|
+
- [WAW068](/rules/WAW068.md): VPN Gateway or Transit Gateway has only one attached VPN Connection — no redundant path for hybrid connectivity
|
|
@@ -26,3 +26,7 @@ resource_type: AWS::EC2::TransitGatewayPeeringAttachment
|
|
|
26
26
|
- `State`
|
|
27
27
|
- `Status`
|
|
28
28
|
- `TransitGatewayAttachmentId`
|
|
29
|
+
|
|
30
|
+
## Governed by
|
|
31
|
+
|
|
32
|
+
- [WAW065](/rules/WAW065.md): Transit Gateway route table has associations but no propagations, or an attachment wired into no route table
|
|
@@ -14,3 +14,8 @@ resource_type: AWS::EC2::TransitGatewayRoute
|
|
|
14
14
|
- `TransitGatewayRouteTableId` (`string`, required): The ID of transit gateway route table.
|
|
15
15
|
- `Blackhole` (`boolean`, optional): Indicates whether to drop traffic that matches this route.
|
|
16
16
|
- `TransitGatewayAttachmentId` (`string`, optional): The ID of transit gateway attachment.
|
|
17
|
+
|
|
18
|
+
## Governed by
|
|
19
|
+
|
|
20
|
+
- [WAW064](/rules/WAW064.md): Transit Gateway route table declares a Blackhole route — confirm the traffic drop is intentional, not an accident
|
|
21
|
+
- [WAW065](/rules/WAW065.md): Transit Gateway route table has associations but no propagations, or an attachment wired into no route table
|
|
@@ -17,3 +17,7 @@ resource_type: AWS::EC2::TransitGatewayRouteTable
|
|
|
17
17
|
## Attributes
|
|
18
18
|
|
|
19
19
|
- `TransitGatewayRouteTableId`
|
|
20
|
+
|
|
21
|
+
## Governed by
|
|
22
|
+
|
|
23
|
+
- [WAW065](/rules/WAW065.md): Transit Gateway route table has associations but no propagations, or an attachment wired into no route table
|
|
@@ -12,3 +12,7 @@ resource_type: AWS::EC2::TransitGatewayRouteTableAssociation
|
|
|
12
12
|
|
|
13
13
|
- `TransitGatewayAttachmentId` (`string`, required): The ID of transit gateway attachment.
|
|
14
14
|
- `TransitGatewayRouteTableId` (`string`, required): The ID of transit gateway route table.
|
|
15
|
+
|
|
16
|
+
## Governed by
|
|
17
|
+
|
|
18
|
+
- [WAW065](/rules/WAW065.md): Transit Gateway route table has associations but no propagations, or an attachment wired into no route table
|
|
@@ -12,3 +12,7 @@ resource_type: AWS::EC2::TransitGatewayRouteTablePropagation
|
|
|
12
12
|
|
|
13
13
|
- `TransitGatewayAttachmentId` (`string`, required): The ID of transit gateway attachment.
|
|
14
14
|
- `TransitGatewayRouteTableId` (`string`, required): The ID of transit gateway route table.
|
|
15
|
+
|
|
16
|
+
## Governed by
|
|
17
|
+
|
|
18
|
+
- [WAW065](/rules/WAW065.md): Transit Gateway route table has associations but no propagations, or an attachment wired into no route table
|
package/dist/okf/types/Type.md
CHANGED
|
@@ -75,3 +75,11 @@ resource_type: AWS::Cassandra::Type
|
|
|
75
75
|
- [WAW058](/rules/WAW058.md): Organization audit trail missing, not logging, or scoped down to a single region
|
|
76
76
|
- [WAW059](/rules/WAW059.md): Wildcard Resource where the declared graph enumerates the touched set — tighten to the consumers' declared Arns
|
|
77
77
|
- [WAW060](/rules/WAW060.md): IAM policy attached to no principal — it grants nothing
|
|
78
|
+
- [WAW061](/rules/WAW061.md): Subnet CidrBlock falls outside its VPC's CidrBlock — fails at deploy time
|
|
79
|
+
- [WAW062](/rules/WAW062.md): Duplicate export name or explicit resource name within a template — fails at deploy time
|
|
80
|
+
- [WAW063](/rules/WAW063.md): IAM policy denies an action another attached policy on the same role allows — explicit Deny wins, runtime 403
|
|
81
|
+
- [WAW064](/rules/WAW064.md): Transit Gateway route table declares a Blackhole route — confirm the traffic drop is intentional, not an accident
|
|
82
|
+
- [WAW065](/rules/WAW065.md): Transit Gateway route table has associations but no propagations, or an attachment wired into no route table
|
|
83
|
+
- [WAW066](/rules/WAW066.md): Private subnet's route table has no default route, or its default route targets a gateway that does not exist in the template
|
|
84
|
+
- [WAW067](/rules/WAW067.md): A single-AZ NAT gateway serves private subnets across multiple Availability Zones — single point of failure for cross-AZ egress
|
|
85
|
+
- [WAW068](/rules/WAW068.md): VPN Gateway or Transit Gateway has only one attached VPN Connection — no redundant path for hybrid connectivity
|
package/dist/okf/types/Vpc.md
CHANGED
|
@@ -18,6 +18,12 @@ export { flociUp, flociDown, flociRunCommand, flociRmCommand, flociExistsCommand
|
|
|
18
18
|
export type { FlociUpArgs, FlociDownArgs } from "./floci.js";
|
|
19
19
|
export { awsApply, awsDelete, rollbackStack, waitForStackSettled, cfnUrl, cfnForm, capabilityParams, xmlField, stackStatus, stackId, cfnErrorMessage, isStackMissing, isNoUpdates, isSuccessStatus, isFailureStatus, isTerminalStatus, } from "./aws-apply.js";
|
|
20
20
|
export type { AwsApplyArgs, RollbackStackArgs, AwsHttp } from "./aws-apply.js";
|
|
21
|
+
export declare const receiptRead: (args: import("@intentius/chant/op/receipt-store").ReceiptReadArgs, signal?: AbortSignal) => Promise<import("@intentius/chant/op/receipt-store").ReceiptReadResult>;
|
|
22
|
+
export declare const receiptWrite: (args: import("@intentius/chant/op/receipt-store").ReceiptWriteArgs, signal?: AbortSignal) => Promise<{
|
|
23
|
+
written: true;
|
|
24
|
+
receipt: string;
|
|
25
|
+
}>;
|
|
26
|
+
export declare const receiptStaleness: (args: import("@intentius/chant/op/receipt-store").ReceiptStalenessArgs, signal?: AbortSignal) => Promise<import("@intentius/chant/op/receipt-store").ReceiptStalenessResult>;
|
|
21
27
|
export { awsAgentCoreFetchTrace } from "../../agentcore/trace-fetch.js";
|
|
22
28
|
export type { AgentCoreTraceSource, AwsAgentCoreFetchTraceArgs, AwsAgentCoreFetchTraceResult, } from "../../agentcore/trace-fetch.js";
|
|
23
29
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/op/activities/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EACL,OAAO,EACP,SAAS,EACT,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,QAAQ,EACR,YAAY,GACb,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE1D,OAAO,EACL,QAAQ,EACR,SAAS,EACT,aAAa,EACb,mBAAmB,EACnB,MAAM,EACN,OAAO,EACP,gBAAgB,EAChB,QAAQ,EACR,WAAW,EACX,OAAO,EACP,eAAe,EACf,cAAc,EACd,WAAW,EACX,eAAe,EACf,eAAe,EACf,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/op/activities/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EACL,OAAO,EACP,SAAS,EACT,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,QAAQ,EACR,YAAY,GACb,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE1D,OAAO,EACL,QAAQ,EACR,SAAS,EACT,aAAa,EACb,mBAAmB,EACnB,MAAM,EACN,OAAO,EACP,gBAAgB,EAChB,QAAQ,EACR,WAAW,EACX,OAAO,EACP,eAAe,EACf,cAAc,EACd,WAAW,EACX,eAAe,EACf,eAAe,EACf,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAa5E,eAAO,MAAM,WAAW,qKAAqC,CAAC;AAC9D,eAAO,MAAM,YAAY;;;EAAsC,CAAC;AAChE,eAAO,MAAM,gBAAgB,+KAA0C,CAAC;AAExE,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,YAAY,EACV,oBAAoB,EACpB,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed step-builder wrappers for this lexicon's activities (chant #1288
|
|
3
|
+
* Stage 2). See `lexicons/k8s/src/op/builders.ts`'s module doc for why these
|
|
4
|
+
* live beside their `*Args` interfaces rather than in core or the temporal
|
|
5
|
+
* barrel: core cannot import a lexicon's types (lexicons depend on core, not
|
|
6
|
+
* the reverse), and wiring them into the cloud-agnostic temporal barrel
|
|
7
|
+
* would make it depend on every cloud lexicon at runtime. `opts`'s type in
|
|
8
|
+
* each wrapper below IS the activity's own `*Args` interface (via
|
|
9
|
+
* `Omit`/`WithStepRefs`) — never restated. `core`'s own
|
|
10
|
+
* `awsApply`/`awsDelete`/`flociUp`/`flociDown` are unchanged and produce
|
|
11
|
+
* byte-identical `ActivityStep` output; these are purely additive.
|
|
12
|
+
*/
|
|
13
|
+
import { type ActivityStep, type NamedActivityStep, type WithStepRefs } from "@intentius/chant/op";
|
|
14
|
+
import type { AwsApplyArgs, AwsDeleteArgs } from "./activities/aws-apply.js";
|
|
15
|
+
import type { FlociUpArgs, FlociDownArgs } from "./activities/floci.js";
|
|
16
|
+
/** Extra opts every wrapper below accepts alongside its activity's own fields. */
|
|
17
|
+
type StepOpts = {
|
|
18
|
+
profile?: ActivityStep["profile"];
|
|
19
|
+
id?: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Deploy a built CloudFormation template directly against the CFN API — the
|
|
23
|
+
* fully typed twin of core's `awsApply`. `opts` is {@link AwsApplyArgs}
|
|
24
|
+
* itself, minus the positional `templatePath`. Defaults to the `longInfra`
|
|
25
|
+
* profile.
|
|
26
|
+
*/
|
|
27
|
+
export declare const awsApply: (templatePath: string, opts: WithStepRefs<Omit<AwsApplyArgs, "templatePath">> & StepOpts) => NamedActivityStep;
|
|
28
|
+
/**
|
|
29
|
+
* Delete a CloudFormation stack — the inverse of {@link awsApply}, fully
|
|
30
|
+
* typed twin of core's `awsDelete`. `opts` is {@link AwsDeleteArgs} itself,
|
|
31
|
+
* minus the positional `templatePath`. Defaults to the `longInfra` profile.
|
|
32
|
+
*/
|
|
33
|
+
export declare const awsDelete: (templatePath: string, opts: WithStepRefs<Omit<AwsDeleteArgs, "templatePath">> & StepOpts) => NamedActivityStep;
|
|
34
|
+
/**
|
|
35
|
+
* Boot the local Floci AWS emulator — the fully typed twin of core's
|
|
36
|
+
* `flociUp`. `opts` is {@link FlociUpArgs} itself. Defaults to the
|
|
37
|
+
* `longInfra` profile.
|
|
38
|
+
*/
|
|
39
|
+
export declare const flociUp: (opts?: WithStepRefs<FlociUpArgs> & StepOpts) => NamedActivityStep;
|
|
40
|
+
/**
|
|
41
|
+
* Stop and remove the local Floci emulator container — the fully typed twin
|
|
42
|
+
* of core's `flociDown`. `opts` is {@link FlociDownArgs} itself. Defaults to
|
|
43
|
+
* the `fastIdempotent` profile.
|
|
44
|
+
*/
|
|
45
|
+
export declare const flociDown: (opts?: WithStepRefs<FlociDownArgs> & StepOpts) => NamedActivityStep;
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=builders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../../src/op/builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAErE,kFAAkF;AAClF,KAAK,QAAQ,GAAG;IAAE,OAAO,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,GACnB,cAAc,MAAM,EACpB,MAAM,YAAY,CAAC,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC,GAAG,QAAQ,KAChE,iBAGF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,SAAS,GACpB,cAAc,MAAM,EACpB,MAAM,YAAY,CAAC,IAAI,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC,GAAG,QAAQ,KACjE,iBAGF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,OAAO,GAAI,OAAO,YAAY,CAAC,WAAW,CAAC,GAAG,QAAQ,KAAG,iBAGrE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,OAAO,YAAY,CAAC,aAAa,CAAC,GAAG,QAAQ,KAAG,iBAGzE,CAAC"}
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAgL,MAAM,0BAA0B,CAAC;AAqC5O;yEACyE;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAiBnD,eAAO,MAAM,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAgL,MAAM,0BAA0B,CAAC;AAqC5O;yEACyE;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAiBnD,eAAO,MAAM,SAAS,EAAE,aAk9BvB,CAAC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The aws `ReceiptStore` (#1835, epic #1703) — core's injectable receipt seam
|
|
3
|
+
* (#1834, `@intentius/chant/op/receipt-store`) implemented over SSM Parameter
|
|
4
|
+
* Store, plain `String`, at the path identity ./effect-receipt-row.ts derives
|
|
5
|
+
* from the ownership marker fields.
|
|
6
|
+
*
|
|
7
|
+
* The transport is the lexicon's own read/apply transport (./api/read-client,
|
|
8
|
+
* #1206), pointed at the SSM JSON API: `fetch`, SigV4 when credentials
|
|
9
|
+
* resolve, and the one endpoint-override rule (#1694) — the `endpoint`
|
|
10
|
+
* option, else `AWS_ENDPOINT_URL_SSM`, else `AWS_ENDPOINT_URL` — so a local
|
|
11
|
+
* emulator lane reads and writes receipts without any store-specific wiring.
|
|
12
|
+
*
|
|
13
|
+
* Write discipline (epic decision 3): `write` exists for the `effect()` step
|
|
14
|
+
* alone — the step's read-compare-run-write is the only path that reaches it,
|
|
15
|
+
* on success, last. `PutParameter` is `Type: "String"` always; the first
|
|
16
|
+
* write creates the parameter with the ownership tags, and a later write
|
|
17
|
+
* overwrites the value (SSM refuses `Overwrite` and `Tags` in one call, so
|
|
18
|
+
* tags ride creation only — they never change after).
|
|
19
|
+
*
|
|
20
|
+
* Identity: the parameter name needs `<stack>` and `<env>`, which the
|
|
21
|
+
* activity args deliberately do not carry (the `EffectReceiptRef` is
|
|
22
|
+
* identity-of-the-effect, not identity-of-the-deployment). The store resolves
|
|
23
|
+
* them once, lazily, at first use: an explicit option, else `CHANT_ENV` (what
|
|
24
|
+
* `chant run --env` sets) and the project's `ownership` block — the same
|
|
25
|
+
* fields that stamp markers (epic decision 4). Nothing resolving is an error,
|
|
26
|
+
* never a guessed segment.
|
|
27
|
+
*/
|
|
28
|
+
import type { ReceiptStore } from "@intentius/chant/op/receipt-store";
|
|
29
|
+
import type { ResourceMetadata } from "@intentius/chant/lexicon";
|
|
30
|
+
import type { UnobservedReason } from "@intentius/chant/observation";
|
|
31
|
+
import { type AwsCredentialSource, type AwsReadClientOptions, type AwsReadHttp } from "./api/read-client.js";
|
|
32
|
+
/** Options for {@link awsReceiptStore}. All optional: the default store reads
|
|
33
|
+
* its identity from the project and its endpoint from the environment. */
|
|
34
|
+
export interface AwsReceiptStoreOptions {
|
|
35
|
+
/** The path's `<stack>` segment. Omitted, the project's `ownership.stack`
|
|
36
|
+
* (chant.config.ts, found upward from `cwd`) answers. */
|
|
37
|
+
stack?: string;
|
|
38
|
+
/** The path's `<env>` segment — explicit by decision 4. Omitted, `CHANT_ENV`
|
|
39
|
+
* (set by `chant run --env`) answers, then a literal `ownership.env`. */
|
|
40
|
+
environment?: string;
|
|
41
|
+
/** Where to look for chant.config.ts. Defaults to the working directory. */
|
|
42
|
+
cwd?: string;
|
|
43
|
+
/** Endpoint override; omitted, `AWS_ENDPOINT_URL[_SSM]` answers (#1694). */
|
|
44
|
+
endpoint?: string;
|
|
45
|
+
/** Region for the real-AWS host. */
|
|
46
|
+
region?: string;
|
|
47
|
+
/** Injectable HTTP, mirroring the read client's. Tests avoid the network. */
|
|
48
|
+
http?: AwsReadHttp;
|
|
49
|
+
/** Environment record the endpoint/credential/identity fallbacks read.
|
|
50
|
+
* Defaults to `process.env`; injectable for tests. */
|
|
51
|
+
env?: Record<string, string | undefined>;
|
|
52
|
+
/** What to sign with — same seam as the read client. */
|
|
53
|
+
credentials?: AwsCredentialSource;
|
|
54
|
+
/** Sign even against an endpoint override — for an override that is real AWS. */
|
|
55
|
+
signEndpointOverride?: boolean;
|
|
56
|
+
}
|
|
57
|
+
/** One SSM JSON call. Exported for the observation leg (plugin.ts), which
|
|
58
|
+
* reads the same parameters the store writes. */
|
|
59
|
+
export declare function ssmCall(action: string, payload: Record<string, unknown>, options: AwsReadClientOptions): Promise<{
|
|
60
|
+
status: number;
|
|
61
|
+
json: Record<string, unknown>;
|
|
62
|
+
}>;
|
|
63
|
+
/** The API's own error code from a JSON-protocol error body — `__type`, with
|
|
64
|
+
* any `namespace#` prefix stripped. */
|
|
65
|
+
export declare function ssmErrorCode(json: Record<string, unknown>): string | undefined;
|
|
66
|
+
/**
|
|
67
|
+
* `GetParameter` by name. Absent (`ParameterNotFound`) is `undefined` — a real
|
|
68
|
+
* answer, distinct from a failed read, which throws.
|
|
69
|
+
*/
|
|
70
|
+
export declare function ssmGetParameter(name: string, options?: AwsReadClientOptions): Promise<string | undefined>;
|
|
71
|
+
/**
|
|
72
|
+
* `PutParameter`, plain `String`. Creation carries `tags`; an existing
|
|
73
|
+
* parameter is overwritten (`Overwrite: true`) without them — SSM refuses
|
|
74
|
+
* `Overwrite` and `Tags` in the same call, and ownership tags never change.
|
|
75
|
+
*/
|
|
76
|
+
export declare function ssmPutParameter(name: string, value: string, tags: Record<string, string>, options?: AwsReadClientOptions): Promise<void>;
|
|
77
|
+
/** What the observation leg learned about the declared receipt rows. */
|
|
78
|
+
export interface ReceiptRowObservation {
|
|
79
|
+
resources: Record<string, ResourceMetadata>;
|
|
80
|
+
unobserved: Record<string, {
|
|
81
|
+
type: string;
|
|
82
|
+
reason: UnobservedReason;
|
|
83
|
+
detail: string;
|
|
84
|
+
}>;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The plan-side live read of the receipt rows (#1835's observation leg).
|
|
88
|
+
*
|
|
89
|
+
* A receipt is not a stack member — the applier never writes it (#1832) — so
|
|
90
|
+
* `describe-stack-resources` honestly reports it absent even while the
|
|
91
|
+
* parameter exists. The serializer renders each receipt's derived path into
|
|
92
|
+
* the template's `Metadata` (./serializer.ts), so this leg reads the paths
|
|
93
|
+
* back from the build output — one derivation, decision 4 — and asks SSM
|
|
94
|
+
* `GetParameter` for each. Present maps the stored value onto
|
|
95
|
+
* `attributes.value` (core's `RECEIPT_VALUE_ATTRIBUTE`); `ParameterNotFound`
|
|
96
|
+
* is a real absence and stays one; a failed read is an `unobserved` hole,
|
|
97
|
+
* never a wrong answer — a receipt nobody could read must not arrive
|
|
98
|
+
* downstream as "the effect never ran".
|
|
99
|
+
*/
|
|
100
|
+
export declare function observeReceiptRows(entityNames: string[], buildOutput: string, options?: AwsReadClientOptions): Promise<ReceiptRowObservation>;
|
|
101
|
+
/**
|
|
102
|
+
* The `ReceiptStore` over SSM. Bind it once in the op activities barrel —
|
|
103
|
+
* `receiptActivities(awsReceiptStore())` — and the registry resolves
|
|
104
|
+
* `receiptRead`/`receiptWrite`/`receiptStaleness` by name, exactly like
|
|
105
|
+
* `ensureSecret` (#1830). Identity and endpoint resolve lazily at first use,
|
|
106
|
+
* so module load never reads the project or the environment.
|
|
107
|
+
*/
|
|
108
|
+
export declare function awsReceiptStore(options?: AwsReceiptStoreOptions): ReceiptStore;
|
|
109
|
+
//# sourceMappingURL=receipt-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receipt-store.d.ts","sourceRoot":"","sources":["../src/receipt-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAIH,OAAO,KAAK,EAAoB,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACxF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAKL,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,WAAW,EACjB,MAAM,mBAAmB,CAAC;AAO3B;0EAC0E;AAC1E,MAAM,WAAW,sBAAsB;IACrC;6DACyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;6EACyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB;0DACsD;IACtD,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,wDAAwD;IACxD,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAClC,iFAAiF;IACjF,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;iDACiD;AACjD,wBAAsB,OAAO,CAC3B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,CAyB5D;AAED;uCACuC;AACvC,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,SAAS,CAI9E;AAQD;;;GAGG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAQ7B;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,IAAI,CAAC,CAiBf;AA4CD,wEAAwE;AACxE,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC5C,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,gBAAgB,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EAAE,EACrB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,qBAAqB,CAAC,CA+ChC;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,sBAA2B,GAAG,YAAY,CAyBlF"}
|
package/dist/rules/cf-refs.ts
CHANGED
|
@@ -169,6 +169,46 @@ export function isFullTierEnv(env: string | undefined): boolean {
|
|
|
169
169
|
return env === "prod" || env === "production" || env === "full";
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Parse an IPv4 CIDR literal ("10.0.0.0/16") into its numeric base address
|
|
174
|
+
* and prefix length. Returns null for anything that isn't a plain IPv4 CIDR
|
|
175
|
+
* (IPv6, malformed octets, out-of-range prefix) — callers treat that as
|
|
176
|
+
* "can't prove statically" rather than an error.
|
|
177
|
+
*/
|
|
178
|
+
export function parseIpv4Cidr(cidr: string): { base: number; prefix: number } | null {
|
|
179
|
+
const m = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,2})$/.exec(cidr.trim());
|
|
180
|
+
if (!m) return null;
|
|
181
|
+
const octets = m.slice(1, 5).map(Number);
|
|
182
|
+
if (octets.some((o) => o < 0 || o > 255)) return null;
|
|
183
|
+
const prefix = Number(m[5]);
|
|
184
|
+
if (prefix < 0 || prefix > 32) return null;
|
|
185
|
+
const base = ((octets[0] << 24) | (octets[1] << 16) | (octets[2] << 8) | octets[3]) >>> 0;
|
|
186
|
+
return { base, prefix };
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** [networkAddress, broadcastAddress] for a parsed IPv4 CIDR block. */
|
|
190
|
+
function ipv4Range(cidr: { base: number; prefix: number }): [number, number] {
|
|
191
|
+
const maskBits = cidr.prefix === 0 ? 0 : (0xffffffff << (32 - cidr.prefix)) >>> 0;
|
|
192
|
+
const network = (cidr.base & maskBits) >>> 0;
|
|
193
|
+
const broadcast = (network | (~maskBits >>> 0)) >>> 0;
|
|
194
|
+
return [network, broadcast];
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Whether `inner` (an IPv4 CIDR literal) falls entirely within `outer`.
|
|
199
|
+
* Returns null — not false — when either literal isn't a plain, parseable
|
|
200
|
+
* IPv4 CIDR (e.g. IPv6, or a CloudFormation intrinsic already stringified
|
|
201
|
+
* elsewhere); a null means "statically unprovable", not "violation".
|
|
202
|
+
*/
|
|
203
|
+
export function ipv4CidrContains(outer: string, inner: string): boolean | null {
|
|
204
|
+
const outerCidr = parseIpv4Cidr(outer);
|
|
205
|
+
const innerCidr = parseIpv4Cidr(inner);
|
|
206
|
+
if (!outerCidr || !innerCidr) return null;
|
|
207
|
+
const [oStart, oEnd] = ipv4Range(outerCidr);
|
|
208
|
+
const [iStart, iEnd] = ipv4Range(innerCidr);
|
|
209
|
+
return iStart >= oStart && iEnd <= oEnd;
|
|
210
|
+
}
|
|
211
|
+
|
|
172
212
|
/**
|
|
173
213
|
* Check if a port range [fromPort, toPort] contains any of the sensitive ports.
|
|
174
214
|
*/
|
package/dist/rules/waw016.ts
CHANGED
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
* WAW016: Deprecated Property Usage
|
|
3
3
|
*
|
|
4
4
|
* Flags properties marked as deprecated in the CloudFormation Registry.
|
|
5
|
-
*
|
|
5
|
+
*
|
|
6
|
+
* Two bases feed this, and the finding says which one it stands on (#1701).
|
|
7
|
+
* A `declared` name comes from the Registry schema's own `deprecatedProperties`
|
|
8
|
+
* array. An `inferred` name comes from a regex over the property description,
|
|
9
|
+
* which also matches descriptions that mention the deprecation of a sibling
|
|
10
|
+
* property, an enum value, or the thing the property configures. Declared is a
|
|
11
|
+
* warning; inferred is reported at info and worded as a guess.
|
|
6
12
|
*/
|
|
7
13
|
|
|
8
14
|
import { readFileSync } from "fs";
|
|
@@ -10,18 +16,23 @@ import { join } from "path";
|
|
|
10
16
|
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
11
17
|
import { parseCFTemplate } from "./cf-refs";
|
|
12
18
|
|
|
19
|
+
/** What a deprecation classification rests on. */
|
|
20
|
+
export type DeprecationBasis = "declared" | "inferred";
|
|
21
|
+
|
|
13
22
|
interface LexiconEntry {
|
|
14
23
|
kind: string;
|
|
15
24
|
resourceType: string;
|
|
16
25
|
deprecatedProperties?: string[];
|
|
26
|
+
inferredDeprecations?: string[];
|
|
17
27
|
[key: string]: unknown;
|
|
18
28
|
}
|
|
19
29
|
|
|
20
30
|
/**
|
|
21
|
-
* Load deprecated properties per resource type from the lexicon JSON
|
|
31
|
+
* Load deprecated properties per resource type from the lexicon JSON, each
|
|
32
|
+
* tagged with the basis it was classified on.
|
|
22
33
|
*/
|
|
23
|
-
function loadDeprecatedProperties(): Map<string,
|
|
24
|
-
const map = new Map<string,
|
|
34
|
+
function loadDeprecatedProperties(): Map<string, Map<string, DeprecationBasis>> {
|
|
35
|
+
const map = new Map<string, Map<string, DeprecationBasis>>();
|
|
25
36
|
try {
|
|
26
37
|
const pkgDir = join(__dirname, "..", "..", "..");
|
|
27
38
|
const lexiconPath = join(pkgDir, "src", "generated", "lexicon-aws.json");
|
|
@@ -29,9 +40,15 @@ function loadDeprecatedProperties(): Map<string, Set<string>> {
|
|
|
29
40
|
const data = JSON.parse(content) as Record<string, LexiconEntry>;
|
|
30
41
|
|
|
31
42
|
for (const [_name, entry] of Object.entries(data)) {
|
|
32
|
-
if (entry.kind
|
|
33
|
-
|
|
43
|
+
if (entry.kind !== "resource" || !entry.resourceType) continue;
|
|
44
|
+
if (!entry.deprecatedProperties?.length) continue;
|
|
45
|
+
|
|
46
|
+
const inferred = new Set(entry.inferredDeprecations ?? []);
|
|
47
|
+
const byProp = new Map<string, DeprecationBasis>();
|
|
48
|
+
for (const propName of entry.deprecatedProperties) {
|
|
49
|
+
byProp.set(propName, inferred.has(propName) ? "inferred" : "declared");
|
|
34
50
|
}
|
|
51
|
+
map.set(entry.resourceType, byProp);
|
|
35
52
|
}
|
|
36
53
|
} catch {
|
|
37
54
|
// Lexicon not available — skip
|
|
@@ -44,7 +61,7 @@ function loadDeprecatedProperties(): Map<string, Set<string>> {
|
|
|
44
61
|
*/
|
|
45
62
|
export function checkDeprecatedProperties(
|
|
46
63
|
ctx: PostSynthContext,
|
|
47
|
-
deprecated: Map<string,
|
|
64
|
+
deprecated: Map<string, Map<string, DeprecationBasis>>,
|
|
48
65
|
): PostSynthDiagnostic[] {
|
|
49
66
|
if (deprecated.size === 0) return [];
|
|
50
67
|
|
|
@@ -60,15 +77,19 @@ export function checkDeprecatedProperties(
|
|
|
60
77
|
|
|
61
78
|
const props = resource.Properties ?? {};
|
|
62
79
|
for (const propName of Object.keys(props)) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
80
|
+
const basis = deprProps.get(propName);
|
|
81
|
+
if (!basis) continue;
|
|
82
|
+
|
|
83
|
+
diagnostics.push({
|
|
84
|
+
checkId: "WAW016",
|
|
85
|
+
severity: basis === "declared" ? "warning" : "info",
|
|
86
|
+
message:
|
|
87
|
+
basis === "declared"
|
|
88
|
+
? `Resource "${logicalId}" (${resource.Type}) uses deprecated property "${propName}" — consider alternatives`
|
|
89
|
+
: `Resource "${logicalId}" (${resource.Type}) uses property "${propName}", whose description reads as deprecated — the CloudFormation Registry does not declare it deprecated, so confirm before changing it`,
|
|
90
|
+
entity: logicalId,
|
|
91
|
+
lexicon: "aws",
|
|
92
|
+
});
|
|
72
93
|
}
|
|
73
94
|
}
|
|
74
95
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WAW061: Subnet CIDR Not Contained In VPC CIDR
|
|
3
|
+
*
|
|
4
|
+
* A subnet's CidrBlock must fall entirely inside its VPC's CidrBlock.
|
|
5
|
+
* Stock CDK does not check this — CloudFormation accepts the template and
|
|
6
|
+
* only fails the `AWS::EC2::Subnet` resource at deploy time
|
|
7
|
+
* ("The CIDR ... is invalid" / "does not fall within the CIDR range of the
|
|
8
|
+
* VPC"), after the rest of the stack may have already started rolling out.
|
|
9
|
+
* This is a cheap static graph check: follow the subnet's VpcId Ref to a
|
|
10
|
+
* declared VPC in the same template and do IPv4 CIDR-range math.
|
|
11
|
+
*
|
|
12
|
+
* Stays quiet whenever the graph can't prove it: intrinsic CIDR blocks,
|
|
13
|
+
* IPv6, a VpcId that isn't a simple Ref to a declared AWS::EC2::VPC, or a
|
|
14
|
+
* VPC whose own CidrBlock isn't a literal string.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
18
|
+
import { parseCFTemplate, findResourceRefs, ipv4CidrContains } from "./cf-refs";
|
|
19
|
+
|
|
20
|
+
export function checkSubnetCidrContainment(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
21
|
+
const diagnostics: PostSynthDiagnostic[] = [];
|
|
22
|
+
|
|
23
|
+
for (const [_lexicon, output] of ctx.outputs) {
|
|
24
|
+
const template = parseCFTemplate(output);
|
|
25
|
+
if (!template?.Resources) continue;
|
|
26
|
+
|
|
27
|
+
for (const [logicalId, resource] of Object.entries(template.Resources)) {
|
|
28
|
+
if (resource.Type !== "AWS::EC2::Subnet") continue;
|
|
29
|
+
|
|
30
|
+
const props = resource.Properties ?? {};
|
|
31
|
+
const subnetCidr = props.CidrBlock;
|
|
32
|
+
if (typeof subnetCidr !== "string") continue;
|
|
33
|
+
|
|
34
|
+
const vpcRefs = findResourceRefs(props.VpcId);
|
|
35
|
+
if (vpcRefs.size !== 1) continue;
|
|
36
|
+
const [vpcId] = vpcRefs;
|
|
37
|
+
|
|
38
|
+
const vpc = template.Resources[vpcId];
|
|
39
|
+
if (!vpc || vpc.Type !== "AWS::EC2::VPC") continue;
|
|
40
|
+
|
|
41
|
+
const vpcCidr = vpc.Properties?.CidrBlock;
|
|
42
|
+
if (typeof vpcCidr !== "string") continue;
|
|
43
|
+
|
|
44
|
+
const contained = ipv4CidrContains(vpcCidr, subnetCidr);
|
|
45
|
+
if (contained === false) {
|
|
46
|
+
diagnostics.push({
|
|
47
|
+
checkId: "WAW061",
|
|
48
|
+
severity: "error",
|
|
49
|
+
message: `Subnet "${logicalId}" CidrBlock ${subnetCidr} is not contained within VPC "${vpcId}"'s CidrBlock ${vpcCidr} — CloudFormation rejects this at deploy time`,
|
|
50
|
+
entity: logicalId,
|
|
51
|
+
lexicon: "aws",
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return diagnostics;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const waw061: PostSynthCheck = {
|
|
61
|
+
id: "WAW061",
|
|
62
|
+
description: "Subnet CidrBlock falls outside its VPC's CidrBlock — fails at deploy time",
|
|
63
|
+
|
|
64
|
+
check(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
65
|
+
return checkSubnetCidrContainment(ctx);
|
|
66
|
+
},
|
|
67
|
+
};
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WAW064: Transit Gateway Route Table Declares A Blackhole Route
|
|
3
|
+
*
|
|
4
|
+
* `AWS::EC2::TransitGatewayRoute` with `Blackhole: true` silently drops any
|
|
5
|
+
* traffic matching its destination CIDR instead of forwarding it —
|
|
6
|
+
* CloudFormation deploys this without complaint, and the packet loss only
|
|
7
|
+
* surfaces downstream as unreachable hosts or a timeout nobody can explain
|
|
8
|
+
* from the template alone. A blackhole route is sometimes deliberate — an
|
|
9
|
+
* explicit deny for a CIDR range, or a placeholder pending real
|
|
10
|
+
* infrastructure — but it is also exactly what a copy-pasted route table or
|
|
11
|
+
* a forgotten cleanup step leaves behind. Warn so it stays a conscious
|
|
12
|
+
* choice rather than a silent accident.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
16
|
+
import { parseCFTemplate } from "./cf-refs";
|
|
17
|
+
|
|
18
|
+
export function checkTgwBlackholeRoute(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
19
|
+
const diagnostics: PostSynthDiagnostic[] = [];
|
|
20
|
+
|
|
21
|
+
for (const [_lexicon, output] of ctx.outputs) {
|
|
22
|
+
const template = parseCFTemplate(output);
|
|
23
|
+
if (!template?.Resources) continue;
|
|
24
|
+
|
|
25
|
+
for (const [logicalId, resource] of Object.entries(template.Resources)) {
|
|
26
|
+
if (resource.Type !== "AWS::EC2::TransitGatewayRoute") continue;
|
|
27
|
+
|
|
28
|
+
const props = resource.Properties ?? {};
|
|
29
|
+
if (props.Blackhole !== true) continue;
|
|
30
|
+
|
|
31
|
+
const cidr = typeof props.DestinationCidrBlock === "string" ? props.DestinationCidrBlock : "(unknown destination)";
|
|
32
|
+
diagnostics.push({
|
|
33
|
+
checkId: "WAW064",
|
|
34
|
+
severity: "warning",
|
|
35
|
+
message: `TransitGatewayRoute "${logicalId}" declares Blackhole: true for destination ${cidr} — traffic matching this route is silently dropped; confirm this is intentional`,
|
|
36
|
+
entity: logicalId,
|
|
37
|
+
lexicon: "aws",
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return diagnostics;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const waw064: PostSynthCheck = {
|
|
46
|
+
id: "WAW064",
|
|
47
|
+
description: "Transit Gateway route table declares a Blackhole route — confirm the traffic drop is intentional, not an accident",
|
|
48
|
+
|
|
49
|
+
check(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
50
|
+
return checkTgwBlackholeRoute(ctx);
|
|
51
|
+
},
|
|
52
|
+
};
|