Skip to content

Commit

Permalink
ssc - user force destory
Browse files Browse the repository at this point in the history
  • Loading branch information
DrFaust92 committed Feb 11, 2022
1 parent 62f8af3 commit 438d9f1
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 23 deletions.
72 changes: 49 additions & 23 deletions internal/service/iam/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func resourceUserCreate(d *schema.ResourceData, meta interface{}) error {
}

if err != nil {
return fmt.Errorf("failed creating IAM User (%s): %s", name, err)
return fmt.Errorf("failed creating IAM User (%s): %w", name, err)
}

d.SetId(aws.StringValue(createResp.User.UserName))
Expand Down Expand Up @@ -226,7 +226,7 @@ func resourceUserUpdate(d *schema.ResourceData, meta interface{}) error {
d.SetId("")
return nil
}
return fmt.Errorf("Error updating IAM User %s: %s", d.Id(), err)
return fmt.Errorf("Error updating IAM User %s: %w", d.Id(), err)
}

d.SetId(nn.(string))
Expand All @@ -241,15 +241,15 @@ func resourceUserUpdate(d *schema.ResourceData, meta interface{}) error {
}
_, err := conn.PutUserPermissionsBoundary(input)
if err != nil {
return fmt.Errorf("error updating IAM User permissions boundary: %s", err)
return fmt.Errorf("error updating IAM User permissions boundary: %w", err)
}
} else {
input := &iam.DeleteUserPermissionsBoundaryInput{
UserName: aws.String(d.Id()),
}
_, err := conn.DeleteUserPermissionsBoundary(input)
if err != nil {
return fmt.Errorf("error deleting IAM User permissions boundary: %s", err)
return fmt.Errorf("error deleting IAM User permissions boundary: %w", err)
}
}
}
Expand Down Expand Up @@ -284,27 +284,31 @@ func resourceUserDelete(d *schema.ResourceData, meta interface{}) error {
// All access keys, MFA devices and login profile for the user must be removed
if d.Get("force_destroy").(bool) {
if err := DeleteUserAccessKeys(conn, d.Id()); err != nil {
return fmt.Errorf("error removing IAM User (%s) access keys: %s", d.Id(), err)
return fmt.Errorf("error removing IAM User (%s) access keys: %w", d.Id(), err)
}

if err := DeleteUserSSHKeys(conn, d.Id()); err != nil {
return fmt.Errorf("error removing IAM User (%s) SSH keys: %s", d.Id(), err)
return fmt.Errorf("error removing IAM User (%s) SSH keys: %w", d.Id(), err)
}

if err := DeleteUserVirtualMFADevices(conn, d.Id()); err != nil {
return fmt.Errorf("error removing IAM User (%s) Virtual MFA devices: %s", d.Id(), err)
return fmt.Errorf("error removing IAM User (%s) Virtual MFA devices: %w", d.Id(), err)
}

if err := DeactivateUserMFADevices(conn, d.Id()); err != nil {
return fmt.Errorf("error removing IAM User (%s) MFA devices: %s", d.Id(), err)
return fmt.Errorf("error removing IAM User (%s) MFA devices: %w", d.Id(), err)
}

if err := DeleteUserLoginProfile(conn, d.Id()); err != nil {
return fmt.Errorf("error removing IAM User (%s) login profile: %s", d.Id(), err)
return fmt.Errorf("error removing IAM User (%s) login profile: %w", d.Id(), err)
}

if err := deleteUserSigningCertificates(conn, d.Id()); err != nil {
return fmt.Errorf("error removing IAM User (%s) signing certificate: %s", d.Id(), err)
return fmt.Errorf("error removing IAM User (%s) signing certificate: %w", d.Id(), err)
}

if err := DeleteServiceSpecificCredentials(conn, d.Id()); err != nil {
return fmt.Errorf("error removing IAM User (%s) Service Specific Credentials: %w", d.Id(), err)
}
}

Expand All @@ -320,7 +324,7 @@ func resourceUserDelete(d *schema.ResourceData, meta interface{}) error {
}

if err != nil {
return fmt.Errorf("Error deleting IAM User %s: %s", d.Id(), err)
return fmt.Errorf("Error deleting IAM User %s: %w", d.Id(), err)
}

return nil
Expand Down Expand Up @@ -367,15 +371,15 @@ func DeleteUserSSHKeys(svc *iam.IAM, username string) error {
}
err = svc.ListSSHPublicKeysPages(listSSHPublicKeys, pageOfListSSHPublicKeys)
if err != nil {
return fmt.Errorf("Error removing public SSH keys of user %s: %s", username, err)
return fmt.Errorf("Error removing public SSH keys of user %s: %w", username, err)
}
for _, k := range publicKeys {
_, err := svc.DeleteSSHPublicKey(&iam.DeleteSSHPublicKeyInput{
UserName: aws.String(username),
SSHPublicKeyId: aws.String(k),
})
if err != nil {
return fmt.Errorf("Error deleting public SSH key %s: %s", k, err)
return fmt.Errorf("Error deleting public SSH key %s: %w", k, err)
}
}

Expand All @@ -400,21 +404,21 @@ func DeleteUserVirtualMFADevices(svc *iam.IAM, username string) error {
}
err = svc.ListVirtualMFADevicesPages(listVirtualMFADevices, pageOfVirtualMFADevices)
if err != nil {
return fmt.Errorf("Error removing Virtual MFA devices of user %s: %s", username, err)
return fmt.Errorf("Error removing Virtual MFA devices of user %s: %w", username, err)
}
for _, m := range VirtualMFADevices {
_, err := svc.DeactivateMFADevice(&iam.DeactivateMFADeviceInput{
UserName: aws.String(username),
SerialNumber: aws.String(m),
})
if err != nil {
return fmt.Errorf("Error deactivating Virtual MFA device %s: %s", m, err)
return fmt.Errorf("Error deactivating Virtual MFA device %s: %w", m, err)
}
_, err = svc.DeleteVirtualMFADevice(&iam.DeleteVirtualMFADeviceInput{
SerialNumber: aws.String(m),
})
if err != nil {
return fmt.Errorf("Error deleting Virtual MFA device %s: %s", m, err)
return fmt.Errorf("Error deleting Virtual MFA device %s: %w", m, err)
}
}

Expand All @@ -436,15 +440,15 @@ func DeactivateUserMFADevices(svc *iam.IAM, username string) error {
}
err = svc.ListMFADevicesPages(listMFADevices, pageOfMFADevices)
if err != nil {
return fmt.Errorf("Error removing MFA devices of user %s: %s", username, err)
return fmt.Errorf("Error removing MFA devices of user %s: %w", username, err)
}
for _, m := range MFADevices {
_, err := svc.DeactivateMFADevice(&iam.DeactivateMFADeviceInput{
UserName: aws.String(username),
SerialNumber: aws.String(m),
})
if err != nil {
return fmt.Errorf("Error deactivating MFA device %s: %s", m, err)
return fmt.Errorf("Error deactivating MFA device %s: %w", m, err)
}
}

Expand Down Expand Up @@ -474,7 +478,7 @@ func DeleteUserLoginProfile(svc *iam.IAM, username string) error {
_, err = svc.DeleteLoginProfile(input)
}
if err != nil {
return fmt.Errorf("Error deleting Account Login Profile: %s", err)
return fmt.Errorf("Error deleting Account Login Profile: %w", err)
}

return nil
Expand All @@ -494,15 +498,15 @@ func DeleteUserAccessKeys(svc *iam.IAM, username string) error {
}
err = svc.ListAccessKeysPages(listAccessKeys, pageOfAccessKeys)
if err != nil {
return fmt.Errorf("Error removing access keys of user %s: %s", username, err)
return fmt.Errorf("Error removing access keys of user %s: %w", username, err)
}
for _, k := range accessKeys {
_, err := svc.DeleteAccessKey(&iam.DeleteAccessKeyInput{
UserName: aws.String(username),
AccessKeyId: aws.String(k),
})
if err != nil {
return fmt.Errorf("Error deleting access key %s: %s", k, err)
return fmt.Errorf("Error deleting access key %s: %w", k, err)
}
}

Expand All @@ -523,7 +527,7 @@ func deleteUserSigningCertificates(svc *iam.IAM, userName string) error {
return !lastPage
})
if err != nil {
return fmt.Errorf("Error removing signing certificates of user %s: %s", userName, err)
return fmt.Errorf("Error removing signing certificates of user %s: %w", userName, err)
}

