Rotating AWS Access Keys as a Distributed Team.

By Mark McKenzie

Who doesn’t love rotating access keys?

If you are anything like us at Vizibl, January brings about another security audit with external penetration testing and AWS account audits.

Rotating AWS access keys across the team has become increasingly tricky as we become more of a distributed team.

Our solution was to enable team members to rotate their own access keys at their own discretion.

In order to facilitate this, you first need to create a new policy for each user that has an access key.$new?step=edit

When creating this policy we typical give it the same name as the user. The following policy JSON assumes an IAM user is to be granted permission to get, modify, create and delete access keys for the IAM arn for user joebloggs.

Note that the arn: arn:aws:iam::210000000:user/joebloggs will be unique for your account and you can find this on the user IAM page.
"Version": "2012-10-17",
"Statement": [
"Action": [
"Effect": "Allow",
"Resource": [

Once you have done this the user can then use the following script to rotate access keys from their machine.


get_user_name() {
aws sts get-caller-identity \
--query Arn \
--output text | cut -f 2 -d /

get_access_keys() {
aws iam list-access-keys \
--user-name "$1" \
--query 'AccessKeyMetadata[].AccessKeyId' \
--output text

create_new_access_key() {
aws iam create-access-key \
--query '[AccessKey.AccessKeyId,AccessKey.SecretAccessKey]' \
--output text | awk '{ print "AWS_ACCESS_KEY_ID=\"" $1 "\"\n" "AWS_SECRET_ACCESS_KEY=\"" $2 "\"" }'

delete_keys_from_aws() {
for key in "$@"; do
aws iam delete-access-key \
--access-key-id "${key}"

set -eu -o pipefail

access_keys="$(get_access_keys "${username}")"
delete_keys_from_aws ${access_keys}

This script will rotate the access keys for the currently configured AWS user removing the old access keys and printing the new ones into the terminal.

$ bash
$ aws configure
AWS Access Key ID [****************key]: access_key
AWS Secret Access Key [****************key]: secret_key
Default region name [eu-west-1]:
Default output format [None]:

That’s it! There are a couple of improvements you could make that were not suitable for our needs. Such as, having the script modify the config file rather than requiring the additional step aws configure.