Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ACM Support #466

Merged
merged 15 commits into from
Jun 30, 2023
Merged
122 changes: 63 additions & 59 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,62 +36,63 @@ The currently supported functionality includes:

Cloud-nuke suppports 🔎 inspecting and 🔥💀 deleting the following AWS resources:

| Resource Family | Resource type
| --------------- |----------------------------------------------------------
| EC2 | Auto scaling groups |
| EC2 | Elastic Load Balancers (v1 and v2) |
| EC2 | EBS Volumes |
| EC2 | Unprotected EC2 instances |
| EC2 | AMIS |
| EC2 | Snapshots |
| EC2 | Elastic IPs |
| EC2 | Launch Configurations |
| Certificate Manager | ACM Private CA |
| Direct Connect | Transit Gateways |
| Elasticache | Clusters |
| Elasticache | Parameter Groups |
| Elasticache | Subnet Groups |
| ECS | Services |
| ECS | Clusters |
| EKS | Clusters |
| RDS | RDS databases |
| RDS | Neptune |
| RDS | Document DB instances |
| DynamoDB | Tables |
| Lambda | Functions |
| SQS | Queues |
| S3 | Buckets |
| VPC | Default VPCs |
| VPC | Default rules in the un-deletable default security group |
| VPC | NAT Gateways |
| IAM | Users |
| IAM | Roles (and any associated EC2 instance profiles) |
| IAM | Service-linked-roles |
| IAM | Groups |
| IAM | Policies |
| IAM | Customer-managed policies |
| IAM | Access analyzers |
| IAM | OpenID Connect providers |
| Secrets Manager | Secrets |
| CloudWatch | Dashboard |
| CloudWatch | Log groups |
| CloudWatch | Alarms |
| OpenSearch | Domains |
| KMS | Custgomer managed keys (and associated key aliases) |
| GuardDuty | Detectors |
| Macie | Member accounts |
| SageMaker | Notebook instances |
| Kinesis | Streams |
| API Gateway | Gateways (v1 and v2) |
| EFS | File systems |
| SNS | Topics |
| CloudTrail | Trails |
| ECR | Repositories |
| Config | Service recorders |
| Config | Service rules |
| Security Hub | Hubs |
| Security Hub | Members |
| Security Hub | Administrators |
| Resource Family | Resource type |
| ----------------------- | -------------------------------------------------------- |
| EC2 | Auto scaling groups |
| EC2 | Elastic Load Balancers (v1 and v2) |
| EC2 | EBS Volumes |
| EC2 | Unprotected EC2 instances |
| EC2 | AMIS |
| EC2 | Snapshots |
| EC2 | Elastic IPs |
| EC2 | Launch Configurations |
| Certificate Manager | ACM Private CA |
| Direct Connect | Transit Gateways |
| Elasticache | Clusters |
| Elasticache | Parameter Groups |
| Elasticache | Subnet Groups |
| ECS | Services |
| ECS | Clusters |
| EKS | Clusters |
| RDS | RDS databases |
| RDS | Neptune |
| RDS | Document DB instances |
| DynamoDB | Tables |
| Lambda | Functions |
| SQS | Queues |
| S3 | Buckets |
| VPC | Default VPCs |
| VPC | Default rules in the un-deletable default security group |
| VPC | NAT Gateways |
| IAM | Users |
| IAM | Roles (and any associated EC2 instance profiles) |
| IAM | Service-linked-roles |
| IAM | Groups |
| IAM | Policies |
| IAM | Customer-managed policies |
| IAM | Access analyzers |
| IAM | OpenID Connect providers |
| Secrets Manager | Secrets |
| CloudWatch | Dashboard |
| CloudWatch | Log groups |
| CloudWatch | Alarms |
| OpenSearch | Domains |
| KMS | Custgomer managed keys (and associated key aliases) |
| GuardDuty | Detectors |
| Macie | Member accounts |
| SageMaker | Notebook instances |
| Kinesis | Streams |
| API Gateway | Gateways (v1 and v2) |
| EFS | File systems |
| SNS | Topics |
| CloudTrail | Trails |
| ECR | Repositories |
| Config | Service recorders |
| Config | Service rules |
| Security Hub | Hubs |
| Security Hub | Members |
| Security Hub | Administrators |
| AWS Certificate Manager | Certificates |

> **WARNING:** The RDS APIs also interact with neptune and document db resources. Running `cloud-nuke aws --resource-type rds` without a config file will remove any neptune and document db resources in the account.

