Skip to content

An AWS Lambda that can be invoked as a custom resource from an AWS CloudFormation stack to clean up any left over stack resources such as S3 buckets and Log Groups

License

Notifications You must be signed in to change notification settings

xavier-thomas/aws-cfn-stack-cleanup

Repository files navigation

AWS CloudFormation Stack Cleanup λ

Quality Gate Status Tests Coverage Mutation testing badge Dependency Status

An AWS Lambda that can be invoked as a custom resource from an AWS CloudFormation stack to clean up any left over stack resources such as S3 buckets and Log Groups

Overview | Getting Started | Deploying the Lambda | Permissions | Invoking the Lambda | Contributing | Authors | Licence

Overview

Cloudformation does not always cleanly delete the resources that it's created. The most notable example is with S3 Buckets created by Cloudformation. If these bucket's contain objects, they cannot be deleted during Cloudformation stack deletion.

Similarly, there are other resources like, Log Groups or sub-stacks deployed by a CodePipeline that need to be cleaned up.

This lambda is meant to be invoked as a Cloudformation custom resource that when passed resource names, will clean up those resources during stack deletion.

Any other event other than stack deletion (such as stack creation or stack update) are ignored.

Currently this lambda only supports Emptying and Deletion of S3 buckets, and deleting Cloudwatch Log Groups, however it's planned to support other resource types in the future.

Getting Started

Deploying the Lambda

The lambda needs to be deployed into the same account as your invoking cloudformation stack. It can be deployed through the console from here or it can be deployed from Cloudformation.

In order to deploy from CloudFormation, use the following as an example for your template.

Description: Deploys Cfn-Stack-Cleanup Lambda function from Serverless Application Repo
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31


Resources:
  CfnStackCleanup:
    Type: AWS::Serverless::Application
    Properties:
      Location:
        ApplicationId: arn:aws:serverlessrepo:us-east-1:673103718481:applications/Cfn-Stack-Cleanup
      SemanticVersion: 1.3.1
      # Optional Parameter to control the export name of the nested stack
      Parameters:
        ExportPrefix: !Ref AWS::StackName

Manual Deployment - Not Recommended

If you choose not to use the lambda from the Servlerless Repo, you can also manually build and deploy the lambda into your own account. The following methods are not recommended due to the additional complexity this adds, use at your own discression.

# Build the Lambda
yarn build

Once built locally you can use one of several of the following methods.

  • SAM Deploy
  • SAM Package or Cloudformation Package along with manual deployment of the resulting packaged template.
  • Build and deploy the lambda from an AWS CodePipeline / CodeBuild that's watching this repository
  • Zip the lambda and deploy it manually.

Permissions

All Lambda permissions are created during deployment. Currently these are permissions to list s3 objects, delete s3 objects and delete s3 buckets.

    - Effect: Allow
      Action:
        - s3:DeleteBucket
        - s3:DeleteObjects
        - s3:List*
      Resource: '*'

Invoking the Lambda

Resources:
  StackCleanup:
    Type: Custom::StackCleanup
    Properties:
      ServiceToken:
        Fn::ImportValue: !Sub ${ExportPrefix}StackCleanupLambdaArn
      BucketNames:
      # (Optional) Array of bucket names you want to delete
        - ...
        - ...
      LogGroupNames:
      # (Optional) Array of log group names you want to delete
        - ...
        - ...

Example Stack with Cleanup

AWSTemplateFormatVersion: '2010-09-09'
Description: >
  Example Stack with Cleanup

Parameters:
  EnableLogging:
    Description: Enable/Disable logging
    AllowedValues:
      - Enable
      - Disable
    Default: Disable
    Type: String

  Cleanup:
    AllowedValues:
      - Enable
      - Disable
    Default: Disable
    Description: Auto Cleanup this stack's resources during deletion to simplify maintenance during development. Do Not Enable on Production
    Type: String

  ExportPrefix:
    Type: String
    Description: (Optional) The Prefix name used when deploying the cfn-stack-cleanup lambda
    Default: ""

Conditions:
  cEnableCleanup: !Equals [!Ref Cleanup, 'Enable']
  cEnableLogging: !Equals [!Ref EnableLogging, 'Enable']


Resources:
  AutoCleanup:
    Type: Custom::AutoCleanup
    Condition: cEnableCleanup # You may not always want to clean up resources. For instance on Production environments
    Properties:
      ServiceToken:
        Fn::ImportValue: !Sub ${ExportPrefix}StackCleanupLambdaArn
      BucketNames:
        - !Ref 'ArtifactBucket'
        - !Ref 'ApplicationBucket'
        - !If
          - cEnableLogging
          - !Ref 'LogsBucket'
          - !Ref 'AWS::NoValue'
      LogGroupNames:
        - !If
          - cEnableLogging
          - - !Ref LogGroup1
            - !Ref LogGroup2
          - !Ref 'AWS::NoValue'

  ApplicationBucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain #This will prevent Cloudformation from throwing an error when trying to delete the bucket
    Properties:
      BucketName: !Sub '${DomainName}'
      AccessControl: 'PublicRead'
      WebsiteConfiguration:
        IndexDocument: 'index.html'

  ArtifactBucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain #This will prevent Cloudformation from throwing an error when trying to delete the bucket
    Properties:
      BucketName: !Sub '${AWS::StackName}-artifacts'

  LogsBucket:
    Type: AWS::S3::Bucket
    Condition: cEnableLogging
    DeletionPolicy: Retain #This will prevent Cloudformation from throwing an error when trying to delete the bucket
    Properties:
      BucketName: !Sub '${AWS::StackName}-logs'

  LogGroup1:
    Type: AWS::Logs::LogGroup
    Condition: cEnableLogging
    Properties:
      LogGroupName: "test"
      RetentionInDays: 7

  LogGroup2:
    Type: AWS::Logs::LogGroup
    Condition: cEnableLogging
    Properties:
      RetentionInDays: 7

Contributing

Prerequisites

To clone and contribute to this application, you'll need Git, Node.js and Yarn installed. You can also use an alternative package manager, such as NPM if you prefer!

Installing

From your favourite command line tool, run the following:

# Clone the repo
git clone git@github.com:xavier-thomas/aws-cfn-stack-cleanup.git

## or if you use HTTPS instead of SSH
git clone https://github.com/xavier-thomas/aws-cfn-stack-cleanup.git

# Install dependencies
yarn

Running tests

From your favourite command line tool, run the following:

# Run the unit tests
yarn test

Running Mutation Tests

This project uses Stryker for mutation testing. From your favourite command line tool, run the following:

# Mutate and test the unit tests
yarn mutate

Linting & code formatting

From your favourite command line tool, run the following:

# Run the linter
yarn lint

Raising Issues

We welcome anyone to contribute to this project. Before raising a PR, reach out to us by raising an issue or by emailing the author. There is a helpful issue template that can be used as a guideline to report issues or suggest new features.

Raising PRs

Once you are satisfied with your work, you can raise a Pull Request. The project's maintainers will need to approve this before it can be merged in and atleast 1 approving review is needed before your work can be merged in.

Note: Pre-Commit hooks are in place to perform audit, lint fix and run tests before you can commit. To ensure that unverified changes are not merged into master, when a new PR is raised on GitHub, the github actions workflow automatically runs the unit tests, mutation tests, Sonar and cfn-lint to validate the PR. Without successful checks, your pull request will be blocked from being merged as a safeguard.

Authors

Licence

3-Clause BSD

About

An AWS Lambda that can be invoked as a custom resource from an AWS CloudFormation stack to clean up any left over stack resources such as S3 buckets and Log Groups

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published