Pragmatism in the real world

Circular dependencies in AWS SAM Policies

I’m trying to tighten up the policies of my AWS Lambda function so that it only has access to the one S3 bucket that it needed, so I added an S3CrudPolicy with the BucketName referencing the bucket that’s defined in the template.

The relevant part of template.yaml looks like this:

Resources:
    ImagesBucket:
        Type: AWS::S3::Bucket
        Properties:
            BucketName: !Sub "${ProjectName}-${UniqueKey}-images"

    ResizeFunction:
        Type: AWS::Serverless::Function
        Properties:
            FunctionName: resize
			# ...
            Events:
                CreateThumbnailEvent:
                    Type: S3
                    Properties:
                        Bucket: !Ref ImagesBucket
                        Events: s3:ObjectCreated:*
            Policies:
                - S3CrudPolicy:
                    BucketName: !Ref ImagesBucket

However, this creates an error:

Failed to create the changeset: Waiter ChangeSetCreateComplete failed: Waiter encountered
a terminal failure state Status: FAILED. Reason: Circular dependency between resources:
[ImagesBucket, ResizeFunctionRole, ResizeFunction, ResizeFunctionCreateThumbnailEventPermission]

(Who is this waiter anyway? This isn’t a restaurant!)

Solution

To solve this, instead of referencing ImageBucket in the BucketName of the S3CrudPolicy, we can put the image name in directly. This is not the ARN, just the name, so we can do:

            Policies:
                - S3CrudPolicy:
                    BucketName: !Sub "${ProjectName}-${UniqueKey}-images"

This works because by setting the BucketName to a string, there’s no dependency on the ImagesBucket resource itself, so it all works.