Skip to content

Instantly share code, notes, and snippets.

@klejejs
Last active August 18, 2023 08:20
Show Gist options
  • Select an option

  • Save klejejs/e422da26cf5dff245fa9d9d86e88ec3f to your computer and use it in GitHub Desktop.

Select an option

Save klejejs/e422da26cf5dff245fa9d9d86e88ec3f to your computer and use it in GitHub Desktop.
Generate AWS MFA credentials using OTP code stored in 1Password

Generate AWS MFA credentials using OTP code stored in 1Password

This script helps generate AWS MFA credentials using OTP code stored in 1Password. It can be used in setups where you have a single AWS main account with multiple roles for other accounts and you want to use one MFA for all of them.

Requirements

  1. 1Password CLI with op command installed and configured; AWS MFA secret stored in 1Password
  2. AWS CLI installed and configured

Usage

  1. Edit your ~/.aws/credentials file like the credentials file provided in this Gist. You have to add the AWS key and secret, as well as change role ARNs to match your setup. Profile names can be anything you want as long as the mfa account profile is named the same as the main account profile with -mfa suffix.
  2. Edit the aws_auth.sh script and change the environment variables to match your setup. The AWS_MAIN_ACCOUNT here needs to match the main account profile name in ~/.aws/credentials file. The ONE_PASSWORD_ITEM_ID needs to match the 1Password item ID that has your AWS OTP code stored in it.
  3. Source the aws_auth.sh script to generate the credentials for the main account and all the roles. You can also add this to your .bashrc or .zshrc file to make it available in all your terminal sessions, e.g. source ~/aws_auth.sh

To make the usage even easier, you can create an alias in your .bashrc or .zshrc file, e.g. alias aco="aws_check_auth" and then you can just run aco to check and generate the credentials.

Afterwards, you can set the desired profile in your terminal session by running export AWS_PROFILE=profile_name and then you can use the AWS CLI as usual.

AWS_MFA_ARN="arn:aws:iam::{accountid}:mfa/{loginid}" # TODO: change the account id and loginid to match your AWS MFA SERIAL
AWS_MAIN_ACCOUNT="main-account" # TODO: Change this to your main account name that matches the one in .aws/credentials file
ONE_PASSWORD_ITEM_ID="aws-item-id-with-otp" # TODO: Change this to your 1Password item id that matches the one in 1Password
AWS_MFA_SESSION_DURATION="36000" # TODO: Change this to your desired session duration
aws_mfa_auth() {
mfa_arn=${1:-"$AWS_MFA_ARN"}
profileid=${2:-"$AWS_MAIN_ACCOUNT"}
opitemid=${3:-"$ONE_PASSWORD_ITEM_ID"}
echo "Getting MFA code..."
echo "Using mfa arn: $AWS_MFA_ARN"
authcode=$(op item get $opitemid --otp)
output=$(aws --profile ${profileid}-mfa sts get-session-token --serial-number ${AWS_MFA_ARN} --duration-seconds ${AWS_MFA_SESSION_DURATION} --token-code $authcode)
AWS_ACCESS_KEY_ID=$(jq -r '.Credentials.AccessKeyId' <<<$output)
AWS_SECRET_ACCESS_KEY=$(jq -r '.Credentials.SecretAccessKey' <<<$output)
AWS_SESSION_TOKEN=$(jq -r '.Credentials.SessionToken' <<<$output)
AWS_TOKEN_EXPIRATION=$(jq -r '.Credentials.Expiration' <<<$output)
aws configure set aws_access_key_id ${AWS_ACCESS_KEY_ID} --profile $profileid
aws configure set aws_secret_access_key ${AWS_SECRET_ACCESS_KEY} --profile $profileid
aws configure set aws_session_token ${AWS_SESSION_TOKEN} --profile $profileid
aws configure set token_expiration ${AWS_TOKEN_EXPIRATION} --profile $profileid
echo "AWS credentials set"
}
aws_check_auth() {
profileid=${1:-"$AWS_MAIN_ACCOUNT"}
aws_token_expiration=$(aws configure get token_expiration --profile ${profileid})
aws_token_expiration_no_tz=${aws_token_expiration%?}
aws_token_expiration_seconds=$(date -j -u -f "%FT%T" "${aws_token_expiration_no_tz}" "+%s")
if [ $(date +%s) -gt ${aws_token_expiration_seconds} ]; then
echo "Token expired, re-authenticating..."
aws_mfa_auth
else
echo "AWS token checked. It is still valid."
fi
}
[main-account] # this is automatically filled by a script, except for region
aws_access_key_id =
aws_secret_access_key =
aws_session_token =
region = eu-west-1
[main-account-mfa]
aws_access_key_id = # TODO: Add your main account access key id
aws_secret_access_key = # TODO: Add your main account secret access key
region = eu-west-1
[sub-account-1]
source_profile = main-account
role_arn = arn:aws:iam::{account_id}:role/{role-1} # TODO: set sub account role
region = eu-west-1
[sub-account-2]
source_profile = main-account
role_arn = arn:aws:iam::{account_id}:role/{role-2} # TODO: set sub account role
region = eu-west-1
[sub-account-3]
source_profile = main-account
role_arn = arn:aws:iam::{account_id}:role/{role-3} # TODO: set sub account role
region = eu-west-1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment