-
Notifications
You must be signed in to change notification settings - Fork 68
Description
Describe the bug
CDK diff shows nested stack resource paths for changes related to parent stack resource paths.
Regression Issue
- Select this option if this issue appears to be a regression.
Last Known Working CDK Version
No response
Expected Behavior
If a stack that has a defined nested stack, where both stacks have a resource that share an id, then running cdk diff should show the parent resource's path for changes related to it, and the child resource's path for changes related to it.
Current Behavior
If a stack that has a defined nested stack, where both stacks have a resource that share an id, then running cdk diff will show the child resource's path for all changes related to the parent and child resource.
Reproduction Steps
from aws_cdk import (
Stack,
NestedStack,
aws_s3 as s3,
RemovalPolicy,
)
from constructs import Construct
class TestNestedStack(NestedStack):
def __init__(
self,
scope: Construct,
construct_id: str,
**kwargs,
) -> None:
super().__init__(scope, construct_id, **kwargs)
self.test_bucket = s3.Bucket(
self,
"TestBucket",
bucket_name=None,
removal_policy=RemovalPolicy.DESTROY,
auto_delete_objects=True,
)
class TestStack(Stack):
def __init__(
self,
scope: Construct,
construct_id: str,
**kwargs,
) -> None:
super().__init__(scope, construct_id, **kwargs)
self.test_bucket = s3.Bucket(
self,
"TestBucket",
bucket_name=None,
removal_policy=RemovalPolicy.DESTROY,
auto_delete_objects=True,
)
self.nested_stack = TestNestedStack(
self,
"TestNestedStack",
)Running CDK diff on this stack when it has never been deployed produces the following:
Stack TestStack
IAM Statement Changes
┌───┬───────────────────────────────────────────────────────────────────────────────┬────────┬────────────────────┬───────────────────────────────────────────────────────────────────────────────────┬───────────┐
│ │ Resource │ Effect │ Action │ Principal │ Condition │
├───┼───────────────────────────────────────────────────────────────────────────────┼────────┼────────────────────┼───────────────────────────────────────────────────────────────────────────────────┼───────────┤
│ + │ ${TestNestedStack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role.Arn} │ Allow │ sts:AssumeRole │ Service:lambda.amazonaws.com │ │
├───┼───────────────────────────────────────────────────────────────────────────────┼────────┼────────────────────┼───────────────────────────────────────────────────────────────────────────────────┼───────────┤
│ + │ ${TestNestedStack/TestBucket.Arn} │ Allow │ s3:DeleteObject* │ AWS:${TestNestedStack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role.Arn} │ │
│ │ ${TestNestedStack/TestBucket.Arn}/* │ │ s3:GetBucket* │ │ │
│ │ │ │ s3:List* │ │ │
│ │ │ │ s3:PutBucketPolicy │ │ │
└───┴───────────────────────────────────────────────────────────────────────────────┴────────┴────────────────────┴───────────────────────────────────────────────────────────────────────────────────┴───────────┘
IAM Policy Changes
┌───┬───────────────────────────────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────┐
│ │ Resource │ Managed Policy ARN │
├───┼───────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────┤
│ + │ ${TestNestedStack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role} │ {"Fn::Sub":"arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"} │
└───┴───────────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)
Parameters
[+] Parameter BootstrapVersion BootstrapVersion: {"Type":"AWS::SSM::Parameter::Value<String>","Default":"/cdk-bootstrap/hnb659fds/version","Description":"Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"}
Resources
[+] AWS::S3::Bucket TestNestedStack/TestBucket TestBucket560B80BC
[+] AWS::S3::BucketPolicy TestNestedStack/TestBucket/Policy TestBucketPolicyBA12ED38
[+] Custom::S3AutoDeleteObjects TestNestedStack/TestBucket/AutoDeleteObjectsCustomResource TestBucketAutoDeleteObjectsCustomResource8FEAABD5
[+] AWS::IAM::Role TestNestedStack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092
[+] AWS::Lambda::Function TestNestedStack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F
[+] AWS::CloudFormation::Stack TestNestedStack.NestedStack/TestNestedStack.NestedStackResource TestNestedStackNestedStackTestNestedStackNestedStackResource68E05791
Stack TestNestedStackNestedStackTestNestedStackNestedStackResource68E05791
IAM Statement Changes
┌───┬───────────────────────────────────────────────────────────────────────────────┬────────┬────────────────────┬───────────────────────────────────────────────────────────────────────────────────┬───────────┐
│ │ Resource │ Effect │ Action │ Principal │ Condition │
├───┼───────────────────────────────────────────────────────────────────────────────┼────────┼────────────────────┼───────────────────────────────────────────────────────────────────────────────────┼───────────┤
│ + │ ${TestNestedStack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role.Arn} │ Allow │ sts:AssumeRole │ Service:lambda.amazonaws.com │ │
├───┼───────────────────────────────────────────────────────────────────────────────┼────────┼────────────────────┼───────────────────────────────────────────────────────────────────────────────────┼───────────┤
│ + │ ${TestNestedStack/TestBucket.Arn} │ Allow │ s3:DeleteObject* │ AWS:${TestNestedStack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role.Arn} │ │
│ │ ${TestNestedStack/TestBucket.Arn}/* │ │ s3:GetBucket* │ │ │
│ │ │ │ s3:List* │ │ │
│ │ │ │ s3:PutBucketPolicy │ │ │
└───┴───────────────────────────────────────────────────────────────────────────────┴────────┴────────────────────┴───────────────────────────────────────────────────────────────────────────────────┴───────────┘
IAM Policy Changes
┌───┬───────────────────────────────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────┐
│ │ Resource │ Managed Policy ARN │
├───┼───────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────┤
│ + │ ${TestNestedStack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role} │ {"Fn::Sub":"arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"} │
└───┴───────────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)
Resources
[+] AWS::S3::Bucket TestNestedStack/TestBucket TestBucket560B80BC
[+] AWS::S3::BucketPolicy TestNestedStack/TestBucket/Policy TestBucketPolicyBA12ED38
[+] Custom::S3AutoDeleteObjects TestNestedStack/TestBucket/AutoDeleteObjectsCustomResource TestBucketAutoDeleteObjectsCustomResource8FEAABD5
[+] AWS::IAM::Role TestNestedStack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092
[+] AWS::Lambda::Function TestNestedStack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F
In the table shown above, even for the parent stack, all paths related to the created buckets points to the child resource, even when they should be pointing to the parent resource.
Possible Solution
The reason the bug happens is because logical ids for these resources is created using their route to their parent stack (but excluding the parent stack) here, both parent and child resources share the same id, therefore, they have the same logical id. When the buildLogicalToPathMap method is called, it iterates over all resources in the stack to setup the map, but when the stack and the nested stack have a logical id collision, the path value for the parent resource is overridden.
I added a log to that method before it sets the map value, here is the result of diffing:
-STACK TestStack LOGID TestBucket560B80BC PATH /TestStack/TestBucket/Resource
STACK TestStack LOGID TestBucketPolicyBA12ED38 PATH /TestStack/TestBucket/Policy/Resource
STACK TestStack LOGID TestBucketAutoDeleteObjectsCustomResource8FEAABD5 PATH /TestStack/TestBucket/AutoDeleteObjectsCustomResource/Default
STACK TestStack LOGID CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092 PATH /TestStack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role
STACK TestStack LOGID CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F PATH /TestStack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler
STACK TestStack LOGID TestBucket560B80BC PATH /TestStack/TestNestedStack/TestBucket/Resource
STACK TestStack LOGID TestBucketPolicyBA12ED38 PATH /TestStack/TestNestedStack/TestBucket/Policy/Resource
STACK TestStack LOGID TestBucketAutoDeleteObjectsCustomResource8FEAABD5 PATH /TestStack/TestNestedStack/TestBucket/AutoDeleteObjectsCustomResource/Default
STACK TestStack LOGID CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092 PATH /TestStack/TestNestedStack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role
STACK TestStack LOGID CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F PATH /TestStack/TestNestedStack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler
STACK TestStack LOGID CDKMetadata PATH /TestStack/TestNestedStack/CDKMetadata/Default
STACK TestStack LOGID TestNestedStackNestedStackTestNestedStackNestedStackResource68E05791 PATH /TestStack/TestNestedStack.NestedStack/TestNestedStack.NestedStackResource
STACK TestStack LOGID CDKMetadata PATH /TestStack/CDKMetadata/Default
STACK TestStack LOGID BootstrapVersion PATH /TestStack/BootstrapVersion
STACK TestStack LOGID CheckBootstrapVersion PATH /TestStack/CheckBootstrapVersion
STACK TestStack LOGID TestBucket560B80BC PATH /TestStack/TestBucket/Resource
STACK TestStack LOGID TestBucketPolicyBA12ED38 PATH /TestStack/TestBucket/Policy/Resource
STACK TestStack LOGID TestBucketAutoDeleteObjectsCustomResource8FEAABD5 PATH /TestStack/TestBucket/AutoDeleteObjectsCustomResource/Default
STACK TestStack LOGID CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092 PATH /TestStack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role
STACK TestStack LOGID CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F PATH /TestStack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler
-STACK TestStack LOGID TestBucket560B80BC PATH /TestStack/TestNestedStack/TestBucket/Resource
STACK TestStack LOGID TestBucketPolicyBA12ED38 PATH /TestStack/TestNestedStack/TestBucket/Policy/Resource
STACK TestStack LOGID TestBucketAutoDeleteObjectsCustomResource8FEAABD5 PATH /TestStack/TestNestedStack/TestBucket/AutoDeleteObjectsCustomResource/Default
STACK TestStack LOGID CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092 PATH /TestStack/TestNestedStack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role
STACK TestStack LOGID CustomS3AutoDeleteObjectsCustomResourceProviderHandler9D90184F PATH /TestStack/TestNestedStack/Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler
STACK TestStack LOGID CDKMetadata PATH /TestStack/TestNestedStack/CDKMetadata/Default
STACK TestStack LOGID TestNestedStackNestedStackTestNestedStackNestedStackResource68E05791 PATH /TestStack/TestNestedStack.NestedStack/TestNestedStack.NestedStackResource
STACK TestStack LOGID CDKMetadata PATH /TestStack/CDKMetadata/Default
STACK TestStack LOGID BootstrapVersion PATH /TestStack/BootstrapVersion
STACK TestStack LOGID CheckBootstrapVersion PATH /TestStack/CheckBootstrapVersionthe highlighted lines show the collision clearly.
Additional Information/Context
No response
CDK CLI Version
2.1033.0 (build 1ec3310)
Framework Version
No response
Node.js Version
v25.2.1
OS
MacOS
Language
TypeScript, Python
Language Version
No response
Other information
No response