Add script for batch deletion of AWS IAM users
This commit is contained in:
parent
6b49d958d8
commit
b117557525
1 changed files with 125 additions and 0 deletions
125
aws/delete-iam-users.py
Executable file
125
aws/delete-iam-users.py
Executable 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)
|
Loading…
Reference in a new issue