Expand Down Expand Up @@ -465,6 +466,9 @@ The following resources support the Config file:
- Redshift
- Resource type: `redshift`
- Config key: `Redshift`
- AWS Certificate Manager
- Resource type: `acm`
- Config key: `ACM`



Expand Down Expand Up @@ -560,7 +564,7 @@ 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 | names | names_regex | tags | tags_regex |
|-------------------------------|-------|-------------|------|------------|
| ----------------------------- | ----- | ----------- | ---- | ---------- |
| s3 | none | ✅ | none | none |
| iam user | none | ✅ | none | none |
| ecsserv | none | ✅ | none | none |
Expand Down Expand Up @@ -589,7 +593,7 @@ To find out what we options are supported in the config file today, consult this
| eks | none | ✅ | none | none |
| kinesis-stream | none | ✅ | none | none |
| efs | none | ✅ | none | none |
| acmpca | none | none | none | none |
| acmpca | none | none | none | none |
| iam role | none | ✅ | none | none |
| iam service-linked role | none | ✅ | none | none |
| iam policy | none | ✅ | none | none |
Expand All @@ -602,7 +606,7 @@ To find out what we options are supported in the config file today, consult this
| config-rules | none | ✅ | none | none |
| cloudwatch-alarm | none | ✅ | none | none |
| redshift | none | ✅ | none | none |
| ... (more to come) | none | none | none | none |
| ... (more to come) | none | none | none | none |


### Log level
Expand Down
105 changes: 105 additions & 0 deletions aws/acm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package aws

import (
"time"

"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/acm"
"github.com/gruntwork-io/cloud-nuke/config"
"github.com/gruntwork-io/cloud-nuke/logging"
"github.com/gruntwork-io/cloud-nuke/report"
"github.com/gruntwork-io/cloud-nuke/telemetry"
"github.com/gruntwork-io/go-commons/errors"
commonTelemetry "github.com/gruntwork-io/go-commons/telemetry"
)

// Returns a list of strings of ACM ARNs
func getAllACMs(session *session.Session, excludeAfter time.Time, configObj config.Config) ([]string, error) {
svc := acm.New(session)

params := &acm.ListCertificatesInput{}

acmArns := []string{}
err := svc.ListCertificatesPages(params,
func(page *acm.ListCertificatesOutput, lastPage bool) bool {
for i := range page.CertificateSummaryList {
if shouldIncludeACM(page.CertificateSummaryList[i], excludeAfter, configObj) {
acmArns = append(acmArns, *page.CertificateSummaryList[i].CertificateArn)
}
}

return !lastPage
},
)
if err != nil {
return nil, errors.WithStackTrace(err)
}

return acmArns, nil
}

func shouldIncludeACM(acm *acm.CertificateSummary, excludeAfter time.Time, configObj config.Config) bool {
if acm == nil {
return false
}

if acm.InUse != nil && *acm.InUse {
logging.Logger.Debugf("Skipping ACM %s as it is in use", *acm.CertificateArn)
return false
}

if acm.CreatedAt != nil {
if excludeAfter.Before(*acm.CreatedAt) {
return false
}
}

return config.ShouldInclude(
*acm.DomainName,
configObj.ACM.IncludeRule.NamesRegExp,
configObj.ACM.ExcludeRule.NamesRegExp,
)
}

// Deletes all ACMs
func nukeAllACMs(session *session.Session, acmArns []*string) error {
svc := acm.New(session)

if len(acmArns) == 0 {
logging.Logger.Debugf("No ACMs to nuke in region %s", *session.Config.Region)
return nil
}

logging.Logger.Debugf("Deleting all ACMs in region %s", *session.Config.Region)

deletedCount := 0
for _, acmArn := range acmArns {
params := &acm.DeleteCertificateInput{
CertificateArn: acmArn,
}

_, err := svc.DeleteCertificate(params)
if err != nil {
logging.Logger.Debugf("[Failed] %s", err)
telemetry.TrackEvent(commonTelemetry.EventContext{
EventName: "Error Nuking ACM",
}, map[string]interface{}{
"region": *session.Config.Region,
})
} else {
deletedCount++
logging.Logger.Debugf("Deleted ACM: %s", *acmArn)
}

e := report.Entry{
Identifier: *acmArn,
ResourceType: "ACM",
Error: err,
}
report.Record(e)
}

logging.Logger.Debugf("[OK] %d ACM(s) terminated in %s", deletedCount, *session.Config.Region)

return nil
}
Loading