Published on

Wiping an AWS Account with aws-nuke

Tagged with: AWSDevOpsSRE

When you're an SRE/DevOps engineer you'll end up making AWS accounts and create a lot of cruft in your sandbox and development accounts. AWS does not make it easy to clear these up but there is a tool called aws-nuke that will do it for you!

Safe Guards

aws-nuke has a few safeguards in place to prevent inadvertent data loss. The first of which is it requires you to alias the targetted account. I like to put nuke in the alias to make it clear.

aws iam create-account-alias --account-alias nuke-<account>

The second safe-guard is the config takes a key called account-blocklist that will guarantee nuke will not run against it no matter what.

The final safety switch it has is it will not take any action by default, it will only execute a dry-run. You need to run the CLI with --no-dry-run if you want it to take action.

Getting Started

You configure aws-nuke with YAML, so the first step is to define that:

regions:
  - us-east-1
  - global

account-blocklist:
  - "888888888888" # production

accounts:
  "777777777777": {} # nuke-<account>

This will prevent us from nuking our production account and target all resources in the account we actually want to nuke.

You might want to have it nuke ALL REGIONS in AWS since you may not know which regions resources are deployed in. To do this you can query the regions from AWS:

 aws ec2 describe-regions --all-regions --query "Regions[*].RegionName" --output text | xargs -n 1 | sort
 
af-south-1
ap-east-1
ap-northeast-1
ap-northeast-2
ap-northeast-3
ap-south-1
ap-south-2
ap-southeast-1
ap-southeast-2
ap-southeast-3
ap-southeast-4
ca-central-1
eu-central-1
eu-central-2
eu-north-1
eu-south-1
eu-south-2
eu-west-1
eu-west-2
eu-west-3
me-central-1
me-south-1
sa-east-1
us-east-1
us-east-2
us-west-1
us-west-2

Which would give you an updated config of:

regions:
  - global  # Global resources like IAM
  - af-south-1
  - ap-east-1
  - ap-northeast-1
  - ap-northeast-2
  - ap-northeast-3
  - ap-south-1
  - ap-south-2
  - ap-southeast-1
  - ap-southeast-2
  - ap-southeast-3
  - ap-southeast-4
  - ca-central-1
  - eu-central-1
  - eu-central-2
  - eu-north-1
  - eu-south-1
  - eu-south-2
  - eu-west-1
  - eu-west-2
  - eu-west-3
  - me-central-1
  - me-south-1
  - sa-east-1
  - us-east-1
  - us-east-2
  - us-west-1
  - us-west-2

I personally don't recommend targetting all AWS regions at the same time. It will generate a lot of output and be slow. You could do it if necessary but most people only have a few regions they use and so they can set those directly. For example it, maybe you only use us- based regions?

So lets run the dry-run and see what it wants to nuke:

 aws-nuke -c nuke.yaml

This should output something like:

Do you really want to nuke the account with the ID 777777777777 and the alias 'nuke-sandbox'?
Do you want to continue? Enter account alias to continue.
> nuke-sandbox
us-east-1 - EC2Subnet - subnet-0cd9975a443a6304b - [DefaultForAz: "true", DefaultVPC: "true", OwnerID: "777777777777"] - would remove
us-east-1 - EC2Subnet - subnet-0be39d02e399a371c - [DefaultForAz: "true", DefaultVPC: "true", OwnerID: "777777777777"] - would remove
us-east-1 - EC2Subnet - subnet-02d7017bd4730ea63 - [DefaultForAz: "true", DefaultVPC: "true", OwnerID: "777777777777"] - would remove
us-east-1 - EC2Subnet - subnet-0ec04b28c32708ab2 - [DefaultForAz: "true", DefaultVPC: "true", OwnerID: "777777777777"] - would remove
us-east-1 - EC2Subnet - subnet-0eea1b4be084840ed - [DefaultForAz: "true", DefaultVPC: "true", OwnerID: "777777777777"] - would remove
us-east-1 - EC2Subnet - subnet-05a294cc04736012e - [DefaultForAz: "true", DefaultVPC: "true", OwnerID: "777777777777"] - would remove
us-east-1 - EC2RouteTable - rtb-0abda0e94015064ca - [DefaultVPC: "true"] - would remove
us-east-1 - EC2DefaultSecurityGroupRule - sgr-0368525f77bf566ac - [SecurityGroupId: "sg-0a59900b52ced5e10"] - would remove
us-east-1 - EC2DefaultSecurityGroupRule - sgr-0890a837ed6148729 - [SecurityGroupId: "sg-0a59900b52ced5e10"] - would remove
us-east-1 - EC2InternetGatewayAttachment - igw-0acfb474f1fd71375 -> vpc-0be5d310ab44c239a - [DefaultVPC: "true"] - would remove
us-east-1 - SQSQueue - https://sqs.us-east-1.amazonaws.com/777777777777/example-sqs - would remove
global - IAMSAMLProvider - arn:aws:iam::777777777777:saml-provider/AWSSSO_254abb4071f10b25_DO_NOT_DELETE - would remove
global - IAMOpenIDConnectProvider - arn:aws:iam::777777777777:oidc-provider/app.terraform.io - [Arn: "arn:aws:iam::777777777777:oidc-provider/app.terraform.io"] - would remove
global - IAMPolicy - arn:aws:iam::777777777777:policy/tfc-agent-access-policy - [ARN: "arn:aws:iam::777777777777:policy/tfc-agent-access-policy", Name: "tfc-agent-access-policy", Path: "/", PolicyID: "ANPA2T6PZOBNWI76TKQRF"] - would remove
global - IAMRole - tfc-agent - [CreateDate: "2023-04-02T17:55:23Z", LastUsedDate: "2023-06-22T13:45:02Z", Name: "tfc-agent", Path: "/"] - would remove
global - IAMRolePolicyAttachment - tfc-agent -> tfc-agent-access-policy - [PolicyArn: "arn:aws:iam::777777777777:policy/tfc-agent-access-policy", PolicyName: "tfc-agent-access-policy", RoleCreateDate: "2023-04-02T17:55:23Z", RoleLastUsed: "2023-06-22T13:45:02Z", RoleName: "tfc-agent", RolePath: "/"] - would remove
Scan complete: 85 total, 19 nukeable, 66 filtered.
 
