Skip to content

Commit d706bda

Browse files
authored
Merge pull request #1 from tgoetsch/feature/aws-mfa-auth
Feature/aws mfa auth
2 parents 63db2fd + 94af401 commit d706bda

File tree

2 files changed

+185
-0
lines changed

2 files changed

+185
-0
lines changed

README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,37 @@
11
# aws-scripts
22
AWS scripts to make things a little easier.
3+
4+
## Bash scripts
5+
### set_aws_mfa_auth.sh
6+
Authenticates the AWS CLI using an MFA token to avoid needing to manually running the AWS STS command and setting the environmental variables. AWS CLI profiles are supported.
7+
8+
The script uses the AWS CLI commands to retrieve the ARN (serial number) of the MFA device configured for the AWS account. It then uses sts to authenticate using the provided 6 digit token and parses the response to set the environmental variables AWS_SECRET_ACCESS_KEY, AWS_ACCESS_KEY_ID, and AWS_SESSION_TOKEN so the AWS CLI commands will use the authentication token.
9+
10+
#### Requirements
11+
- AWS CLI must already be installed and configured with at least one profile that requires MFA
12+
- jq must be installed, it is used for parsing the JSON response from AWS CLI
13+
14+
#### Usage
15+
Since the script is setting environmental variables, it must be ran with *source*. Two arguments are accepted, the profile name (if one is not provided, it will use the default profile) and the MFA token value.
16+
17+
Multiple profiles are supported by the script allowing the ability to switch between profiles once they have been authenticated without needing to authenticate again by running the script and only providing the profile name, or no arguments is switching back to the default profile.
18+
19+
##### Syntax
20+
```bash
21+
$ source ./set_aws_mfa_auth.sh [<profile_name>] [<mfa_token>]
22+
```
23+
24+
##### Examples
25+
```bash
26+
# Authenticate to the default AWS CLI profile
27+
$ source ./set_aws_mfa_auth.sh 123456
28+
29+
# Authenticate to the test AWS CLI profile
30+
$ source ./set_aws_mfa_auth.sh test 123456
31+
32+
# Switch back to the default profile
33+
$ source ./set_aws_mfa_auth.sh
34+
35+
# Switch back to the test profile
36+
$ source ./set_aws_mfa_auth.sh
37+
```

bash/set_aws_mfa_auth.sh

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
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

Comments
 (0)