Source code for awscli_bastion.minimal
"""
If you are like me, you do not trust open-source tools and libraries to handle admin
credentials for your aws accounts. awscli_bastion/minimal.py is written as a script that offers
minimal bastion functionality. It is intended to be quick and easy to understand.
A minimal number of python libraries are used to reduce security risks.
"""
import boto3
import configparser
import pathlib
import random
import sys
[docs]def main():
##############
# Set defaults
##############
bastion = "bastion"
bastion_sts = "bastion-sts"
aws_shared_credentials_path = "{}/.aws/credentials".format(pathlib.Path.home())
token_code = None
#################
# Parse arguments
#################
args = sys.argv[1:]
if len(args) == 0:
print("python auth.py ASSUME_ROLE_PROFILE TOKEN_CODE")
print("python auth.py dev-admin 123456")
print("python auth.py dev-admin")
sys.exit(1)
if len(args) >= 1:
assume_role_profile = args[0]
if len(args) >= 2:
token_code = args[1]
##################################
# Read aws shared credentials file
##################################
config = configparser.ConfigParser()
config.read(aws_shared_credentials_path)
#######################
# STS get session token
#######################
if token_code:
try:
bastion_client = boto3.Session(profile_name=bastion).client("sts")
twelve_hours_in_seconds = 43200
serial_number = config[bastion_sts]["mfa_serial"]
sts_get_session_token_creds = bastion_client.get_session_token(
DurationSeconds=twelve_hours_in_seconds,
SerialNumber=serial_number,
TokenCode=token_code
)["Credentials"]
config[bastion_sts]["aws_access_key_id"] = sts_get_session_token_creds["AccessKeyId"]
config[bastion_sts]["aws_secret_access_key"] = sts_get_session_token_creds["SecretAccessKey"]
config[bastion_sts]["aws_session_token"] = sts_get_session_token_creds["SessionToken"]
with open(aws_shared_credentials_path, 'w') as f:
config.write(f)
print("Setting the '{}' profile with sts get session token credentials.".format(bastion_sts))
except Exception:
print("Failed to set the '{}' profile with sts get session token credentials.".format(bastion_sts))
sys.exit(1)
elif "aws_session_token" not in config[bastion_sts]:
print("An MFA token code is required when the bastion-sts does not have previous sts credentials.")
sys.exit(1)
#################
# STS assume role
#################
try:
bastion_sts_client = boto3.Session(profile_name=bastion_sts).client("sts")
one_hour_in_seconds = 3600
role_arn = config[assume_role_profile]["role_arn"]
role_session_name = "bastion-assume-role-{}".format(random.randint(0, 1000))
sts_assume_role_creds = bastion_sts_client.assume_role(
DurationSeconds=one_hour_in_seconds,
RoleArn=role_arn,
RoleSessionName=role_session_name
)["Credentials"]
config[assume_role_profile]["aws_access_key_id"] = sts_assume_role_creds["AccessKeyId"]
config[assume_role_profile]["aws_secret_access_key"] = sts_assume_role_creds["SecretAccessKey"]
config[assume_role_profile]["aws_session_token"] = sts_assume_role_creds["SessionToken"]
with open(aws_shared_credentials_path, 'w') as f:
config.write(f)
print("Setting the '{}' profile with sts assume role credentials.".format(assume_role_profile))
except Exception:
print("Failed to set the '{}' profile with sts assume role credentials.".format(assume_role_profile))
sys.exit(1)
if __name__ == "__main__":
main()