diff --git a/aws/iam-last-activity.py b/aws/iam-last-activity.py new file mode 100755 index 0000000..c4c11a9 --- /dev/null +++ b/aws/iam-last-activity.py @@ -0,0 +1,91 @@ +#!/usr/bin/python3 +import boto3 +import jmespath +import time +import re +import json +from pprint import pprint +from jmespath.exceptions import JMESPathTypeError + + +# dump user/group/role last activity + +def generateLastAccessed(myclient, arn, myAccountId: str): + response = myclient.generate_service_last_accessed_details( + Arn=arn, + Granularity='SERVICE_LEVEL') + jobId = response.get("JobId") + accessDetails = client.get_service_last_accessed_details(JobId=jobId, MaxItems=20) + while True: + time.sleep(2) + accessDetails = client.get_service_last_accessed_details(JobId=jobId, MaxItems=20) + if accessDetails.get("JobStatus") != "COMPLETED": + continue + else: + break + r2 = client.list_policies_granting_service_access( + Arn=arn, + ServiceNamespaces=jmespath.search("ServicesLastAccessed[*].ServiceNamespace", accessDetails) + ) + returnString = [] + try: + for p in jmespath.search( + f"PoliciesGrantingServiceAccess[*].Policies[?contains(PolicyArn,'${myAccountId}')].PolicyArn", r2): + if len(p) > 0: + returnString.append(p[0]) + except JMESPathTypeError: + pass + return list(dict.fromkeys(returnString)) + + +sts = boto3.client('sts') +accountId = sts.get_caller_identity()["Account"] + +client = boto3.client('iam') +print("=" * 40) +print("** Users **") +print("=" * 40) +entity = client.list_users() +for u in jmespath.search("Users[*]", entity): + accessKeyQuery = client.list_access_keys(UserName=u.get('UserName')) + keys = accessKeyQuery.get("AccessKeyMetadata") + print("UserName", u.get("UserName"), sep=": ") + print("CreateDate", u.get("CreateDate"), sep=": ") + print("PasswordLastUsed", u.get("PasswordLastUsed"), sep=": ") + doPolicyLastUsed = False if u.get("PasswordLastUsed") is None else True + for k in accessKeyQuery.get("AccessKeyMetadata"): + print("AccessKeyId", k.get("AccessKeyId"), sep=": ") + print("AccessKeyStatus", k.get("Status"), sep=": ") + if k.get("Status") == "Inactive": + doPolicyLastUsed = False + print("AccessKeyCreateDate", k.get("CreateDate"), sep=": ") + akLastUsedQuery = client.get_access_key_last_used(AccessKeyId=k.get("AccessKeyId")) + print("AccessKeyLastUsed", akLastUsedQuery.get("AccessKeyLastUsed").get("LastUsedDate"), sep=": ") + if doPolicyLastUsed: + print("CustomerPolicyLastUsed", generateLastAccessed(client, u.get("Arn"), accountId), sep=": ") + print("-" * 10) + +print("=" * 40) +print("** Groups **") +print("=" * 40) +entity = client.list_groups() +print("GroupName", "CreateDate", sep=",") +for g in jmespath.search("Groups[*]", entity): + print(g.get("GroupName"), g.get("CreateDate"), sep=", ") + +print("=" * 40) +print("** Roles **") +print("=" * 40) +entity = client.list_roles() +for r in jmespath.search("Roles[*]", entity): + if re.match("^/.*service-role/.*", r.get("Path")) is not None or re.match("^/aws-reserved/", + r.get("Path")) is not None: + continue + getRoleQuery = client.get_role(RoleName=r.get("RoleName")) + r1 = getRoleQuery.get("Role") + print("RoleName", r1.get("RoleName"), sep=": ") + print("CreateDate", r1.get("CreateDate"), sep=": ") + print("RoleLastUsed", jmespath.search("RoleLastUsed.LastUsedDate", r1), sep=": ") + if jmespath.search("RoleLastUsed.LastUsedDate", r1) is not None: + print("CustomerPolicyLastUsed", generateLastAccessed(client, r1.get("Arn"), accountId), sep=": ") + print("-" * 10)