Add script for batch deletion of AWS IAM users

This commit is contained in:
Ray Miller 2024-02-10 15:45:36 +00:00
parent 6b49d958d8
commit b117557525

125
aws/delete-iam-users.py Executable file
View file

@ -0,0 +1,125 @@
#!/usr/bin/python3
#
# Deleting a user programmatically requires deletion of several
# entities for each user:
#
# Password ( DeleteLoginProfile)
# Access keys ( DeleteAccessKey)
# Signing certificate ( DeleteSigningCertificate)
# SSH public key ( DeleteSSHPublicKey)
# Git credentials ( DeleteServiceSpecificCredential)
# Multi-factor authentication (MFA) device ( DeactivateMFADevice, DeleteVirtualMFADevice)
# Inline policies ( DeleteUserPolicy)
# Attached managed policies ( DetachUserPolicy)
# Group memberships ( RemoveUserFromGroup)
#
import argparse
import boto3
import botocore
iam_client = boto3.client("iam")
def list_all(paginator_name, collection_name, key_name, init_args):
result = []
paginator = iam_client.get_paginator(paginator_name)
for page in paginator.paginate(**init_args):
for item in page.get(collection_name, []):
if key_name:
result.append(item[key_name])
else:
result.append(item)
return result
def list_access_keys(user_name):
return list_all("list_access_keys", "AccessKeyMetadata", "AccessKeyId", {"UserName": user_name})
def list_signing_certificates(user_name):
return list_all("list_signing_certificates", "Certificates", "CertificateId", {"UserName": user_name})
def list_ssh_public_keys(user_name):
return list_all("list_ssh_public_keys", "SSHPublicKeys", "SSHPublicKeyId", {"UserName": user_name})
def list_mfa_devices(user_name):
return list_all("list_mfa_devices", "MFADevices", "SerialNumber", {"UserName": user_name})
def list_service_specific_credentials(user_name):
credential_ids = []
response = iam_client.list_service_specific_credentials(UserName=user_name)
for item in response.get("ServiceSpecificCredentials", []):
credential_ids.append(item["ServiceSpecificCredentialId"])
return credential_ids
def list_inline_policies(user_name):
return list_all("list_user_policies", "PolicyNames", None, {"UserName": user_name})
def list_attached_policies(user_name):
return list_all("list_attached_user_policies", "AttachedPolicies", "PolicyArn", {"UserName": user_name})
def list_groups(user_name):
return list_all("list_groups_for_user", "Groups", "GroupName", {"UserName": user_name})
def delete_user(user_name, dry_run=True):
print(f"Delete user {user_name}:")
user = iam_client.get_user(UserName=user_name)
try:
if not dry_run:
iam_client.delete_login_profile(UserName=user_name)
print(" Delete login profile")
except botocore.exceptions.ClientError as err:
if err.response["Error"]["Code"] != "NoSuchEntity":
raise
for key_id in list_access_keys(user_name):
if not dry_run:
iam_client.delete_access_key(UserName=user_name, AccessKeyId=key_id)
print(f" Delete access key {key_id}")
for cert_id in list_signing_certificates(user_name):
if not dry_run:
iam_client.delete_signing_certificate(UserName=user_name, CertificateId=cert_id)
print(f" Delete signing certificate {cert_id}")
for key_id in list_ssh_public_keys(user_name):
if not dry_run:
iam_client.delete_ssh_public_key(UserName=user_name, SSHPublicKeyId=key_id)
print(f" Delete SSH public key {key_id}")
for cred_id in list_service_specific_credentials(user_name):
if not dry_run:
iam_client.delete_service_specific_credential(UserName=user_name, ServiceSpecificCredentialId=cred_id)
print(f" Delete service-specific credential {cred_id}")
for serial_no in list_mfa_devices(user_name):
if not dry_run:
iam_client.deactivate_mfa_device(UserName=user_name, SerialNumber=serial_no)
iam_client.delete_virtual_mfa_device(SerialNumber=serial_no)
print(f" Delete MFA device {serial_no}")
for policy_name in list_inline_policies(user_name):
if not dry_run:
iam_client.delete_user_policy(UserName=user_name, PolicyName=policy_name)
print(f" Delete inline policy {policy_name}")
for policy_arn in list_attached_policies(user_name):
if not dry_run:
iam_client.detach_user_policy(UserName=user_name, PolicyArn=policy_arn)
print(f" Detach policy {policy_arn}")
for group_name in list_groups(user_name):
if not dry_run:
iam_client.remove_user_from_group(UserName=user_name, GroupName=group_name)
print(f" Remove user from group {group_name}")
if not dry_run:
iam_client.delete_user(UserName=user_name)
print(f" Deleted {user_name}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Delete IAM user(s)")
parser.add_argument("--dry-run", help="Show the actions that would be performed", action=argparse.BooleanOptionalAction, default=True)
parser.add_argument("user_names", nargs="+", )
args = parser.parse_args()
for user_name in args.user_names:
delete_user(user_name, args.dry_run)