diff --git a/README.md b/README.md index 07c70c5a..e3f9053b 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Cloud-nuke suppports 🔎 inspecting and 🔥💀 deleting the following AWS res | Resource Family | Resource type | |-------------------------|----------------------------------------------------------| +| App Runner | Service | | EC2 | Auto scaling groups | | EC2 | Elastic Load Balancers (v1 and v2) | | EC2 | EBS Volumes | @@ -547,6 +548,7 @@ of the file that are supported are listed here. | apigatewayv2 | APIGatewayV2 | ✅ (API Name) | ✅ (Created Time) | ❌ | ✅ | | accessanalyzer | AccessAnalyzer | ✅ (Analyzer Name) | ✅ (Created Time) | ❌ | ✅ | | asg | AutoScalingGroup | ✅ (ASG Name) | ✅ (Created Time) | ✅ | ✅ | +| app-runner-service | AppRunnerService | ✅ (App Runner Service Name) | ✅ (Created Time) | ❌ | ✅ | | backup-vault | BackupVault | ✅ (Backup Vault Name) | ✅ (Created Time) | ❌ | ✅ | | cloudwatch-alarm | CloudWatchAlarm | ✅ (Alarm Name) | ✅ (AlarmConfigurationUpdated Time) | ❌ | ✅ | | cloudwatch-dashboard | CloudWatchDashboard | ✅ (Dashboard Name) | ✅ (LastModified Time) | ❌ | ✅ | diff --git a/aws/resource_registry.go b/aws/resource_registry.go index 0232d656..5aeda874 100644 --- a/aws/resource_registry.go +++ b/aws/resource_registry.go @@ -58,6 +58,7 @@ func getRegisteredRegionalResources() []AwsResource { &resources.ApiGateway{}, &resources.ApiGatewayV2{}, &resources.ASGroups{}, + &resources.AppRunnerService{}, &resources.BackupVault{}, &resources.CloudtrailTrail{}, &resources.CloudWatchAlarms{}, diff --git a/aws/resources/apprunner_service.go b/aws/resources/apprunner_service.go new file mode 100644 index 00000000..6d21acb7 --- /dev/null +++ b/aws/resources/apprunner_service.go @@ -0,0 +1,72 @@ +package resources + +import ( + "context" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/apprunner" + "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/go-commons/errors" +) + +func (a *AppRunnerService) nukeAll(identifiers []*string) error { + if len(identifiers) == 0 { + logging.Debugf("[App Runner Service] No App Runner Services found in region %s", a.Region) + return nil + } + + logging.Debugf("[App Runner Service] Deleting all App Runner Services in region %s", a.Region) + var deleted []*string + + for _, identifier := range identifiers { + logging.Debugf("[App Runner Service] Deleting App Runner Service %s in region %s", *identifier, a.Region) + + _, err := a.Client.DeleteServiceWithContext(a.Context, &apprunner.DeleteServiceInput{ + ServiceArn: identifier, + }) + if err != nil { + logging.Debugf("[App Runner Service] Error deleting App Runner Service %s in region %s", *identifier, a.Region) + } else { + deleted = append(deleted, identifier) + logging.Debugf("[App Runner Service] Deleted App Runner Service %s in region %s", *identifier, a.Region) + } + + e := report.Entry{ + Identifier: aws.StringValue(identifier), + ResourceType: a.ResourceName(), + Error: err, + } + report.Record(e) + } + + logging.Debugf("[OK] %d App Runner Service(s) nuked in %s", len(deleted), a.Region) + return nil +} + +func (a *AppRunnerService) getAll(c context.Context, configObj config.Config) ([]*string, error) { + var identifiers []*string + paginator := func(output *apprunner.ListServicesOutput, lastPage bool) bool { + for _, service := range output.ServiceSummaryList { + if configObj.AppRunnerService.ShouldInclude(config.ResourceValue{ + Name: service.ServiceName, + Time: service.CreatedAt, + }) { + identifiers = append(identifiers, service.ServiceArn) + } + } + return !lastPage + } + + param := &apprunner.ListServicesInput{ + MaxResults: aws.Int64(19), + } + + if err := a.Client.ListServicesPagesWithContext(c, param, paginator); err != nil { + logging.Debugf("[App Runner Service] Failed to list app runner services: %s", err) + return nil, errors.WithStackTrace(err) + } + + return identifiers, nil +} diff --git a/aws/resources/apprunner_service_test.go b/aws/resources/apprunner_service_test.go new file mode 100644 index 00000000..4b75d472 --- /dev/null +++ b/aws/resources/apprunner_service_test.go @@ -0,0 +1,109 @@ +package resources + +import ( + "context" + "fmt" + "regexp" + "testing" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/service/apprunner" + "github.com/aws/aws-sdk-go/service/apprunner/apprunneriface" + "github.com/gruntwork-io/cloud-nuke/config" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +type mockedAppRunnerService struct { + apprunneriface.AppRunnerAPI + ListServicesOutput apprunner.ListServicesOutput + DeleteServiceOutput apprunner.DeleteServiceOutput +} + +func (m mockedAppRunnerService) ListServicesPagesWithContext(_ aws.Context, _ *apprunner.ListServicesInput, callback func(*apprunner.ListServicesOutput, bool) bool, _ ...request.Option) error { + callback(&m.ListServicesOutput, true) + return nil +} + +func (m mockedAppRunnerService) DeleteServiceWithContext(aws.Context, *apprunner.DeleteServiceInput, ...request.Option) (*apprunner.DeleteServiceOutput, error) { + return &m.DeleteServiceOutput, nil +} + +func Test_AppRunnerService_GetAll(t *testing.T) { + + t.Parallel() + + testName1 := "test-service-1" + testName2 := "test-service-2" + now := time.Now() + service := AppRunnerService{ + Client: mockedAppRunnerService{ + ListServicesOutput: apprunner.ListServicesOutput{ + ServiceSummaryList: []*apprunner.ServiceSummary{ + { + ServiceName: &testName1, + ServiceArn: aws.String(fmt.Sprintf("arn::%s", testName1)), + CreatedAt: &now, + }, + { + ServiceName: &testName2, + ServiceArn: aws.String(fmt.Sprintf("arn::%s", testName2)), + CreatedAt: aws.Time(now.Add(1)), + }, + }, + }, + }, + } + + tests := map[string]struct { + configObj config.ResourceType + expected []string + }{ + "emptyFilter": { + configObj: config.ResourceType{}, + expected: []string{fmt.Sprintf("arn::%s", testName1), fmt.Sprintf("arn::%s", testName2)}, + }, + "nameExclusionFilter": { + configObj: config.ResourceType{ + ExcludeRule: config.FilterRule{ + NamesRegExp: []config.Expression{{ + RE: *regexp.MustCompile(testName1), + }}, + }}, + expected: []string{fmt.Sprintf("arn::%s", testName2)}, + }, + "timeAfterExclusionFilter": { + configObj: config.ResourceType{ + ExcludeRule: config.FilterRule{ + TimeAfter: aws.Time(now.Add(-1 * time.Hour)), + }}, + expected: []string{}, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + names, err := service.getAll(context.Background(), config.Config{ + AppRunnerService: tc.configObj, + }) + require.NoError(t, err) + require.Equal(t, tc.expected, aws.StringValueSlice(names)) + }) + } +} + +func TestAppRunnerService_NukeAll(t *testing.T) { + + t.Parallel() + + testName := "test-app-runner-service" + service := AppRunnerService{ + Client: mockedAppRunnerService{ + DeleteServiceOutput: apprunner.DeleteServiceOutput{}, + }, + } + + err := service.nukeAll([]*string{&testName}) + assert.NoError(t, err) +} diff --git a/aws/resources/apprunner_service_types.go b/aws/resources/apprunner_service_types.go new file mode 100644 index 00000000..8c9e43dc --- /dev/null +++ b/aws/resources/apprunner_service_types.go @@ -0,0 +1,51 @@ +package resources + +import ( + "context" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/apprunner" + "github.com/aws/aws-sdk-go/service/apprunner/apprunneriface" + "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/go-commons/errors" +) + +type AppRunnerService struct { + BaseAwsResource + Client apprunneriface.AppRunnerAPI + Region string + AppRunners []string +} + +func (a *AppRunnerService) GetAndSetResourceConfig(configObj config.Config) config.ResourceType { + return configObj.AppRunnerService +} + +func (a *AppRunnerService) Init(session *session.Session) { + a.Client = apprunner.New(session) +} + +func (a *AppRunnerService) ResourceName() string { return "app-runner-service" } + +func (a *AppRunnerService) ResourceIdentifiers() []string { return a.AppRunners } + +func (a *AppRunnerService) MaxBatchSize() int { return 19 } + +func (a *AppRunnerService) Nuke(identifiers []string) error { + if err := a.nukeAll(aws.StringSlice(identifiers)); err != nil { + return errors.WithStackTrace(err) + } + + return nil +} + +func (a *AppRunnerService) GetAndSetIdentifiers(c context.Context, configObj config.Config) ([]string, error) { + identifiers, err := a.getAll(c, configObj) + if err != nil { + return nil, err + } + + a.AppRunners = aws.StringValueSlice(identifiers) + return a.AppRunners, nil +} diff --git a/config/config.go b/config/config.go index 5bfa1484..e9733fa7 100644 --- a/config/config.go +++ b/config/config.go @@ -22,6 +22,7 @@ type Config struct { APIGatewayV2 ResourceType `yaml:"APIGatewayV2"` AccessAnalyzer ResourceType `yaml:"AccessAnalyzer"` AutoScalingGroup ResourceType `yaml:"AutoScalingGroup"` + AppRunnerService ResourceType `yaml:"AppRunnerService"` BackupVault ResourceType `yaml:"BackupVault"` CloudWatchAlarm ResourceType `yaml:"CloudWatchAlarm"` CloudWatchDashboard ResourceType `yaml:"CloudWatchDashboard"` diff --git a/config/config_test.go b/config/config_test.go index 9ffe1dbe..1d953e7a 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -13,107 +13,109 @@ import ( func emptyConfig() *Config { return &Config{ - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - EC2ResourceType{false, ResourceType{FilterRule{}, FilterRule{}, ""}}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - KMSCustomerKeyResourceType{false, ResourceType{FilterRule{}, FilterRule{}, ""}}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - EC2ResourceType{false, ResourceType{FilterRule{}, FilterRule{}, ""}}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - EC2ResourceType{false, ResourceType{FilterRule{}, FilterRule{}, ""}}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, - ResourceType{FilterRule{}, FilterRule{}, ""}, + ACM: ResourceType{FilterRule{}, FilterRule{}, ""}, + ACMPCA: ResourceType{FilterRule{}, FilterRule{}, ""}, + AMI: ResourceType{FilterRule{}, FilterRule{}, ""}, + APIGateway: ResourceType{FilterRule{}, FilterRule{}, ""}, + APIGatewayV2: ResourceType{FilterRule{}, FilterRule{}, ""}, + AccessAnalyzer: ResourceType{FilterRule{}, FilterRule{}, ""}, + AutoScalingGroup: ResourceType{FilterRule{}, FilterRule{}, ""}, + AppRunnerService: ResourceType{FilterRule{}, FilterRule{}, ""}, + BackupVault: ResourceType{FilterRule{}, FilterRule{}, ""}, + CloudWatchAlarm: ResourceType{FilterRule{}, FilterRule{}, ""}, + CloudWatchDashboard: ResourceType{FilterRule{}, FilterRule{}, ""}, + CloudWatchLogGroup: ResourceType{FilterRule{}, FilterRule{}, ""}, + CloudtrailTrail: ResourceType{FilterRule{}, FilterRule{}, ""}, + CodeDeployApplications: ResourceType{FilterRule{}, FilterRule{}, ""}, + ConfigServiceRecorder: ResourceType{FilterRule{}, FilterRule{}, ""}, + ConfigServiceRule: ResourceType{FilterRule{}, FilterRule{}, ""}, + DBGlobalClusters: ResourceType{FilterRule{}, FilterRule{}, ""}, + DBClusters: ResourceType{FilterRule{}, FilterRule{}, ""}, + DBInstances: ResourceType{FilterRule{}, FilterRule{}, ""}, + DBGlobalClusterMemberships: ResourceType{FilterRule{}, FilterRule{}, ""}, + DBSubnetGroups: ResourceType{FilterRule{}, FilterRule{}, ""}, + DynamoDB: ResourceType{FilterRule{}, FilterRule{}, ""}, + EBSVolume: ResourceType{FilterRule{}, FilterRule{}, ""}, + ElasticBeanstalk: ResourceType{FilterRule{}, FilterRule{}, ""}, + EC2: ResourceType{FilterRule{}, FilterRule{}, ""}, + EC2DedicatedHosts: ResourceType{FilterRule{}, FilterRule{}, ""}, + EC2DHCPOption: ResourceType{FilterRule{}, FilterRule{}, ""}, + EC2KeyPairs: ResourceType{FilterRule{}, FilterRule{}, ""}, + EC2IPAM: ResourceType{FilterRule{}, FilterRule{}, ""}, + EC2IPAMPool: ResourceType{FilterRule{}, FilterRule{}, ""}, + EC2IPAMResourceDiscovery: ResourceType{FilterRule{}, FilterRule{}, ""}, + EC2IPAMScope: ResourceType{FilterRule{}, FilterRule{}, ""}, + EC2Endpoint: ResourceType{FilterRule{}, FilterRule{}, ""}, + EC2Subnet: EC2ResourceType{false, ResourceType{FilterRule{}, FilterRule{}, ""}}, + EgressOnlyInternetGateway: ResourceType{FilterRule{}, FilterRule{}, ""}, + ECRRepository: ResourceType{FilterRule{}, FilterRule{}, ""}, + ECSCluster: ResourceType{FilterRule{}, FilterRule{}, ""}, + ECSService: ResourceType{FilterRule{}, FilterRule{}, ""}, + EKSCluster: ResourceType{FilterRule{}, FilterRule{}, ""}, + ELBv1: ResourceType{FilterRule{}, FilterRule{}, ""}, + ELBv2: ResourceType{FilterRule{}, FilterRule{}, ""}, + ElasticFileSystem: ResourceType{FilterRule{}, FilterRule{}, ""}, + ElasticIP: ResourceType{FilterRule{}, FilterRule{}, ""}, + Elasticache: ResourceType{FilterRule{}, FilterRule{}, ""}, + ElasticacheParameterGroups: ResourceType{FilterRule{}, FilterRule{}, ""}, + ElasticacheSubnetGroups: ResourceType{FilterRule{}, FilterRule{}, ""}, + GuardDuty: ResourceType{FilterRule{}, FilterRule{}, ""}, + IAMGroups: ResourceType{FilterRule{}, FilterRule{}, ""}, + IAMPolicies: ResourceType{FilterRule{}, FilterRule{}, ""}, + IAMRoles: ResourceType{FilterRule{}, FilterRule{}, ""}, + IAMServiceLinkedRoles: ResourceType{FilterRule{}, FilterRule{}, ""}, + IAMUsers: ResourceType{FilterRule{}, FilterRule{}, ""}, + KMSCustomerKeys: KMSCustomerKeyResourceType{false, ResourceType{}}, + KinesisStream: ResourceType{FilterRule{}, FilterRule{}, ""}, + KinesisFirehose: ResourceType{FilterRule{}, FilterRule{}, ""}, + LambdaFunction: ResourceType{FilterRule{}, FilterRule{}, ""}, + LambdaLayer: ResourceType{FilterRule{}, FilterRule{}, ""}, + LaunchConfiguration: ResourceType{FilterRule{}, FilterRule{}, ""}, + LaunchTemplate: ResourceType{FilterRule{}, FilterRule{}, ""}, + MacieMember: ResourceType{FilterRule{}, FilterRule{}, ""}, + MSKCluster: ResourceType{FilterRule{}, FilterRule{}, ""}, + NatGateway: ResourceType{FilterRule{}, FilterRule{}, ""}, + OIDCProvider: ResourceType{FilterRule{}, FilterRule{}, ""}, + OpenSearchDomain: ResourceType{FilterRule{}, FilterRule{}, ""}, + Redshift: ResourceType{FilterRule{}, FilterRule{}, ""}, + RdsSnapshot: ResourceType{FilterRule{}, FilterRule{}, ""}, + RdsParameterGroup: ResourceType{FilterRule{}, FilterRule{}, ""}, + RdsProxy: ResourceType{FilterRule{}, FilterRule{}, ""}, + S3: ResourceType{FilterRule{}, FilterRule{}, ""}, + S3AccessPoint: ResourceType{FilterRule{}, FilterRule{}, ""}, + S3ObjectLambdaAccessPoint: ResourceType{FilterRule{}, FilterRule{}, ""}, + S3MultiRegionAccessPoint: ResourceType{FilterRule{}, FilterRule{}, ""}, + SESIdentity: ResourceType{FilterRule{}, FilterRule{}, ""}, + SESConfigurationSet: ResourceType{FilterRule{}, FilterRule{}, ""}, + SESReceiptRuleSet: ResourceType{FilterRule{}, FilterRule{}, ""}, + SESReceiptFilter: ResourceType{FilterRule{}, FilterRule{}, ""}, + SESEmailTemplates: ResourceType{FilterRule{}, FilterRule{}, ""}, + SNS: ResourceType{FilterRule{}, FilterRule{}, ""}, + SQS: ResourceType{FilterRule{}, FilterRule{}, ""}, + SageMakerNotebook: ResourceType{FilterRule{}, FilterRule{}, ""}, + SecretsManagerSecrets: ResourceType{FilterRule{}, FilterRule{}, ""}, + SecurityHub: ResourceType{FilterRule{}, FilterRule{}, ""}, + Snapshots: ResourceType{FilterRule{}, FilterRule{}, ""}, + TransitGateway: ResourceType{FilterRule{}, FilterRule{}, ""}, + TransitGatewayRouteTable: ResourceType{FilterRule{}, FilterRule{}, ""}, + TransitGatewaysVpcAttachment: ResourceType{FilterRule{}, FilterRule{}, ""}, + TransitGatewayPeeringAttachment: ResourceType{FilterRule{}, FilterRule{}, ""}, + VPC: EC2ResourceType{false, ResourceType{FilterRule{}, FilterRule{}, ""}}, + Route53HostedZone: ResourceType{FilterRule{}, FilterRule{}, ""}, + Route53CIDRCollection: ResourceType{FilterRule{}, FilterRule{}, ""}, + Route53TrafficPolicy: ResourceType{FilterRule{}, FilterRule{}, ""}, + InternetGateway: ResourceType{FilterRule{}, FilterRule{}, ""}, + NetworkACL: ResourceType{FilterRule{}, FilterRule{}, ""}, + NetworkInterface: ResourceType{FilterRule{}, FilterRule{}, ""}, + SecurityGroup: EC2ResourceType{false, ResourceType{FilterRule{}, FilterRule{}, ""}}, + NetworkFirewall: ResourceType{FilterRule{}, FilterRule{}, ""}, + NetworkFirewallPolicy: ResourceType{FilterRule{}, FilterRule{}, ""}, + NetworkFirewallRuleGroup: ResourceType{FilterRule{}, FilterRule{}, ""}, + NetworkFirewallTLSConfig: ResourceType{FilterRule{}, FilterRule{}, ""}, + NetworkFirewallResourcePolicy: ResourceType{FilterRule{}, FilterRule{}, ""}, + VPCLatticeServiceNetwork: ResourceType{FilterRule{}, FilterRule{}, ""}, + VPCLatticeService: ResourceType{FilterRule{}, FilterRule{}, ""}, + VPCLatticeTargetGroup: ResourceType{FilterRule{}, FilterRule{}, ""}, } }