amazon-web-servicesamazon-s3aws-cli

Can I force CloudFormation to delete non-empty S3 Bucket?


Is there any way to force CloudFormation to delete a non-empty S3 Bucket?


Solution

  • You can create a lambda function to clean up your bucket and invoke your lambda from your CloudFormation stack using a CustomResource.

    Below a lambda example cleaning up your bucket:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import json
    import boto3
    from botocore.vendored import requests
    
    
    def lambda_handler(event, context):
        try:
            bucket = event['ResourceProperties']['BucketName']
    
            if event['RequestType'] == 'Delete':
                s3 = boto3.resource('s3')
                bucket = s3.Bucket(bucket)
                for obj in bucket.objects.filter():
                    s3.Object(bucket.name, obj.key).delete()
    
            sendResponseCfn(event, context, "SUCCESS")
        except Exception as e:
            print(e)
            sendResponseCfn(event, context, "FAILED")
    
    
    def sendResponseCfn(event, context, responseStatus):
        response_body = {'Status': responseStatus,
                         'Reason': 'Log stream name: ' + context.log_stream_name,
                         'PhysicalResourceId': context.log_stream_name,
                         'StackId': event['StackId'],
                         'RequestId': event['RequestId'],
                         'LogicalResourceId': event['LogicalResourceId'],
                         'Data': json.loads("{}")}
    
        requests.put(event['ResponseURL'], data=json.dumps(response_body))
    

    After you create the lambda above, just put the CustomResource in your CloudFormation stack:

     ---
     AWSTemplateFormatVersion: '2010-09-09'
    
     Resources:
    
       myBucketResource:
         Type: AWS::S3::Bucket
         Properties:
           BucketName: my-test-bucket-cleaning-on-delete
    
       cleanupBucketOnDelete:
         Type: Custom::cleanupbucket
         Properties:
           ServiceToken: arn:aws:lambda:eu-west-1:123456789012:function:clean-bucket-lambda
           BucketName: !Ref myBucketResource
    

    Remember to attach a role to your lambda that has permission to remove objects from your bucket.

    Furthermore keep in mind that you can create a lambda function that accepts CLI command line using the lambda function cli2cloudformation. You can download and install from here. Using that you just need to create a CustomResource like bellow:

    "removeBucket": {
            "Type": "Custom::cli2cloudformation",
            "Properties": {
              "ServiceToken": "arn:aws:lambda:eu-west-1:123456789000:function:custom-lambda-name",
              "CliCommandDelete": "aws s3 rb s3://bucket-name --force",
            }
    }