[default]
aws_access_key_id = XXXXXXXXXXX
aws_secret_access_key = XXXXXXXXXXXXXXXXXXXXXXXXXXXX
[default]
region = eu-west-1
output = json
pip3 install Click==7.0 boto3
"""
rotator.py
Rotate AWS credentials, when MFA and role-based (assume role) access are in use.
Python requirements:
- boto3
- Click>=7.0
Run:
python3 rotator.py [aws-credentials-file] [MFA-device-arn] [MFA-token-from-device]
References:
https://docs.python.org/3/library/configparser.html
https://aws.amazon.com/premiumsupport/knowledge-center/authenticate-mfa-cli/
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sts.html#STS.Client.get_session_token
"""
import configparser
import os.path
import sys
import boto3
import click
''' Allowed values between 900 - 43200 sec (12 hrs). '''
TOKEN_DURATION = 43200
REGION = 'eu-west-1'
def get_tokens(mfa_device_arn=None, mfa_code=None):
""" Get new session tokens with AWS Security Token Service.
The default profile is used to get new tokens.
"""
session = boto3.Session(profile_name='default')
client = session.client('sts')
response = client.get_session_token(
DurationSeconds=TOKEN_DURATION,
SerialNumber=mfa_device_arn,
TokenCode=mfa_code
)
tokens = {
'output': 'json',
'region': REGION,
'aws_access_key_id': response['Credentials']['AccessKeyId'],
'aws_secret_access_key': response['Credentials']['SecretAccessKey'],
'aws_session_token': response['Credentials']['SessionToken']
}
print(f"Token expiration: {response['Credentials']['Expiration']}")
return tokens
@click.command()
@click.argument('credentials_file')
@click.argument('mfa_device_arn')
@click.argument('mfa_code')
def rotate(credentials_file, mfa_device_arn, mfa_code):
""" Rotate sessions tokens for AWS CLI. """
''' Check that the required parameters have values. '''
if not os.path.isfile(credentials_file):
print('Credentials file is missing!')
sys.exit()
if not mfa_device_arn.startswith('arn:aws:iam:'):
print('MFA Device ARN should have a correct value.')
sys.exit()
if len(mfa_code) != 6:
print('MFA Code should contain 6 characters.')
sys.exit()
''' Get the new session tokens from AWS. '''
tokens = get_tokens(mfa_device_arn, mfa_code)
''' Set the new tokens to credentials config file. '''
config = configparser.ConfigParser()
config.read(credentials_file)
config['mfa'] = tokens
with open(credentials_file, 'w') as configfile:
config.write(configfile)
print('New session tokens have been set successfully.')
sys.exit()
if __name__ == '__main__':
rotate()
python3 rotator.py [aws-credentials-file] [MFA-device-arn] [MFA-token-from-device]
For example:
# The ARN must contain mfa/<YourUserName>
python3 rotator.py ~/.aws/credentials arn:aws:iam::12xxxxxxxxx:mfa/achintyak 445334
export AWS_PROFILE=mfa
aws s3 ls