The above resources would be deleted with the supplied configuration. Provide --no-dry-run to actually destroy resources.

This is great, it fully scanned the account and found every resource to delete! It even wants to delete the DefaultVPC which is usually a good idea. The one resource that should catch your eye that you probably do not want to delete:

  • arn:aws:iam::777777777777:saml-provider/AWSSSO_254abb4071f10b25_DO_NOT_DELETE

AWS clearly doesn't want us to delete that!

Filters

To prevent nuke from deleting resources you want to keep you can define presets that you use on each account. So with our SSO example we want to prevent it from deleting those resources in a preset.

presets:
  sso:
    filters:
      IAMSAMLProvider:
      - type: "regex"
        value: "AWSSSO_.*_DO_NOT_DELETE"
      IAMRole:
      - type: "glob"
        value: "AWSReservedSSO_*"
      IAMRolePolicyAttachment:
      - type: "glob"
        value: "AWSReservedSSO_*"

You can see in this example I'm targetting specific resource types and then matching them with both regex and glob filter types. These are super powerful but a lot of times the simpler filters can be used. I start with contains filter and then go from there:

      - type: contains
        value: AWSReservedSSO

Then the other thing you may have noticed is that I was repeating AWSReservedSSO multiple times. To reduce that you can use standard YAML anchors. So the final config for your preset would look like this:

presets:
  sso:
    filters:
      _DEFAULT_FILTERS: &DEFAULT
        - type: "contains"
          value: "DO_NOT_DELETE"
        - type: "contains"
          value: "AWSReservedSSO"
 
      IAMSAMLProvider: *DEFAULT
      IAMRole: *DEFAULT
      IAMRolePolicyAttachment: *DEFAULT

Now we can use that preset in our accounts configuration:

accounts:
  "777777777777":
    "presets":
      - sso

So your final config should look something like this:

regions:
  - us-east-1
  - global
 
account-blocklist:
  - "888888888888" # production
 
 
presets:
  sso:
    filters:
      _DEFAULT_FILTERS: &DEFAULT
        - type: "contains"
          value: "DO_NOT_DELETE"
        - type: "contains"
          value: "AWSReservedSSO"
 
      IAMSAMLProvider: *DEFAULT
      IAMRole: *DEFAULT
      IAMRolePolicyAttachment: *DEFAULT
 
accounts:
  "777777777777":
    "presets":
      - sso

When you run this you should see now the resources we want to keep are filtered out:

global - IAMSAMLProvider - arn:aws:iam::777777777777:saml-provider/AWSSSO_254abb4071f10b25_DO_NOT_DELETE - filtered by config

Once you are ready and have your filters in place you can run it for real!

 aws-nuke -c nuke.yaml --no-dry-run

Next steps

One final note about it is that it does not understand the relationship between resources and so it could try deleting an EBS volume that is still in use by an EC2 instance. There isn't a great solution for this outside of running nuke a few times.

The tool is well documented and so you can find the rest of information going to https://github.com/rebuy-de/aws-nuke!