Created
August 14, 2024 09:01
-
-
Save gauravtoshniwal1989/8cd0daa51a055a4f20e92f7235e8213a to your computer and use it in GitHub Desktop.
Use this script (carefully) to find IAM Policies not attached to any entity
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
import boto3 | |
from datetime import datetime as dt | |
import os | |
from tqdm import tqdm | |
import json | |
import datetime | |
def datetime_handler(x): | |
if isinstance(x, dt): | |
return x.isoformat() | |
raise TypeError("Unknown type") | |
class AWSIAMDiscovery: | |
def __init__(self, region_name, aws_profile): | |
self.session = boto3.Session(profile_name=aws_profile, region_name=region_name) | |
self.iam_client = self.session.client("iam") | |
def get_iam_users(self): | |
users = [] | |
paginator = self.iam_client.get_paginator("list_users") | |
for page in tqdm(paginator.paginate(), desc="Fetching IAM Users"): | |
for user in page["Users"]: | |
user_info = { | |
"UserName": user["UserName"], | |
"UserId": user["UserId"], | |
"Arn": user["Arn"], | |
"CreateDate": user["CreateDate"], | |
"PasswordLastUsed": user.get("PasswordLastUsed", "N/A"), | |
"AccessKeys": [], | |
"AttachedPolicies": [], | |
"Groups": [], | |
} | |
# Get access keys | |
access_keys = self.iam_client.list_access_keys( | |
UserName=user["UserName"] | |
)["AccessKeyMetadata"] | |
user_info["AccessKeys"] = [ | |
{"AccessKeyId": key["AccessKeyId"], "Status": key["Status"]} | |
for key in access_keys | |
] | |
# Get attached policies | |
attached_policies = self.iam_client.list_attached_user_policies( | |
UserName=user["UserName"] | |
)["AttachedPolicies"] | |
user_info["AttachedPolicies"] = [ | |
policy["PolicyName"] for policy in attached_policies | |
] | |
# Get group memberships | |
groups = self.iam_client.list_groups_for_user( | |
UserName=user["UserName"] | |
)["Groups"] | |
user_info["Groups"] = [group["GroupName"] for group in groups] | |
users.append(user_info) | |
return users | |
def get_iam_roles(self): | |
roles = [] | |
paginator = self.iam_client.get_paginator("list_roles") | |
for page in tqdm(paginator.paginate(), desc="Fetching IAM Roles"): | |
for role in page["Roles"]: | |
role_info = { | |
"RoleName": role["RoleName"], | |
"RoleId": role["RoleId"], | |
"Arn": role["Arn"], | |
"CreateDate": role["CreateDate"], | |
"AssumeRolePolicyDocument": role["AssumeRolePolicyDocument"], | |
"AttachedPolicies": [], | |
} | |
# Get attached policies | |
attached_policies = self.iam_client.list_attached_role_policies( | |
RoleName=role["RoleName"] | |
)["AttachedPolicies"] | |
role_info["AttachedPolicies"] = [ | |
policy["PolicyName"] for policy in attached_policies | |
] | |
roles.append(role_info) | |
return roles | |
def get_iam_policies(self): | |
policies = [] | |
paginator = self.iam_client.get_paginator("list_policies") | |
for page in tqdm( | |
paginator.paginate(Scope="Local"), desc="Fetching IAM Policies" | |
): | |
for policy in page["Policies"]: | |
policy_info = { | |
"PolicyName": policy["PolicyName"], | |
"PolicyId": policy["PolicyId"], | |
"Arn": policy["Arn"], | |
"CreateDate": policy["CreateDate"], | |
"UpdateDate": policy["UpdateDate"], | |
"PolicyDocument": None, | |
"AttachedEntities": {"Users": [], "Groups": [], "Roles": []}, | |
} | |
# Get policy document | |
policy_version = self.iam_client.get_policy_version( | |
PolicyArn=policy["Arn"], VersionId=policy["DefaultVersionId"] | |
) | |
policy_info["PolicyDocument"] = policy_version["PolicyVersion"][ | |
"Document" | |
] | |
# Get attached entities | |
entities = self.iam_client.list_entities_for_policy( | |
PolicyArn=policy["Arn"] | |
) | |
policy_info["AttachedEntities"]["Users"] = [ | |
user["UserName"] for user in entities["PolicyUsers"] | |
] | |
policy_info["AttachedEntities"]["Groups"] = [ | |
group["GroupName"] for group in entities["PolicyGroups"] | |
] | |
policy_info["AttachedEntities"]["Roles"] = [ | |
role["RoleName"] for role in entities["PolicyRoles"] | |
] | |
policies.append(policy_info) | |
return policies | |
def get_unattached_policies(self, policies): | |
return [ | |
policy | |
for policy in policies | |
if not any(policy["AttachedEntities"].values()) | |
] | |
def discover_all(self): | |
iam_users = self.get_iam_users() | |
iam_roles = self.get_iam_roles() | |
iam_policies = self.get_iam_policies() | |
unattached_policies = self.get_unattached_policies(iam_policies) | |
print(f"\nFound {len(unattached_policies)} unattached policies:") | |
for policy in unattached_policies: | |
print(f"- {policy['PolicyName']} (ARN: {policy['Arn']})") | |
delte_unattached_policies = input( | |
"Do you want to delete them? (yes_really_sure/n): " | |
) | |
if delte_unattached_policies.lower() == "yes_really_sure": | |
for policy in unattached_policies: | |
self.iam_client.delete_policy(PolicyArn=policy["Arn"]) | |
print(f"Deleted policy: {policy['PolicyName']} (ARN: {policy['Arn']})") | |
return iam_users, iam_roles, iam_policies | |
# Usage | |
if __name__ == "__main__": | |
discoverer = AWSIAMDiscovery("ap-south-1", os.getenv("AWS_PROFILE")) | |
users, roles, policies = discoverer.discover_all() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment