diff --git a/cmd/nuke.go b/cmd/nuke.go index 093a7e608..f6437e3de 100644 --- a/cmd/nuke.go +++ b/cmd/nuke.go @@ -173,6 +173,11 @@ func (n *Nuke) Scan() error { ffGetter.FeatureFlags(n.Config.FeatureFlags) } + settingsGetter, ok := item.Resource.(resources.SettingsGetter) + if ok { + settingsGetter.Settings(n.Config.Settings) + } + queue = append(queue, item) err := n.Filter(item) if err != nil { diff --git a/go.mod b/go.mod index 0e3138a1e..9dd821dd4 100644 --- a/go.mod +++ b/go.mod @@ -4,11 +4,14 @@ go 1.21 require ( github.com/aws/aws-sdk-go v1.53.15 - github.com/aws/aws-sdk-go-v2 v1.30.0 + github.com/aws/aws-sdk-go-v2 v1.30.3 github.com/aws/aws-sdk-go-v2/config v1.27.22 github.com/aws/aws-sdk-go-v2/credentials v1.17.22 + github.com/aws/aws-sdk-go-v2/service/appstream v1.37.0 + github.com/aws/aws-sdk-go-v2/service/kafka v1.35.3 github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.40.0 github.com/aws/aws-sdk-go-v2/service/sts v1.30.0 + github.com/aws/aws-sdk-go-v2/service/wafregional v1.23.3 github.com/fatih/color v1.17.0 github.com/golang/mock v1.6.0 github.com/google/uuid v1.6.0 @@ -24,14 +27,14 @@ require ( require ( github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.8 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.12 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.12 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.14 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.22.0 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.0 // indirect - github.com/aws/smithy-go v1.20.2 // indirect + github.com/aws/smithy-go v1.20.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/gemnasium/logrus-graylog-hook/v3 v3.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect diff --git a/go.sum b/go.sum index 9a0dcb15a..76a148cfc 100644 --- a/go.sum +++ b/go.sum @@ -1,23 +1,27 @@ github.com/aws/aws-sdk-go v1.53.15 h1:FtZmkg7xM8RfP2oY6p7xdKBYrRgkITk9yve2QV7N938= github.com/aws/aws-sdk-go v1.53.15/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.30.0 h1:6qAwtzlfcTtcL8NHtbDQAqgM5s6NDipQTkPxyH/6kAA= -github.com/aws/aws-sdk-go-v2 v1.30.0/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= +github.com/aws/aws-sdk-go-v2 v1.30.3 h1:jUeBtG0Ih+ZIFH0F4UkmL9w3cSpaMv9tYYDbzILP8dY= +github.com/aws/aws-sdk-go-v2 v1.30.3/go.mod h1:nIQjQVp5sfpQcTc9mPSr1B0PaWK5ByX9MOoDadSN4lc= github.com/aws/aws-sdk-go-v2/config v1.27.22 h1:TRkQVtpDINt+Na/ToU7iptyW6U0awAwJ24q4XN+59k8= github.com/aws/aws-sdk-go-v2/config v1.27.22/go.mod h1:EYY3mVgFRUWkh6QNKH64MdyKs1YSUgatc0Zp3MDxi7c= github.com/aws/aws-sdk-go-v2/credentials v1.17.22 h1:wu9kXQbbt64ul09v3ye4HYleAr4WiGV/uv69EXKDEr0= github.com/aws/aws-sdk-go-v2/credentials v1.17.22/go.mod h1:pcvMtPcxJn3r2k6mZD9I0EcumLqPLA7V/0iCgOIlY+o= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.8 h1:FR+oWPFb/8qMVYMWN98bUZAGqPvLHiyqg1wqQGfUAXY= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.8/go.mod h1:EgSKcHiuuakEIxJcKGzVNWh5srVAQ3jKaSrBGRYvM48= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.12 h1:SJ04WXGTwnHlWIODtC5kJzKbeuHt+OUNOgKg7nfnUGw= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.12/go.mod h1:FkpvXhA92gb3GE9LD6Og0pHHycTxW7xGpnEh5E7Opwo= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.12 h1:hb5KgeYfObi5MHkSSZMEudnIvX30iB+E21evI4r6BnQ= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.12/go.mod h1:CroKe/eWJdyfy9Vx4rljP5wTUjNJfb+fPz1uMYUhEGM= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 h1:SoNJ4RlFEQEbtDcCEt+QG56MY4fm4W8rYirAmq+/DdU= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15/go.mod h1:U9ke74k1n2bf+RIgoX1SXFed1HLs51OgUSs+Ph0KJP8= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 h1:C6WHdGnTDIYETAm5iErQUiVNsclNx9qbJVPIt03B6bI= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15/go.mod h1:ZQLZqhcu+JhSrA9/NXRm8SkDvsycE+JkV3WGY41e+IM= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= +github.com/aws/aws-sdk-go-v2/service/appstream v1.37.0 h1:novlmw4mzemK9FHfneoni0pG0eCPISgeW72apbWSxdY= +github.com/aws/aws-sdk-go-v2/service/appstream v1.37.0/go.mod h1:zgB9SASIAI0KWFuUSlo9pGC37f6DDjh1ZJfZEhQcPhU= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.14 h1:zSDPny/pVnkqABXYRicYuPf9z2bTqfH13HT3v6UheIk= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.14/go.mod h1:3TTcI5JSzda1nw/pkVC9dhgLre0SNBFj2lYS4GctXKI= +github.com/aws/aws-sdk-go-v2/service/kafka v1.35.3 h1:MUx27PrqicGxgsiDWo7xv/Zsl4b0X8kHCRvMpX7XrQs= +github.com/aws/aws-sdk-go-v2/service/kafka v1.35.3/go.mod h1:mBWO7tOHjEvfZ88cUBhCfViO9vclCumFcTeiR1cB4IA= github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.40.0 h1:ZKjJJWxZ4cGM6LWxXsnviGlBpqPvifSod4U8gOXik9U= github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.40.0/go.mod h1:23qyfghRkv9qOMRIL9KdUHiKyhARU/0FddRMtvMSVV0= github.com/aws/aws-sdk-go-v2/service/sso v1.22.0 h1:lPIAPCRoJkmotLTU/9B6icUFlYDpEuWjKeL79XROv1M= @@ -26,8 +30,10 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.0 h1:/4r71ghx+hX9spr884cqXHPE github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.0/go.mod h1:z0P8K+cBIsFXUr5rzo/psUeJ20XjPN0+Nn8067Nd+E4= github.com/aws/aws-sdk-go-v2/service/sts v1.30.0 h1:9ja34PaKybhCJjVKvxtDsUjbATUJGN+eF6QnO58u5cI= github.com/aws/aws-sdk-go-v2/service/sts v1.30.0/go.mod h1:N2mQiucsO0VwK9CYuS4/c2n6Smeh1v47Rz3dWCPFLdE= -github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= -github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= +github.com/aws/aws-sdk-go-v2/service/wafregional v1.23.3 h1:7dr6En0/6KRFoz8VmnYks9dVvL+tkL5RjRrxqGzr1zI= +github.com/aws/aws-sdk-go-v2/service/wafregional v1.23.3/go.mod h1:24TtlRsv4LKAE3VnRJQhpatr8cpX0yj8NSzg8/lxOCw= +github.com/aws/smithy-go v1.20.3 h1:ryHwveWzPV5BIof6fyDvor6V3iUL7nTfiTKXHiW05nE= +github.com/aws/smithy-go v1.20.3/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/pkg/config/config.go b/pkg/config/config.go index 30234c264..e96e2ab4a 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -33,6 +33,7 @@ type Nuke struct { ResourceTypes ResourceTypes `yaml:"resource-types"` Presets map[string]PresetDefinitions `yaml:"presets"` FeatureFlags FeatureFlags `yaml:"feature-flags"` + Settings Settings `yaml:"settings"` CustomEndpoints CustomEndpoints `yaml:"endpoints"` } @@ -43,10 +44,23 @@ type FeatureFlags struct { DisableFailOnKMSError bool `yaml:"disable-fail-on-kms-error"` } +type Settings struct { + CloudFormationStack CloudFormationStackSettings `yaml:"CloudFormationStack"` +} + +type ResourceSettings struct { + DisableDeletionProtection bool `yaml:"DisableDeletionProtection"` +} + +type CloudFormationStackSettings struct { + ResourceSettings `yaml:",inline"` + ServiceRoleArn string `yaml:"ServiceRoleArn"` +} + type DisableDeletionProtection struct { RDSInstance bool `yaml:"RDSInstance"` EC2Instance bool `yaml:"EC2Instance"` - CloudformationStack bool `yaml:"CloudformationStack"` + CloudFormationStack bool `yaml:"CloudFormationStack"` ELBv2 bool `yaml:"ELBv2"` QLDBLedger bool `yaml:"QLDBLedger"` DynamoDBTable bool `yaml:"DynamoDBTable"` diff --git a/resources/appstream-images.go b/resources/appstream-images.go index 4530d26cc..b3c471c4b 100644 --- a/resources/appstream-images.go +++ b/resources/appstream-images.go @@ -1,50 +1,99 @@ package resources import ( + "context" "fmt" "strings" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/appstream" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/rebuy-de/aws-nuke/v2/pkg/types" + + "github.com/aws/aws-sdk-go-v2/service/appstream" ) type AppStreamImage struct { - svc *appstream.AppStream + svc *appstream.Client + context context.Context + name *string - visibility *string + visibility string + + sharedAccounts []*string } func init() { - register("AppStreamImage", ListAppStreamImages) + registerV2("AppStreamImage", ListAppStreamImages) } -func ListAppStreamImages(sess *session.Session) ([]Resource, error) { - svc := appstream.New(sess) +func ListAppStreamImages(cfg *aws.Config) ([]Resource, error) { + svc := appstream.NewFromConfig(*cfg) + ctx := context.TODO() + resources := []Resource{} + var nextToken *string - params := &appstream.DescribeImagesInput{} + for ok := true; ok; ok = (nextToken != nil) { + params := &appstream.DescribeImagesInput{ + NextToken: nextToken, + } - output, err := svc.DescribeImages(params) - if err != nil { - return nil, err - } + output, err := svc.DescribeImages(ctx, params) + if err != nil { + return nil, err + } + nextToken = output.NextToken + + for _, image := range output.Images { + sharedAccounts := []*string{} + visibility := string(image.Visibility) + + // Filter out public images + if strings.ToUpper(visibility) != "PUBLIC" { + imagePerms, err := svc.DescribeImagePermissions(ctx, &appstream.DescribeImagePermissionsInput{ + Name: image.Name, + }) + + if err != nil { + return nil, err + } + + for _, permission := range imagePerms.SharedImagePermissionsList { + sharedAccounts = append(sharedAccounts, permission.SharedAccountId) + } + + resources = append(resources, &AppStreamImage{ + svc: svc, + context: ctx, + name: image.Name, + visibility: visibility, + sharedAccounts: sharedAccounts, + }) + } + } - for _, image := range output.Images { - resources = append(resources, &AppStreamImage{ - svc: svc, - name: image.Name, - visibility: image.Visibility, - }) } return resources, nil } func (f *AppStreamImage) Remove() error { + for _, account := range f.sharedAccounts { + _, err := f.svc.DeleteImagePermissions(f.context, &appstream.DeleteImagePermissionsInput{ + Name: f.name, + SharedAccountId: account, + }) + if err != nil { + fmt.Println("Error deleting image permissions", err) + return err + } + } - _, err := f.svc.DeleteImage(&appstream.DeleteImageInput{ + _, err := f.svc.DeleteImage(f.context, &appstream.DeleteImageInput{ Name: f.name, }) + if err != nil { + fmt.Println("Error deleting image", err) + } return err } @@ -54,8 +103,24 @@ func (f *AppStreamImage) String() string { } func (f *AppStreamImage) Filter() error { - if strings.ToUpper(*f.visibility) == "PUBLIC" { + if strings.ToUpper(f.visibility) == "PUBLIC" { return fmt.Errorf("cannot delete public AWS images") } return nil } + +func (f *AppStreamImage) Properties() types.Properties { + properties := types.NewProperties() + + properties.Set("Name", f.name) + + sharedAccounts := make([]string, len(f.sharedAccounts)) + for i, account := range f.sharedAccounts { + sharedAccounts[i] = *account + } + if len(sharedAccounts) > 0 { + properties.Set("Accounts with shared image", strings.Join(sharedAccounts, ", ")) + } + + return properties +} diff --git a/resources/cloudformation-stack.go b/resources/cloudformation-stack.go index ce194d646..ba72020b1 100644 --- a/resources/cloudformation-stack.go +++ b/resources/cloudformation-stack.go @@ -2,6 +2,7 @@ package resources import ( "errors" + "fmt" "strings" "time" @@ -57,11 +58,15 @@ type CloudFormationStack struct { svc cloudformationiface.CloudFormationAPI stack *cloudformation.Stack maxDeleteAttempts int - featureFlags config.FeatureFlags + settings config.Settings } -func (cfs *CloudFormationStack) FeatureFlags(ff config.FeatureFlags) { - cfs.featureFlags = ff +func (cfs *CloudFormationStack) Settings(settings config.Settings) { + cfs.settings = settings + + if cfs.settings.CloudFormationStack.ServiceRoleArn != "" { + fmt.Printf("ServiceRoleArn: %s\n", cfs.settings.CloudFormationStack.ServiceRoleArn) + } } func (cfs *CloudFormationStack) Remove() error { @@ -74,7 +79,7 @@ func (cfs *CloudFormationStack) removeWithAttempts(attempt int) error { awsErr, ok := err.(awserr.Error) if ok && awsErr.Code() == "ValidationError" && awsErr.Message() == "Stack ["+*cfs.stack.StackName+"] cannot be deleted while TerminationProtection is enabled" { - if cfs.featureFlags.DisableDeletionProtection.CloudformationStack { + if cfs.settings.CloudFormationStack.DisableDeletionProtection { logrus.Infof("CloudFormationStack stackName=%s attempt=%d maxAttempts=%d updating termination protection", *cfs.stack.StackName, attempt, cfs.maxDeleteAttempts) _, err = cfs.svc.UpdateTerminationProtection(&cloudformation.UpdateTerminationProtectionInput{ EnableTerminationProtection: aws.Bool(false), @@ -89,7 +94,7 @@ func (cfs *CloudFormationStack) removeWithAttempts(attempt int) error { } } if attempt >= cfs.maxDeleteAttempts { - return errors.New("CFS might not be deleted after this run.") + return errors.New("CFS might not be deleted after this run") } else { return cfs.removeWithAttempts(attempt + 1) } @@ -140,9 +145,14 @@ func (cfs *CloudFormationStack) doRemove() error { } } + var roleArn *string + if cfs.settings.CloudFormationStack.ServiceRoleArn != "" { + roleArn = aws.String(cfs.settings.CloudFormationStack.ServiceRoleArn) + } _, err = cfs.svc.DeleteStack(&cloudformation.DeleteStackInput{ StackName: cfs.stack.StackName, RetainResources: retain, + RoleARN: roleArn, }) if err != nil { return err @@ -151,10 +161,16 @@ func (cfs *CloudFormationStack) doRemove() error { StackName: cfs.stack.StackName, }) } else { + var roleArn *string + if cfs.settings.CloudFormationStack.ServiceRoleArn != "" { + roleArn = aws.String(cfs.settings.CloudFormationStack.ServiceRoleArn) + } + if err := cfs.waitForStackToStabilize(*stack.StackStatus); err != nil { return err } else if _, err := cfs.svc.DeleteStack(&cloudformation.DeleteStackInput{ StackName: cfs.stack.StackName, + RoleARN: roleArn, }); err != nil { return err } else if err := cfs.svc.WaitUntilStackDeleteComplete(&cloudformation.DescribeStacksInput{ diff --git a/resources/interface.go b/resources/interface.go index af8035ea0..a94ccda3c 100644 --- a/resources/interface.go +++ b/resources/interface.go @@ -41,6 +41,11 @@ type FeatureFlagGetter interface { FeatureFlags(config.FeatureFlags) } +type SettingsGetter interface { + Resource + Settings(config.Settings) +} + var resourceListers = make(ResourceListers) var resourceListersV2 = make(ResourceListersV2) diff --git a/resources/msk-cluster.go b/resources/msk-cluster.go index 4c3be6c3e..5b19c0495 100644 --- a/resources/msk-cluster.go +++ b/resources/msk-cluster.go @@ -1,27 +1,33 @@ package resources import ( - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/kafka" + "context" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/kafka" + "github.com/rebuy-de/aws-nuke/v2/pkg/types" ) type MSKCluster struct { - svc *kafka.Kafka + svc *kafka.Client + context context.Context + arn string name string - tags map[string]*string + tags map[string]string } func init() { - register("MSKCluster", ListMSKCluster) + registerV2("MSKCluster", ListMSKCluster) } -func ListMSKCluster(sess *session.Session) ([]Resource, error) { - svc := kafka.New(sess) - params := &kafka.ListClustersInput{} - resp, err := svc.ListClusters(params) +func ListMSKCluster(cfg *aws.Config) ([]Resource, error) { + svc := kafka.NewFromConfig(*cfg) + ctx := context.TODO() + + params := &kafka.ListClustersV2Input{} + resp, err := svc.ListClustersV2(ctx, params) if err != nil { return nil, err @@ -29,10 +35,11 @@ func ListMSKCluster(sess *session.Session) ([]Resource, error) { resources := make([]Resource, 0) for _, cluster := range resp.ClusterInfoList { resources = append(resources, &MSKCluster{ - svc: svc, - arn: *cluster.ClusterArn, - name: *cluster.ClusterName, - tags: cluster.Tags, + svc: svc, + context: ctx, + arn: *cluster.ClusterArn, + name: *cluster.ClusterName, + tags: cluster.Tags, }) } @@ -44,7 +51,7 @@ func (m *MSKCluster) Remove() error { ClusterArn: &m.arn, } - _, err := m.svc.DeleteCluster(params) + _, err := m.svc.DeleteCluster(m.context, params) if err != nil { return err } diff --git a/resources/network-firewall.go b/resources/network-firewall.go index b8463468c..f9b7fede5 100644 --- a/resources/network-firewall.go +++ b/resources/network-firewall.go @@ -11,7 +11,8 @@ import ( ) type NetworkFirewall struct { - svc *networkfirewall.Client + svc *networkfirewall.Client + context context.Context firewall networkfirwallTypes.FirewallMetadata logConfig *networkfirwallTypes.LoggingConfiguration @@ -69,6 +70,7 @@ func ListNetworkFirewalls(cfg *aws.Config) ([]Resource, error) { resources = append(resources, &NetworkFirewall{ svc: svc, + context: ctx, firewall: firewall, logConfig: logResp.LoggingConfiguration, tags: tags, @@ -84,12 +86,10 @@ func ListNetworkFirewalls(cfg *aws.Config) ([]Resource, error) { } func (i *NetworkFirewall) Remove() error { - ctx := context.TODO() - if i.logConfig != nil { for index := 1; index <= len(i.logConfig.LogDestinationConfigs); index++ { // aws forces to only remove one at a time - _, err := i.svc.UpdateLoggingConfiguration(ctx, &networkfirewall.UpdateLoggingConfigurationInput{ + _, err := i.svc.UpdateLoggingConfiguration(i.context, &networkfirewall.UpdateLoggingConfigurationInput{ FirewallArn: i.firewall.FirewallArn, LoggingConfiguration: &networkfirwallTypes.LoggingConfiguration{ LogDestinationConfigs: i.logConfig.LogDestinationConfigs[index:], @@ -105,7 +105,7 @@ func (i *NetworkFirewall) Remove() error { FirewallArn: i.firewall.FirewallArn, } - _, err := i.svc.DeleteFirewall(ctx, params) + _, err := i.svc.DeleteFirewall(i.context, params) if err != nil { return err } diff --git a/resources/wafregional-rules.go b/resources/wafregional-rules.go index 5dd83ff9e..5ff9e2179 100644 --- a/resources/wafregional-rules.go +++ b/resources/wafregional-rules.go @@ -1,50 +1,55 @@ package resources import ( - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/waf" - "github.com/aws/aws-sdk-go/service/wafregional" + "context" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/wafregional" + wafregionalTypes "github.com/aws/aws-sdk-go-v2/service/wafregional/types" "github.com/rebuy-de/aws-nuke/v2/pkg/types" ) type WAFRegionalRule struct { - svc *wafregional.WAFRegional + svc *wafregional.Client + context context.Context + ID *string name *string - rule *waf.Rule + rule *wafregionalTypes.Rule } func init() { - register("WAFRegionalRule", ListWAFRegionalRules) + registerV2("WAFRegionalRule", ListWAFRegionalRules) } -func ListWAFRegionalRules(sess *session.Session) ([]Resource, error) { - svc := wafregional.New(sess) +func ListWAFRegionalRules(cfg *aws.Config) ([]Resource, error) { + svc := wafregional.NewFromConfig(*cfg) + ctx := context.TODO() resources := []Resource{} - params := &waf.ListRulesInput{ - Limit: aws.Int64(50), + params := &wafregional.ListRulesInput{ + Limit: 50, } for { - resp, err := svc.ListRules(params) + resp, err := svc.ListRules(ctx, params) if err != nil { return nil, err } for _, rule := range resp.Rules { - ruleResp, err := svc.GetRule(&waf.GetRuleInput{ + ruleResp, err := svc.GetRule(ctx, &wafregional.GetRuleInput{ RuleId: rule.RuleId, }) if err != nil { return nil, err } resources = append(resources, &WAFRegionalRule{ - svc: svc, - ID: rule.RuleId, - name: rule.Name, - rule: ruleResp.Rule, + svc: svc, + context: ctx, + ID: rule.RuleId, + name: rule.Name, + rule: ruleResp.Rule, }) } @@ -60,35 +65,37 @@ func ListWAFRegionalRules(sess *session.Session) ([]Resource, error) { func (f *WAFRegionalRule) Remove() error { - tokenOutput, err := f.svc.GetChangeToken(&waf.GetChangeTokenInput{}) + tokenOutput, err := f.svc.GetChangeToken(f.context, &wafregional.GetChangeTokenInput{}) if err != nil { return err } - ruleUpdates := []*waf.RuleUpdate{} + ruleUpdates := []wafregionalTypes.RuleUpdate{} for _, predicate := range f.rule.Predicates { - ruleUpdates = append(ruleUpdates, &waf.RuleUpdate{ - Action: aws.String(waf.ChangeActionDelete), - Predicate: predicate, + ruleUpdates = append(ruleUpdates, wafregionalTypes.RuleUpdate{ + Action: wafregionalTypes.ChangeActionDelete, + Predicate: &predicate, }) } - _, err = f.svc.UpdateRule(&waf.UpdateRuleInput{ - ChangeToken: tokenOutput.ChangeToken, - RuleId: f.ID, - Updates: ruleUpdates, - }) + if len(ruleUpdates) > 0 { + _, err = f.svc.UpdateRule(f.context, &wafregional.UpdateRuleInput{ + ChangeToken: tokenOutput.ChangeToken, + RuleId: f.ID, + Updates: ruleUpdates, + }) - if err != nil { - return err + if err != nil { + return err + } } - tokenOutput, err = f.svc.GetChangeToken(&waf.GetChangeTokenInput{}) + tokenOutput, err = f.svc.GetChangeToken(f.context, &wafregional.GetChangeTokenInput{}) if err != nil { return err } - _, err = f.svc.DeleteRule(&waf.DeleteRuleInput{ + _, err = f.svc.DeleteRule(f.context, &wafregional.DeleteRuleInput{ RuleId: f.ID, ChangeToken: tokenOutput.ChangeToken, })