Post

AWS-nuke controlled resources cleanup in multiple aws accounts

AWS-Nuke is an open-source tool, designed to automate the removal of AWS resources from an account. It can be used to quickly and safely delete all resources in a given AWS account, or it can be customized to delete specific types of resources based on user-defined rules.

What is AWS-Nuke?

Whether you’re spinning up test environments or decommissioning an old project, AWS-Nuke is particularly useful for keeping AWS accounts clean, ensuring that old, unused resources do not pile up, leading to cost overruns, security risks, and unnecessary complexity.

AWS-Nuke is a command-line tool that supports multiple AWS services and can be run from any machine that has access to AWS credentials.

Why Use AWS-Nuke?

Before diving into the technical details of AWS-Nuke, it’s important to understand why this tool is useful.

  • Cost Management: One of the biggest challenges in cloud environments is managing costs. AWS charges based on the resources you use, and sometimes resources that are no longer in use are forgotten and left running. By using AWS-Nuke, you can regularly clean up old resources, ensuring that you only pay for what you actively use.

  • Environment Cleanup: In development and test environments, resources are often created, modified, and left without proper deletion. AWS-Nuke can help by regularly purging these environments of unnecessary resources, making it easier to manage infrastructure.

  • Security: Resources left running for extended periods can pose security risks. For instance, unused EC2 instances, security groups, or S3 buckets might expose your environment to attacks. AWS-Nuke helps minimize such risks by cleaning up unused resources.

  • Automation: AWS-Nuke offers automation capabilities, making it easier to integrate into continuous integration (CI) pipelines or scheduled jobs for periodic account cleanups.

  • Simplification: With hundreds of AWS services and resources to manage, AWS-Nuke simplifies the task of cleaning up resources by providing a centralized and automated way to perform deletions.

How AWS-Nuke Works

AWS-Nuke works by scanning all the resources in your AWS account and then deleting them based on a configuration file. You can configure AWS-Nuke to delete specific types of resources or to leave certain critical resources untouched.

AWS-Nuke uses the AWS SDK to list and delete resources. It can handle a wide range of AWS services, including but not limited to:

EC2 Instances S3 Buckets RDS Instances IAM Users and Roles VPCs Elastic Load Balancers CloudWatch Alarms CloudFormation Stacks ECR Repositories

Configuration

AWS-Nuke uses a YAML configuration file to specify what resources should or should not be deleted. This configuration file is highly customizable, allowing users to target specific AWS resources while leaving others intact.

Here’s a simple example of an AWS-Nuke configuration:

yaml Copy code regions:

  • “us-east-1”
  • “us-west-2”

resource-types: excludes:

  • EC2::KeyPair
  • IAM::Role
  • IAM::User This configuration specifies that AWS-Nuke should only run in the us-east-1 and us-west-2 regions, and it will exclude deleting EC2 Key Pairs, IAM Roles, and IAM Users.

Dry-Run Mode One of AWS-Nuke’s most useful features is the dry-run mode, which allows users to see what resources will be deleted without actually deleting them. This is useful for reviewing the results of a cleanup before making any irreversible changes.

To run AWS-Nuke in dry-run mode, simply use the –dry-run flag:

1
aws-nuke --config config.yml --dry-run

This command will output a list of resources that AWS-Nuke will delete based on the configuration file, without actually performing the deletions.

Running AWS-Nuke Once you’re confident in your configuration, running AWS-Nuke is simple. First, ensure you have the correct AWS credentials for the account you want to clean up. Then, use the following command:

1
aws-nuke --config config.yml

This command will delete all resources in the account, except for the ones excluded in the configuration.

Resource Dependencies AWS-Nuke also handles resource dependencies. For example, it will not delete an S3 bucket until all objects within the bucket have been deleted. This ensures that AWS resources are deleted in the correct order, preventing errors and failed deletions.

1
brew install aws-nuke

After checking version installed from brew repo is outdated:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 aws-nuke -c config/nuke-config.yml --profile technology
Incorrect Usage: flag provided but not defined: -c

NAME:
   aws-nuke - remove everything from an aws account

USAGE:
   aws-nuke [global options] command [command options]

VERSION:
   3.22.0

AUTHOR:
   Erik Kristensen <erik@erikkristensen.com>

FATA[0000] flag provided but not defined: -c

So I will use the latest version installed from sources:

Contributing to aws-nuke

When running locally aws-nuke with aws profile I got error.

1
2
3
4
5
aws_nuke_v2 -c config/nuke-config.yaml --profile personal_profile
Error: failed get caller identity: NoCredentialProviders: no valid providers in chain. Deprecated.
For verbose messaging see aws.Config.CredentialsChainVerboseErrors

Process finished with the exit code 255

And after checking the sources, I find out that profile is present in parameters for aws-nuke, but not implemented. So I have added this feature to aws-nuke:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
if params.Profile != "" {
			cfg, err := awsSDKConfig.LoadDefaultConfig(context.TODO(), awsSDKConfig.WithSharedConfigProfile(params.Profile))
			if err != nil {
				log.Fatalf("unable to load SDK config, %v", err)
			}
			log.Infof("using profile %v", params.Profile)
			/// Extract credentials from the configuration
			cred, err := cfg.Credentials.Retrieve(context.TODO())
			if err != nil {
				log.Fatalf("unable to retrieve credentials, %v", err)
			}
			creds.AccessKeyID = cred.AccessKeyID
			creds.SecretAccessKey = cred.SecretAccessKey
			defaultRegion = cfg.Region
		}

		if !creds.HasKeys() && !creds.HasProfile() {
			creds.AccessKeyID = os.Getenv("AWS_ACCESS_KEY_ID")
			creds.SecretAccessKey = os.Getenv("AWS_SECRET_ACCESS_KEY")
		}