for _, c := range certificateIDList {
Expand All @@ -532,7 +536,29 @@ func deleteUserSigningCertificates(svc *iam.IAM, userName string) error {
UserName: aws.String(userName),
})
if err != nil {
return fmt.Errorf("Error deleting signing certificate %s: %s", c, err)
return fmt.Errorf("Error deleting signing certificate %s: %w", c, err)
}
}

return nil
}

func DeleteServiceSpecificCredentials(svc *iam.IAM, username string) error {
input := &iam.ListServiceSpecificCredentialsInput{
UserName: aws.String(username),
}

output, err := svc.ListServiceSpecificCredentials(input)
if err != nil {
return fmt.Errorf("Error listing Service Specific Credentials of user %s: %w", username, err)
}
for _, m := range output.ServiceSpecificCredentials {
_, err := svc.DeleteServiceSpecificCredential(&iam.DeleteServiceSpecificCredentialInput{
UserName: aws.String(username),
ServiceSpecificCredentialId: m.ServiceSpecificCredentialId,
})
if err != nil {
return fmt.Errorf("Error deleting Service Specific Credentials %s: %w", m, err)
}
}

Expand Down
49 changes: 49 additions & 0 deletions internal/service/iam/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,35 @@ func TestAccIAMUser_ForceDestroy_sshKey(t *testing.T) {
})
}

