-
Notifications
You must be signed in to change notification settings - Fork 2
[BB-1367] add delete iam user resource (NEW PERMISSIONS NEEDED) #89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -288,3 +288,170 @@ func (o *iamUserResourceType) CreateAccount( | |
| IsCreateAccountResult: true, | ||
| }, nil, nil, nil | ||
| } | ||
|
|
||
| func (o *iamUserResourceType) Delete(ctx context.Context, resourceId *v2.ResourceId) (annotations.Annotations, error) { | ||
| var noSuchEntity *iamTypes.NoSuchEntityException | ||
| l := ctxzap.Extract(ctx) | ||
| if resourceId.ResourceType != resourceTypeIAMUser.Id { | ||
| return nil, fmt.Errorf("aws-connector: only IAM user resources can be deleted") | ||
| } | ||
| userName, err := iamUserNameFromARN(resourceId.Resource) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| awsStringUserName := awsSdk.String(userName) | ||
|
|
||
| // try to fetch the user, if not found then the user has already been deleted | ||
| user, err := o.iamClient.GetUser(ctx, &iam.GetUserInput{UserName: awsStringUserName}) | ||
| if err != nil { | ||
| if errors.As(err, &noSuchEntity) { | ||
| l.Info("User not found, returning success for delete operation") | ||
| return nil, nil | ||
| } | ||
| return nil, fmt.Errorf("aws-connector: iam.GetUser failed: %w", err) | ||
| } | ||
|
|
||
| if user.User == nil { | ||
| return nil, fmt.Errorf("aws-connector: user not found") | ||
| } | ||
|
|
||
| // To delete a user through the API we'll need to manually delete information associated with it, | ||
| // which is a 10 step process (9 + delete itself). | ||
| // https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_remove.html#id_users_deleting_cli | ||
|
|
||
| // Permission needed: iam:DeleteLoginProfile | ||
| _, err = o.iamClient.DeleteLoginProfile(ctx, &iam.DeleteLoginProfileInput{UserName: awsStringUserName}) | ||
| if err != nil { | ||
| if !errors.As(err, &noSuchEntity) { | ||
| return nil, fmt.Errorf("aws-connector: failed to delete login profile: %w", err) | ||
| } | ||
| l.Info("login profile not found, skipping") | ||
| } | ||
|
|
||
| // Delete all access keys | ||
| // Permission needed: iam:ListAccessKeys, iam:DeleteAccessKey | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are these necessary permissions mentioned in the Readme file or in doc-info.md? This would also make it clear which permissions are required. The implementation is good and makes sense. |
||
| keys, err := o.iamClient.ListAccessKeys(ctx, &iam.ListAccessKeysInput{UserName: awsStringUserName}) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("aws-connector: failed to list access keys: %w", err) | ||
| } | ||
|
|
||
| for _, key := range keys.AccessKeyMetadata { | ||
| _, err = o.iamClient.DeleteAccessKey(ctx, &iam.DeleteAccessKeyInput{UserName: awsStringUserName, AccessKeyId: awsSdk.String(awsSdk.ToString(key.AccessKeyId))}) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("aws-connector: failed to delete access key: %w", err) | ||
| } | ||
| } | ||
|
|
||
| // Delete all signing certificates | ||
| // Permission needed: iam:ListSigningCertificates, iam:DeleteSigningCertificate | ||
| certificates, err := o.iamClient.ListSigningCertificates(ctx, &iam.ListSigningCertificatesInput{UserName: awsStringUserName}) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("aws-connector: failed to list signing certificates: %w", err) | ||
| } | ||
|
|
||
| for _, certificate := range certificates.Certificates { | ||
| _, err = o.iamClient.DeleteSigningCertificate(ctx, &iam.DeleteSigningCertificateInput{UserName: awsStringUserName, CertificateId: awsSdk.String(awsSdk.ToString(certificate.CertificateId))}) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("aws-connector: failed to delete signing certificate: %w", err) | ||
| } | ||
| } | ||
|
|
||
| // Delete all SSH public keys | ||
| // Permission needed: iam:ListSSHPublicKeys, iam:DeleteSSHPublicKey | ||
| sshKeys, err := o.iamClient.ListSSHPublicKeys(ctx, &iam.ListSSHPublicKeysInput{UserName: awsStringUserName}) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("aws-connector: failed to list SSH public keys: %w", err) | ||
| } | ||
|
|
||
| for _, key := range sshKeys.SSHPublicKeys { | ||
| _, err = o.iamClient.DeleteSSHPublicKey(ctx, &iam.DeleteSSHPublicKeyInput{UserName: awsStringUserName, SSHPublicKeyId: awsSdk.String(awsSdk.ToString(key.SSHPublicKeyId))}) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("aws-connector: failed to delete SSH public key: %w", err) | ||
| } | ||
| } | ||
|
|
||
| // Delete all service specific credentials | ||
| // Permission needed: iam:ListServiceSpecificCredentials, iam:DeleteServiceSpecificCredential | ||
| ssCredentials, err := o.iamClient.ListServiceSpecificCredentials(ctx, &iam.ListServiceSpecificCredentialsInput{UserName: awsStringUserName}) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("aws-connector: failed to list service specific credentials: %w", err) | ||
| } | ||
|
|
||
| for _, credential := range ssCredentials.ServiceSpecificCredentials { | ||
| _, err = o.iamClient.DeleteServiceSpecificCredential( | ||
| ctx, | ||
| &iam.DeleteServiceSpecificCredentialInput{ | ||
| UserName: awsStringUserName, | ||
| ServiceSpecificCredentialId: awsSdk.String(awsSdk.ToString(credential.ServiceSpecificCredentialId)), | ||
| }, | ||
| ) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("aws-connector: failed to delete service specific credential: %w", err) | ||
| } | ||
| } | ||
|
|
||
| // If user has MFA, deactivate them | ||
| // Permission needed: iam:ListMFADevices, iam:DeactivateMFADevice | ||
| mfaDevices, err := o.iamClient.ListMFADevices(ctx, &iam.ListMFADevicesInput{UserName: awsStringUserName}) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("aws-connector: failed to list MFA devices: %w", err) | ||
| } | ||
|
|
||
| for _, device := range mfaDevices.MFADevices { | ||
| _, err = o.iamClient.DeactivateMFADevice(ctx, &iam.DeactivateMFADeviceInput{UserName: awsStringUserName, SerialNumber: awsSdk.String(awsSdk.ToString(device.SerialNumber))}) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("aws-connector: failed to deactivate MFA device: %w", err) | ||
| } | ||
| } | ||
|
|
||
| // Delete users inline policies | ||
| // Permission needed: iam:ListUserPolicies, iam:DeleteUserPolicy | ||
| userPolicies, err := o.iamClient.ListUserPolicies(ctx, &iam.ListUserPoliciesInput{UserName: awsStringUserName}) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("aws-connector: failed to list user policies: %w", err) | ||
| } | ||
|
|
||
| for _, policy := range userPolicies.PolicyNames { | ||
| _, err = o.iamClient.DeleteUserPolicy(ctx, &iam.DeleteUserPolicyInput{UserName: awsStringUserName, PolicyName: awsSdk.String(policy)}) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("aws-connector: failed to delete user policy: %w", err) | ||
| } | ||
| } | ||
|
|
||
| // List and detach all attached policies | ||
| // Permission needed: iam:ListAttachedUserPolicies, iam:DetachUserPolicy | ||
| attachedPolicies, err := o.iamClient.ListAttachedUserPolicies(ctx, &iam.ListAttachedUserPoliciesInput{UserName: awsStringUserName}) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("aws-connector: failed to list attached user policies: %w", err) | ||
| } | ||
|
|
||
| for _, policy := range attachedPolicies.AttachedPolicies { | ||
| _, err = o.iamClient.DetachUserPolicy(ctx, &iam.DetachUserPolicyInput{UserName: awsStringUserName, PolicyArn: awsSdk.String(awsSdk.ToString(policy.PolicyArn))}) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("aws-connector: failed to detach user policy: %w", err) | ||
| } | ||
| } | ||
|
|
||
| // Remove the user from any IAM groups | ||
| // Permission needed: iam:ListGroupsForUser, iam:RemoveUserFromGroup | ||
| userGroups, err := o.iamClient.ListGroupsForUser(ctx, &iam.ListGroupsForUserInput{UserName: awsStringUserName}) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("aws-connector: failed to list groups for user: %w", err) | ||
| } | ||
|
|
||
| for _, group := range userGroups.Groups { | ||
| _, err = o.iamClient.RemoveUserFromGroup(ctx, &iam.RemoveUserFromGroupInput{UserName: awsStringUserName, GroupName: awsSdk.String(awsSdk.ToString(group.GroupName))}) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("aws-connector: failed to remove user from group: %w", err) | ||
| } | ||
| } | ||
|
|
||
| // Proceed to delete the user | ||
| // Permission needed: iam:DeleteUser | ||
| _, err = o.iamClient.DeleteUser(ctx, &iam.DeleteUserInput{UserName: awsStringUserName}) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("aws-connector: failed to delete user: %w", err) | ||
| } | ||
|
|
||
| return nil, nil | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.