Also added Contribution PR to aws-nuke: https://github.com/rebuy-de/aws-nuke/pull/1263/files

Now aws-nuke correctly process –profile cli argument and is ready to run

Working with implemented profile feature:

1
2
3
4
5
6
7
8
go run main.go -c config/nuke-config.yaml --profile personal_account

INFO[0000] using profile personal_account
aws-nuke version unknown - unknown - unknown

Do you really want to nuke the account with the ID 123456789012 and the alias 'personal_account'?
Do you want to continue? Enter account alias to continue.
> personal_account

Tool will query existing resources, match them with filters that we have configured in exclusion and will do dry run.

Resources that we want to leave in account

Let’s say we do not want to affect IAM users/permissions/policies, also MFA devices and some route53 records. These all resources should be declared in aws-nuke config, so when running it will not touch them.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
regions:
  - eu-east-1
  - global

accounts:
123456789012:
filters:
PolicyName:
  - property: "UserName"
  - value: "aws-cli"
IAMRole:
  - "OrganizationAccountAccessRole"
IAMRolePolicyAttachment:
  - "OrganizationAccountAccessRole"
  - property: arn
  - value: "arn:aws:iam::aws:policy/AdministratorAccess"
IAMUser:
  - "admin"
  - "aws-cli"
IAMUserAccessKey:
  - property: UserName
value: "aws-cli"
IAMUserPolicyAttachment:
  - property: "arn"
  - value: "arn:aws:iam::aws:policy/AdministratorAccess"
IAMVirtualMFADevice:
  - property: arn
  - value: "arn:aws:iam::123456789012:mfa/to.root.iphone"
Route53HostedZone:
  - property: "Name"
  - value: "xxxxx.xx."

account-blocklist:
  - 1234567890

resource-types:
excludes:
  - Route53ResourceRecordSet
  - Route53HostedZone

Review resources in output

1
2
3
4
5
6
7
8
9
10
...
global - IAMPolicy - arn:aws:iam::123456789012:policy/terraform-20230725102234859300000005 - [ARN: "arn:aws:iam::123456789012:policy/terraform-20230725102234859300000005", Name: "terraform-20230725102234859300000005", Path: "/", PolicyID: "ANPAVFCI6B4SXG62NJLCB"] - would remove

global - IAMRole - AmazonGrafanaServiceRole-Skz3Lbeo2 - [CreateDate: "2023-03-21T16:02:03Z", LastUsedDate: "2023-03-21T16:02:03Z", Name: "AmazonGrafanaServiceRole-Skz3Lbeo2", Path: "/service-role/"] - would remove

123456789012", PolicyName: "terraform-20230725102234859300000005", RoleCreateDate: "2023-07-25T10:22:27Z", RoleLastUsed: "2023-07-25T10:22:27Z", RoleName: "terraform-20230725102226616700000002", RolePath: "/"] - filtered by config
global - IAMRolePolicy - terraform-20230725102226616700000003 -> terraform-20230725102227744300000004 - [PolicyName: "terraform-20230725102227744300000004", role:CreateDate: "2023-07-25T10:22:27Z", role:LastUsed: "2023-07-25T10:22:56Z", role:Path: "/", role:RoleID: "AROAVFCI6B4SWQNDRGVXF", role:RoleName: "terraform-20230725102226616700000003"] - would remove
Scan complete: 44 total, 13 nukeable, 31 filtered.

The above resources would be deleted with the supplied configuration. Provide --no-dry-run to actually destroy resources.

Perform cleanup

1
2
3
4
5
6
7
8
9
go run main.go -c config/nuke-config.yaml --profile personal_account --no-dry-run

INFO[0000] using profile personal_account
aws-nuke version unknown - unknown - unknown

Do you really want to nuke the account with the ID 123456789012 and the alias 'personal_account'?
Do you want to continue? Enter account alias to continue.
> personal_account

First aws-nuke will scan as in dry-run, and also propose to confirm deletion.

Tool has issues deleting IAMs - it has logic to retry but does not understand resources dependencies. For instance, it can not delete role with attached policies that it also should delete:

1
2
ERRO[0373] DeleteConflict: Cannot delete entity, must detach all policies first.
status code: 409, request id: 9506e3fd-5945-48b3-9031-826d28d2abec

so you have manually delete from CLI or aws console

Integration with CI/CD

One of the best use cases for AWS-Nuke is integrating it into a CI/CD pipeline. You can use AWS-Nuke as part of your continuous integration (CI) process to clean up test environments after running tests. This ensures that no unnecessary resources remain after testing is complete, keeping your environment clean and your costs under control.

Here’s an example of how you might integrate AWS-Nuke into a CI/CD pipeline:

  • Run AWS-Nuke in dry-run mode before deploying a new version of your application to ensure there are no unnecessary resources left over from previous tests.
  • After the deployment and testing are complete, run AWS-Nuke in full mode to clean up all resources.

Conclusion

AWS-Nuke is a powerful and versatile tool for cleaning up AWS environments. It helps prevent cost overruns, reduces security risks, and simplifies the management of AWS resources. Whether you’re managing a development environment, performing testing, or decommissioning an old project, AWS-Nuke provides an efficient way to automate the cleanup process.

However, AWS-Nuke also requires careful configuration to avoid deleting critical resources. Always use the dry-run mode to review deletions before making any changes, and ensure that your configuration file accurately reflects your environment.

In an age where cloud resources can grow exponentially, tools like AWS-Nuke are indispensable for keeping your infrastructure lean and efficient.

This post is licensed under CC BY 4.0 by the author.