Source code for awscli_bastion.rotate
from configparser import ConfigParser
import click
import boto3
import pathlib
import time
import sys
[docs]class Rotate:
""" Manages the creation, verification, deletion or deactivation, replacment of aws access keys for the bastion account. """
def __init__(self, deactivate=False, username=None, bastion="bastion", bastion_sts="bastion-sts", region="us-west-2", credentials=None):
self.deactivate = deactivate
self.bastion = bastion
self.region = region
self.credentials = credentials
try:
self.bastion_session = boto3.Session(profile_name=bastion,region_name=self.region)
self.bastion_sts_session = boto3.Session(profile_name=bastion_sts,region_name=self.region)
iam = self.bastion_session.client("iam")
self.username = username if username else iam.get_user()["User"]["UserName"]
except Exception as e:
print(e)
sys.exit(1)
[docs] def create_access_key(self):
""" Create aws access key for the bastion profile. """
try:
iam_client = self.bastion_sts_session.client("iam")
return iam_client.create_access_key(UserName=self.username)
except Exception as e:
print(e)
sys.exit(1)
[docs] def is_active(self, access_key):
""" Ensure that aws access key is active.
:param access_key: The aws access key to verify activation.
:type access_key: str
:return: Whether or not the aws access key is active.
:rtype: bool
"""
# https://github.com/boto/boto3/issues/2133
# iam = boto3.resource('iam')
# return iam.AccessKey('user_name', access_key.access_key_id).status == "Active"
return True
[docs] def retire_bastion_access_key(self):
"""
Retire aws access key for the bastion profile.
By default, this means deletion. Specify the 'deactivate' class variable to deactivate.
"""
bastion_aws_access_key_id = self.credentials.config.get(
self.bastion, 'aws_access_key_id', fallback=None)
iam = self.bastion_sts_session.resource("iam")
access_key = iam.AccessKey(self.username, bastion_aws_access_key_id)
if self.deactivate:
access_key.deactivate()
else:
access_key.delete()
self.credentials.config[self.bastion]["aws_access_key_id"] = ""
self.credentials.config[self.bastion]["aws_secret_access_key"] = ""
[docs] def write(self, access_key):
""" Write access key to the bastion profile in the aws share credentials file.
:param access_key: The aws access key access key to write.
:type access_key: str
"""
self.credentials.config[self.bastion]["aws_access_key_id"] = access_key["AccessKey"]["AccessKeyId"]
self.credentials.config[self.bastion]["aws_secret_access_key"] = access_key["AccessKey"]["SecretAccessKey"]
self.credentials.write()
[docs] def rotate(self):
""" Rotate aws access key credentials for the bastion profile. """
access_key = self.create_access_key()
if self.is_active(access_key):
self.retire_bastion_access_key()
self.write(access_key)
click.echo("Rotating long-lived credentials for the {} profile.".format(self.bastion))
else:
click.echo("There was a problem creating the new long-lived credentials. Will not rotate current credentials.")
sys.exit(1)