|
@@ -0,0 +1,113 @@
|
|
|
+#!/usr/bin/env python3
|
|
|
+"""
|
|
|
+Delete an IAM User from an AWS Account.
|
|
|
+
|
|
|
+Copyright (c) 2019 TKalus <tkalus@users.noreply.github.com>
|
|
|
+
|
|
|
+Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
|
+this software and associated documentation files (the "Software"), to deal in
|
|
|
+the Software without restriction, including without limitation the rights to
|
|
|
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
|
+the Software, and to permit persons to whom the Software is furnished to do so,
|
|
|
+subject to the following conditions:
|
|
|
+
|
|
|
+The above copyright notice and this permission notice shall be included in all
|
|
|
+copies or substantial portions of the Software.
|
|
|
+
|
|
|
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
|
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
|
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
|
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
+
|
|
|
+SOURCE: https://gist.github.com/tkalus/e91c1d2d68bff68e9c6fa2b8ab2f5485
|
|
|
+"""
|
|
|
+
|
|
|
+import logging
|
|
|
+import sys
|
|
|
+
|
|
|
+import boto3.session
|
|
|
+import botocore.exceptions
|
|
|
+
|
|
|
+logger = logging.getLogger(__file__)
|
|
|
+
|
|
|
+
|
|
|
+def delete_iam_user(session: boto3.session.Session, user_name: str) -> None:
|
|
|
+ """For a given boto3.session.Session, delete the IAM User and all assoc'd resources."""
|
|
|
+ iam = session.resource("iam")
|
|
|
+ iam_client = session.client("iam")
|
|
|
+ user = iam.User(user_name)
|
|
|
+ try:
|
|
|
+ user.load()
|
|
|
+ except botocore.exceptions.ClientError as err:
|
|
|
+ # If load failed with NoSuchEntity, IAM User doesn't exist.
|
|
|
+ if err.response.get("Error", {}).get("Code", "") == "NoSuchEntity":
|
|
|
+ logger.error(f"User {user_name} does not exist")
|
|
|
+ return
|
|
|
+ raise err
|
|
|
+ logger.debug(f"Deleting IAM User: {user.arn}")
|
|
|
+ for group in user.groups.all():
|
|
|
+ logger.debug(f"Removing {user.arn} from Group {group.arn}")
|
|
|
+ user.remove_group(GroupName=group.name)
|
|
|
+ try:
|
|
|
+ login_profile = iam.LoginProfile(user.name)
|
|
|
+ login_profile.load()
|
|
|
+ logger.debug(f"Deleting Login Profile (I.E. Password) from {user.arn}")
|
|
|
+ login_profile.delete()
|
|
|
+ except botocore.exceptions.ClientError as err:
|
|
|
+ # If load failed with NoSuchEntity, No Login Profile
|
|
|
+ if err.response.get("Error", {}).get("Code", "") != "NoSuchEntity":
|
|
|
+ raise err
|
|
|
+ for device in user.mfa_devices.all():
|
|
|
+ logger.debug(f"Removing MFA Device from {user.arn}: {device.serial_number}")
|
|
|
+ device.disassociate()
|
|
|
+ for access_key in user.access_keys.all():
|
|
|
+ logger.debug(f"Deleting Access Key from {user.arn}: {access_key.access_key_id}")
|
|
|
+ access_key.delete()
|
|
|
+ for policy in user.policies.all():
|
|
|
+ logger.debug(f"Deleting Inline Policy from {user.arn}: {policy.name}")
|
|
|
+ policy.delete()
|
|
|
+ for policy in user.attached_policies.all():
|
|
|
+ logger.debug(f"Detatching Managed Policy from {user.arn}: {policy.arn}")
|
|
|
+ user.detach_policy(PolicyArn=policy.arn)
|
|
|
+ for cert in user.signing_certificates.all():
|
|
|
+ logger.debug(f"Deleting Signing Cert from {user.arn}: {cert.id}")
|
|
|
+ iam_client.delete_signing_certificate(UserName=user.name, CertificateId=cert.id)
|
|
|
+ for ssh_public_key_id in [
|
|
|
+ key.get("SSHPublicKeyId", "")
|
|
|
+ for key in iam_client.list_ssh_public_keys(UserName=user.name).get(
|
|
|
+ "SSHPublicKeys", []
|
|
|
+ )
|
|
|
+ ]:
|
|
|
+ logger.debug(f"Deleting SSH Public Key from {user.arn}: {ssh_public_key_id}")
|
|
|
+ iam_client.delete_ssh_public_key(
|
|
|
+ UserName=user.name, SSHPublicKeyId=ssh_public_key_id
|
|
|
+ )
|
|
|
+ for service_name, service_specific_credential_id in {
|
|
|
+ cred.get("ServiceName", ""): cred.get("ServiceSpecificCredentialId", "")
|
|
|
+ for cred in iam_client.list_service_specific_credentials(
|
|
|
+ UserName=user.name
|
|
|
+ ).get("ServiceSpecificCredentials", [])
|
|
|
+ }.items():
|
|
|
+ logger.debug(
|
|
|
+ f"Deleting Service Specific Cred from {user.arn}:"
|
|
|
+ f" {service_name}:{service_specific_credential_id}"
|
|
|
+ )
|
|
|
+ iam_client.delete_service_specific_credential(
|
|
|
+ UserName=user.name,
|
|
|
+ ServiceSpecificCredentialId=service_specific_credential_id,
|
|
|
+ )
|
|
|
+ logger.info(f"Deleted IAM user: {user.name}")
|
|
|
+ user.delete()
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
|
|
|
+ logging.getLogger("boto3").setLevel(logging.ERROR)
|
|
|
+ logging.getLogger("botocore").setLevel(logging.ERROR)
|
|
|
+ logging.getLogger("urllib3").setLevel(logging.ERROR)
|
|
|
+ session = boto3.session.Session()
|
|
|
+ user_name = dict(enumerate(sys.argv)).get(1)
|
|
|
+ if user_name:
|
|
|
+ delete_iam_user(session, user_name)
|