Skip to content

Instantly share code, notes, and snippets.

@lrvick
Last active April 22, 2018 11:27
Show Gist options
  • Save lrvick/60d31dac10395ac18dccd83e8b99f7b0 to your computer and use it in GitHub Desktop.
Save lrvick/60d31dac10395ac18dccd83e8b99f7b0 to your computer and use it in GitHub Desktop.
Use AWS CLI transparently with TOTP and IAM accounts.
[default]
region = us-west-2
output = json
[profile example]
role_session_name = example
mfa_serial = arn:aws:iam::567582265868:mfa/example
credential_process = bash -c "~/.aws/aws-mfa.sh example path/to/credentials.gpg"
#!/bin/bash
set -e
function get_mfa_token {
mfa_token=$(echo "GETPIN" | pinentry-gtk-2 | grep -o "[0-9]\\+");
[[ "$mfa_token" =~ ^[0-9]{6}$ ]] || \
{ ( >&2 echo "TOTP token must be 6 digits" ); exit 1; }
echo "$mfa_token"
}
function get_session {
creds="$1"
profile="$2"
mfa_serial=$(aws --profile "$profile" configure get mfa_serial)
[[ "$mfa_serial" =~ ^arn:aws:iam::[0-9]{12}:mfa/[a-z]+$ ]] || \
{ (>&2 echo "mfa_serial invalid in ~/.aws/config" ); exit 1; }
mfa_token=$(get_mfa_token) || exit 1;
AWS_ACCESS_KEY_ID=$(echo "$creds" | jq -r '.AccessKeyId')
AWS_SECRET_ACCESS_KEY=$(echo "$creds" | jq -r '.SecretAccessKey')
export AWS_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY
response=$(
aws sts get-session-token \
--serial-number "$mfa_serial" \
--token-code "$mfa_token"
)
echo "$response" | jq -r '.[] + { Version: 1 }'
}
function cache_valid {
cache_file=$1
[ -e "$cache_file" ] || return 1
exp=$( jq -r '.Expiration' < "$cache_file" | xargs date +%s -d )
now=$( date +%s )
[[ "$exp" > "$now" ]] || return 1
}
function cache_update {
session="$1"
profile="${2}-role"
cache_file="$3"
key_id=$( echo "$session" | jq -r '.AccessKeyId')
key_secret=$( echo "$session" | jq -r '.SecretAccessKey' )
session_token=$( echo "$session" | jq -r '.SessionToken' )
aws --profile "$profile" configure set aws_access_key_id "$key_id"
aws --profile "$profile" configure set aws_secret_access_key "$key_secret"
aws --profile "$profile" configure set aws_session_token "$session_token"
echo "$session" > "$cache_file"
}
function get_creds {
creds_file="$1"
gpg -d "$creds_file" 2>/dev/null
}
profile=$1
creds_file=$2; [ -e "$2" ] || { echo "File does not exist: $2"; exit 1; }
cache_file="$HOME/.aws/cache/${profile}-creds.json"
if cache_valid "$cache_file"; then
cat "$cache_file"
else
creds=$(get_creds "$creds_file");
session=$(get_session "$creds" "$profile")
cache_update "$session" "$profile" "$cache_file"
echo "$session"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment