This script is designed to check for inactive IAM (Identity and Access Management) users within a specified AWS account. It utilizes the AWS SDK for Python (Boto3) to retrieve user data and provides information about the last console access and last programmatic access for each user.

Code

"""
AWS IAM User Inactivity Checker
Author: Mario Lechończak (mario at lechonczak.pl)
"""

import csv
import sys
from datetime import datetime
import boto3
import pytz


# Define variable
max_date = sys.argv[1]
AWS_PROFILE = sys.argv[2]
AWS_REGION = "eu-central-1"



# Initialize session
session = boto3.Session(profile_name=AWS_PROFILE)
iam = session.client('iam', region_name=AWS_REGION)


def get_inactive_iam_users(max_date):
    # Get list of users
    users = iam.list_users()['Users']
    user_data = []
    target_date = datetime.strptime(max_date, "%Y-%m-%d").replace(tzinfo=pytz.UTC)

    for user in users:
        create_date = user['CreateDate']
        # use create_date if PasswordLastUsed is not available
        last_used_date = user.get('PasswordLastUsed', create_date)

        if create_date <= target_date and last_used_date <= target_date:
            # Get the last console access date
            last_console_access_response = iam.get_user(UserName=user['UserName'])
            last_console_access = last_console_access_response['User'].get('PasswordLastUsed', None)

            # Get list of access keys
            access_keys = iam.list_access_keys(UserName=user['UserName'])['AccessKeyMetadata']

            last_key_used_date = datetime.min.replace(tzinfo=pytz.UTC) # Initialize to a minimum date

            for key in access_keys:
                # Get last used date of access key
                last_used_response = iam.get_access_key_last_used(AccessKeyId=key['AccessKeyId'])
                if last_used_response['AccessKeyLastUsed'].get('LastUsedDate') is not None:
                    last_key_used_date = max(
                        last_key_used_date,
                        last_used_response['AccessKeyLastUsed'].get('LastUsedDate')
                        )

            # If last used date of any key is more recent than the target date,
            # move to the next user

            if last_key_used_date >= target_date:
                continue

            if last_key_used_date == datetime.min.replace(tzinfo=pytz.UTC):
                last_key_used_date = None

            user_data.append([user['UserName'], str(last_console_access), str(last_key_used_date)])
    return user_data

def save_user_info_to_csv(user_data):
    current_date = datetime.now().strftime("%Y-%m-%d")
    filename = f"output_{AWS_PROFILE}_{current_date}.csv"

    with open(filename, mode='w', newline='', encoding="utf-8") as csv_file:
        writer = csv.writer(csv_file)
        writer.writerow(["User", "Last Console Access", "Last Programmatic Access"])
        for user_info in user_data:
            writer.writerow(user_info)

def print_inactive_iam_users(user_data):
    print(f"{'User':<20}{'Last Console Access':<25}{'Last Programmatic Access':<25}")
    for user_info in user_data:
        user = user_info[0]
        last_console_access = user_info[1]
        last_programmatic_access = user_info[2]
        print(f"{user:<20}{last_console_access:<25}{last_programmatic_access:<25}")

if __name__ == "__main__":
    get_inactive_iam_users(max_date)
    print_inactive_iam_users(get_inactive_iam_users(max_date))
    save_user_info_to_csv(get_inactive_iam_users(max_date))

Functions

get_inactive_iam_users(max_date)

This function retrieves and identifies inactive IAM users based on a specific target date. It takes in the max_date parameter, which represents the target date in “YYYY-MM-DD” format. The function first initializes the AWS session using the provided AWS profile name and region. It then uses the IAM client to fetch information about all IAM users in the account. For each user, it checks if their creation date and last used date (either console access or programmatic access) are before or on the target date. If both dates are before or on the target date, the user is considered inactive. The function compiles a list of user data for inactive users, including their username, last console access date, and last programmatic access date.

print(get_inactive_iam_users(max_date))

[['user1', 'None', '2023-02-10 18:16:00+00:00'], ['user2', 'None', '2023-10-27 17:50:00+00:00'], ['user3', 'None', '2023-08-17 06:26:00+00:00']]

save_user_info_to_csv(user_data)

This function saves the user data obtained from get_inactive_iam_users to a CSV file. It takes in the user_data parameter, which is a list of user data to be saved to the CSV file. The function also uses the AWS_PROFILE and current_date variables to generate a filename for the CSV file. It opens the file in write mode and creates a CSV writer object. It writes a header row with column names: “User,” “Last Console Access,” and “Last Programmatic Access.” It then iterates over the user data list and writes each user’s information as a row in the CSV file.

mario@local:~$ cat output_personal_2023_10_31.csv
User,Last Console Access,Last Programmatic Access
user1,None,2023-02-10 18:16:00+00:00
user2,None,2023-10-27 17:50:00+00:00
user3,None,2023-08-17 06:26:00+00:00

This function prints the user data obtained from get_inactive_iam_users in a tabular format for easy readability. It takes in the user_data parameter, which is a list of user data to be displayed in the tabular format. The function uses string formatting to align the data within columns. It prints a header row with column names: “User,” “Last Console Access,” and “Last Programmatic Access.” It then iterates over the user data list and prints each user’s information as a row in the tabular format.

mario@local:~$ python3 main.py 2023-10-31 personal
User                Last Console Access      Last Programmatic Access
user1               None                     2023-02-10 18:16:00+00:00
user2               None                     2023-10-27 17:50:00+00:00
user3               None                     2023-08-17 06:26:00+00:00

Usage

To use this script, you need to provide two command line arguments:

max_date: The target date in “YYYY-MM-DD” format to determine user inactivity.

AWS_PROFILE: The AWS profile name used to initialize the session.

Here is an example command to run the script:

python3 main.py 2022-01-01 my-aws-profile

The script will retrieve the inactive IAM users based on the provided target date, print their data in a tabular format, and save the data to a CSV file named output_<AWS_PROFILE>_<current_date>.csv. The CSV file includes the user data with columns User, Last Console Access, and Last Programmatic Access.