func TestAccIAMUser_ForceDestroy_serviceSpecificCred(t *testing.T) {
var user iam.GetUserOutput

rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_iam_user.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, iam.EndpointsID),
Providers: acctest.Providers,
CheckDestroy: testAccCheckUserDestroy,
Steps: []resource.TestStep{
{
Config: testAccUserForceDestroyConfig(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckUserExists(resourceName, &user),
testAccCheckUserServiceSpecificCredential(&user),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"force_destroy"},
},
},
})
}

func TestAccIAMUser_ForceDestroy_signingCertificate(t *testing.T) {
var user iam.GetUserOutput

Expand Down Expand Up @@ -621,6 +650,26 @@ func testAccCheckUserUploadsSSHKey(getUserOutput *iam.GetUserOutput) resource.Te
}
}

// Creates an IAM User Service Specific Credential outside of Terraform to verify that it is deleted when `force_destroy` is set
func testAccCheckUserServiceSpecificCredential(getUserOutput *iam.GetUserOutput) resource.TestCheckFunc {
return func(s *terraform.State) error {

conn := acctest.Provider.Meta().(*conns.AWSClient).IAMConn

input := &iam.CreateServiceSpecificCredentialInput{
UserName: getUserOutput.User.UserName,
ServiceName: aws.String("codecommit.amazonaws.com"),
}

_, err := conn.CreateServiceSpecificCredential(input)
if err != nil {
return fmt.Errorf("error uploading IAM User (%s) Service Specifc Credential: %w", aws.StringValue(getUserOutput.User.UserName), err)
}

return nil
}
}

func testAccCheckUserUploadSigningCertificate(getUserOutput *iam.GetUserOutput) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.AWSClient).IAMConn
Expand Down

0 comments on commit 438d9f1

Please sign in to comment.