AWS Access Key rotation for IAM Users | Boto3 Script

Overview

Rotate your AWS API access keys using this Boto3 script for IAM users that I wrote. Optional arguments include create, update, delete, and list access keys. When applying the create new 🔑 feature, the user is prompted whether or not to overwrite their existing ~/.aws/credentials file contents with the [default] profile, newly created access key ID and secret. If they enter 'n', the new key is still created however, the user will need to update their credentials file manually with the new key ID and secret when ready to use it locally.

Although this AWS blog post is 10 years old, I still find it to be the most succinct procedure explaining how to rotate your access keys. Highlighting the general steps to follow from the post below which should be considered when using this script:

To rotate access keys, you should follow these steps:

  1. Create a second access key in addition to the one in use.

  2. Update all your applications to use the new access key and validate applications are working.

  3. Change the state of the previous access key to inactive.

  4. Validate that your applications are still working as expected.

  5. Delete the inactive access key.

Purpose

AWS access keys should be treated like any other security credentials you use daily. Just as it's best practice to change your password regularly, the same treatment should be applied to your access keys. Regularly rotating your keys helps mitigate the potential risk of a security breach occurring within your cloud estate should your keys become compromised.

Script Functionality

Link to script: https://github.com/jksprattler/aws-security/blob/main/scripts/aws_iam_self_service_key_rotation.py

Here's a look at the options available from the -h/--help output:

❯ python aws_iam_self_service_key_rotation.py -h
usage: aws_iam_self_service_key_rotation.py [-h] [-c] [-u UPDATE UPDATE] [-d DELETE] [-l]

create|update|delete|list API access keys

optional arguments:
  -h, --help            show this help message and exit
  -c, --create          create access key
  -u UPDATE UPDATE, --update UPDATE UPDATE
                        update access key; 2 expected inputs: <keyID> <active|inactive>
  -d DELETE, --delete DELETE
                        delete access key; 1 expected input: <keyID>
  -l, --list            list access key ID, status, creation date

Here's a list of my current access key(s):

❯ python aws_iam_self_service_key_rotation.py -l
Key:        ****************4NOP
Status:     Active
Created:    2023-02-19 14:51:31+00:00

Following the general steps outlined in the Overview section above, I'll go ahead and create a new access key since I only have 1 currently and there's a limit of 2 you can have at one time:

❯ python aws_iam_self_service_key_rotation.py -c
New Key:        ****************QJLD
Secret:         ****************Epm2

Metadata response output:
{'AccessKey': {'UserName': 'jslabs', 'AccessKeyId': '****************QJLD', 'Status': 'Active', 'SecretAccessKey': '****************Epm2', 'CreateDate': datetime.datetime(2023, 4, 13, 20, 58, 23, tzinfo=tzutc())}, 'ResponseMetadata': {'RequestId': '12345678-79aa-4f83-a17e-cee94d4d51f2', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amzn-requestid': '12345678-79aa-4f83-a17e-cee94d4d51f2', 'content-type': 'text/xml', 'content-length': '598', 'date': 'Thu, 13 Apr 2023 20:58:22 GMT'}, 'RetryAttempts': 0}} 

Update /home/jenna/.aws/credentials file w/ new key (y/n)? Warning: File contents will be overwritten! y

Updated /home/jenna/.aws/credentials file contents:
[default]
aws_access_key_id = ****************QJLD
aws_secret_access_key = ****************Epm2

At this point, you should update all of your applications to use the new key. Update your ~/.aws/credentials file manually if needed or run aws configure

Next, we'll update the status of the old key to inactive and check that the status has been updated:

❯ python aws_iam_self_service_key_rotation.py -u ****************4NOP inactive
Metadata response output:
{'ResponseMetadata': {'RequestId': '12345678-5823-4038-be27-63b574b41359', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amzn-requestid': '12345678-5823-4038-be27-63b574b41359', 'content-type': 'text/xml', 'content-length': '210', 'date': 'Thu, 13 Apr 2023 21:04:12 GMT'}, 'RetryAttempts': 0}}
❯ python aws_iam_self_service_key_rotation.py -l
Key:        ****************QJLD
Status:     Active
Created:    2023-04-13 20:58:23+00:00

Key:        ****************4NOP
Status:     Inactive
Created:    2023-02-19 14:51:31+00:00

Once we've validated our applications are working as expected with the new key, we can proceed with deleting the old/inactive key and validate we're left with the 1 active/in-use key:

❯ python aws_iam_self_service_key_rotation.py -d ****************4NOP
****************4NOP has been deleted!

Metadata response output:
{'ResponseMetadata': {'RequestId': '12345678-21d2-4f42-b0ff-9e26d4ff5a02', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amzn-requestid': '12345678-21d2-4f42-b0ff-9e26d4ff5a02', 'content-type': 'text/xml', 'content-length': '210', 'date': 'Thu, 13 Apr 2023 21:08:19 GMT'}, 'RetryAttempts': 0}}
❯ python aws_iam_self_service_key_rotation.py -l
Key:        ****************QJLD
Status:     Active
Created:    2023-04-13 20:58:23+00:00

Conclusion

You now have a self-service tool for your AWS IAM users to use for rotating their access keys on an as-needed basis. Although there are more automated approaches out there for AWS key rotation, I like the option of giving users some control over how and when to update their keys.

Hope you've found this useful! Let me know in the comments what you think and how this script could be improved. As an extension to this tool, I'm looking into creating a Lambda function that automatically expires access keys older than 90 days and includes an 📨 notification to users that their keys are expiring via SES so stay tuned for that!