Provisioning an S3 bucket as part of your stack is challenging because you can’t manipulate the bucket once it contains objects.
CloudFormation and S3 bucket resource
CloudFormation provides an S3 bucket resource for your stacks. This resource will behave quite differently once you’ve written objects to it. With CloudFormation stacks, there are major differences between empty buckets and buckets with objects. You can test this yourself:
- Create a CloudFormation stack with just an S3 bucket resource and no additional options.
- Write a random object to the bucket.
- Attempt to delete the stack you created.
The result will be an error during deletion of the CloudFormation stack. The error will say that buckets with objects cannot be deleted. From a CloudFormation perspective, this is logical because you didn’t provision objects inside the bucket as part of your stack. You’re responsible for deleting them before you attempt to delete the stack.
Let’s take a look at the policies that CloudFormation provides for resources. One of them is DeletionPolicy
. Repeat the above example with the DeletionPolicy: retain
set on the bucket resource. The result will be the stack is successfully deleted. However, the bucket resource will be left behind. CloudFormation will just skip deleting it. If you open the S3 section of the web console or if you list your S3 bucket through a CLI command, you’ll see the bucket you provisioned is still around. The resource is left dangling in your account.
We can conclude that an S3 bucket resource containing data cannot be deleted with the stack it was provisioned from. When a resource is provisioned inside a stack, I expect that resource to also be destroyed with the stack. The lifetime of the resource should be driven by the lifetime of it’s stack. EC2 or RDS instances can be used as examples. Compute resources may be destroyed or terminated with your data with the stack. This outlier example of S3 bucket deletion conditions is something to keep in mind.
Using CloudFormation Custom Resource
This issue came up enough times that I have decided to address it. I’ve created a CloudFormation Custom Resource which handles deletion of S3 bucket objects. The Custom Resource is implemented using an AWS Lambda function listing the bucket content and deleting all objects or their versions.
|
|
The crhelper
module is provided by the CloudFormation team. I recommend using it together with Serverless Application Model or SAM tools. Serverless Application Model helps you manage dependencies and deploy the Custom Resource and Lambda function in one step.
The Lambda function is implemented in Python and is using AWS CloudFormation Custom Resource module. Keep in mind this example is limited and designed to illustrate the problem. If your S3 bucket contains many objects, you may need to extend the Lambda function timeout or even consider making the S3 delete requests in parallel.
|
|
S3 Bucket Wipe Example Code
You may be interested in seeing or running the full example. I made a demo SAM project containing the Custom Resource available under the MIT license. Inspect the example SAM stack and the S3 Wipe Lambda function code. You can review the full S3 bucket wipe example code or make a copy of the repository using the following command:
git clone https://git.adamkonrad.com/aws_bucket_wipe.git
The demo assumes you have SAM CLI installed and setup. Run sam build
and sam deploy
from the directory as you’d normally would to deploy other serverless applications.
I hope you find this code useful in your stacks and applications.