A useful script for AWS credentials

21 January 2020

My work involves elevated access to computers, including Amazon Web Services (AWS) accounts.

Our security team requires multi-factor authentication (MFA) for elevated access. For command-line access using MFA, I use the awscli’s aws sts get-session-token function. This grants AWS security credentials that are valid for a few hours.

I do this multiple times each day, so I made a quick utility script: sessioner.

To set up my credentials, I run the following commands:

. sessioner.sh -e development -t <development_token_value>
. sessioner.sh -e testing -t <testing_token_value>
. sessioner.sh -e production -t <production_token_value>

The token values come from an MFA device.

This code has 5 parts. Let’s take a look…

Part A: Input Parsing

The first step is to parse the inputs.

The script needs 2 parameters: the AWS profile (-e or --env) and MFA token code (-t or --token).

# inputs needed - environment (ENV) and code (TOKEN)
echo $@
POSITIONAL=()
while [[ $# -gt 0 ]]
do
key="$1"

case $key in
    -e|--env)
    ENV="$2"
    shift # past argument
    shift # past value
    ;;
    -t|--token)
    TOKEN="$2"
    shift # past argument
    shift # past value
    ;;
    *)    # unknown option
    POSITIONAL+=("$1") # save it in an array for later
    shift # past argument
    ;;
esac
done
set -- "${POSITIONAL[@]}" # restore positional parameters

Part B: Environment Setup

The second step is to create a few variables; the MFA device serial number, and the AWS profilename with elevated permissions.

Let’s say I’m connecting to AWS accounts 111111111111 and 222222222222 for development and testing. Inside each is an IAM user with elevated access called DevTheAlmighty.

if [ "${ENV}" = "development" ]; then
  SERIAL='arn:aws:iam::111111111111:mfa/DevTheAlmighty'
fi

if [ "${ENV}" = "testing" ]; then
  SERIAL='arn:aws:iam::222222222222:mfa/DevTheAlmighty'
fi

PROFILENAME="$ENV"mfa

Inside my AWS credentials, I have 2 configurations for each AWS account. I use the development profile to get credentials for the developmentmfa profile. The former has limited permissions; it can only retrieve permissions for the latter.

[development]
region = us-east-1

[developmentmfa]
region = us-east-1

Part C: Get Session Credentials

I get temporary credentials via aws sts get-session-token, which returns a JSON object. I run the command and save the results to a variable.

echo "Configuring $ENV with token $TOKEN"
CREDJSON="$(aws sts get-session-token --serial-number $SERIAL --profile $ENV --token-code $TOKEN)"
#echo $CREDJSON

Jq navigates through the JSON on the command line, and then sed removes the " character.

One line of code assigns an access_key, secret_key, or session_token value to a variable.

ACCESSKEY="$(echo $CREDJSON | jq '.Credentials.AccessKeyId' | sed 's/"//g')"
SECRETKEY="$(echo $CREDJSON | jq '.Credentials.SecretAccessKey' | sed 's/"//g')"
SESSIONTOKEN="$(echo $CREDJSON | jq '.Credentials.SessionToken' | sed 's/"//g')"

Part D: Set Session Credentials

aws configure set sets credentials for the higher-permissions profile.

aws configure set aws_access_key_id $ACCESSKEY --profile $PROFILENAME
aws configure set aws_secret_access_key $SECRETKEY --profile $PROFILENAME
aws configure set aws_session_token $SESSIONTOKEN --profile $PROFILENAME

Part E: Validate

Has my script worked? I run a simple check: listing all the S3 buckets I can see. Their names are familiar and distinctive, so I immediately know which AWS account I’m using.

aws s3 ls / --profile $PROFILENAME

I’ve put my code on GitHub, since no piece of code is ever done. I’ll add functionality over time, as I need to.

Happy coding!