Boto3: Python script to find AWS IAM access keys older than 90 days

To access AWS programmatically via CLI or api, we can use IAM access keys provided by AWS. The access key consists of an access key ID and a secret access key. We can generate these keys in the IAM console and configure these keys in our local laptop by running aws configure command.

These keys are very confidential and should not be shared it with anyone as it’s equivalent to your AWS console username and password. As a best practice, AWS recommends to rotate these keys every 90 days.

Access key age

We can check the age of the access keys in IAM users page. IAM page highlights the access key age in different colors based on the access key creation date.

If the access key is created

  • less than 90 days ago – Green
  • 91-365 days ago – Yellow (Warning )
  • more than 365 days ago – Red (Danger)
AWS IAM users page shows access keys age
AWS IAM users page highlights access key age

We can refer the IAM page if I have few users. But if the number of users are more than 100, it is not feasible to scroll through each user and check their key age.

To automate this, I created a python script using boto3 to print the details of access key id which are older than 90 days along with their owners, key age information.

Boto3 script

""" This script will print the list of access keys older than 90 days.
Author: Kannan Anandakrishnan
Requirements: boto3 package installed, standard libraries - datetime, csv, and aws credentials configured.
"""

import datetime, boto3, csv

IAM = boto3.client('iam')

def access_key(user):

    """List the access key(s) of every user. Then iterate over the keys and pass the created date to time_diff()
    CreateDate of Access Key is a datetime object. Passing it as an input to time_diff func to get the age in days.
       Parameters: user (string) : Username of IAM user
    """
    keydetails=IAM.list_access_keys(UserName=user)

    # Some user may have 2 access keys. So iterating over them and listing the details of active access key.
    for keys in keydetails['AccessKeyMetadata']:
        if keys['Status']=='Active' and (time_diff(keys['CreateDate'])) >= 90:
            print (keys['UserName'],keys['AccessKeyId'], time_diff(keys['CreateDate']),sep=',')

def time_diff(keycreatedtime):
    # Getting the current time in utc format
    now=datetime.datetime.now(datetime.timezone.utc)

	# Calculating diff between two datetime objects.
    diff=now-keycreatedtime
    # Returning the difference in days
    return diff.days
	

if __name__ == '__main__':
    """ In this main function, we are fetching the users from IAM and passing the username to access_key() """
    
    # This returns a dictionary response
    details = IAM.list_users(MaxItems=300)

    # Header information
    print ("Username","AccessKey","KeyAge",sep=',')
    for user in details['Users']:
        access_key(user['UserName'])

When you run the script, you will get an output as shown below.

Username,AccessKey,KeyAge
user1,AKGHFIWHBFHDNBDSDIFKS,477
user2,AKRHUTN578DG123BAUTM,136
user3,AKRHUTN57HUYTW3BAUTM,292
user4,A2DBYQERNMOUTHAVSNWA,249
user5,ARANDOMLETTERSTYPED,264
user6,AHOLLAMI421AMOR921DNB,444

Further enhancements

  • We can integrate Sendgrid or SES with this script to mail the users notifying to rotate the access keys.
  • We can automatically disable and delete the access keys which are more than 90 days old.

If you like this post, please like it/share it using the social plugins below. Your valuable comments and feedback are always welcome!

You can also subscribe to this blog to get notified of new posts by email.

Leave a Reply

Your email address will not be published. Required fields are marked *