CDK: NestedStack can produce invalid template when referencing parent stack parameters
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
### Describe the bug
In a situation where VPC details need to be passed into a parent stack as parameters, a nested stack that relies on those parameters can synthesize an invalid template that includes a reference to a Logical ID that only exists in the parent stack. In this case that appears to occur in situations where some of those parameter details will be used in a CloudFormation resource that requires the values be stringified as JSON.
### Regression Issue
- [ ] Select this option if this issue appears to be a regression.
### Last Known Working CDK Library Version
_No response_
### Expected Behavior
The nested stack should _not_ include a `Custom::AWSCDKCfnJsonStringify` that it does not need, and should not attempt to reference a Logical ID from the parent stack.
### Current Behavior
In the test case I've attached, the `ChildStack` template ends up with 2 `Custom::AWSCDKCfnJsonStringify` resources. The 2nd one is used elsewhere in the template. But `"CdkJsonStringify1"` one is not used anywhere in the template and it also contains `"Ref": "PrivateSubnetIds"`, where `PrivateSubnetIds` is the verbatim name of the parameter of the parent stack. This makes the child stack fail to deploy due to invalid syntax.
```json
"CdkJsonStringify1": {
"Type": "Custom::AWSCDKCfnJsonStringify",
"Properties": {
"ServiceToken": {
"Fn::GetAtt": [
"AWSCDKCfnUtilsProviderCustomResourceProviderHandlerCF82AA57",
"Arn"
]
},
"Value": {
"Fn::Split": [
",",
{
"Ref": "PrivateSubnetIds"
}
]
}
},
"UpdateReplacePolicy": "Delete",
"DeletionPolicy": "Delete",
"Metadata": {
"aws:cdk:path": "ParentStack/ChildStack/CdkJsonStringify1/Default"
}
},
```
### Reproduction Steps
Run `cdk synth` on this app and inspect the child stack's template that is produced.
```py
import aws_cdk
import constructs
class ParentStack(aws_cdk.Stack):
vpc: aws_cdk.aws_ec2.IVpc
def __init__(self, scope: constructs.Construct, id: str) -> None:
super().__init__(scope, id)
private_subnet_ids = aws_cdk.CfnParameter(
self, "PrivateSubnetIds", type="String", default=""
)
availability_zones = aws_cdk.CfnParameter(
self, "AvailabilityZones", type="String", default=""
)
vpc_id = aws_cdk.CfnParameter(
self, "VpcId", type="String", default=""
)
self.vpc = aws_cdk.aws_ec2.Vpc.from_vpc_attributes(
self, "Vpc",
vpc_id=vpc_id.value_as_string,
private_subnet_ids=aws_cdk.Fn.split(",", private_subnet_ids.value_as_string),
availability_zones=aws_cdk.Fn.split(",", availability_zones.value_as_string),
)
ChildStack(self, "ChildStack")
class ChildStack(aws_cdk.NestedStack):
def __init__(self, scope: constructs.Construct, id: str) -> None:
super().__init__(scope, id)
parent = self.nested_stack_parent
assert parent is not None
assert isinstance(parent, ParentStack)
cluster = aws_cdk.aws_ecs.Cluster(
self, "Cluster",
vpc=parent.vpc
)
task_definition = aws_cdk.aws_ecs.FargateTaskDefinition(
self, "TaskDefinition",
)
task_definition.add_container(
"Container",
image=aws_cdk.aws_ecs.ContainerImage.from_registry("hello-world"),
)
aws_cdk.aws_stepfunctions.StateMachine(
self, "StateMachine",
definition_body=aws_cdk.aws_stepfunctions.DefinitionBody.from_chainable(
aws_cdk.aws_stepfunctions_tasks.EcsRunTask(
self, "RunTask",
integration_pattern=aws_cdk.aws_stepfunctions.IntegrationPattern.RUN_JOB,
cluster=cluster,
task_definition=task_definition,
launch_target=aws_cdk.aws_stepfunctions_tasks.EcsFargateLaunchTarget(
platform_version=aws_cdk.aws_ecs.FargatePlatformVersion.LATEST
),
)
)
)
if __name__ == "__main__":
app = aws_cdk.App()
ParentStack(app, "ParentStack")
app.synth()
```
### Possible Solution
_No response_
### Additional Information/Context
_No response_
### AWS CDK Library version (aws-cdk-lib)
2.146.0
### AWS CDK CLI version
2.1010.0 (build 6b421db)
### Node.js Version
22.12.0
### OS
MacOS
### Language
Python
### Language Version
_No response_
### Other information
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.