AWS MFA Authentication Helper
The helper script below assumes the following configuration:
- MFA key is stored on Yubikey.
- Key name is set appropriately to match Yubikey. (line 11)
 
- AWS IAM MFA ARN is set appropriately. (line 17)
How it works...
Once authenticated, the script adds a new entry to the bottom of ~/.aws/credentials labeled [cli]; however, session variables are also assigned. As long as you remain in the same shell session, you will not have to pass --profile cli with each command. 
Additional terminal windows is a new session and can't use the previously set local variables, so to utilize the authentication performed earlier, pass --profile cli with each command to utilize the existing valid authentication. Example: aws s3 ls --profile cli
Performing a second authentication in a different window will overwrite the previous authentication's token and invalidate that session.
 
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 | alias awslogin="awsToken "
awsToken() { 
    ykTest=$(ykman list)
    if [ -z "$ykTest" ]; then
        printf "${color_yellow_italic}YubiKey not detected.${color_nocolor}\n"
        printf "Insert key and try again.\n"
        return 1
    fi
    printf "${cyanarrow}${color_cyan2} YubiKey detected...${color_nocolor}\n"
    ykOathValue="AWS [Prod]:name@example.com" # (1)
    unset AWS_SESSION_TOKEN;
    unset AWS_SECRET_ACCESS_KEY;
    unset AWS_ACCESS_KEY_ID;
    unset PROFTXT;
    unset AWSUME_PROFILE;
    MFA="arn:aws:iam::123456789876:mfa/name@example.com" # (2)
    MFACODE=$(ykman oath accounts code -s "$ykOathValue")
    if [ $? -eq 1 ]; then
        printf "${color_yellow_italic}Correct OATH token not found on YubiKey!${color_nocolor}\n"
        return 1
    fi
    AWSCREDS=`aws sts get-session-token --serial-number $MFA --token-code $MFACODE`;
    ACCESS_KEY=`echo $AWSCREDS | jq .Credentials.AccessKeyId`
    SECRET_KEY=`echo $AWSCREDS | jq .Credentials.SecretAccessKey`
    SESSION_TOKEN=`echo $AWSCREDS | jq .Credentials.SessionToken`
    export AWS_ACCESS_KEY_ID=`echo $ACCESS_KEY | sed -e 's/^"//' -e 's/"$//'`
    export AWS_SECRET_ACCESS_KEY=`echo $SECRET_KEY | sed -e 's/^"//' -e 's/"$//'`
    export AWS_SESSION_TOKEN=`echo $SESSION_TOKEN | sed -e 's/^"//' -e 's/"$//'`
    export PROFTXT="XYZ AWS" # (3)
    export AWSUME_PROFILE="prod" # (4)
    echo "$(awk '/cli/{n=4}; n {n--; next}; 1' $HOME/.aws/credentials)" > $HOME/.aws/credentials
    echo "" >> $HOME/.aws/credentials
    echo "[cli]" >> $HOME/.aws/credentials
    TMP1=$(echo "aws_access_key_id = $ACCESS_KEY" | tr -d \")
    echo $TMP1 >> $HOME/.aws/credentials
    TMP2=$(echo "aws_secret_access_key = $SECRET_KEY" | tr -d \")
    echo $TMP2 >> $HOME/.aws/credentials
    TMP3=$(echo "aws_session_token = $SESSION_TOKEN" | tr -d \")
    echo $TMP3 >> $HOME/.aws/credentials
    echo -e "\n\033[7;33""m NOTICE - NOTICE - NOTICE - NOTICE - NOTICE \033[0m"
    echo -e "\033[5;33""m ==> -> DLRDMV AWS ACCOUNT ACTIVE <- <== \033[0m"
    echo " "
    export AWS_PAGER='' && aws sts get-caller-identity --output yaml && export AWS_PAGER='less'
}
# Quickly identify which profile you're authenticated against.
awsprofile() { 
    if [ -z "$PROFTXT" ]
    then
        echo "${color_yellow_italic}NO PROFILE IS ACTIVE${color_nocolor}"
    else
        echo -e "\033[7;33""m =========================================== \033[0m"
        echo -e "\033[5;33""m ==> -> $PROFTXT ACCOUNT ACTIVE <- <== \033[0m"
        echo -e "\033[7;33""m =========================================== \033[0m"
        echo " "
        export AWS_PAGER='' && aws sts get-caller-identity --output yaml && export AWS_PAGER='less'
    fi
}
 | 
- Key value must match the name as defined when the MFA value was added to Yubikey.
- MFA ARN is located under the "Security credentials" tab of the IAM user.
- If you regularly access multiple AWS accounts, PROFTXTcan be used to quickly identify which environment is currently active.
- p10k can read AWSUME_PROFILE (/internal/p10k.zsh) to show this value on the terminal prompt. It's useful for seeing at a glance which environment your command will apply to.
 
 