|
| 1 | +#!/bin/bash |
| 2 | +# set_aws_mfa_auth.sh |
| 3 | +# Created By: Timothy Goetsch |
| 4 | +# Creation Date: 03/06/2020 |
| 5 | +#---------------------------- |
| 6 | +# Change Log: |
| 7 | +# 03/06/2020 - Timothy Goetsch |
| 8 | +# - Initial development |
| 9 | + |
| 10 | +Help() { |
| 11 | + echo "Description:" |
| 12 | + echo " Authenticate to AWS CLI with MFA token." |
| 13 | + echo |
| 14 | + echo "Requirements:" |
| 15 | + echo " - AWS CLI is already installed" |
| 16 | + echo " - AWS CLI is configured for your account/user" |
| 17 | + echo " - jq is installed to parse the JSON string" |
| 18 | + echo |
| 19 | + echo "Usage:" |
| 20 | + echo " $ source ./set_aws_mfa_auth.sh [<aws cli profile name>] [<mfa token>]" |
| 21 | + echo " aws cli profile name: name of the configured AWS CLI profile" |
| 22 | + echo " mfa token: the 6 number generatd by your MFA device" |
| 23 | + echo |
| 24 | + echo "Examples:" |
| 25 | + echo " authenticate to the default AWS CLI profile" |
| 26 | + echo " $ source ./set_aws_mfa_auth.sh 123456" |
| 27 | + echo |
| 28 | + echo " authenticate to a named AWS CLI profile" |
| 29 | + echo " $ source ./set_aws_mfa_auth.sh named-profile 123456" |
| 30 | + echo |
| 31 | + echo " switch to the default profile that has already been authenticated in" |
| 32 | + echo " the current bash session" |
| 33 | + echo " $ source ./set_aws_mfa_auth.sh named-profile" |
| 34 | + echo |
| 35 | + echo " switch to a named profile that has already been authenticated in the" |
| 36 | + echo " current bash session" |
| 37 | + echo " $ source ./set_aws_mfa_auth.sh" |
| 38 | + echo |
| 39 | +} |
| 40 | + |
| 41 | +# need to unset these env vars or inital aws calls may fail authentication |
| 42 | +unset AWS_SECRET_ACCESS_KEY |
| 43 | +unset AWS_ACCESS_KEY_ID |
| 44 | +unset AWS_SESSION_TOKEN |
| 45 | + |
| 46 | +valid_args=true |
| 47 | +failure_detected=false |
| 48 | +help_called=false |
| 49 | + |
| 50 | +if [[ $# -ge 1 ]]; then |
| 51 | + # detect if the first argument is a valid token |
| 52 | + if [[ $1 =~ ^[0-9]{6}$ ]]; then |
| 53 | + token_arg=$1 |
| 54 | + # check if the -h option was provided |
| 55 | + elif [[ $1 == '-h' ]]; then |
| 56 | + Help |
| 57 | + help_called=true |
| 58 | + # assume it's a profile |
| 59 | + else |
| 60 | + profile_arg=$1 |
| 61 | + fi |
| 62 | +fi |
| 63 | + |
| 64 | +if [[ $# > 1 ]]; then |
| 65 | + # if token_arg is set, assume the second arg is the profile |
| 66 | + if [[ -v token_arg ]]; then |
| 67 | + profile_arg=$2 |
| 68 | + else |
| 69 | + # verify that the second argument is an MFA token |
| 70 | + if [[ $2 =~ ^[0-9]{6}$ ]]; then |
| 71 | + token_arg=$2 |
| 72 | + else |
| 73 | + valid_args=false |
| 74 | + fi |
| 75 | + fi |
| 76 | +fi |
| 77 | + |
| 78 | +if [[ $valid_args == true ]] && [[ $help_called == false ]]; then |
| 79 | + if [[ -v profile_arg ]]; then |
| 80 | + # set the value for the stored profile variable; remove - from the profile name since that's not a valid variable character |
| 81 | + profile_var=$(echo "aws_token_response_$profile_arg" | sed s/\-//) |
| 82 | + |
| 83 | + if [[ -v token_arg ]]; then |
| 84 | + # authenticate to aws using the provided profile |
| 85 | + aws_serial_number=$(aws iam list-mfa-devices --profile $profile_arg | jq -r '.MFADevices[0].SerialNumber') |
| 86 | + aws_token_response=$(aws sts get-session-token --profile $profile_arg --serial-number $aws_serial_number --token-code $token_arg) |
| 87 | + |
| 88 | + # make sure the AWS authentication was successful |
| 89 | + if [[ $? == 0 ]]; then |
| 90 | + # copy the response to a profile variable to be used to switch back to the profile |
| 91 | + # without the need to authenticate again |
| 92 | + IFS= read -r -d '' "$profile_var" <<< $aws_token_response |
| 93 | + else |
| 94 | + failure_detected=true |
| 95 | + fi |
| 96 | + # test to see if the profile response is stored |
| 97 | + elif [[ ${!profile_var} != '' ]]; then |
| 98 | + # load the profile response |
| 99 | + IFS= read -r -d '' aws_token_response <<< "${!profile_var}" |
| 100 | + else |
| 101 | + echo -e "\e[33mYou have not yet authenticated to $profile_arg, please profide the MFA token.\e[39m" |
| 102 | + failure_detected=true |
| 103 | + fi |
| 104 | + else |
| 105 | + if [[ -v token_arg ]]; then |
| 106 | + # authenticate to aws using the default profile |
| 107 | + aws_serial_number=$(aws iam list-mfa-devices | jq -r '.MFADevices[0].SerialNumber') |
| 108 | + aws_token_response=$(aws sts get-session-token --serial-number $aws_serial_number --token-code $token_arg) |
| 109 | + |
| 110 | + # make sure the authentication was successful |
| 111 | + if [[ $? == 0 ]]; then |
| 112 | + # copy the response to a default profile variable to be used to switch back to the profile |
| 113 | + # without the need to authenticate again |
| 114 | + IFS= read -r -d '' aws_token_response_default <<< $aws_token_response |
| 115 | + else |
| 116 | + failure_detected=true |
| 117 | + fi |
| 118 | + # check to see if the default profile response is stored |
| 119 | + elif [[ -v aws_token_response_default ]]; then |
| 120 | + # load the profile response |
| 121 | + IFS= read -r -d '' aws_token_response <<< $aws_token_response_default |
| 122 | + else |
| 123 | + echo -e "\e[33mYou have not yet authenticated to the default profile, please profide the MFA token.\e[39m" |
| 124 | + failure_detected=true |
| 125 | + fi |
| 126 | + fi |
| 127 | + |
| 128 | + # if no failures occred, set the env variables for aws cli |
| 129 | + if [[ $failure_detected == false ]]; then |
| 130 | + export AWS_SESSION_TOKEN=$(echo $aws_token_response | jq -r '.Credentials.SessionToken') |
| 131 | + export AWS_SECRET_ACCESS_KEY=$(echo $aws_token_response | jq -r '.Credentials.SecretAccessKey') |
| 132 | + export AWS_ACCESS_KEY_ID=$(echo $aws_token_response | jq -r '.Credentials.AccessKeyId') |
| 133 | + else |
| 134 | + echo -e "\e[33mFailed to authenticate to AWS\e[39m" |
| 135 | + Help |
| 136 | + fi |
| 137 | +elif [[ $help_called == false ]]; then |
| 138 | + echo -e "\e[31mArguments provided do not contain a valid mfa token\e[39m" |
| 139 | +fi |
| 140 | + |
| 141 | +# need to unset all used vars or they could cause |
| 142 | +# the next execution to behave unexplectedly since this |
| 143 | +# is ran in the same scope as the user's session |
| 144 | +unset aws_token_response |
| 145 | +unset aws_serial_number |
| 146 | +unset valid_args |
| 147 | +unset profile_arg |
| 148 | +unset token_arg |
| 149 | +unset profile_var |
| 150 | +unset failure_detected |
0 commit comments