From 21f3ef385c356a7b0e4cc4e7151e0d0ced939968 Mon Sep 17 00:00:00 2001 From: Yoriyasu Yano <430092+yorinasub17@users.noreply.github.com> Date: Fri, 25 Jun 2021 16:03:59 -0500 Subject: [PATCH] Add config support for nuking NAT gateways --- .circleci/nuke_config.yml | 10 ++++++++ README.md | 52 ++++++++++----------------------------- aws/aws.go | 2 +- aws/nat_gateway.go | 23 ++++++++++++++--- aws/nat_gateway_test.go | 7 +++--- config/config.go | 1 + 6 files changed, 48 insertions(+), 47 deletions(-) diff --git a/.circleci/nuke_config.yml b/.circleci/nuke_config.yml index 9ce736b3..9abb23c0 100644 --- a/.circleci/nuke_config.yml +++ b/.circleci/nuke_config.yml @@ -24,3 +24,13 @@ SecretsManager: - "^RDSDBConfig[a-zA-Z0-9]{6}$" - "ECRDeployRunnerTestSSHKey-[a-zA-Z0-9]{6}$" - "ECRDeployRunnerTestGitPAT-[a-zA-Z0-9]{6}$" + +NatGateway: + # There is a bug in the cloud-nuke config where exclude does not work by itself, so we add a null include rule that + # includes everything. + include: + names_regex: + - ".*" + exclude: + names_regex: + - "^ecs-deploy-runner-v2-nat-gateway-0$" diff --git a/README.md b/README.md index c33fe70e..0f36a481 100644 --- a/README.md +++ b/README.md @@ -149,6 +149,9 @@ The following resources support the Config file: - Secrets Manager Secrets - Resource type: `secretsmanager` - Config key: `SecretsManager` +- NAT Gateways + - Resource type: `nat-gateway` + - Config key: `NATGateway` #### Example @@ -234,45 +237,16 @@ Be careful when nuking and append the `--dry-run` option if you're unsure. Even To find out what we options are supported in the config file today, consult this table. Resource types at the top level of the file that are supported are listed here. -| resource type | support | -|----------------|---------| -| s3 | partial | -| iam | partial | -| secretsmanager | partial | -| ec2 instance | none | -| iam role | none | -| ... (more to come) | none | - - -##### s3 resource type: -_Note: the fields without `_regex` suffixes refer to support for plain-text matching against those fields._ - -| field | include | exclude | -|-------------|---------|---------| -| names | none | none | -| names_regex | ✅ | ✅ | -| tags | none | none | -| tags_regex | none | none | - -##### iam resource type: -_Note: the fields without `_regex` suffixes refer to support for plain-text matching against those fields._ - -| field | include | exclude | -|-------------|---------|---------| -| names | none | none | -| names_regex | ✅ | ✅ | -| tags | none | none | -| tags_regex | none | none | - -##### secretsmanager resource type: -_Note: the fields without `_regex` suffixes refer to support for plain-text matching against those fields._ - -| field | include | exclude | -|-------------|---------|---------| -| names | none | none | -| names_regex | ✅ | ✅ | -| tags | none | none | -| tags_regex | none | none | +| resource type | names | names_regex | tags | tags_regex | +|--------------------|-------|-------------|------|------------| +| s3 | none | ✅ | none | none | +| iam | none | ✅ | none | none | +| secretsmanager | none | ✅ | none | none | +| nat-gateway | none | ✅ | none | none | +| ec2 instance | none | none | none | none | +| iam role | none | none | none | none | +| ... (more to come) | none | none | none | none | + ### Log level diff --git a/aws/aws.go b/aws/aws.go index 07c45926..c4f710be 100644 --- a/aws/aws.go +++ b/aws/aws.go @@ -339,7 +339,7 @@ func GetAllResources(targetRegions []string, excludeAfter time.Time, resourceTyp // NATGateway natGateways := NatGateways{} if IsNukeable(natGateways.ResourceName(), resourceTypes) { - ngwIDs, err := getAllNatGateways(session, excludeAfter) + ngwIDs, err := getAllNatGateways(session, excludeAfter, configObj) if err != nil { return nil, errors.WithStackTrace(err) } diff --git a/aws/nat_gateway.go b/aws/nat_gateway.go index 8d3d12c2..fecd3476 100644 --- a/aws/nat_gateway.go +++ b/aws/nat_gateway.go @@ -12,10 +12,11 @@ import ( "github.com/gruntwork-io/go-commons/retry" multierror "github.com/hashicorp/go-multierror" + "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" ) -func getAllNatGateways(session *session.Session, excludeAfter time.Time) ([]*string, error) { +func getAllNatGateways(session *session.Session, excludeAfter time.Time, configObj config.Config) ([]*string, error) { svc := ec2.New(session) allNatGateways := []*string{} @@ -24,7 +25,7 @@ func getAllNatGateways(session *session.Session, excludeAfter time.Time) ([]*str input, func(page *ec2.DescribeNatGatewaysOutput, lastPage bool) bool { for _, ngw := range page.NatGateways { - if shouldIncludeNatGateway(ngw, excludeAfter) { + if shouldIncludeNatGateway(ngw, excludeAfter, configObj) { allNatGateways = append(allNatGateways, ngw.NatGatewayId) } } @@ -34,7 +35,7 @@ func getAllNatGateways(session *session.Session, excludeAfter time.Time) ([]*str return allNatGateways, errors.WithStackTrace(err) } -func shouldIncludeNatGateway(ngw *ec2.NatGateway, excludeAfter time.Time) bool { +func shouldIncludeNatGateway(ngw *ec2.NatGateway, excludeAfter time.Time, configObj config.Config) bool { if ngw == nil { return false } @@ -42,7 +43,21 @@ func shouldIncludeNatGateway(ngw *ec2.NatGateway, excludeAfter time.Time) bool { if ngw.CreateTime != nil && excludeAfter.Before(*ngw.CreateTime) { return false } - return true + + return config.ShouldInclude( + getNatGatewayName(ngw), + configObj.NatGateway.IncludeRule.NamesRegExp, + configObj.NatGateway.ExcludeRule.NamesRegExp, + ) +} + +func getNatGatewayName(ngw *ec2.NatGateway) string { + for _, tag := range ngw.Tags { + if aws.StringValue(tag.Key) == "Name" { + return aws.StringValue(tag.Value) + } + } + return "" } func nukeAllNatGateways(session *session.Session, identifiers []*string) error { diff --git a/aws/nat_gateway_test.go b/aws/nat_gateway_test.go index 1695cbc6..c43bcb8e 100644 --- a/aws/nat_gateway_test.go +++ b/aws/nat_gateway_test.go @@ -7,6 +7,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/gruntwork-io/cloud-nuke/config" terraws "github.com/gruntwork-io/terratest/modules/aws" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -25,7 +26,7 @@ func TestListNatGateways(t *testing.T) { ngwID := createNatGateway(t, svc, region) defer deleteNatGateway(t, svc, ngwID, true) - natGatewayIDs, err := getAllNatGateways(session, time.Now()) + natGatewayIDs, err := getAllNatGateways(session, time.Now(), config.Config{}) require.NoError(t, err) assert.Contains(t, aws.StringValueSlice(natGatewayIDs), aws.StringValue(ngwID)) } @@ -45,13 +46,13 @@ func TestTimeFilterExclusionNewlyCreatedNatGateway(t *testing.T) { defer deleteNatGateway(t, svc, ngwID, true) // Assert NGW is picked up without filters - natGatewayIDsNewer, err := getAllNatGateways(session, time.Now()) + natGatewayIDsNewer, err := getAllNatGateways(session, time.Now(), config.Config{}) require.NoError(t, err) assert.Contains(t, aws.StringValueSlice(natGatewayIDsNewer), aws.StringValue(ngwID)) // Assert user doesn't appear when we look at users older than 1 Hour olderThan := time.Now().Add(-1 * time.Hour) - natGatewayIDsOlder, err := getAllNatGateways(session, olderThan) + natGatewayIDsOlder, err := getAllNatGateways(session, olderThan, config.Config{}) require.NoError(t, err) assert.NotContains(t, aws.StringValueSlice(natGatewayIDsOlder), aws.StringValue(ngwID)) } diff --git a/config/config.go b/config/config.go index 28ca1a3d..2a26c755 100644 --- a/config/config.go +++ b/config/config.go @@ -13,6 +13,7 @@ type Config struct { S3 ResourceType `yaml:"s3"` IAMUsers ResourceType `yaml:"IAMUsers"` SecretsManagerSecrets ResourceType `yaml:"SecretsManager"` + NatGateway ResourceType `yaml:"NatGateway"` } type ResourceType struct {