From 988919d431a3133a67be2c45d3ef15a31c13bb44 Mon Sep 17 00:00:00 2001 From: AJ Date: Fri, 1 Nov 2024 14:02:19 +0000 Subject: [PATCH] change port iam, iam-group, iam-policy, iam-role, iam-service-linked-role to awsSDKv2 #770 --- aws/resources/iam.go | 136 ++++++++------- aws/resources/iam_group.go | 105 +++++------ aws/resources/iam_group_test.go | 99 +++++------ aws/resources/iam_group_types.go | 29 ++- aws/resources/iam_policy.go | 134 +++++++------- aws/resources/iam_policy_test.go | 83 ++++----- aws/resources/iam_policy_types.go | 29 ++- aws/resources/iam_role.go | 67 ++++--- aws/resources/iam_role_test.go | 72 ++++---- aws/resources/iam_role_types.go | 30 +++- aws/resources/iam_service_linked_role.go | 56 +++--- aws/resources/iam_service_linked_role_test.go | 33 ++-- .../iam_service_linked_role_types.go | 26 +-- aws/resources/iam_test.go | 165 +++++++++--------- aws/resources/iam_types.go | 42 ++++- go.mod | 1 + go.sum | 39 +---- util/tag.go | 4 +- v2_migration_report/output.md | 10 +- 19 files changed, 583 insertions(+), 577 deletions(-) diff --git a/aws/resources/iam.go b/aws/resources/iam.go index cd6e0cff..12f069a3 100644 --- a/aws/resources/iam.go +++ b/aws/resources/iam.go @@ -2,30 +2,36 @@ package resources import ( "context" + goerr "errors" "fmt" "time" + "github.com/aws/aws-sdk-go-v2/service/iam/types" + "github.com/gruntwork-io/cloud-nuke/report" "github.com/gruntwork-io/cloud-nuke/util" + "github.com/hashicorp/go-multierror" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/service/iam" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/iam" "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" "github.com/gruntwork-io/go-commons/retry" - "github.com/hashicorp/go-multierror" ) // List all IAM users in the AWS account and returns a slice of the UserNames func (iu *IAMUsers) getAll(c context.Context, configObj config.Config) ([]*string, error) { + var userNames []*string + input := &iam.ListUsersInput{} + paginator := iam.NewListUsersPaginator(iu.Client, input) + for paginator.HasMorePages() { + page, err := paginator.NextPage(c) + if err != nil { + return nil, errors.WithStackTrace(err) + } - var userNames []*string - err := iu.Client.ListUsersPagesWithContext(iu.Context, input, func(page *iam.ListUsersOutput, lastPage bool) bool { for _, user := range page.Users { - // Note : // IAM resource-listing operations return a subset of the available attributes for the resource. // This operation does not return the following attributes, even though they are an attribute of the returned object: @@ -33,13 +39,19 @@ func (iu *IAMUsers) getAll(c context.Context, configObj config.Config) ([]*strin // Tags // Referene : https://docs.aws.amazon.com/cli/latest/reference/iam/list-users.html - var tags []*iam.Tag - iu.Client.ListUserTagsPagesWithContext(iu.Context, &iam.ListUserTagsInput{ + var tags []types.Tag + + tagsPaginator := iam.NewListUserTagsPaginator(iu.Client, &iam.ListUserTagsInput{ UserName: user.UserName, - }, func(page *iam.ListUserTagsOutput, lastPage bool) bool { - tags = append(tags, page.Tags...) - return !lastPage }) + for tagsPaginator.HasMorePages() { + tagsPage, errListTags := tagsPaginator.NextPage(c) + if errListTags != nil { + return nil, errors.WithStackTrace(errListTags) + } + + tags = append(tags, tagsPage.Tags...) + } if configObj.IAMUsers.ShouldInclude(config.ResourceValue{ Name: user.UserName, @@ -49,15 +61,13 @@ func (iu *IAMUsers) getAll(c context.Context, configObj config.Config) ([]*strin userNames = append(userNames, user.UserName) } } + } - return !lastPage - }) - - return userNames, errors.WithStackTrace(err) + return userNames, nil } func (iu *IAMUsers) detachUserPolicies(userName *string) error { - policiesOutput, err := iu.Client.ListAttachedUserPoliciesWithContext(iu.Context, &iam.ListAttachedUserPoliciesInput{ + policiesOutput, err := iu.Client.ListAttachedUserPolicies(iu.Context, &iam.ListAttachedUserPoliciesInput{ UserName: userName, }) if err != nil { @@ -66,7 +76,7 @@ func (iu *IAMUsers) detachUserPolicies(userName *string) error { for _, attachedPolicy := range policiesOutput.AttachedPolicies { arn := attachedPolicy.PolicyArn - _, err = iu.Client.DetachUserPolicyWithContext(iu.Context, &iam.DetachUserPolicyInput{ + _, err = iu.Client.DetachUserPolicy(iu.Context, &iam.DetachUserPolicyInput{ PolicyArn: arn, UserName: userName, }) @@ -74,14 +84,14 @@ func (iu *IAMUsers) detachUserPolicies(userName *string) error { logging.Errorf("[Failed] %s", err) return errors.WithStackTrace(err) } - logging.Debugf("Detached Policy %s from User %s", aws.StringValue(arn), aws.StringValue(userName)) + logging.Debugf("Detached Policy %s from User %s", aws.ToString(arn), aws.ToString(userName)) } return nil } func (iu *IAMUsers) deleteInlineUserPolicies(userName *string) error { - policyOutput, err := iu.Client.ListUserPoliciesWithContext(iu.Context, &iam.ListUserPoliciesInput{ + policyOutput, err := iu.Client.ListUserPolicies(iu.Context, &iam.ListUserPoliciesInput{ UserName: userName, }) if err != nil { @@ -90,22 +100,22 @@ func (iu *IAMUsers) deleteInlineUserPolicies(userName *string) error { } for _, policyName := range policyOutput.PolicyNames { - _, err := iu.Client.DeleteUserPolicyWithContext(iu.Context, &iam.DeleteUserPolicyInput{ - PolicyName: policyName, + _, err := iu.Client.DeleteUserPolicy(iu.Context, &iam.DeleteUserPolicyInput{ + PolicyName: aws.String(policyName), UserName: userName, }) if err != nil { logging.Errorf("[Failed] %s", err) return errors.WithStackTrace(err) } - logging.Debugf("Deleted Inline Policy %s from User %s", aws.StringValue(policyName), aws.StringValue(userName)) + logging.Debugf("Deleted Inline Policy %s from User %s", policyName, aws.ToString(userName)) } return nil } func (iu *IAMUsers) removeUserFromGroups(userName *string) error { - groupsOutput, err := iu.Client.ListGroupsForUserWithContext(iu.Context, &iam.ListGroupsForUserInput{ + groupsOutput, err := iu.Client.ListGroupsForUser(iu.Context, &iam.ListGroupsForUserInput{ UserName: userName, }) if err != nil { @@ -113,7 +123,7 @@ func (iu *IAMUsers) removeUserFromGroups(userName *string) error { } for _, group := range groupsOutput.Groups { - _, err := iu.Client.RemoveUserFromGroupWithContext(iu.Context, &iam.RemoveUserFromGroupInput{ + _, err := iu.Client.RemoveUserFromGroup(iu.Context, &iam.RemoveUserFromGroupInput{ GroupName: group.GroupName, UserName: userName, }) @@ -121,7 +131,7 @@ func (iu *IAMUsers) removeUserFromGroups(userName *string) error { logging.Errorf("[Failed] %s", err) return errors.WithStackTrace(err) } - logging.Debugf("Removed user %s from group %s", aws.StringValue(userName), aws.StringValue(group.GroupName)) + logging.Debugf("Removed user %s from group %s", aws.ToString(userName), aws.ToString(group.GroupName)) } return nil @@ -135,34 +145,36 @@ func (iu *IAMUsers) deleteLoginProfile(userName *string) error { 2*time.Second, func() error { // Delete Login Profile attached to the user - _, err := iu.Client.DeleteLoginProfileWithContext(iu.Context, &iam.DeleteLoginProfileInput{ + _, err := iu.Client.DeleteLoginProfile(iu.Context, &iam.DeleteLoginProfileInput{ UserName: userName, }) if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - case iam.ErrCodeNoSuchEntityException: - // This is expected if the user doesn't have a Login Profile - // (automated users created via API calls withouth further - // configuration) - return nil - case iam.ErrCodeEntityTemporarilyUnmodifiableException: - // The request was rejected because it referenced an entity that is - // temporarily unmodifiable. We have to try again. - return fmt.Errorf("Login Profile for user %s cannot be deleted now", aws.StringValue(userName)) - default: - return retry.FatalError{Underlying: err} - } + var ( + errNoSuchEntityException *types.NoSuchEntityException + errEntityTemporarilyUnmodifiableException *types.EntityTemporarilyUnmodifiableException + ) + switch { + case goerr.As(err, &errNoSuchEntityException): + // This is expected if the user doesn't have a Login Profile + // (automated users created via API calls withouth further + // configuration) + return nil + case goerr.As(err, &errEntityTemporarilyUnmodifiableException): + // The request was rejected because it referenced an entity that is + // temporarily unmodifiable. We have to try again. + return fmt.Errorf("Login Profile for user %s cannot be deleted now", aws.ToString(userName)) + default: + return retry.FatalError{Underlying: err} } } - logging.Debugf("Deleted Login Profile from user %s", aws.StringValue(userName)) + logging.Debugf("Deleted Login Profile from user %s", aws.ToString(userName)) return nil }) } func (iu *IAMUsers) deleteAccessKeys(userName *string) error { - output, err := iu.Client.ListAccessKeysWithContext(iu.Context, &iam.ListAccessKeysInput{ + output, err := iu.Client.ListAccessKeys(iu.Context, &iam.ListAccessKeysInput{ UserName: userName, }) if err != nil { @@ -172,7 +184,7 @@ func (iu *IAMUsers) deleteAccessKeys(userName *string) error { for _, md := range output.AccessKeyMetadata { accessKeyId := md.AccessKeyId - _, err := iu.Client.DeleteAccessKeyWithContext(iu.Context, &iam.DeleteAccessKeyInput{ + _, err := iu.Client.DeleteAccessKey(iu.Context, &iam.DeleteAccessKeyInput{ AccessKeyId: accessKeyId, UserName: userName, }) @@ -181,14 +193,14 @@ func (iu *IAMUsers) deleteAccessKeys(userName *string) error { return errors.WithStackTrace(err) } - logging.Debugf("Deleted Access Key %s from user %s", aws.StringValue(accessKeyId), aws.StringValue(userName)) + logging.Debugf("Deleted Access Key %s from user %s", aws.ToString(accessKeyId), aws.ToString(userName)) } return nil } func (iu *IAMUsers) deleteSigningCertificate(userName *string) error { - output, err := iu.Client.ListSigningCertificatesWithContext(iu.Context, &iam.ListSigningCertificatesInput{ + output, err := iu.Client.ListSigningCertificates(iu.Context, &iam.ListSigningCertificatesInput{ UserName: userName, }) if err != nil { @@ -198,7 +210,7 @@ func (iu *IAMUsers) deleteSigningCertificate(userName *string) error { for _, cert := range output.Certificates { certificateId := cert.CertificateId - _, err := iu.Client.DeleteSigningCertificateWithContext(iu.Context, &iam.DeleteSigningCertificateInput{ + _, err := iu.Client.DeleteSigningCertificate(iu.Context, &iam.DeleteSigningCertificateInput{ CertificateId: certificateId, UserName: userName, }) @@ -207,14 +219,14 @@ func (iu *IAMUsers) deleteSigningCertificate(userName *string) error { return errors.WithStackTrace(err) } - logging.Debugf("Deleted Signing Certificate ID %s from user %s", aws.StringValue(certificateId), aws.StringValue(userName)) + logging.Debugf("Deleted Signing Certificate ID %s from user %s", aws.ToString(certificateId), aws.ToString(userName)) } return nil } func (iu *IAMUsers) deleteSSHPublicKeys(userName *string) error { - output, err := iu.Client.ListSSHPublicKeysWithContext(iu.Context, &iam.ListSSHPublicKeysInput{ + output, err := iu.Client.ListSSHPublicKeys(iu.Context, &iam.ListSSHPublicKeysInput{ UserName: userName, }) if err != nil { @@ -224,7 +236,7 @@ func (iu *IAMUsers) deleteSSHPublicKeys(userName *string) error { for _, key := range output.SSHPublicKeys { keyId := key.SSHPublicKeyId - _, err := iu.Client.DeleteSSHPublicKeyWithContext(iu.Context, &iam.DeleteSSHPublicKeyInput{ + _, err := iu.Client.DeleteSSHPublicKey(iu.Context, &iam.DeleteSSHPublicKeyInput{ SSHPublicKeyId: keyId, UserName: userName, }) @@ -233,7 +245,7 @@ func (iu *IAMUsers) deleteSSHPublicKeys(userName *string) error { return errors.WithStackTrace(err) } - logging.Debugf("Deleted SSH Public Key with ID %s from user %s", aws.StringValue(keyId), aws.StringValue(userName)) + logging.Debugf("Deleted SSH Public Key with ID %s from user %s", aws.ToString(keyId), aws.ToString(userName)) } return nil @@ -245,7 +257,7 @@ func (iu *IAMUsers) deleteServiceSpecificCredentials(userName *string) error { "codecommit.amazonaws.com", } for _, service := range services { - output, err := iu.Client.ListServiceSpecificCredentialsWithContext(iu.Context, &iam.ListServiceSpecificCredentialsInput{ + output, err := iu.Client.ListServiceSpecificCredentials(iu.Context, &iam.ListServiceSpecificCredentialsInput{ ServiceName: aws.String(service), UserName: userName, }) @@ -257,7 +269,7 @@ func (iu *IAMUsers) deleteServiceSpecificCredentials(userName *string) error { for _, metadata := range output.ServiceSpecificCredentials { serviceSpecificCredentialId := metadata.ServiceSpecificCredentialId - _, err := iu.Client.DeleteServiceSpecificCredentialWithContext(iu.Context, &iam.DeleteServiceSpecificCredentialInput{ + _, err := iu.Client.DeleteServiceSpecificCredential(iu.Context, &iam.DeleteServiceSpecificCredentialInput{ ServiceSpecificCredentialId: serviceSpecificCredentialId, UserName: userName, }) @@ -266,7 +278,7 @@ func (iu *IAMUsers) deleteServiceSpecificCredentials(userName *string) error { return errors.WithStackTrace(err) } - logging.Debugf("Deleted Service Specific Credential with ID %s of service %s from user %s", aws.StringValue(serviceSpecificCredentialId), service, aws.StringValue(userName)) + logging.Debugf("Deleted Service Specific Credential with ID %s of service %s from user %s", aws.ToString(serviceSpecificCredentialId), service, aws.ToString(userName)) } } @@ -274,7 +286,7 @@ func (iu *IAMUsers) deleteServiceSpecificCredentials(userName *string) error { } func (iu *IAMUsers) deleteMFADevices(userName *string) error { - output, err := iu.Client.ListMFADevicesWithContext(iu.Context, &iam.ListMFADevicesInput{ + output, err := iu.Client.ListMFADevices(iu.Context, &iam.ListMFADevicesInput{ UserName: userName, }) if err != nil { @@ -286,7 +298,7 @@ func (iu *IAMUsers) deleteMFADevices(userName *string) error { for _, device := range output.MFADevices { serialNumber := device.SerialNumber - _, err := iu.Client.DeactivateMFADeviceWithContext(iu.Context, &iam.DeactivateMFADeviceInput{ + _, err := iu.Client.DeactivateMFADevice(iu.Context, &iam.DeactivateMFADeviceInput{ SerialNumber: serialNumber, UserName: userName, }) @@ -295,14 +307,14 @@ func (iu *IAMUsers) deleteMFADevices(userName *string) error { return errors.WithStackTrace(err) } - logging.Debugf("Deactivated Virtual MFA Device with ID %s from user %s", aws.StringValue(serialNumber), aws.StringValue(userName)) + logging.Debugf("Deactivated Virtual MFA Device with ID %s from user %s", aws.ToString(serialNumber), aws.ToString(userName)) } // After their deactivation we can delete them for _, device := range output.MFADevices { serialNumber := device.SerialNumber - _, err := iu.Client.DeleteVirtualMFADeviceWithContext(iu.Context, &iam.DeleteVirtualMFADeviceInput{ + _, err := iu.Client.DeleteVirtualMFADevice(iu.Context, &iam.DeleteVirtualMFADeviceInput{ SerialNumber: serialNumber, }) if err != nil { @@ -310,14 +322,14 @@ func (iu *IAMUsers) deleteMFADevices(userName *string) error { return errors.WithStackTrace(err) } - logging.Debugf("Deleted Virtual MFA Device with ID %s from user %s", aws.StringValue(serialNumber), aws.StringValue(userName)) + logging.Debugf("Deleted Virtual MFA Device with ID %s from user %s", aws.ToString(serialNumber), aws.ToString(userName)) } return nil } func (iu *IAMUsers) deleteUser(userName *string) error { - _, err := iu.Client.DeleteUserWithContext(iu.Context, &iam.DeleteUserInput{ + _, err := iu.Client.DeleteUser(iu.Context, &iam.DeleteUserInput{ UserName: userName, }) if err != nil { @@ -371,7 +383,7 @@ func (iu *IAMUsers) nukeAll(userNames []*string) error { err := iu.nukeUser(userName) // Record status of this resource e := report.Entry{ - Identifier: aws.StringValue(userName), + Identifier: aws.ToString(userName), ResourceType: "IAM User", Error: err, } diff --git a/aws/resources/iam_group.go b/aws/resources/iam_group.go index 96caa378..345a7e4b 100644 --- a/aws/resources/iam_group.go +++ b/aws/resources/iam_group.go @@ -4,8 +4,8 @@ import ( "context" "sync" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/iam" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/iam" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" "github.com/gruntwork-io/cloud-nuke/report" @@ -15,23 +15,21 @@ import ( func (ig *IAMGroups) getAll(c context.Context, configObj config.Config) ([]*string, error) { var allIamGroups []*string - err := ig.Client.ListGroupsPagesWithContext( - ig.Context, - &iam.ListGroupsInput{}, - func(page *iam.ListGroupsOutput, lastPage bool) bool { - for _, iamGroup := range page.Groups { - if configObj.IAMGroups.ShouldInclude(config.ResourceValue{ - Time: iamGroup.CreateDate, - Name: iamGroup.GroupName, - }) { - allIamGroups = append(allIamGroups, iamGroup.GroupName) - } + paginator := iam.NewListGroupsPaginator(ig.Client, &iam.ListGroupsInput{}) + for paginator.HasMorePages() { + page, err := paginator.NextPage(c) + if err != nil { + return nil, errors.WithStackTrace(err) + } + + for _, iamGroup := range page.Groups { + if configObj.IAMGroups.ShouldInclude(config.ResourceValue{ + Time: iamGroup.CreateDate, + Name: iamGroup.GroupName, + }) { + allIamGroups = append(allIamGroups, iamGroup.GroupName) } - return !lastPage - }, - ) - if err != nil { - return nil, errors.WithStackTrace(err) + } } return allIamGroups, nil @@ -44,13 +42,13 @@ func (ig *IAMGroups) nukeAll(groupNames []*string) error { return nil } - //Probably not required since pagination is handled by the caller + // Probably not required since pagination is handled by the caller if len(groupNames) > 100 { logging.Errorf("Nuking too many IAM Groups at once (100): Halting to avoid rate limits") return TooManyIamGroupErr{} } - //No bulk delete exists, do it with goroutines + // No bulk delete exists, do it with goroutines logging.Debug("Deleting all IAM Groups") wg := new(sync.WaitGroup) wg.Add(len(groupNames)) @@ -61,7 +59,7 @@ func (ig *IAMGroups) nukeAll(groupNames []*string) error { } wg.Wait() - //Collapse the errors down to one + // Collapse the errors down to one var allErrs *multierror.Error for _, errChan := range errChans { if err := <-errChan; err != nil { @@ -82,71 +80,80 @@ func (ig *IAMGroups) deleteAsync(wg *sync.WaitGroup, errChan chan error, groupNa defer wg.Done() var multierr *multierror.Error - //Remove any users from the group + // Remove any users from the group getGroupInput := &iam.GetGroupInput{ GroupName: groupName, } - grp, err := ig.Client.GetGroupWithContext(ig.Context, getGroupInput) + grp, err := ig.Client.GetGroup(ig.Context, getGroupInput) for _, user := range grp.Users { unlinkUserInput := &iam.RemoveUserFromGroupInput{ UserName: user.UserName, GroupName: groupName, } - _, err := ig.Client.RemoveUserFromGroupWithContext(ig.Context, unlinkUserInput) + _, err := ig.Client.RemoveUserFromGroup(ig.Context, unlinkUserInput) if err != nil { multierr = multierror.Append(multierr, err) } } - //Detach any policies on the group - allPolicies := []*string{} - err = ig.Client.ListAttachedGroupPoliciesPagesWithContext(ig.Context, &iam.ListAttachedGroupPoliciesInput{GroupName: groupName}, - func(page *iam.ListAttachedGroupPoliciesOutput, lastPage bool) bool { - for _, iamPolicy := range page.AttachedPolicies { - allPolicies = append(allPolicies, iamPolicy.PolicyArn) - } - return !lastPage - }, - ) + // Detach any policies on the group + var allPolicies []*string + paginator := iam.NewListAttachedGroupPoliciesPaginator(ig.Client, &iam.ListAttachedGroupPoliciesInput{GroupName: groupName}) + for paginator.HasMorePages() { + page, err := paginator.NextPage(ig.Context) + if err != nil { + multierr = multierror.Append(multierr, err) + break + } + + for _, iamPolicy := range page.AttachedPolicies { + allPolicies = append(allPolicies, iamPolicy.PolicyArn) + } + } for _, policy := range allPolicies { unlinkPolicyInput := &iam.DetachGroupPolicyInput{ GroupName: groupName, PolicyArn: policy, } - _, err = ig.Client.DetachGroupPolicyWithContext(ig.Context, unlinkPolicyInput) + _, err = ig.Client.DetachGroupPolicy(ig.Context, unlinkPolicyInput) } // Detach any inline policies on the group - allInlinePolicyNames := []*string{} - err = ig.Client.ListGroupPoliciesPagesWithContext(ig.Context, &iam.ListGroupPoliciesInput{GroupName: groupName}, - func(page *iam.ListGroupPoliciesOutput, lastPage bool) bool { - for _, policyName := range page.PolicyNames { - allInlinePolicyNames = append(allInlinePolicyNames, policyName) - } - return !lastPage - }, - ) + var allInlinePolicyNames []*string + + policiesPaginator := iam.NewListGroupPoliciesPaginator(ig.Client, &iam.ListGroupPoliciesInput{GroupName: groupName}) + for policiesPaginator.HasMorePages() { + page, err := policiesPaginator.NextPage(ig.Context) + if err != nil { + multierr = multierror.Append(multierr, err) + break + } + + for _, policyName := range page.PolicyNames { + allInlinePolicyNames = append(allInlinePolicyNames, aws.String(policyName)) + } + } for _, policyName := range allInlinePolicyNames { - _, err = ig.Client.DeleteGroupPolicyWithContext(ig.Context, &iam.DeleteGroupPolicyInput{ + _, err = ig.Client.DeleteGroupPolicy(ig.Context, &iam.DeleteGroupPolicyInput{ GroupName: groupName, PolicyName: policyName, }) } - //Delete the group - _, err = ig.Client.DeleteGroupWithContext(ig.Context, &iam.DeleteGroupInput{ + // Delete the group + _, err = ig.Client.DeleteGroup(ig.Context, &iam.DeleteGroupInput{ GroupName: groupName, }) if err != nil { multierr = multierror.Append(multierr, err) } else { - logging.Debugf("[OK] IAM Group %s was deleted in global", aws.StringValue(groupName)) + logging.Debugf("[OK] IAM Group %s was deleted in global", aws.ToString(groupName)) } e := report.Entry{ - Identifier: aws.StringValue(groupName), + Identifier: aws.ToString(groupName), ResourceType: "IAM Group", Error: multierr.ErrorOrNil(), } diff --git a/aws/resources/iam_group_test.go b/aws/resources/iam_group_test.go index 4f03f7d5..7dae9f36 100644 --- a/aws/resources/iam_group_test.go +++ b/aws/resources/iam_group_test.go @@ -6,84 +6,73 @@ import ( "testing" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/service/iam/iamiface" - - awsgo "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/iam" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/iam" + "github.com/aws/aws-sdk-go-v2/service/iam/types" "github.com/gruntwork-io/cloud-nuke/config" "github.com/stretchr/testify/require" ) type mockedIAMGroups struct { - iamiface.IAMAPI - ListGroupsPagesOutput iam.ListGroupsOutput - GetGroupOutput iam.GetGroupOutput - RemoveUserFromGroupOutput iam.RemoveUserFromGroupOutput - DeleteGroupOutput iam.DeleteGroupOutput - ListAttachedGroupPoliciesPagesOutput iam.ListAttachedGroupPoliciesOutput - DetachGroupPolicyOutput iam.DetachGroupPolicyOutput - ListGroupPoliciesOutput iam.ListGroupPoliciesOutput - DeleteGroupPolicyOutput iam.DeleteGroupPolicyOutput + IAMGroupsAPI + DetachGroupPolicyOutput iam.DetachGroupPolicyOutput + DeleteGroupPolicyOutput iam.DeleteGroupPolicyOutput + DeleteGroupOutput iam.DeleteGroupOutput + GetGroupOutput iam.GetGroupOutput + ListAttachedGroupPoliciesOutput iam.ListAttachedGroupPoliciesOutput + ListGroupsOutput iam.ListGroupsOutput + ListGroupPoliciesOutput iam.ListGroupPoliciesOutput + RemoveUserFromGroupOutput iam.RemoveUserFromGroupOutput } -func (m mockedIAMGroups) ListGroupsPagesWithContext( - _ aws.Context, input *iam.ListGroupsInput, fn func(*iam.ListGroupsOutput, bool) bool, _ ...request.Option) error { - fn(&m.ListGroupsPagesOutput, true) - return nil +func (m mockedIAMGroups) DetachGroupPolicy(ctx context.Context, params *iam.DetachGroupPolicyInput, optFns ...func(*iam.Options)) (*iam.DetachGroupPolicyOutput, error) { + return &m.DetachGroupPolicyOutput, nil } -func (m mockedIAMGroups) DeleteGroupWithContext(_ aws.Context, input *iam.DeleteGroupInput, _ ...request.Option) (*iam.DeleteGroupOutput, error) { - return &m.DeleteGroupOutput, nil +func (m mockedIAMGroups) DeleteGroupPolicy(ctx context.Context, params *iam.DeleteGroupPolicyInput, optFns ...func(*iam.Options)) (*iam.DeleteGroupPolicyOutput, error) { + return &m.DeleteGroupPolicyOutput, nil } -func (m mockedIAMGroups) ListAttachedGroupPoliciesPagesWithContext( - _ aws.Context, input *iam.ListAttachedGroupPoliciesInput, fn func(*iam.ListAttachedGroupPoliciesOutput, bool) bool, _ ...request.Option) error { - fn(&m.ListAttachedGroupPoliciesPagesOutput, true) - return nil +func (m mockedIAMGroups) DeleteGroup(ctx context.Context, params *iam.DeleteGroupInput, optFns ...func(*iam.Options)) (*iam.DeleteGroupOutput, error) { + return &m.DeleteGroupOutput, nil } -func (m mockedIAMGroups) ListGroupPoliciesPagesWithContext( - _ aws.Context, input *iam.ListGroupPoliciesInput, fn func(*iam.ListGroupPoliciesOutput, bool) bool, _ ...request.Option) error { - fn(&m.ListGroupPoliciesOutput, true) - return nil +func (m mockedIAMGroups) GetGroup(ctx context.Context, params *iam.GetGroupInput, optFns ...func(*iam.Options)) (*iam.GetGroupOutput, error) { + return &m.GetGroupOutput, nil } -func (m mockedIAMGroups) DetachGroupPolicyWithContext(_ aws.Context, input *iam.DetachGroupPolicyInput, _ ...request.Option) (*iam.DetachGroupPolicyOutput, error) { - return &m.DetachGroupPolicyOutput, nil +func (m mockedIAMGroups) ListAttachedGroupPolicies(ctx context.Context, params *iam.ListAttachedGroupPoliciesInput, optFns ...func(*iam.Options)) (*iam.ListAttachedGroupPoliciesOutput, error) { + return &m.ListAttachedGroupPoliciesOutput, nil } -func (m mockedIAMGroups) DeleteGroupPolicyWithContext(_ aws.Context, input *iam.DeleteGroupPolicyInput, _ ...request.Option) (*iam.DeleteGroupPolicyOutput, error) { - return &m.DeleteGroupPolicyOutput, nil +func (m mockedIAMGroups) ListGroups(ctx context.Context, params *iam.ListGroupsInput, optFns ...func(*iam.Options)) (*iam.ListGroupsOutput, error) { + return &m.ListGroupsOutput, nil } -func (m mockedIAMGroups) GetGroupWithContext(_ aws.Context, input *iam.GetGroupInput, _ ...request.Option) (*iam.GetGroupOutput, error) { - return &m.GetGroupOutput, nil +func (m mockedIAMGroups) ListGroupPolicies(ctx context.Context, params *iam.ListGroupPoliciesInput, optFns ...func(*iam.Options)) (*iam.ListGroupPoliciesOutput, error) { + return &m.ListGroupPoliciesOutput, nil } -func (m mockedIAMGroups) RemoveUserFromGroupWithContext(_ aws.Context, input *iam.RemoveUserFromGroupInput, _ ...request.Option) (*iam.RemoveUserFromGroupOutput, error) { +func (m mockedIAMGroups) RemoveUserFromGroup(ctx context.Context, params *iam.RemoveUserFromGroupInput, optFns ...func(*iam.Options)) (*iam.RemoveUserFromGroupOutput, error) { return &m.RemoveUserFromGroupOutput, nil } func TestIamGroups_GetAll(t *testing.T) { - t.Parallel() - testName1 := "group1" testName2 := "group2" now := time.Now() ig := IAMGroups{ Client: mockedIAMGroups{ - ListGroupsPagesOutput: iam.ListGroupsOutput{ - Groups: []*iam.Group{ + ListGroupsOutput: iam.ListGroupsOutput{ + Groups: []types.Group{ { - GroupName: awsgo.String(testName1), - CreateDate: awsgo.Time(now), + GroupName: aws.String(testName1), + CreateDate: aws.Time(now), }, { - GroupName: awsgo.String(testName2), - CreateDate: awsgo.Time(now.Add(1)), + GroupName: aws.String(testName2), + CreateDate: aws.Time(now.Add(1)), }, }, }, @@ -110,7 +99,7 @@ func TestIamGroups_GetAll(t *testing.T) { "timeAfterExclusionFilter": { configObj: config.ResourceType{ ExcludeRule: config.FilterRule{ - TimeAfter: awsgo.Time(now), + TimeAfter: aws.Time(now), }}, expected: []string{testName1}, }, @@ -121,36 +110,34 @@ func TestIamGroups_GetAll(t *testing.T) { IAMGroups: tc.configObj, }) require.NoError(t, err) - require.Equal(t, tc.expected, awsgo.StringValueSlice(names)) + require.Equal(t, tc.expected, aws.ToStringSlice(names)) }) } } func TestIamGroups_NukeAll(t *testing.T) { - t.Parallel() - ig := IAMGroups{ Client: mockedIAMGroups{ GetGroupOutput: iam.GetGroupOutput{ - Users: []*iam.User{ + Users: []types.User{ { - UserName: awsgo.String("user1"), + UserName: aws.String("user1"), }, }, }, RemoveUserFromGroupOutput: iam.RemoveUserFromGroupOutput{}, - ListAttachedGroupPoliciesPagesOutput: iam.ListAttachedGroupPoliciesOutput{ - AttachedPolicies: []*iam.AttachedPolicy{ + ListAttachedGroupPoliciesOutput: iam.ListAttachedGroupPoliciesOutput{ + AttachedPolicies: []types.AttachedPolicy{ { - PolicyName: awsgo.String("policy1"), + PolicyName: aws.String("policy1"), }, }, }, DetachGroupPolicyOutput: iam.DetachGroupPolicyOutput{}, ListGroupPoliciesOutput: iam.ListGroupPoliciesOutput{ - PolicyNames: []*string{ - awsgo.String("policy2"), + PolicyNames: []string{ + "policy2", }, }, DeleteGroupPolicyOutput: iam.DeleteGroupPolicyOutput{}, @@ -158,6 +145,6 @@ func TestIamGroups_NukeAll(t *testing.T) { }, } - err := ig.nukeAll([]*string{awsgo.String("group1")}) + err := ig.nukeAll([]*string{aws.String("group1")}) require.NoError(t, err) } diff --git a/aws/resources/iam_group_types.go b/aws/resources/iam_group_types.go index bb0eaa99..7d5a9ed4 100644 --- a/aws/resources/iam_group_types.go +++ b/aws/resources/iam_group_types.go @@ -3,25 +3,36 @@ package resources import ( "context" - awsgo "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/iam" - "github.com/aws/aws-sdk-go/service/iam/iamiface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/iam" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/go-commons/errors" ) +type IAMGroupsAPI interface { + DetachGroupPolicy(ctx context.Context, params *iam.DetachGroupPolicyInput, optFns ...func(*iam.Options)) (*iam.DetachGroupPolicyOutput, error) + DeleteGroupPolicy(ctx context.Context, params *iam.DeleteGroupPolicyInput, optFns ...func(*iam.Options)) (*iam.DeleteGroupPolicyOutput, error) + DeleteGroup(ctx context.Context, params *iam.DeleteGroupInput, optFns ...func(*iam.Options)) (*iam.DeleteGroupOutput, error) + GetGroup(ctx context.Context, params *iam.GetGroupInput, optFns ...func(*iam.Options)) (*iam.GetGroupOutput, error) + ListAttachedGroupPolicies(ctx context.Context, params *iam.ListAttachedGroupPoliciesInput, optFns ...func(*iam.Options)) (*iam.ListAttachedGroupPoliciesOutput, error) + ListGroups(ctx context.Context, params *iam.ListGroupsInput, optFns ...func(*iam.Options)) (*iam.ListGroupsOutput, error) + ListGroupPolicies(ctx context.Context, params *iam.ListGroupPoliciesInput, optFns ...func(*iam.Options)) (*iam.ListGroupPoliciesOutput, error) + RemoveUserFromGroup(ctx context.Context, params *iam.RemoveUserFromGroupInput, optFns ...func(*iam.Options)) (*iam.RemoveUserFromGroupOutput, error) +} + // IAMGroups - represents all IAMGroups on the AWS Account type IAMGroups struct { BaseAwsResource - Client iamiface.IAMAPI + Client IAMGroupsAPI GroupNames []string } -func (ig *IAMGroups) Init(session *session.Session) { - ig.Client = iam.New(session) +func (ig *IAMGroups) InitV2(cfg aws.Config) { + ig.Client = iam.NewFromConfig(cfg) } +func (ig *IAMGroups) IsUsingV2() bool { return true } + // ResourceName - the simple name of the AWS resource func (ig *IAMGroups) ResourceName() string { return "iam-group" @@ -48,13 +59,13 @@ func (ig *IAMGroups) GetAndSetIdentifiers(c context.Context, configObj config.Co return nil, err } - ig.GroupNames = awsgo.StringValueSlice(identifiers) + ig.GroupNames = aws.ToStringSlice(identifiers) return ig.GroupNames, nil } // Nuke - Destroy every group in this collection func (ig *IAMGroups) Nuke(identifiers []string) error { - if err := ig.nukeAll(awsgo.StringSlice(identifiers)); err != nil { + if err := ig.nukeAll(aws.StringSlice(identifiers)); err != nil { return errors.WithStackTrace(err) } diff --git a/aws/resources/iam_policy.go b/aws/resources/iam_policy.go index 02574a3d..461514d1 100644 --- a/aws/resources/iam_policy.go +++ b/aws/resources/iam_policy.go @@ -4,8 +4,9 @@ import ( "context" "sync" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/iam" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/iam" + "github.com/aws/aws-sdk-go-v2/service/iam/types" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" "github.com/gruntwork-io/cloud-nuke/report" @@ -16,25 +17,21 @@ import ( // Returns the ARN of all customer managed policies func (ip *IAMPolicies) getAll(c context.Context, configObj config.Config) ([]*string, error) { var allIamPolicies []*string + paginator := iam.NewListPoliciesPaginator(ip.Client, &iam.ListPoliciesInput{Scope: types.PolicyScopeTypeLocal}) + for paginator.HasMorePages() { + page, err := paginator.NextPage(c) + if err != nil { + return nil, errors.WithStackTrace(err) + } - err := ip.Client.ListPoliciesPagesWithContext( - ip.Context, - &iam.ListPoliciesInput{Scope: aws.String(iam.PolicyScopeTypeLocal)}, - func(page *iam.ListPoliciesOutput, lastPage bool) bool { - for _, policy := range page.Policies { - if configObj.IAMPolicies.ShouldInclude(config.ResourceValue{ - Name: policy.PolicyName, - Time: policy.CreateDate, - }) { - allIamPolicies = append(allIamPolicies, policy.Arn) - } + for _, policy := range page.Policies { + if configObj.IAMPolicies.ShouldInclude(config.ResourceValue{ + Name: policy.PolicyName, + Time: policy.CreateDate, + }) { + allIamPolicies = append(allIamPolicies, policy.Arn) } - - return !lastPage - }, - ) - if err != nil { - return nil, errors.WithStackTrace(err) + } } return allIamPolicies, nil @@ -46,13 +43,13 @@ func (ip *IAMPolicies) nukeAll(policyArns []*string) error { logging.Debug("No IAM Policies to nuke") } - //Probably not required since pagination is handled by the caller + // Probably not required since pagination is handled by the caller if len(policyArns) > 100 { logging.Errorf("Nuking too many IAM Policies at once (100): Halting to avoid rate limits") return TooManyIamPolicyErr{} } - //No Bulk Delete exists, do it with goroutines + // No Bulk Delete exists, do it with goroutines logging.Debug("Deleting all IAM Policies") wg := new(sync.WaitGroup) wg.Add(len(policyArns)) @@ -63,7 +60,7 @@ func (ip *IAMPolicies) nukeAll(policyArns []*string) error { } wg.Wait() - //Collapse the errors down to one + // Collapse the errors down to one var allErrs *multierror.Error for _, errChan := range errChans { if err := <-errChan; err != nil { @@ -84,44 +81,46 @@ func (ip *IAMPolicies) deleteIamPolicyAsync(wg *sync.WaitGroup, errChan chan err defer wg.Done() var multierr *multierror.Error - //Detach any entities the policy is attached to + // Detach any entities the policy is attached to err := ip.detachPolicyEntities(policyArn) if err != nil { multierr = multierror.Append(multierr, err) } - //Get Old Policy Versions + // Get Old Policy Versions var versionsToRemove []*string - err = ip.Client.ListPolicyVersionsPagesWithContext(ip.Context, &iam.ListPolicyVersionsInput{PolicyArn: policyArn}, - func(page *iam.ListPolicyVersionsOutput, lastPage bool) bool { - for _, policyVersion := range page.Versions { - if !*policyVersion.IsDefaultVersion { - versionsToRemove = append(versionsToRemove, policyVersion.VersionId) - } + paginator := iam.NewListPolicyVersionsPaginator(ip.Client, &iam.ListPolicyVersionsInput{PolicyArn: policyArn}) + for paginator.HasMorePages() { + page, err := paginator.NextPage(context.Background()) + if err != nil { + multierr = multierror.Append(multierr, err) + break + } + + for _, policyVersion := range page.Versions { + if !policyVersion.IsDefaultVersion { + versionsToRemove = append(versionsToRemove, policyVersion.VersionId) } - return !lastPage - }) - if err != nil { - multierr = multierror.Append(multierr, err) + } } - //Delete old policy versions + // Delete old policy versions for _, versionId := range versionsToRemove { - _, err = ip.Client.DeletePolicyVersionWithContext(ip.Context, &iam.DeletePolicyVersionInput{VersionId: versionId, PolicyArn: policyArn}) + _, err = ip.Client.DeletePolicyVersion(ip.Context, &iam.DeletePolicyVersionInput{VersionId: versionId, PolicyArn: policyArn}) if err != nil { multierr = multierror.Append(multierr, err) } } - //Delete the policy - _, err = ip.Client.DeletePolicyWithContext(ip.Context, &iam.DeletePolicyInput{PolicyArn: policyArn}) + // Delete the policy + _, err = ip.Client.DeletePolicy(ip.Context, &iam.DeletePolicyInput{PolicyArn: policyArn}) if err != nil { multierr = multierror.Append(multierr, err) } else { - logging.Debugf("[OK] IAM Policy %s was deleted in global", aws.StringValue(policyArn)) + logging.Debugf("[OK] IAM Policy %s was deleted in global", aws.ToString(policyArn)) } e := report.Entry{ - Identifier: aws.StringValue(policyArn), + Identifier: aws.ToString(policyArn), ResourceType: "IAM Policy", Error: multierr.ErrorOrNil(), } @@ -134,57 +133,60 @@ func (ip *IAMPolicies) detachPolicyEntities(policyArn *string) error { var allPolicyGroups []*string var allPolicyRoles []*string var allPolicyUsers []*string - err := ip.Client.ListEntitiesForPolicyPagesWithContext(ip.Context, &iam.ListEntitiesForPolicyInput{PolicyArn: policyArn}, - func(page *iam.ListEntitiesForPolicyOutput, lastPage bool) bool { - for _, group := range page.PolicyGroups { - allPolicyGroups = append(allPolicyGroups, group.GroupName) - } - for _, role := range page.PolicyRoles { - allPolicyRoles = append(allPolicyRoles, role.RoleName) - } - for _, user := range page.PolicyUsers { - allPolicyUsers = append(allPolicyUsers, user.UserName) - } - return !lastPage - }, - ) - if err != nil { - return err + + paginator := iam.NewListEntitiesForPolicyPaginator(ip.Client, &iam.ListEntitiesForPolicyInput{PolicyArn: policyArn}) + for paginator.HasMorePages() { + page, err := paginator.NextPage(ip.Context) + if err != nil { + return errors.WithStackTrace(err) + } + + for _, group := range page.PolicyGroups { + allPolicyGroups = append(allPolicyGroups, group.GroupName) + } + for _, role := range page.PolicyRoles { + allPolicyRoles = append(allPolicyRoles, role.RoleName) + } + for _, user := range page.PolicyUsers { + allPolicyUsers = append(allPolicyUsers, user.UserName) + } } - //Detach policy from any users + + // Detach policy from any users for _, userName := range allPolicyUsers { detachUserInput := &iam.DetachUserPolicyInput{ UserName: userName, PolicyArn: policyArn, } - _, err = ip.Client.DetachUserPolicyWithContext(ip.Context, detachUserInput) + _, err := ip.Client.DetachUserPolicy(ip.Context, detachUserInput) if err != nil { - return err + return errors.WithStackTrace(err) } } - //Detach policy from any groups + // Detach policy from any groups for _, groupName := range allPolicyGroups { detachGroupInput := &iam.DetachGroupPolicyInput{ GroupName: groupName, PolicyArn: policyArn, } - _, err = ip.Client.DetachGroupPolicyWithContext(ip.Context, detachGroupInput) + _, err := ip.Client.DetachGroupPolicy(ip.Context, detachGroupInput) if err != nil { - return err + return errors.WithStackTrace(err) } } - //Detach policy from any roles + // Detach policy from any roles for _, roleName := range allPolicyRoles { detachRoleInput := &iam.DetachRolePolicyInput{ RoleName: roleName, PolicyArn: policyArn, } - _, err = ip.Client.DetachRolePolicyWithContext(ip.Context, detachRoleInput) + _, err := ip.Client.DetachRolePolicy(ip.Context, detachRoleInput) if err != nil { - return err + return errors.WithStackTrace(err) } } - return err + + return nil } // TooManyIamPolicyErr Custom Errors diff --git a/aws/resources/iam_policy_test.go b/aws/resources/iam_policy_test.go index 5ab07b74..a4ba17a3 100644 --- a/aws/resources/iam_policy_test.go +++ b/aws/resources/iam_policy_test.go @@ -6,69 +6,59 @@ import ( "testing" "time" + "github.com/aws/aws-sdk-go-v2/service/iam" + "github.com/aws/aws-sdk-go-v2/service/iam/types" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/service/iam" - "github.com/aws/aws-sdk-go/service/iam/iamiface" "github.com/gruntwork-io/cloud-nuke/config" "github.com/stretchr/testify/require" ) type mockedIAMPolicies struct { - iamiface.IAMAPI - ListPoliciesPagesOutput iam.ListPoliciesOutput - - ListEntitiesForPolicyPagesOutput iam.ListEntitiesForPolicyOutput - DetachUserPolicyOutput iam.DetachUserPolicyOutput - DetachGroupPolicyOutput iam.DetachGroupPolicyOutput - DetachRolePolicyOutput iam.DetachRolePolicyOutput - ListPolicyVersionsPagesOutput iam.ListPolicyVersionsOutput - DeletePolicyVersionOutput iam.DeletePolicyVersionOutput - DeletePolicyOutput iam.DeletePolicyOutput + IAMPoliciesAPI + ListEntitiesForPolicyOutput iam.ListEntitiesForPolicyOutput + ListPoliciesOutput iam.ListPoliciesOutput + ListPolicyVersionsOutput iam.ListPolicyVersionsOutput + DeletePolicyOutput iam.DeletePolicyOutput + DeletePolicyVersionOutput iam.DeletePolicyVersionOutput + DetachGroupPolicyOutput iam.DetachGroupPolicyOutput + DetachUserPolicyOutput iam.DetachUserPolicyOutput + DetachRolePolicyOutput iam.DetachRolePolicyOutput } -func (m mockedIAMPolicies) ListPoliciesPagesWithContext( - _ aws.Context, input *iam.ListPoliciesInput, fn func(*iam.ListPoliciesOutput, bool) bool, _ ...request.Option) error { - fn(&m.ListPoliciesPagesOutput, true) - return nil +func (m mockedIAMPolicies) ListEntitiesForPolicy(ctx context.Context, params *iam.ListEntitiesForPolicyInput, optFns ...func(*iam.Options)) (*iam.ListEntitiesForPolicyOutput, error) { + return &m.ListEntitiesForPolicyOutput, nil } -func (m mockedIAMPolicies) ListEntitiesForPolicyPagesWithContext( - _ aws.Context, input *iam.ListEntitiesForPolicyInput, fn func(*iam.ListEntitiesForPolicyOutput, bool) bool, _ ...request.Option) error { - fn(&m.ListEntitiesForPolicyPagesOutput, true) - return nil +func (m mockedIAMPolicies) ListPolicies(ctx context.Context, params *iam.ListPoliciesInput, optFns ...func(*iam.Options)) (*iam.ListPoliciesOutput, error) { + return &m.ListPoliciesOutput, nil } -func (m mockedIAMPolicies) DetachUserPolicyWithContext(_ aws.Context, input *iam.DetachUserPolicyInput, _ ...request.Option) (*iam.DetachUserPolicyOutput, error) { - return &m.DetachUserPolicyOutput, nil +func (m mockedIAMPolicies) ListPolicyVersions(ctx context.Context, params *iam.ListPolicyVersionsInput, optFns ...func(*iam.Options)) (*iam.ListPolicyVersionsOutput, error) { + return &m.ListPolicyVersionsOutput, nil } -func (m mockedIAMPolicies) DetachGroupPolicyWithContext(_ aws.Context, input *iam.DetachGroupPolicyInput, _ ...request.Option) (*iam.DetachGroupPolicyOutput, error) { - return &m.DetachGroupPolicyOutput, nil +func (m mockedIAMPolicies) DeletePolicy(ctx context.Context, params *iam.DeletePolicyInput, optFns ...func(*iam.Options)) (*iam.DeletePolicyOutput, error) { + return &m.DeletePolicyOutput, nil } -func (m mockedIAMPolicies) DetachRolePolicyWithContext(_ aws.Context, input *iam.DetachRolePolicyInput, _ ...request.Option) (*iam.DetachRolePolicyOutput, error) { - return &m.DetachRolePolicyOutput, nil +func (m mockedIAMPolicies) DeletePolicyVersion(ctx context.Context, params *iam.DeletePolicyVersionInput, optFns ...func(*iam.Options)) (*iam.DeletePolicyVersionOutput, error) { + return &m.DeletePolicyVersionOutput, nil } -func (m mockedIAMPolicies) ListPolicyVersionsPagesWithContext( - _ aws.Context, input *iam.ListPolicyVersionsInput, fn func(*iam.ListPolicyVersionsOutput, bool) bool, _ ...request.Option) error { - fn(&m.ListPolicyVersionsPagesOutput, true) - return nil +func (m mockedIAMPolicies) DetachGroupPolicy(ctx context.Context, params *iam.DetachGroupPolicyInput, optFns ...func(*iam.Options)) (*iam.DetachGroupPolicyOutput, error) { + return &m.DetachGroupPolicyOutput, nil } -func (m mockedIAMPolicies) DeletePolicyVersionWithContext(_ aws.Context, input *iam.DeletePolicyVersionInput, _ ...request.Option) (*iam.DeletePolicyVersionOutput, error) { - return &m.DeletePolicyVersionOutput, nil +func (m mockedIAMPolicies) DetachUserPolicy(ctx context.Context, params *iam.DetachUserPolicyInput, optFns ...func(*iam.Options)) (*iam.DetachUserPolicyOutput, error) { + return &m.DetachUserPolicyOutput, nil } -func (m mockedIAMPolicies) DeletePolicyWithContext(_ aws.Context, input *iam.DeletePolicyInput, _ ...request.Option) (*iam.DeletePolicyOutput, error) { - return &m.DeletePolicyOutput, nil +func (m mockedIAMPolicies) DetachRolePolicy(ctx context.Context, params *iam.DetachRolePolicyInput, optFns ...func(*iam.Options)) (*iam.DetachRolePolicyOutput, error) { + return &m.DetachRolePolicyOutput, nil } func TestIAMPolicy_GetAll(t *testing.T) { - t.Parallel() - testName1 := "MyPolicy1" testName2 := "MyPolicy2" testArn1 := "arn:aws:iam::123456789012:policy/MyPolicy1" @@ -76,8 +66,8 @@ func TestIAMPolicy_GetAll(t *testing.T) { now := time.Now() ip := IAMPolicies{ Client: mockedIAMPolicies{ - ListPoliciesPagesOutput: iam.ListPoliciesOutput{ - Policies: []*iam.Policy{ + ListPoliciesOutput: iam.ListPoliciesOutput{ + Policies: []types.Policy{ { Arn: aws.String(testArn1), PolicyName: aws.String(testName1), @@ -130,30 +120,29 @@ func TestIAMPolicy_GetAll(t *testing.T) { } func TestIAMPolicy_NukeAll(t *testing.T) { - t.Parallel() ip := IAMPolicies{ Client: mockedIAMPolicies{ - ListEntitiesForPolicyPagesOutput: iam.ListEntitiesForPolicyOutput{ - PolicyGroups: []*iam.PolicyGroup{ + ListEntitiesForPolicyOutput: iam.ListEntitiesForPolicyOutput{ + PolicyGroups: []types.PolicyGroup{ {GroupName: aws.String("group1")}, }, - PolicyUsers: []*iam.PolicyUser{ + PolicyUsers: []types.PolicyUser{ {UserName: aws.String("user1")}, }, - PolicyRoles: []*iam.PolicyRole{ + PolicyRoles: []types.PolicyRole{ {RoleName: aws.String("role1")}, }, }, DetachUserPolicyOutput: iam.DetachUserPolicyOutput{}, DetachGroupPolicyOutput: iam.DetachGroupPolicyOutput{}, DetachRolePolicyOutput: iam.DetachRolePolicyOutput{}, - ListPolicyVersionsPagesOutput: iam.ListPolicyVersionsOutput{ - Versions: []*iam.PolicyVersion{ + ListPolicyVersionsOutput: iam.ListPolicyVersionsOutput{ + Versions: []types.PolicyVersion{ { VersionId: aws.String("v1"), - IsDefaultVersion: aws.Bool(false), + IsDefaultVersion: false, }, }, }, diff --git a/aws/resources/iam_policy_types.go b/aws/resources/iam_policy_types.go index 7152f723..e302e853 100644 --- a/aws/resources/iam_policy_types.go +++ b/aws/resources/iam_policy_types.go @@ -3,25 +3,36 @@ package resources import ( "context" - awsgo "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/iam" - "github.com/aws/aws-sdk-go/service/iam/iamiface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/iam" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/go-commons/errors" ) +type IAMPoliciesAPI interface { + ListEntitiesForPolicy(ctx context.Context, params *iam.ListEntitiesForPolicyInput, optFns ...func(*iam.Options)) (*iam.ListEntitiesForPolicyOutput, error) + ListPolicies(ctx context.Context, params *iam.ListPoliciesInput, optFns ...func(*iam.Options)) (*iam.ListPoliciesOutput, error) + ListPolicyVersions(ctx context.Context, params *iam.ListPolicyVersionsInput, optFns ...func(*iam.Options)) (*iam.ListPolicyVersionsOutput, error) + DeletePolicy(ctx context.Context, params *iam.DeletePolicyInput, optFns ...func(*iam.Options)) (*iam.DeletePolicyOutput, error) + DeletePolicyVersion(ctx context.Context, params *iam.DeletePolicyVersionInput, optFns ...func(*iam.Options)) (*iam.DeletePolicyVersionOutput, error) + DetachGroupPolicy(ctx context.Context, params *iam.DetachGroupPolicyInput, optFns ...func(*iam.Options)) (*iam.DetachGroupPolicyOutput, error) + DetachUserPolicy(ctx context.Context, params *iam.DetachUserPolicyInput, optFns ...func(*iam.Options)) (*iam.DetachUserPolicyOutput, error) + DetachRolePolicy(ctx context.Context, params *iam.DetachRolePolicyInput, optFns ...func(*iam.Options)) (*iam.DetachRolePolicyOutput, error) +} + // IAMPolicies - represents all IAM Policies on the AWS account type IAMPolicies struct { BaseAwsResource - Client iamiface.IAMAPI + Client IAMPoliciesAPI PolicyArns []string } -func (ip *IAMPolicies) Init(session *session.Session) { - ip.Client = iam.New(session) +func (ip *IAMPolicies) InitV2(cfg aws.Config) { + ip.Client = iam.NewFromConfig(cfg) } +func (ip *IAMPolicies) IsUsingV2() bool { return true } + // ResourceName - the simple name of the AWS resource func (ip *IAMPolicies) ResourceName() string { return "iam-policy" @@ -47,13 +58,13 @@ func (ip *IAMPolicies) GetAndSetIdentifiers(c context.Context, configObj config. return nil, err } - ip.PolicyArns = awsgo.StringValueSlice(identifiers) + ip.PolicyArns = aws.ToStringSlice(identifiers) return ip.PolicyArns, nil } // Nuke - Destroy every group in this collection func (ip *IAMPolicies) Nuke(identifiers []string) error { - if err := ip.nukeAll(awsgo.StringSlice(identifiers)); err != nil { + if err := ip.nukeAll(aws.StringSlice(identifiers)); err != nil { return errors.WithStackTrace(err) } diff --git a/aws/resources/iam_role.go b/aws/resources/iam_role.go index 61605e60..8568a454 100644 --- a/aws/resources/iam_role.go +++ b/aws/resources/iam_role.go @@ -5,8 +5,9 @@ import ( "strings" "sync" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/iam" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/iam" + "github.com/aws/aws-sdk-go-v2/service/iam/types" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" "github.com/gruntwork-io/cloud-nuke/report" @@ -16,28 +17,26 @@ import ( // List all IAM Roles in the AWS account func (ir *IAMRoles) getAll(c context.Context, configObj config.Config) ([]*string, error) { - allIAMRoles := []*string{} - err := ir.Client.ListRolesPagesWithContext( - ir.Context, - &iam.ListRolesInput{}, - func(page *iam.ListRolesOutput, lastPage bool) bool { - for _, iamRole := range page.Roles { - if ir.shouldInclude(iamRole, configObj) { - allIAMRoles = append(allIAMRoles, iamRole.RoleName) - } - } + var allIAMRoles []*string + paginator := iam.NewListRolesPaginator(ir.Client, &iam.ListRolesInput{}) + for paginator.HasMorePages() { + page, err := paginator.NextPage(c) + if err != nil { + return nil, errors.WithStackTrace(err) + } - return !lastPage - }, - ) - if err != nil { - return nil, errors.WithStackTrace(err) + for _, iamRole := range page.Roles { + if ir.shouldInclude(&iamRole, configObj) { + allIAMRoles = append(allIAMRoles, iamRole.RoleName) + } + } } + return allIAMRoles, nil } func (ir *IAMRoles) deleteManagedRolePolicies(roleName *string) error { - policiesOutput, err := ir.Client.ListAttachedRolePoliciesWithContext(ir.Context, &iam.ListAttachedRolePoliciesInput{ + policiesOutput, err := ir.Client.ListAttachedRolePolicies(ir.Context, &iam.ListAttachedRolePoliciesInput{ RoleName: roleName, }) if err != nil { @@ -46,7 +45,7 @@ func (ir *IAMRoles) deleteManagedRolePolicies(roleName *string) error { for _, attachedPolicy := range policiesOutput.AttachedPolicies { arn := attachedPolicy.PolicyArn - _, err = ir.Client.DetachRolePolicyWithContext(ir.Context, &iam.DetachRolePolicyInput{ + _, err = ir.Client.DetachRolePolicy(ir.Context, &iam.DetachRolePolicyInput{ PolicyArn: arn, RoleName: roleName, }) @@ -54,14 +53,14 @@ func (ir *IAMRoles) deleteManagedRolePolicies(roleName *string) error { logging.Errorf("[Failed] %s", err) return errors.WithStackTrace(err) } - logging.Debugf("Detached Policy %s from Role %s", aws.StringValue(arn), aws.StringValue(roleName)) + logging.Debugf("Detached Policy %s from Role %s", aws.ToString(arn), aws.ToString(roleName)) } return nil } func (ir *IAMRoles) deleteInlineRolePolicies(roleName *string) error { - policyOutput, err := ir.Client.ListRolePoliciesWithContext(ir.Context, &iam.ListRolePoliciesInput{ + policyOutput, err := ir.Client.ListRolePolicies(ir.Context, &iam.ListRolePoliciesInput{ RoleName: roleName, }) if err != nil { @@ -70,22 +69,22 @@ func (ir *IAMRoles) deleteInlineRolePolicies(roleName *string) error { } for _, policyName := range policyOutput.PolicyNames { - _, err := ir.Client.DeleteRolePolicyWithContext(ir.Context, &iam.DeleteRolePolicyInput{ - PolicyName: policyName, + _, err := ir.Client.DeleteRolePolicy(ir.Context, &iam.DeleteRolePolicyInput{ + PolicyName: aws.String(policyName), RoleName: roleName, }) if err != nil { logging.Debugf("[Failed] %s", err) return errors.WithStackTrace(err) } - logging.Debugf("Deleted Inline Policy %s from Role %s", aws.StringValue(policyName), aws.StringValue(roleName)) + logging.Debugf("Deleted Inline Policy %s from Role %s", policyName, aws.ToString(roleName)) } return nil } func (ir *IAMRoles) deleteInstanceProfilesFromRole(roleName *string) error { - profilesOutput, err := ir.Client.ListInstanceProfilesForRoleWithContext(ir.Context, &iam.ListInstanceProfilesForRoleInput{ + profilesOutput, err := ir.Client.ListInstanceProfilesForRole(ir.Context, &iam.ListInstanceProfilesForRoleInput{ RoleName: roleName, }) if err != nil { @@ -95,7 +94,7 @@ func (ir *IAMRoles) deleteInstanceProfilesFromRole(roleName *string) error { for _, profile := range profilesOutput.InstanceProfiles { // Role needs to be removed from instance profile before it can be deleted - _, err := ir.Client.RemoveRoleFromInstanceProfileWithContext(ir.Context, &iam.RemoveRoleFromInstanceProfileInput{ + _, err := ir.Client.RemoveRoleFromInstanceProfile(ir.Context, &iam.RemoveRoleFromInstanceProfileInput{ InstanceProfileName: profile.InstanceProfileName, RoleName: roleName, }) @@ -103,7 +102,7 @@ func (ir *IAMRoles) deleteInstanceProfilesFromRole(roleName *string) error { logging.Debugf("[Failed] %s", err) return errors.WithStackTrace(err) } else { - _, err := ir.Client.DeleteInstanceProfileWithContext(ir.Context, &iam.DeleteInstanceProfileInput{ + _, err := ir.Client.DeleteInstanceProfile(ir.Context, &iam.DeleteInstanceProfileInput{ InstanceProfileName: profile.InstanceProfileName, }) if err != nil { @@ -111,13 +110,13 @@ func (ir *IAMRoles) deleteInstanceProfilesFromRole(roleName *string) error { return errors.WithStackTrace(err) } } - logging.Debugf("Detached and Deleted InstanceProfile %s from Role %s", aws.StringValue(profile.InstanceProfileName), aws.StringValue(roleName)) + logging.Debugf("Detached and Deleted InstanceProfile %s from Role %s", aws.ToString(profile.InstanceProfileName), aws.ToString(roleName)) } return nil } func (ir *IAMRoles) deleteIamRole(roleName *string) error { - _, err := ir.Client.DeleteRoleWithContext(ir.Context, &iam.DeleteRoleInput{ + _, err := ir.Client.DeleteRole(ir.Context, &iam.DeleteRoleInput{ RoleName: roleName, }) if err != nil { @@ -168,12 +167,12 @@ func (ir *IAMRoles) nukeAll(roleNames []*string) error { } for _, roleName := range roleNames { - logging.Debugf("[OK] IAM Role %s was deleted", aws.StringValue(roleName)) + logging.Debugf("[OK] IAM Role %s was deleted", aws.ToString(roleName)) } return nil } -func (ir *IAMRoles) shouldInclude(iamRole *iam.Role, configObj config.Config) bool { +func (ir *IAMRoles) shouldInclude(iamRole *types.Role, configObj config.Config) bool { if iamRole == nil { return false } @@ -181,13 +180,13 @@ func (ir *IAMRoles) shouldInclude(iamRole *iam.Role, configObj config.Config) bo // The OrganizationAccountAccessRole is a special role that is created by AWS Organizations, and is used to allow // users to access the AWS account. We should not delete this role, so we can filter it out of the Roles found and // managed by cloud-nuke. - if strings.Contains(aws.StringValue(iamRole.RoleName), "OrganizationAccountAccessRole") { + if strings.Contains(aws.ToString(iamRole.RoleName), "OrganizationAccountAccessRole") { return false } // The ARNs of AWS-reserved IAM roles, which can only be modified or deleted by AWS, contain "aws-reserved", so we can filter them out // of the Roles found and managed by cloud-nuke - if strings.Contains(aws.StringValue(iamRole.Arn), "aws-reserved") { + if strings.Contains(aws.ToString(iamRole.Arn), "aws-reserved") { return false } @@ -221,7 +220,7 @@ func (ir *IAMRoles) deleteIamRoleAsync(wg *sync.WaitGroup, errChan chan error, r // Record status of this resource e := report.Entry{ - Identifier: aws.StringValue(roleName), + Identifier: aws.ToString(roleName), ResourceType: "IAM Role", Error: result.ErrorOrNil(), } diff --git a/aws/resources/iam_role_test.go b/aws/resources/iam_role_test.go index c48ca18b..5d94cd06 100644 --- a/aws/resources/iam_role_test.go +++ b/aws/resources/iam_role_test.go @@ -6,75 +6,71 @@ import ( "testing" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/service/iam" - "github.com/aws/aws-sdk-go/service/iam/iamiface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/iam" + "github.com/aws/aws-sdk-go-v2/service/iam/types" "github.com/gruntwork-io/cloud-nuke/config" "github.com/stretchr/testify/require" ) type mockedIAMRoles struct { - iamiface.IAMAPI - ListRolesPagesOutput iam.ListRolesOutput + IAMRolesAPI + ListAttachedRolePoliciesOutput iam.ListAttachedRolePoliciesOutput ListInstanceProfilesForRoleOutput iam.ListInstanceProfilesForRoleOutput - RemoveRoleFromInstanceProfileOutput iam.RemoveRoleFromInstanceProfileOutput - DeleteInstanceProfileOutput iam.DeleteInstanceProfileOutput ListRolePoliciesOutput iam.ListRolePoliciesOutput - DeleteRolePolicyOutput iam.DeleteRolePolicyOutput - ListAttachedRolePoliciesOutput iam.ListAttachedRolePoliciesOutput + ListRolesOutput iam.ListRolesOutput + DeleteInstanceProfileOutput iam.DeleteInstanceProfileOutput DetachRolePolicyOutput iam.DetachRolePolicyOutput + DeleteRolePolicyOutput iam.DeleteRolePolicyOutput DeleteRoleOutput iam.DeleteRoleOutput + RemoveRoleFromInstanceProfileOutput iam.RemoveRoleFromInstanceProfileOutput } -func (m mockedIAMRoles) ListRolesPagesWithContext(_ aws.Context, input *iam.ListRolesInput, f func(*iam.ListRolesOutput, bool) bool, _ ...request.Option) error { - f(&m.ListRolesPagesOutput, true) - return nil +func (m mockedIAMRoles) ListAttachedRolePolicies(ctx context.Context, params *iam.ListAttachedRolePoliciesInput, optFns ...func(*iam.Options)) (*iam.ListAttachedRolePoliciesOutput, error) { + return &m.ListAttachedRolePoliciesOutput, nil } -func (m mockedIAMRoles) ListInstanceProfilesForRoleWithContext(_ aws.Context, input *iam.ListInstanceProfilesForRoleInput, _ ...request.Option) (*iam.ListInstanceProfilesForRoleOutput, error) { +func (m mockedIAMRoles) ListInstanceProfilesForRole(ctx context.Context, params *iam.ListInstanceProfilesForRoleInput, optFns ...func(*iam.Options)) (*iam.ListInstanceProfilesForRoleOutput, error) { return &m.ListInstanceProfilesForRoleOutput, nil } -func (m mockedIAMRoles) RemoveRoleFromInstanceProfileWithContext(_ aws.Context, input *iam.RemoveRoleFromInstanceProfileInput, _ ...request.Option) (*iam.RemoveRoleFromInstanceProfileOutput, error) { - return &m.RemoveRoleFromInstanceProfileOutput, nil +func (m mockedIAMRoles) ListRolePolicies(ctx context.Context, params *iam.ListRolePoliciesInput, optFns ...func(*iam.Options)) (*iam.ListRolePoliciesOutput, error) { + return &m.ListRolePoliciesOutput, nil } -func (m mockedIAMRoles) DeleteInstanceProfileWithContext(_ aws.Context, input *iam.DeleteInstanceProfileInput, _ ...request.Option) (*iam.DeleteInstanceProfileOutput, error) { - return &m.DeleteInstanceProfileOutput, nil +func (m mockedIAMRoles) ListRoles(ctx context.Context, params *iam.ListRolesInput, optFns ...func(*iam.Options)) (*iam.ListRolesOutput, error) { + return &m.ListRolesOutput, nil } -func (m mockedIAMRoles) ListRolePoliciesWithContext(_ aws.Context, input *iam.ListRolePoliciesInput, _ ...request.Option) (*iam.ListRolePoliciesOutput, error) { - return &m.ListRolePoliciesOutput, nil +func (m mockedIAMRoles) DeleteInstanceProfile(ctx context.Context, params *iam.DeleteInstanceProfileInput, optFns ...func(*iam.Options)) (*iam.DeleteInstanceProfileOutput, error) { + return &m.DeleteInstanceProfileOutput, nil } -func (m mockedIAMRoles) DeleteRolePolicyWithContext(_ aws.Context, input *iam.DeleteRolePolicyInput, _ ...request.Option) (*iam.DeleteRolePolicyOutput, error) { - return &m.DeleteRolePolicyOutput, nil +func (m mockedIAMRoles) DetachRolePolicy(ctx context.Context, params *iam.DetachRolePolicyInput, optFns ...func(*iam.Options)) (*iam.DetachRolePolicyOutput, error) { + return &m.DetachRolePolicyOutput, nil } -func (m mockedIAMRoles) ListAttachedRolePoliciesWithContext(_ aws.Context, input *iam.ListAttachedRolePoliciesInput, _ ...request.Option) (*iam.ListAttachedRolePoliciesOutput, error) { - return &m.ListAttachedRolePoliciesOutput, nil +func (m mockedIAMRoles) DeleteRolePolicy(ctx context.Context, params *iam.DeleteRolePolicyInput, optFns ...func(*iam.Options)) (*iam.DeleteRolePolicyOutput, error) { + return &m.DeleteRolePolicyOutput, nil } -func (m mockedIAMRoles) DetachRolePolicyWithContext(_ aws.Context, input *iam.DetachRolePolicyInput, _ ...request.Option) (*iam.DetachRolePolicyOutput, error) { - return &m.DetachRolePolicyOutput, nil +func (m mockedIAMRoles) DeleteRole(ctx context.Context, params *iam.DeleteRoleInput, optFns ...func(*iam.Options)) (*iam.DeleteRoleOutput, error) { + return &m.DeleteRoleOutput, nil } -func (m mockedIAMRoles) DeleteRoleWithContext(_ aws.Context, input *iam.DeleteRoleInput, _ ...request.Option) (*iam.DeleteRoleOutput, error) { - return &m.DeleteRoleOutput, nil +func (m mockedIAMRoles) RemoveRoleFromInstanceProfile(ctx context.Context, params *iam.RemoveRoleFromInstanceProfileInput, optFns ...func(*iam.Options)) (*iam.RemoveRoleFromInstanceProfileOutput, error) { + return &m.RemoveRoleFromInstanceProfileOutput, nil } func TestIAMRoles_GetAll(t *testing.T) { - t.Parallel() - testName1 := "test-role1" testName2 := "test-role2" now := time.Now() ir := IAMRoles{ Client: mockedIAMRoles{ - ListRolesPagesOutput: iam.ListRolesOutput{ - Roles: []*iam.Role{ + ListRolesOutput: iam.ListRolesOutput{ + Roles: []types.Role{ { RoleName: aws.String(testName1), CreateDate: aws.Time(now), @@ -119,20 +115,18 @@ func TestIAMRoles_GetAll(t *testing.T) { IAMRoles: tc.configObj, }) require.NoError(t, err) - require.Equal(t, tc.expected, aws.StringValueSlice(names)) + require.Equal(t, tc.expected, aws.ToStringSlice(names)) }) } } func TestIAMRoles_NukeAll(t *testing.T) { - t.Parallel() - ir := IAMRoles{ Client: mockedIAMRoles{ ListInstanceProfilesForRoleOutput: iam.ListInstanceProfilesForRoleOutput{ - InstanceProfiles: []*iam.InstanceProfile{ + InstanceProfiles: []types.InstanceProfile{ { InstanceProfileName: aws.String("test-instance-profile"), }, @@ -141,13 +135,13 @@ func TestIAMRoles_NukeAll(t *testing.T) { RemoveRoleFromInstanceProfileOutput: iam.RemoveRoleFromInstanceProfileOutput{}, DeleteInstanceProfileOutput: iam.DeleteInstanceProfileOutput{}, ListRolePoliciesOutput: iam.ListRolePoliciesOutput{ - PolicyNames: []*string{ - aws.String("test-policy"), + PolicyNames: []string{ + "test-policy", }, }, DeleteRolePolicyOutput: iam.DeleteRolePolicyOutput{}, ListAttachedRolePoliciesOutput: iam.ListAttachedRolePoliciesOutput{ - AttachedPolicies: []*iam.AttachedPolicy{ + AttachedPolicies: []types.AttachedPolicy{ { PolicyArn: aws.String("test-policy-arn"), }, diff --git a/aws/resources/iam_role_types.go b/aws/resources/iam_role_types.go index 177cf285..091c5cea 100644 --- a/aws/resources/iam_role_types.go +++ b/aws/resources/iam_role_types.go @@ -3,25 +3,37 @@ package resources import ( "context" - awsgo "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/iam" - "github.com/aws/aws-sdk-go/service/iam/iamiface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/iam" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/go-commons/errors" ) +type IAMRolesAPI interface { + ListAttachedRolePolicies(ctx context.Context, params *iam.ListAttachedRolePoliciesInput, optFns ...func(*iam.Options)) (*iam.ListAttachedRolePoliciesOutput, error) + ListInstanceProfilesForRole(ctx context.Context, params *iam.ListInstanceProfilesForRoleInput, optFns ...func(*iam.Options)) (*iam.ListInstanceProfilesForRoleOutput, error) + ListRolePolicies(ctx context.Context, params *iam.ListRolePoliciesInput, optFns ...func(*iam.Options)) (*iam.ListRolePoliciesOutput, error) + ListRoles(ctx context.Context, params *iam.ListRolesInput, optFns ...func(*iam.Options)) (*iam.ListRolesOutput, error) + DeleteInstanceProfile(ctx context.Context, params *iam.DeleteInstanceProfileInput, optFns ...func(*iam.Options)) (*iam.DeleteInstanceProfileOutput, error) + DetachRolePolicy(ctx context.Context, params *iam.DetachRolePolicyInput, optFns ...func(*iam.Options)) (*iam.DetachRolePolicyOutput, error) + DeleteRolePolicy(ctx context.Context, params *iam.DeleteRolePolicyInput, optFns ...func(*iam.Options)) (*iam.DeleteRolePolicyOutput, error) + DeleteRole(ctx context.Context, params *iam.DeleteRoleInput, optFns ...func(*iam.Options)) (*iam.DeleteRoleOutput, error) + RemoveRoleFromInstanceProfile(ctx context.Context, params *iam.RemoveRoleFromInstanceProfileInput, optFns ...func(*iam.Options)) (*iam.RemoveRoleFromInstanceProfileOutput, error) +} + // IAMRoles - represents all IAMRoles on the AWS Account type IAMRoles struct { BaseAwsResource - Client iamiface.IAMAPI + Client IAMRolesAPI RoleNames []string } -func (ir *IAMRoles) Init(session *session.Session) { - ir.Client = iam.New(session) +func (ir *IAMRoles) InitV2(cfg aws.Config) { + ir.Client = iam.NewFromConfig(cfg) } +func (ir *IAMRoles) IsUsingV2() bool { return true } + // ResourceName - the simple name of the aws resource func (ir *IAMRoles) ResourceName() string { return "iam-role" @@ -47,13 +59,13 @@ func (ir *IAMRoles) GetAndSetIdentifiers(c context.Context, configObj config.Con return nil, err } - ir.RoleNames = awsgo.StringValueSlice(identifiers) + ir.RoleNames = aws.ToStringSlice(identifiers) return ir.RoleNames, nil } // Nuke - nuke 'em all!!! func (ir *IAMRoles) Nuke(identifiers []string) error { - if err := ir.nukeAll(awsgo.StringSlice(identifiers)); err != nil { + if err := ir.nukeAll(aws.StringSlice(identifiers)); err != nil { return errors.WithStackTrace(err) } diff --git a/aws/resources/iam_service_linked_role.go b/aws/resources/iam_service_linked_role.go index 67521665..fe11a2ba 100644 --- a/aws/resources/iam_service_linked_role.go +++ b/aws/resources/iam_service_linked_role.go @@ -8,8 +8,9 @@ import ( "sync" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/iam" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/iam" + "github.com/aws/aws-sdk-go-v2/service/iam/types" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" "github.com/gruntwork-io/cloud-nuke/report" @@ -19,31 +20,30 @@ import ( // List all IAM Roles in the AWS account func (islr *IAMServiceLinkedRoles) getAll(c context.Context, configObj config.Config) ([]*string, error) { - allIAMServiceLinkedRoles := []*string{} - err := islr.Client.ListRolesPagesWithContext( - islr.Context, - &iam.ListRolesInput{}, - func(page *iam.ListRolesOutput, lastPage bool) bool { - for _, iamServiceLinkedRole := range page.Roles { - if islr.shouldInclude(iamServiceLinkedRole, configObj) { - allIAMServiceLinkedRoles = append(allIAMServiceLinkedRoles, iamServiceLinkedRole.RoleName) - } + var allIAMServiceLinkedRoles []*string + paginator := iam.NewListRolesPaginator(islr.Client, &iam.ListRolesInput{}) + for paginator.HasMorePages() { + page, err := paginator.NextPage(c) + if err != nil { + return nil, gruntworkerrors.WithStackTrace(err) + } + + for _, iamServiceLinkedRole := range page.Roles { + if islr.shouldInclude(&iamServiceLinkedRole, configObj) { + allIAMServiceLinkedRoles = append(allIAMServiceLinkedRoles, iamServiceLinkedRole.RoleName) } - return !lastPage - }, - ) - if err != nil { - return nil, gruntworkerrors.WithStackTrace(err) + } } + return allIAMServiceLinkedRoles, nil } func (islr *IAMServiceLinkedRoles) deleteIamServiceLinkedRole(roleName *string) error { // Deletion ID looks like this: " - //{ + // { // DeletionTaskId: "task/aws-service-role/autoscaling.amazonaws.com/AWSServiceRoleForAutoScaling_2/d3c4c9fc-7fd3-4a36-974a-afb0eb78f102" - //} - deletionData, err := islr.Client.DeleteServiceLinkedRoleWithContext(islr.Context, &iam.DeleteServiceLinkedRoleInput{ + // } + deletionData, err := islr.Client.DeleteServiceLinkedRole(islr.Context, &iam.DeleteServiceLinkedRoleInput{ RoleName: roleName, }) if err != nil { @@ -59,22 +59,22 @@ func (islr *IAMServiceLinkedRoles) deleteIamServiceLinkedRole(roleName *string) for !done { done = true // Check if the deletion is complete - deletionStatus, err = islr.Client.GetServiceLinkedRoleDeletionStatusWithContext(islr.Context, &iam.GetServiceLinkedRoleDeletionStatusInput{ + deletionStatus, err = islr.Client.GetServiceLinkedRoleDeletionStatus(islr.Context, &iam.GetServiceLinkedRoleDeletionStatusInput{ DeletionTaskId: deletionData.DeletionTaskId, }) if err != nil { return gruntworkerrors.WithStackTrace(err) } - if aws.StringValue(deletionStatus.Status) == "IN_PROGRESS" { - logging.Debugf("Deletion of IAM ServiceLinked Role %s is still in progress", aws.StringValue(roleName)) + if deletionStatus.Status == types.DeletionTaskStatusTypeInProgress { + logging.Debugf("Deletion of IAM ServiceLinked Role %s is still in progress", aws.ToString(roleName)) done = false time.Sleep(3 * time.Second) } } - if aws.StringValue(deletionStatus.Status) != "SUCCEEDED" { - err := fmt.Sprintf("Deletion of IAM ServiceLinked Role %s failed with status %s", aws.StringValue(roleName), aws.StringValue(deletionStatus.Status)) + if deletionStatus.Status != types.DeletionTaskStatusTypeSucceeded { + err := fmt.Sprintf("Deletion of IAM ServiceLinked Role %s failed with status %s", aws.ToString(roleName), string(deletionStatus.Status)) return gruntworkerrors.WithStackTrace(errors.New(err)) } @@ -122,13 +122,13 @@ func (islr *IAMServiceLinkedRoles) nukeAll(roleNames []*string) error { } for _, roleName := range roleNames { - logging.Debugf("[OK] IAM Service Linked Role %s was deleted.", aws.StringValue(roleName)) + logging.Debugf("[OK] IAM Service Linked Role %s was deleted.", aws.ToString(roleName)) } return nil } -func (islr *IAMServiceLinkedRoles) shouldInclude(iamServiceLinkedRole *iam.Role, configObj config.Config) bool { - if !strings.Contains(aws.StringValue(iamServiceLinkedRole.Arn), "aws-service-role") { +func (islr *IAMServiceLinkedRoles) shouldInclude(iamServiceLinkedRole *types.Role, configObj config.Config) bool { + if !strings.Contains(aws.ToString(iamServiceLinkedRole.Arn), "aws-service-role") { return false } @@ -159,7 +159,7 @@ func (islr *IAMServiceLinkedRoles) deleteIamServiceLinkedRoleAsync(wg *sync.Wait // Record status of this resource e := report.Entry{ - Identifier: aws.StringValue(roleName), + Identifier: aws.ToString(roleName), ResourceType: "IAM Service Linked Role", Error: result.ErrorOrNil(), } diff --git a/aws/resources/iam_service_linked_role_test.go b/aws/resources/iam_service_linked_role_test.go index 3393c069..9ae51877 100644 --- a/aws/resources/iam_service_linked_role_test.go +++ b/aws/resources/iam_service_linked_role_test.go @@ -6,45 +6,41 @@ import ( "testing" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/service/iam" - "github.com/aws/aws-sdk-go/service/iam/iamiface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/iam" + "github.com/aws/aws-sdk-go-v2/service/iam/types" "github.com/gruntwork-io/cloud-nuke/config" "github.com/stretchr/testify/require" ) type mockedIAMServiceLinkedRoles struct { - iamiface.IAMAPI - ListRolesPagesOutput iam.ListRolesOutput + IAMServiceLinkedRolesAPI + ListRolesOutput iam.ListRolesOutput DeleteServiceLinkedRoleOutput iam.DeleteServiceLinkedRoleOutput GetServiceLinkedRoleDeletionStatusOutput iam.GetServiceLinkedRoleDeletionStatusOutput } -func (m mockedIAMServiceLinkedRoles) ListRolesPagesWithContext(_ aws.Context, input *iam.ListRolesInput, fn func(*iam.ListRolesOutput, bool) bool, _ ...request.Option) error { - fn(&m.ListRolesPagesOutput, true) - return nil +func (m mockedIAMServiceLinkedRoles) ListRoles(ctx context.Context, params *iam.ListRolesInput, optFns ...func(*iam.Options)) (*iam.ListRolesOutput, error) { + return &m.ListRolesOutput, nil } -func (m mockedIAMServiceLinkedRoles) DeleteServiceLinkedRoleWithContext(_ aws.Context, input *iam.DeleteServiceLinkedRoleInput, _ ...request.Option) (*iam.DeleteServiceLinkedRoleOutput, error) { +func (m mockedIAMServiceLinkedRoles) DeleteServiceLinkedRole(ctx context.Context, params *iam.DeleteServiceLinkedRoleInput, optFns ...func(*iam.Options)) (*iam.DeleteServiceLinkedRoleOutput, error) { return &m.DeleteServiceLinkedRoleOutput, nil } -func (m mockedIAMServiceLinkedRoles) GetServiceLinkedRoleDeletionStatusWithContext(_ aws.Context, input *iam.GetServiceLinkedRoleDeletionStatusInput, _ ...request.Option) (*iam.GetServiceLinkedRoleDeletionStatusOutput, error) { +func (m mockedIAMServiceLinkedRoles) GetServiceLinkedRoleDeletionStatus(ctx context.Context, params *iam.GetServiceLinkedRoleDeletionStatusInput, optFns ...func(*iam.Options)) (*iam.GetServiceLinkedRoleDeletionStatusOutput, error) { return &m.GetServiceLinkedRoleDeletionStatusOutput, nil } func TestIAMServiceLinkedRoles_GetAll(t *testing.T) { - t.Parallel() - now := time.Now() testName1 := "test-role1" testName2 := "test-role2" islr := IAMServiceLinkedRoles{ Client: &mockedIAMServiceLinkedRoles{ - ListRolesPagesOutput: iam.ListRolesOutput{ - Roles: []*iam.Role{ + ListRolesOutput: iam.ListRolesOutput{ + Roles: []types.Role{ { RoleName: aws.String(testName1), CreateDate: aws.Time(now), @@ -91,22 +87,19 @@ func TestIAMServiceLinkedRoles_GetAll(t *testing.T) { IAMServiceLinkedRoles: tc.configObj, }) require.NoError(t, err) - require.Equal(t, tc.expected, aws.StringValueSlice(names)) + require.Equal(t, tc.expected, aws.ToStringSlice(names)) }) } } func TestIAMServiceLinkedRoles_NukeAll(t *testing.T) { - t.Parallel() - islr := IAMServiceLinkedRoles{ - Client: &mockedIAMServiceLinkedRoles{ DeleteServiceLinkedRoleOutput: iam.DeleteServiceLinkedRoleOutput{}, GetServiceLinkedRoleDeletionStatusOutput: iam.GetServiceLinkedRoleDeletionStatusOutput{ - Status: aws.String("SUCCEEDED"), + Status: types.DeletionTaskStatusTypeSucceeded, }, }, } diff --git a/aws/resources/iam_service_linked_role_types.go b/aws/resources/iam_service_linked_role_types.go index a87c63cd..9d6983fa 100644 --- a/aws/resources/iam_service_linked_role_types.go +++ b/aws/resources/iam_service_linked_role_types.go @@ -3,25 +3,31 @@ package resources import ( "context" - awsgo "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/iam" - "github.com/aws/aws-sdk-go/service/iam/iamiface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/iam" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/go-commons/errors" ) +type IAMServiceLinkedRolesAPI interface { + ListRoles(ctx context.Context, params *iam.ListRolesInput, optFns ...func(*iam.Options)) (*iam.ListRolesOutput, error) + DeleteServiceLinkedRole(ctx context.Context, params *iam.DeleteServiceLinkedRoleInput, optFns ...func(*iam.Options)) (*iam.DeleteServiceLinkedRoleOutput, error) + GetServiceLinkedRoleDeletionStatus(ctx context.Context, params *iam.GetServiceLinkedRoleDeletionStatusInput, optFns ...func(*iam.Options)) (*iam.GetServiceLinkedRoleDeletionStatusOutput, error) +} + // IAMServiceLinkedRoles - represents all IAMServiceLinkedRoles on the AWS Account type IAMServiceLinkedRoles struct { BaseAwsResource - Client iamiface.IAMAPI + Client IAMServiceLinkedRolesAPI RoleNames []string } -func (islr *IAMServiceLinkedRoles) Init(session *session.Session) { - islr.Client = iam.New(session) +func (islr *IAMServiceLinkedRoles) InitV2(cfg aws.Config) { + islr.Client = iam.NewFromConfig(cfg) } +func (islr *IAMServiceLinkedRoles) IsUsingV2() bool { return true } + // ResourceName - the simple name of the aws resource func (islr *IAMServiceLinkedRoles) ResourceName() string { return "iam-service-linked-role" @@ -32,7 +38,7 @@ func (islr *IAMServiceLinkedRoles) ResourceIdentifiers() []string { return islr.RoleNames } -// Tentative batch size to ensure AWS doesn't throttle +// MaxBatchSize Tentative batch size to ensure AWS doesn't throttle func (islr *IAMServiceLinkedRoles) MaxBatchSize() int { return 49 } @@ -47,13 +53,13 @@ func (islr *IAMServiceLinkedRoles) GetAndSetIdentifiers(c context.Context, confi return nil, err } - islr.RoleNames = awsgo.StringValueSlice(identifiers) + islr.RoleNames = aws.ToStringSlice(identifiers) return islr.RoleNames, nil } // Nuke - nuke 'em all!!! func (islr *IAMServiceLinkedRoles) Nuke(identifiers []string) error { - if err := islr.nukeAll(awsgo.StringSlice(identifiers)); err != nil { + if err := islr.nukeAll(aws.StringSlice(identifiers)); err != nil { return errors.WithStackTrace(err) } diff --git a/aws/resources/iam_test.go b/aws/resources/iam_test.go index 0e503fd5..bfb74c5d 100644 --- a/aws/resources/iam_test.go +++ b/aws/resources/iam_test.go @@ -6,143 +6,138 @@ import ( "testing" "time" - "github.com/aws/aws-sdk-go/aws" - awsgo "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/service/iam" - "github.com/aws/aws-sdk-go/service/iam/iamiface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/iam" + "github.com/aws/aws-sdk-go-v2/service/iam/types" "github.com/gruntwork-io/cloud-nuke/config" "github.com/stretchr/testify/require" ) type mockedIAMUsers struct { - iamiface.IAMAPI - ListUsersPagesOutput iam.ListUsersOutput + IAMUsersAPI + ListAccessKeysOutput iam.ListAccessKeysOutput + ListGroupsForUserOutput iam.ListGroupsForUserOutput + ListUserPoliciesOutput iam.ListUserPoliciesOutput + ListUserTagsOutput iam.ListUserTagsOutput + ListMFADevicesOutput iam.ListMFADevicesOutput + ListSSHPublicKeysOutput iam.ListSSHPublicKeysOutput + ListServiceSpecificCredentialsOutput iam.ListServiceSpecificCredentialsOutput + ListSigningCertificatesOutput iam.ListSigningCertificatesOutput + ListUsersOutput iam.ListUsersOutput ListAttachedUserPoliciesOutput iam.ListAttachedUserPoliciesOutput DetachUserPolicyOutput iam.DetachUserPolicyOutput - ListUserPoliciesOutput iam.ListUserPoliciesOutput - DeleteUserPolicyOutput iam.DeleteUserPolicyOutput - ListGroupsForUserOutput iam.ListGroupsForUserOutput - RemoveUserFromGroupOutput iam.RemoveUserFromGroupOutput DeleteLoginProfileOutput iam.DeleteLoginProfileOutput - ListAccessKeysOutput iam.ListAccessKeysOutput + DeleteUserPolicyOutput iam.DeleteUserPolicyOutput DeleteAccessKeyOutput iam.DeleteAccessKeyOutput - ListSigningCertificatesOutput iam.ListSigningCertificatesOutput DeleteSigningCertificateOutput iam.DeleteSigningCertificateOutput - ListSSHPublicKeysOutput iam.ListSSHPublicKeysOutput DeleteSSHPublicKeyOutput iam.DeleteSSHPublicKeyOutput - ListServiceSpecificCredentialsOutput iam.ListServiceSpecificCredentialsOutput DeleteServiceSpecificCredentialOutput iam.DeleteServiceSpecificCredentialOutput - ListMFADevicesOutput iam.ListMFADevicesOutput DeactivateMFADeviceOutput iam.DeactivateMFADeviceOutput DeleteVirtualMFADeviceOutput iam.DeleteVirtualMFADeviceOutput DeleteUserOutput iam.DeleteUserOutput - ListUserTagsOutput iam.ListUserTagsOutput + RemoveUserFromGroupOutput iam.RemoveUserFromGroupOutput } -func (m mockedIAMUsers) ListUsersPagesWithContext(_ aws.Context, input *iam.ListUsersInput, callback func(*iam.ListUsersOutput, bool) bool, _ ...request.Option) error { - callback(&m.ListUsersPagesOutput, true) - return nil +func (m mockedIAMUsers) ListAccessKeys(ctx context.Context, params *iam.ListAccessKeysInput, optFns ...func(*iam.Options)) (*iam.ListAccessKeysOutput, error) { + return &m.ListAccessKeysOutput, nil } -func (m mockedIAMUsers) ListAttachedUserPoliciesWithContext(_ aws.Context, input *iam.ListAttachedUserPoliciesInput, _ ...request.Option) (*iam.ListAttachedUserPoliciesOutput, error) { - return &m.ListAttachedUserPoliciesOutput, nil +func (m mockedIAMUsers) ListGroupsForUser(ctx context.Context, params *iam.ListGroupsForUserInput, optFns ...func(*iam.Options)) (*iam.ListGroupsForUserOutput, error) { + return &m.ListGroupsForUserOutput, nil } -func (m mockedIAMUsers) DetachUserPolicyWithContext(_ aws.Context, input *iam.DetachUserPolicyInput, _ ...request.Option) (*iam.DetachUserPolicyOutput, error) { - return &m.DetachUserPolicyOutput, nil +func (m mockedIAMUsers) ListUserPolicies(ctx context.Context, params *iam.ListUserPoliciesInput, optFns ...func(*iam.Options)) (*iam.ListUserPoliciesOutput, error) { + return &m.ListUserPoliciesOutput, nil } -func (m mockedIAMUsers) ListUserPoliciesWithContext(_ aws.Context, input *iam.ListUserPoliciesInput, _ ...request.Option) (*iam.ListUserPoliciesOutput, error) { - return &m.ListUserPoliciesOutput, nil +func (m mockedIAMUsers) ListUserTags(ctx context.Context, params *iam.ListUserTagsInput, optFns ...func(*iam.Options)) (*iam.ListUserTagsOutput, error) { + return &m.ListUserTagsOutput, nil } -func (m mockedIAMUsers) DeleteUserPolicyWithContext(_ aws.Context, input *iam.DeleteUserPolicyInput, _ ...request.Option) (*iam.DeleteUserPolicyOutput, error) { - return &m.DeleteUserPolicyOutput, nil +func (m mockedIAMUsers) ListMFADevices(ctx context.Context, params *iam.ListMFADevicesInput, optFns ...func(*iam.Options)) (*iam.ListMFADevicesOutput, error) { + return &m.ListMFADevicesOutput, nil } -func (m mockedIAMUsers) ListGroupsForUserWithContext(_ aws.Context, input *iam.ListGroupsForUserInput, _ ...request.Option) (*iam.ListGroupsForUserOutput, error) { - return &m.ListGroupsForUserOutput, nil +func (m mockedIAMUsers) ListSSHPublicKeys(ctx context.Context, params *iam.ListSSHPublicKeysInput, optFns ...func(*iam.Options)) (*iam.ListSSHPublicKeysOutput, error) { + return &m.ListSSHPublicKeysOutput, nil } -func (m mockedIAMUsers) RemoveUserFromGroupWithContext(_ aws.Context, input *iam.RemoveUserFromGroupInput, _ ...request.Option) (*iam.RemoveUserFromGroupOutput, error) { - return &m.RemoveUserFromGroupOutput, nil +func (m mockedIAMUsers) ListServiceSpecificCredentials(ctx context.Context, params *iam.ListServiceSpecificCredentialsInput, optFns ...func(*iam.Options)) (*iam.ListServiceSpecificCredentialsOutput, error) { + return &m.ListServiceSpecificCredentialsOutput, nil } -func (m mockedIAMUsers) DeleteLoginProfileWithContext(_ aws.Context, input *iam.DeleteLoginProfileInput, _ ...request.Option) (*iam.DeleteLoginProfileOutput, error) { - return &m.DeleteLoginProfileOutput, nil +func (m mockedIAMUsers) ListSigningCertificates(ctx context.Context, params *iam.ListSigningCertificatesInput, optFns ...func(*iam.Options)) (*iam.ListSigningCertificatesOutput, error) { + return &m.ListSigningCertificatesOutput, nil } -func (m mockedIAMUsers) ListAccessKeysWithContext(_ aws.Context, input *iam.ListAccessKeysInput, _ ...request.Option) (*iam.ListAccessKeysOutput, error) { - return &m.ListAccessKeysOutput, nil +func (m mockedIAMUsers) ListUsers(ctx context.Context, params *iam.ListUsersInput, optFns ...func(*iam.Options)) (*iam.ListUsersOutput, error) { + return &m.ListUsersOutput, nil } -func (m mockedIAMUsers) DeleteAccessKeyWithContext(_ aws.Context, input *iam.DeleteAccessKeyInput, _ ...request.Option) (*iam.DeleteAccessKeyOutput, error) { - return &m.DeleteAccessKeyOutput, nil +func (m mockedIAMUsers) ListAttachedUserPolicies(ctx context.Context, params *iam.ListAttachedUserPoliciesInput, optFns ...func(*iam.Options)) (*iam.ListAttachedUserPoliciesOutput, error) { + return &m.ListAttachedUserPoliciesOutput, nil } -func (m mockedIAMUsers) ListSigningCertificatesWithContext(_ aws.Context, input *iam.ListSigningCertificatesInput, _ ...request.Option) (*iam.ListSigningCertificatesOutput, error) { - return &m.ListSigningCertificatesOutput, nil +func (m mockedIAMUsers) DetachUserPolicy(ctx context.Context, params *iam.DetachUserPolicyInput, optFns ...func(*iam.Options)) (*iam.DetachUserPolicyOutput, error) { + return &m.DetachUserPolicyOutput, nil } -func (m mockedIAMUsers) DeleteSigningCertificateWithContext(_ aws.Context, input *iam.DeleteSigningCertificateInput, _ ...request.Option) (*iam.DeleteSigningCertificateOutput, error) { - return &m.DeleteSigningCertificateOutput, nil +func (m mockedIAMUsers) DeleteLoginProfile(ctx context.Context, params *iam.DeleteLoginProfileInput, optFns ...func(*iam.Options)) (*iam.DeleteLoginProfileOutput, error) { + return &m.DeleteLoginProfileOutput, nil } -func (m mockedIAMUsers) ListSSHPublicKeysWithContext(_ aws.Context, input *iam.ListSSHPublicKeysInput, _ ...request.Option) (*iam.ListSSHPublicKeysOutput, error) { - return &m.ListSSHPublicKeysOutput, nil +func (m mockedIAMUsers) DeleteUserPolicy(ctx context.Context, params *iam.DeleteUserPolicyInput, optFns ...func(*iam.Options)) (*iam.DeleteUserPolicyOutput, error) { + return &m.DeleteUserPolicyOutput, nil } -func (m mockedIAMUsers) DeleteSSHPublicKeyWithContext(_ aws.Context, input *iam.DeleteSSHPublicKeyInput, _ ...request.Option) (*iam.DeleteSSHPublicKeyOutput, error) { - return &m.DeleteSSHPublicKeyOutput, nil +func (m mockedIAMUsers) DeleteAccessKey(ctx context.Context, params *iam.DeleteAccessKeyInput, optFns ...func(*iam.Options)) (*iam.DeleteAccessKeyOutput, error) { + return &m.DeleteAccessKeyOutput, nil } -func (m mockedIAMUsers) ListServiceSpecificCredentialsWithContext(_ aws.Context, input *iam.ListServiceSpecificCredentialsInput, _ ...request.Option) (*iam.ListServiceSpecificCredentialsOutput, error) { - return &m.ListServiceSpecificCredentialsOutput, nil +func (m mockedIAMUsers) DeleteSigningCertificate(ctx context.Context, params *iam.DeleteSigningCertificateInput, optFns ...func(*iam.Options)) (*iam.DeleteSigningCertificateOutput, error) { + return &m.DeleteSigningCertificateOutput, nil } -func (m mockedIAMUsers) DeleteServiceSpecificCredentialWithContext(_ aws.Context, input *iam.DeleteServiceSpecificCredentialInput, _ ...request.Option) (*iam.DeleteServiceSpecificCredentialOutput, error) { - return &m.DeleteServiceSpecificCredentialOutput, nil +func (m mockedIAMUsers) DeleteSSHPublicKey(ctx context.Context, params *iam.DeleteSSHPublicKeyInput, optFns ...func(*iam.Options)) (*iam.DeleteSSHPublicKeyOutput, error) { + return &m.DeleteSSHPublicKeyOutput, nil } -func (m mockedIAMUsers) ListMFADevicesWithContext(_ aws.Context, input *iam.ListMFADevicesInput, _ ...request.Option) (*iam.ListMFADevicesOutput, error) { - return &m.ListMFADevicesOutput, nil +func (m mockedIAMUsers) DeleteServiceSpecificCredential(ctx context.Context, params *iam.DeleteServiceSpecificCredentialInput, optFns ...func(*iam.Options)) (*iam.DeleteServiceSpecificCredentialOutput, error) { + return &m.DeleteServiceSpecificCredentialOutput, nil } -func (m mockedIAMUsers) DeactivateMFADeviceWithContext(_ aws.Context, input *iam.DeactivateMFADeviceInput, _ ...request.Option) (*iam.DeactivateMFADeviceOutput, error) { +func (m mockedIAMUsers) DeactivateMFADevice(ctx context.Context, params *iam.DeactivateMFADeviceInput, optFns ...func(*iam.Options)) (*iam.DeactivateMFADeviceOutput, error) { return &m.DeactivateMFADeviceOutput, nil } -func (m mockedIAMUsers) DeleteVirtualMFADeviceWithContext(_ aws.Context, input *iam.DeleteVirtualMFADeviceInput, _ ...request.Option) (*iam.DeleteVirtualMFADeviceOutput, error) { +func (m mockedIAMUsers) DeleteVirtualMFADevice(ctx context.Context, params *iam.DeleteVirtualMFADeviceInput, optFns ...func(*iam.Options)) (*iam.DeleteVirtualMFADeviceOutput, error) { return &m.DeleteVirtualMFADeviceOutput, nil } -func (m mockedIAMUsers) DeleteUserWithContext(_ aws.Context, input *iam.DeleteUserInput, _ ...request.Option) (*iam.DeleteUserOutput, error) { +func (m mockedIAMUsers) DeleteUser(ctx context.Context, params *iam.DeleteUserInput, optFns ...func(*iam.Options)) (*iam.DeleteUserOutput, error) { return &m.DeleteUserOutput, nil } -func (m mockedIAMUsers) ListUserTagsPagesWithContext(_ aws.Context, input *iam.ListUserTagsInput, callback func(*iam.ListUserTagsOutput, bool) bool, _ ...request.Option) error { - callback(&m.ListUserTagsOutput, true) - return nil + +func (m mockedIAMUsers) RemoveUserFromGroup(ctx context.Context, params *iam.RemoveUserFromGroupInput, optFns ...func(*iam.Options)) (*iam.RemoveUserFromGroupOutput, error) { + return &m.RemoveUserFromGroupOutput, nil } func TestIAMUsers_GetAll(t *testing.T) { - t.Parallel() - now := time.Now() testName1 := "test-user1" testName2 := "test-user2" iu := IAMUsers{ Client: mockedIAMUsers{ - ListUsersPagesOutput: iam.ListUsersOutput{ - Users: []*iam.User{ + ListUsersOutput: iam.ListUsersOutput{ + Users: []types.User{ { - UserName: awsgo.String(testName1), - CreateDate: awsgo.Time(now), + UserName: aws.String(testName1), + CreateDate: aws.Time(now), }, { - UserName: awsgo.String(testName2), - CreateDate: awsgo.Time(now.Add(1)), + UserName: aws.String(testName2), + CreateDate: aws.Time(now.Add(1)), }, }, }, @@ -180,77 +175,75 @@ func TestIAMUsers_GetAll(t *testing.T) { IAMUsers: tc.configObj, }) require.NoError(t, err) - require.Equal(t, tc.expected, awsgo.StringValueSlice(names)) + require.Equal(t, tc.expected, aws.ToStringSlice(names)) }) } } func TestIAMUsers_NukeAll(t *testing.T) { - t.Parallel() - iu := IAMUsers{ Client: mockedIAMUsers{ ListAttachedUserPoliciesOutput: iam.ListAttachedUserPoliciesOutput{ - AttachedPolicies: []*iam.AttachedPolicy{ + AttachedPolicies: []types.AttachedPolicy{ { - PolicyName: awsgo.String("test-policy"), + PolicyName: aws.String("test-policy"), }, }, }, DetachUserPolicyOutput: iam.DetachUserPolicyOutput{}, ListUserPoliciesOutput: iam.ListUserPoliciesOutput{ - PolicyNames: []*string{ - awsgo.String("test-policy"), + PolicyNames: []string{ + "test-policy", }, }, DeleteUserPolicyOutput: iam.DeleteUserPolicyOutput{}, ListGroupsForUserOutput: iam.ListGroupsForUserOutput{ - Groups: []*iam.Group{ + Groups: []types.Group{ { - GroupName: awsgo.String("test-group"), + GroupName: aws.String("test-group"), }, }, }, RemoveUserFromGroupOutput: iam.RemoveUserFromGroupOutput{}, DeleteLoginProfileOutput: iam.DeleteLoginProfileOutput{}, ListAccessKeysOutput: iam.ListAccessKeysOutput{ - AccessKeyMetadata: []*iam.AccessKeyMetadata{ + AccessKeyMetadata: []types.AccessKeyMetadata{ { - AccessKeyId: awsgo.String("test-key"), + AccessKeyId: aws.String("test-key"), }, }, }, DeleteAccessKeyOutput: iam.DeleteAccessKeyOutput{}, ListSigningCertificatesOutput: iam.ListSigningCertificatesOutput{ - Certificates: []*iam.SigningCertificate{ + Certificates: []types.SigningCertificate{ { - CertificateId: awsgo.String("test-certificate"), + CertificateId: aws.String("test-certificate"), }, }, }, DeleteSigningCertificateOutput: iam.DeleteSigningCertificateOutput{}, ListSSHPublicKeysOutput: iam.ListSSHPublicKeysOutput{ - SSHPublicKeys: []*iam.SSHPublicKeyMetadata{ + SSHPublicKeys: []types.SSHPublicKeyMetadata{ { - SSHPublicKeyId: awsgo.String("test-ssh-key"), + SSHPublicKeyId: aws.String("test-ssh-key"), }, }, }, DeleteSSHPublicKeyOutput: iam.DeleteSSHPublicKeyOutput{}, ListServiceSpecificCredentialsOutput: iam.ListServiceSpecificCredentialsOutput{ - ServiceSpecificCredentials: []*iam.ServiceSpecificCredentialMetadata{ + ServiceSpecificCredentials: []types.ServiceSpecificCredentialMetadata{ { - ServiceSpecificCredentialId: awsgo.String("test-service-credential"), + ServiceSpecificCredentialId: aws.String("test-service-credential"), }, }, }, DeleteServiceSpecificCredentialOutput: iam.DeleteServiceSpecificCredentialOutput{}, ListMFADevicesOutput: iam.ListMFADevicesOutput{ - MFADevices: []*iam.MFADevice{ + MFADevices: []types.MFADevice{ { - SerialNumber: awsgo.String("test-mfa-device"), + SerialNumber: aws.String("test-mfa-device"), }, }, }, @@ -260,6 +253,6 @@ func TestIAMUsers_NukeAll(t *testing.T) { }, } - err := iu.nukeAll([]*string{awsgo.String("test-user")}) + err := iu.nukeAll([]*string{aws.String("test-user")}) require.NoError(t, err) } diff --git a/aws/resources/iam_types.go b/aws/resources/iam_types.go index d2dadb3d..b83b46ad 100644 --- a/aws/resources/iam_types.go +++ b/aws/resources/iam_types.go @@ -3,25 +3,49 @@ package resources import ( "context" - awsgo "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/iam" - "github.com/aws/aws-sdk-go/service/iam/iamiface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/iam" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/go-commons/errors" ) +type IAMUsersAPI interface { + ListAccessKeys(ctx context.Context, params *iam.ListAccessKeysInput, optFns ...func(*iam.Options)) (*iam.ListAccessKeysOutput, error) + ListGroupsForUser(ctx context.Context, params *iam.ListGroupsForUserInput, optFns ...func(*iam.Options)) (*iam.ListGroupsForUserOutput, error) + ListUserPolicies(ctx context.Context, params *iam.ListUserPoliciesInput, optFns ...func(*iam.Options)) (*iam.ListUserPoliciesOutput, error) + ListUserTags(ctx context.Context, params *iam.ListUserTagsInput, optFns ...func(*iam.Options)) (*iam.ListUserTagsOutput, error) + ListMFADevices(ctx context.Context, params *iam.ListMFADevicesInput, optFns ...func(*iam.Options)) (*iam.ListMFADevicesOutput, error) + ListSSHPublicKeys(ctx context.Context, params *iam.ListSSHPublicKeysInput, optFns ...func(*iam.Options)) (*iam.ListSSHPublicKeysOutput, error) + ListServiceSpecificCredentials(ctx context.Context, params *iam.ListServiceSpecificCredentialsInput, optFns ...func(*iam.Options)) (*iam.ListServiceSpecificCredentialsOutput, error) + ListSigningCertificates(ctx context.Context, params *iam.ListSigningCertificatesInput, optFns ...func(*iam.Options)) (*iam.ListSigningCertificatesOutput, error) + ListUsers(ctx context.Context, params *iam.ListUsersInput, optFns ...func(*iam.Options)) (*iam.ListUsersOutput, error) + ListAttachedUserPolicies(ctx context.Context, params *iam.ListAttachedUserPoliciesInput, optFns ...func(*iam.Options)) (*iam.ListAttachedUserPoliciesOutput, error) + DetachUserPolicy(ctx context.Context, params *iam.DetachUserPolicyInput, optFns ...func(*iam.Options)) (*iam.DetachUserPolicyOutput, error) + DeleteLoginProfile(ctx context.Context, params *iam.DeleteLoginProfileInput, optFns ...func(*iam.Options)) (*iam.DeleteLoginProfileOutput, error) + DeleteUserPolicy(ctx context.Context, params *iam.DeleteUserPolicyInput, optFns ...func(*iam.Options)) (*iam.DeleteUserPolicyOutput, error) + DeleteAccessKey(ctx context.Context, params *iam.DeleteAccessKeyInput, optFns ...func(*iam.Options)) (*iam.DeleteAccessKeyOutput, error) + DeleteSigningCertificate(ctx context.Context, params *iam.DeleteSigningCertificateInput, optFns ...func(*iam.Options)) (*iam.DeleteSigningCertificateOutput, error) + DeleteSSHPublicKey(ctx context.Context, params *iam.DeleteSSHPublicKeyInput, optFns ...func(*iam.Options)) (*iam.DeleteSSHPublicKeyOutput, error) + DeleteServiceSpecificCredential(ctx context.Context, params *iam.DeleteServiceSpecificCredentialInput, optFns ...func(*iam.Options)) (*iam.DeleteServiceSpecificCredentialOutput, error) + DeactivateMFADevice(ctx context.Context, params *iam.DeactivateMFADeviceInput, optFns ...func(*iam.Options)) (*iam.DeactivateMFADeviceOutput, error) + DeleteVirtualMFADevice(ctx context.Context, params *iam.DeleteVirtualMFADeviceInput, optFns ...func(*iam.Options)) (*iam.DeleteVirtualMFADeviceOutput, error) + DeleteUser(ctx context.Context, params *iam.DeleteUserInput, optFns ...func(*iam.Options)) (*iam.DeleteUserOutput, error) + RemoveUserFromGroup(ctx context.Context, params *iam.RemoveUserFromGroupInput, optFns ...func(*iam.Options)) (*iam.RemoveUserFromGroupOutput, error) +} + // IAMUsers - represents all IAMUsers on the AWS Account type IAMUsers struct { BaseAwsResource - Client iamiface.IAMAPI + Client IAMUsersAPI UserNames []string } -func (iu *IAMUsers) Init(session *session.Session) { - iu.Client = iam.New(session) +func (iu *IAMUsers) InitV2(cfg aws.Config) { + iu.Client = iam.NewFromConfig(cfg) } +func (iu *IAMUsers) IsUsingV2() bool { return true } + // ResourceName - the simple name of the aws resource func (iu *IAMUsers) ResourceName() string { return "iam" @@ -47,13 +71,13 @@ func (iu *IAMUsers) GetAndSetIdentifiers(c context.Context, configObj config.Con return nil, err } - iu.UserNames = awsgo.StringValueSlice(identifiers) + iu.UserNames = aws.ToStringSlice(identifiers) return iu.UserNames, nil } // Nuke - nuke 'em all!!! func (iu *IAMUsers) Nuke(users []string) error { - if err := iu.nukeAll(awsgo.StringSlice(users)); err != nil { + if err := iu.nukeAll(aws.StringSlice(users)); err != nil { return errors.WithStackTrace(err) } diff --git a/go.mod b/go.mod index 98f3e046..9a5e7665 100644 --- a/go.mod +++ b/go.mod @@ -34,6 +34,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.41.0 github.com/aws/aws-sdk-go-v2/service/eventbridge v1.35.3 github.com/aws/aws-sdk-go-v2/service/guardduty v1.50.1 + github.com/aws/aws-sdk-go-v2/service/iam v1.37.3 github.com/aws/aws-sdk-go-v2/service/scheduler v1.12.3 github.com/aws/aws-sdk-go-v2/service/sns v1.33.3 github.com/aws/aws-sdk-go-v2/service/sqs v1.36.3 diff --git a/go.sum b/go.sum index 7e6777f7..82e71a4e 100644 --- a/go.sum +++ b/go.sum @@ -15,35 +15,22 @@ github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYew github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= github.com/aws/aws-sdk-go v1.49.13 h1:f4mGztsgnx2dR9r8FQYa9YW/RsKb+N7bgef4UGrOW1Y= github.com/aws/aws-sdk-go v1.49.13/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.16.16/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k= github.com/aws/aws-sdk-go-v2 v1.32.3 h1:T0dRlFBKcdaUPGNtkBSwHZxrtis8CQU17UpNBZYd0wk= github.com/aws/aws-sdk-go-v2 v1.32.3/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.6 h1:pT3hpW0cOHRJx8Y0DfJUEQuqPild8jRGmSFmBgvydr0= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.6/go.mod h1:j/I2++U0xX+cr44QjHay4Cvxj6FUbnxrgmqN3H1jTZA= -github.com/aws/aws-sdk-go-v2/config v1.27.24 h1:NM9XicZ5o1CBU/MZaHwFtimRpWx9ohAUAqkG6AqSqPo= -github.com/aws/aws-sdk-go-v2/config v1.27.24/go.mod h1:aXzi6QJTuQRVVusAO8/NxpdTeTyr/wRcybdDtfUwJSs= github.com/aws/aws-sdk-go-v2/config v1.28.1 h1:oxIvOUXy8x0U3fR//0eq+RdCKimWI900+SV+10xsCBw= github.com/aws/aws-sdk-go-v2/config v1.28.1/go.mod h1:bRQcttQJiARbd5JZxw6wG0yIK3eLeSCPdg6uqmmlIiI= -github.com/aws/aws-sdk-go-v2/credentials v1.17.24 h1:YclAsrnb1/GTQNt2nzv+756Iw4mF8AOzcDfweWwwm/M= -github.com/aws/aws-sdk-go-v2/credentials v1.17.24/go.mod h1:Hld7tmnAkoBQdTMNYZGzztzKRdA4fCdn9L83LOoigac= github.com/aws/aws-sdk-go-v2/credentials v1.17.42 h1:sBP0RPjBU4neGpIYyx8mkU2QqLPl5u9cmdTWVzIpHkM= github.com/aws/aws-sdk-go-v2/credentials v1.17.42/go.mod h1:FwZBfU530dJ26rv9saAbxa9Ej3eF/AK0OAY86k13n4M= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.9 h1:Aznqksmd6Rfv2HQN9cpqIV/lQRMaIpJkLLaJ1ZI76no= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.9/go.mod h1:WQr3MY7AxGNxaqAtsDWn+fBxmd4XvLkzeqQ8P1VM0/w= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.18 h1:68jFVtt3NulEzojFesM/WVarlFpCaXLKaBxDpzkQ9OQ= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.18/go.mod h1:Fjnn5jQVIo6VyedMc0/EhPpfNlPl7dHV916O6B+49aE= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23/go.mod h1:2DFxAQ9pfIRy0imBCJv+vZ2X6RKxves6fbnEuSry6b4= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22 h1:Jw50LwEkVjuVzE1NzkhNKkBf9cRN7MtE1F/b2cOKTUM= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22/go.mod h1:Y/SmAyPcOTmpeVaWSzSKiILfXTVJwrGmYZhcRbhWuEY= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17/go.mod h1:pRwaTYCJemADaqCbUAxltMoHKata7hmB5PjEXeu0kfg= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22 h1:981MHwBaRZM7+9QSR6XamDzF/o7ouUGxFzr+nVSIhrs= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22/go.mod h1:1RA1+aBEfn+CAB/Mh0MB6LsdCYCnjZm7tKXtnk499ZQ= -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/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.17 h1:Roo69qTpfu8OlJ2Tb7pAYVuF0CpuUMB0IYWwYP/4DZM= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.17/go.mod h1:NcWPxQzGM1USQggaTVwz6VpqMZPX1CvDJLDh6jnOCa4= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.22 h1:yV+hCAHZZYJQcwAaszoBNwLbPItHvApxT0kVIw6jRgs= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.22/go.mod h1:kbR1TL8llqB1eGnVbybcA4/wgScxdylOdyAd51yxPdw= github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.34.3 h1:ScJw+8v6RPTJbuWxowSiUw8xdPL0aQOAbakC6mF1uZU= @@ -52,8 +39,6 @@ github.com/aws/aws-sdk-go-v2/service/acm v1.30.3 h1:/7wq5haORYzJUkAbD9Hh4/SGiwup github.com/aws/aws-sdk-go-v2/service/acm v1.30.3/go.mod h1:A4UY3eQPhio6VPEfBhrkafy4rSIjQ/aOggqKZYNHv+c= github.com/aws/aws-sdk-go-v2/service/acmpca v1.37.4 h1:uWqTNc//8pMepB0qUzu+r13QybLum/uLUqU4cehzCew= github.com/aws/aws-sdk-go-v2/service/acmpca v1.37.4/go.mod h1:WVF7A3ipjS/vpzOY09xJDeH8ja+rDbnl5u2mL26rt60= -github.com/aws/aws-sdk-go-v2/service/amp v1.27.1 h1:va9j7MGA8jBlQs9KujMlkSdnC26TuEJXv7ywnFjmTZ8= -github.com/aws/aws-sdk-go-v2/service/amp v1.27.1/go.mod h1:QhmX7qjomjuHJjCJbW+QRdaCBM42v1eAbWvBVFrT1Vw= github.com/aws/aws-sdk-go-v2/service/amp v1.30.0 h1:1AQM/Lo024FKGTW/iwIDQHV8+5j8/h0iabYm+4jB5Bo= github.com/aws/aws-sdk-go-v2/service/amp v1.30.0/go.mod h1:4OQEJHTg0Z2Q32qQUDWquPZKmLagi5/BVzTCYtcnpJo= github.com/aws/aws-sdk-go-v2/service/apigateway v1.27.3 h1:81BvgDQ0bYSim7mFZWSwsX0DRkMkxsYGCpgGfEagnks= @@ -62,8 +47,6 @@ github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.24.3 h1:LNnp0zMnX20sO+lUZ9e github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.24.3/go.mod h1:/uJSiw1R5OvrT3OZcdybich8zaFwaTgX3J1B/CaBhwM= github.com/aws/aws-sdk-go-v2/service/apprunner v1.32.3 h1:wkQpocpYy3/SqFf8iUO1uB5ICK06sm6ajevvft7ijoQ= github.com/aws/aws-sdk-go-v2/service/apprunner v1.32.3/go.mod h1:lOQv8hfiAZCHdi+wNKBKdSqf1yCKzWiOEQNVKoK/Jko= -github.com/aws/aws-sdk-go-v2/service/autoscaling v1.23.16 h1:cp30gVVAbZfeDod6UJGppMH2+p+/cRCG2AZ1TbT+LqA= -github.com/aws/aws-sdk-go-v2/service/autoscaling v1.23.16/go.mod h1:hHTMeJt6CQwFdmS19RK1LsDscus8c25Ve8KiYRhsISg= github.com/aws/aws-sdk-go-v2/service/autoscaling v1.47.0 h1:3yvZKeDa/slOTk8Gym4ym9u7AKhYAvy0Y00oRE+HRvE= github.com/aws/aws-sdk-go-v2/service/autoscaling v1.47.0/go.mod h1:SDmFD5Xuoa8dHPOLakoiURaUXei4zcqrkZ0/myZch/A= github.com/aws/aws-sdk-go-v2/service/backup v1.39.4 h1:4JLXjQf1vEDFmGjr2Z+jLFkMvAEb3aHmq4ChiL+npdA= @@ -82,8 +65,6 @@ github.com/aws/aws-sdk-go-v2/service/datasync v1.43.0 h1:wTaKnkq96RrLoZhFyrPDDh8 github.com/aws/aws-sdk-go-v2/service/datasync v1.43.0/go.mod h1:3INRTlR4HqbSlknYo1dOixcspRw6XtwJWL8cQqMGERM= github.com/aws/aws-sdk-go-v2/service/dynamodb v1.36.3 h1:pS5ka5Z026eG29K3cce+yxG39i5COQARcgheeK9NKQE= github.com/aws/aws-sdk-go-v2/service/dynamodb v1.36.3/go.mod h1:MBT8rSGSZjJiV6X7rlrVGoIt+mCoaw0VbpdVtsrsJfk= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.185.0 h1:WPhQgVHZUEsIRGEFh5B7VmwFzTkYgk7CxjWxZOgjQco= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.185.0/go.mod h1:kYXaB4FzyhEJjvrJ84oPnMElLiEAjGxxUunVW2tBSng= github.com/aws/aws-sdk-go-v2/service/ec2 v1.187.0 h1:cA4hWo269CN5RY7Arqt8BfzXF0KIN8DSNo/KcqHKkWk= github.com/aws/aws-sdk-go-v2/service/ec2 v1.187.0/go.mod h1:ossaD9Z1ugYb6sq9QIqQLEOorCGcqUoxlhud9M9yE70= github.com/aws/aws-sdk-go-v2/service/ecr v1.36.3 h1:bqmoQEKpWFRDRxOv4lC5yZLc+N1cogZHPLeQACfVUJo= @@ -102,47 +83,32 @@ github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.28.3 h1:cRDiIyPNUf7 github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.28.3/go.mod h1:G86bITIZX9wcacVyMHzLz9nEQaQLSBKDHym0spIEr+M= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.41.0 h1:W+xNfPS8dQ8YoszdkHqTDYIgCrWJvyUU/ZgdJ0frCRE= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.41.0/go.mod h1:6WuvTcPjB9gff93p/2LNBg09d8xK99jpVO6+fRSCKEU= -github.com/aws/aws-sdk-go-v2/service/eventbridge v1.33.7 h1:q+xiPu+Dk5MFC20ZjdGGhbihD39Xsih98epvVjnOjyE= -github.com/aws/aws-sdk-go-v2/service/eventbridge v1.33.7/go.mod h1:iQCsmx9LyBMyMEkLCBVqnIAz+rfo6/ss3oLcYn26+no= github.com/aws/aws-sdk-go-v2/service/eventbridge v1.35.3 h1:e/jGXEQi+lyTIhc3s+jbJrq2IWgLXsNbdYxDauWTyPU= github.com/aws/aws-sdk-go-v2/service/eventbridge v1.35.3/go.mod h1:607CryyDS58whuaVno9CCg3L/nnWOqorxiyAS2f9leY= github.com/aws/aws-sdk-go-v2/service/guardduty v1.50.1 h1:0A05jzCVA6W/UFqdtpKm8KXE8QhcEn/Fn01Zxsq2Owg= github.com/aws/aws-sdk-go-v2/service/guardduty v1.50.1/go.mod h1:tfpIzAIeMtSUucGN87ZUA2u5Lqnc04ManYSk3smJpGc= +github.com/aws/aws-sdk-go-v2/service/iam v1.37.3 h1:uuoXyOwX2ReYgHJW0W84cKDUrvQNQA2l9KhkXUgT+R4= +github.com/aws/aws-sdk-go-v2/service/iam v1.37.3/go.mod h1:RCrjvkN/ZpVAzW3ZmIlyflv7MUM45YlWx3v+6MaVX2w= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 h1:TToQNkvGguu209puTojY/ozlqy2d/SFNcoLIqTFi42g= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0/go.mod h1:0jp+ltwkf+SwG2fm/PKo8t4y8pJSgOCO4D8Lz3k0aHQ= github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.3 h1:wudRPcZMKytcywXERkR6PLqD8gPx754ZyIOo0iVg488= github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.3/go.mod h1:yRo5Kj5+m/ScVIZpQOquQvDtSrDM1JLRCnvglBcdNmw= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 h1:s7NA1SOw8q/5c0wr8477yOPp0z+uBaXBnLE0XYb0POA= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2/go.mod h1:fnjjWyAW/Pj5HYOxl9LJqWtEwS7W2qgcRLWP+uWbss0= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.3 h1:qcxX0JYlgWH3hpPUnd6U0ikcl6LLA9sLkXE2w1fpMvY= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.3/go.mod h1:cLSNEmI45soc+Ef8K/L+8sEA3A3pYFEYf5B5UI+6bH4= -github.com/aws/aws-sdk-go-v2/service/scheduler v1.10.7 h1:EcPyKUUo3neD2tDFKnq3TR3B9s2uZe9eWgxVQgixdzc= -github.com/aws/aws-sdk-go-v2/service/scheduler v1.10.7/go.mod h1:MlNx35QVGG8TB2x1kOC0TKd9e93+RmFUE8HzYDLDLso= github.com/aws/aws-sdk-go-v2/service/scheduler v1.12.3 h1:VrfgbM8+DuUaTRx1Lllajic28bHaaUrYx9tN9JCGXVI= github.com/aws/aws-sdk-go-v2/service/scheduler v1.12.3/go.mod h1:0ujC4ruQHlBlToSoHj3s/OL9wr7dp7wPrcACMDc87ME= -github.com/aws/aws-sdk-go-v2/service/sns v1.32.3 h1:LC5JBrEAdJ0SSRLfNcLzOLsfoc3xO/BAsHiUNcQfDI4= -github.com/aws/aws-sdk-go-v2/service/sns v1.32.3/go.mod h1:ZO606Jfatw51c8q29gHVVCnufg2dq3MnmkNLlTZFrkE= github.com/aws/aws-sdk-go-v2/service/sns v1.33.3 h1:coZW/SqpINT0VWG8vRWWY9TWUof8TDdxublw2Xur0Zc= github.com/aws/aws-sdk-go-v2/service/sns v1.33.3/go.mod h1:J/G2xuhwNBlDvEi0WR/bnBbac4KSgpkERna/IXEF52w= -github.com/aws/aws-sdk-go-v2/service/sqs v1.35.3 h1:Lcs658WFW235QuUfpAdxd8RCy8Va2VUA7/U9iIrcjcY= -github.com/aws/aws-sdk-go-v2/service/sqs v1.35.3/go.mod h1:WuGxWQhu2LXoPGA2HBIbotpwhM6T4hAz0Ip/HjdxfJg= github.com/aws/aws-sdk-go-v2/service/sqs v1.36.3 h1:H1bCg79Q4PDtxQH8Fn5kASQlbVv2WGP5o5IEFEBNOAs= github.com/aws/aws-sdk-go-v2/service/sqs v1.36.3/go.mod h1:W6Uy6OWgxF9RZuHoikthB6f+A0oYXqnfWmFl5m7E2G4= -github.com/aws/aws-sdk-go-v2/service/sso v1.22.1 h1:p1GahKIjyMDZtiKoIn0/jAj/TkMzfzndDv5+zi2Mhgc= -github.com/aws/aws-sdk-go-v2/service/sso v1.22.1/go.mod h1:/vWdhoIoYA5hYoPZ6fm7Sv4d8701PiG5VKe8/pPJL60= github.com/aws/aws-sdk-go-v2/service/sso v1.24.3 h1:UTpsIf0loCIWEbrqdLb+0RxnTXfWh2vhw4nQmFi4nPc= github.com/aws/aws-sdk-go-v2/service/sso v1.24.3/go.mod h1:FZ9j3PFHHAR+w0BSEjK955w5YD2UwB/l/H0yAK3MJvI= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.2 h1:ORnrOK0C4WmYV/uYt3koHEWBLYsRDwk2Np+eEoyV4Z0= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.2/go.mod h1:xyFHA4zGxgYkdD73VeezHt3vSKEG9EmFnGwoKlP00u4= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.3 h1:2YCmIXv3tmiItw0LlYf6v7gEHebLY45kBEnPezbUKyU= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.3/go.mod h1:u19stRyNPxGhj6dRm+Cdgu6N75qnbW7+QN0q0dsAk58= -github.com/aws/aws-sdk-go-v2/service/sts v1.30.1 h1:+woJ607dllHJQtsnJLi52ycuqHMwlW+Wqm2Ppsfp4nQ= -github.com/aws/aws-sdk-go-v2/service/sts v1.30.1/go.mod h1:jiNR3JqT15Dm+QWq2SRgh0x0bCNSRP2L25+CqPNpJlQ= github.com/aws/aws-sdk-go-v2/service/sts v1.32.3 h1:wVnQ6tigGsRqSWDEEyH6lSAJ9OyFUsSnbaUWChuSGzs= github.com/aws/aws-sdk-go-v2/service/sts v1.32.3/go.mod h1:VZa9yTFyj4o10YGsmDO4gbQJUvvhY72fhumT8W4LqsE= github.com/aws/aws-sdk-go-v2/service/vpclattice v1.12.3 h1:YwFhhnQNn2bvnJ9HNy7DEhyIf5Ze/9Qn6ad6gtByLko= github.com/aws/aws-sdk-go-v2/service/vpclattice v1.12.3/go.mod h1:wjm69e87s+O7nq0zC54dEJ7M9gLHMfr9ZJ+j5u9IV0Q= -github.com/aws/smithy-go v1.13.3/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM= github.com/aws/smithy-go v1.22.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= @@ -160,7 +126,6 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= diff --git a/util/tag.go b/util/tag.go index 5a9e659e..6dc1d0f2 100644 --- a/util/tag.go +++ b/util/tag.go @@ -3,8 +3,8 @@ package util import ( autoscaling "github.com/aws/aws-sdk-go-v2/service/autoscaling/types" "github.com/aws/aws-sdk-go-v2/service/ec2/types" + iam "github.com/aws/aws-sdk-go-v2/service/iam/types" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/iam" "github.com/aws/aws-sdk-go/service/networkfirewall" "github.com/aws/aws-sdk-go/service/rds" "github.com/aws/aws-sdk-go/service/s3" @@ -55,7 +55,7 @@ func ConvertStringPtrTagsToMap(tags map[string]*string) map[string]string { return tagMap } -func ConvertIAMTagsToMap(tags []*iam.Tag) map[string]string { +func ConvertIAMTagsToMap(tags []iam.Tag) map[string]string { tagMap := make(map[string]string) for _, tag := range tags { tagMap[*tag.Key] = *tag.Value diff --git a/v2_migration_report/output.md b/v2_migration_report/output.md index 64fac786..8ff4f3ca 100644 --- a/v2_migration_report/output.md +++ b/v2_migration_report/output.md @@ -52,11 +52,11 @@ run `go generate ./...` to refresh this report. | event-bridge-schedule | :white_check_mark: | | event-bridge-schedule-group | :white_check_mark: | | guardduty | :white_check_mark: | -| iam | | -| iam-group | | -| iam-policy | | -| iam-role | | -| iam-service-linked-role | | +| iam | :white_check_mark: | +| iam-group | :white_check_mark: | +| iam-policy | :white_check_mark: | +| iam-role | :white_check_mark: | +| iam-service-linked-role | :white_check_mark: | | internet-gateway | | | ipam | | | ipam-byoasn | |