Skip to content

Instantly share code, notes, and snippets.

@skehlet
Last active January 18, 2018 17:22
Show Gist options
  • Save skehlet/8e32eb68658c452b8c51342898936e9f to your computer and use it in GitHub Desktop.
Save skehlet/8e32eb68658c452b8c51342898936e9f to your computer and use it in GitHub Desktop.
#!/bin/bash
#
# Wrapper for any AWS-related command using aws that handles the 1 hour MFA token.
#
# Create an aws-role.config.json file in the same directory as this script that looks like:
# {
# "<your-profile-nickname>": {
# "profile": "<your-hub>",
# "region": "<your-default-region>",
# "mfa_arn": "<your-mfa-arn>",
# "role_arn": "<your-assume-role-arn>"
# }
# }
#
# Also update your ~/.aws/config and ~/.aws/credentials with a "<your-hub>" profile:
#
# ~/.aws/config:
# [profile <your-hub>]
# region = <your-default-region>
#
# ~/.aws/credentials:
# [<your-hub>]
# aws_access_key_id = <your-hub-access-key-id>
# aws_secret_access_key = <your-hub-secret-access-key>
#
# You can either run this script and provide the account name as the first argument,
# or you can make a symlink using the account name to this script.
#
set -e
unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY
unset AWS_SESSION_TOKEN
unset AWS_DEFAULT_REGION
unset AWS_DEFAULT_OUTPUT
unset AWS_PROFILE
unset AWS_CA_BUNDLE
unset AWS_SHARED_CREDENTIALS_FILE
unset AWS_CONFIG_FILE
my_name=$(basename $0)
if [[ $my_name != "aws-role" ]]; then
account=$my_name
else
account=$1
shift
fi
config=$(dirname $0)/aws-role.config.json
session_token_credentials=~/.aws/.aws-role.session-token.${account}
assume_role_credentials=~/.aws/.aws-role.assume-role.${account}
MAX_SESSION_TOKEN_CREDENTIALS_AGE=$(( 129600 - 60 ))
MAX_ASSUME_ROLE_CREDENTIALS_AGE=$(( 1800 )) # half hour, assuming any reasonable aws-related commands (looking at you terraform) will finish in less than 1/2 hour
TMPFILE1=
TMPFILE2=
cleanup() {
[[ -n $TMPFILE1 ]] && rm -f $TMPFILE1
[[ -n $TMPFILE2 ]] && rm -f $TMPFILE2
}
trap cleanup EXIT
now=$(date +%s)
if ! aws_profile=$(jq -r ".\"${account}\".profile" < $config) \
|| ! aws_default_region=$(jq -r ".\"${account}\".region" < $config) \
|| ! mfa_arn=$(jq -r ".\"${account}\".mfa_arn" < $config) \
|| ! role_arn=$(jq -r ".\"${account}\".role_arn" < $config)
then
echo "Missing or incomplete config for account $account. Please update your $config"
exit 1
fi
file_age() {
case "$(uname)" in
Darwin) stat -t %s -f %m -- "$1" 2>/dev/null ;;
Linux) date +%s -r "$1" 2>/dev/null ;;
*) echo "unknown platform"; exit 1 ;;
esac
}
if [[ $(( $(file_age $session_token_credentials) + $MAX_SESSION_TOKEN_CREDENTIALS_AGE)) -lt $now ]]; then
TMPFILE1=$(mktemp)
read -p "MFA code: " code
env \
AWS_PROFILE=$aws_profile \
AWS_DEFAULT_REGION=$aws_default_region \
aws sts get-session-token \
--serial-number "$mfa_arn" \
--token-code "$code" \
--duration-seconds 129600 \
> $TMPFILE1
aws_access_key_id=$(jq -r '.Credentials.AccessKeyId' < $TMPFILE1)
aws_secret_access_key=$(jq -r '.Credentials.SecretAccessKey' < $TMPFILE1)
aws_session_token=$(jq -r '.Credentials.SessionToken' < $TMPFILE1)
cat > $session_token_credentials <<EOF
export AWS_ACCESS_KEY_ID=$aws_access_key_id
export AWS_SECRET_ACCESS_KEY=$aws_secret_access_key
export AWS_SESSION_TOKEN=$aws_session_token
export AWS_DEFAULT_REGION=$aws_default_region
EOF
fi
source $session_token_credentials
if [[ $(( $(file_age $assume_role_credentials) + $MAX_ASSUME_ROLE_CREDENTIALS_AGE)) -lt $now ]]; then
TMPFILE2=$(mktemp)
aws sts assume-role \
--role-arn $role_arn \
--role-session-name $now \
> $TMPFILE2
aws_access_key_id=$(jq -r '.Credentials.AccessKeyId' < $TMPFILE2)
aws_secret_access_key=$(jq -r '.Credentials.SecretAccessKey' < $TMPFILE2)
aws_session_token=$(jq -r '.Credentials.SessionToken' < $TMPFILE2)
cat > $assume_role_credentials <<EOF
export AWS_ACCESS_KEY_ID=$aws_access_key_id
export AWS_SECRET_ACCESS_KEY=$aws_secret_access_key
export AWS_SESSION_TOKEN=$aws_session_token
export AWS_DEFAULT_REGION=$aws_default_region
EOF
fi
source $assume_role_credentials
exec "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment