Unverified Commit 3e6ee85a authored by Maksym's avatar Maksym Committed by GitHub
Browse files

fix(aws): support MFA for profiles without role to assume (#9411)

Previously, the plugin only supported MFA for profiles that had a role to assume, specified in role_arn. Now, the plugin supports MFA for profiles without a role to assume.

Closes #9408

* refactor(aws plugin): remove dependency on jq

Previously, acp command relied on jq. Now that dependency has been removed, as well as some linter suggestions implemented.
parent 852a4409
Showing with 62 additions and 50 deletions
+62 -50
......@@ -3,7 +3,7 @@
This plugin provides completion support for [awscli](https://docs.aws.amazon.com/cli/latest/reference/index.html)
and a few utilities to manage AWS profiles and display them in the prompt.
To use it, make sure [jq](https://stedolan.github.io/jq/download/) is installed, and add `aws` to the plugins array in your zshrc file.
To use it, add `aws` to the plugins array in your zshrc file.
```zsh
plugins=(... aws)
......@@ -40,6 +40,6 @@ plugins=(... aws)
The plugin creates an `aws_prompt_info` function that you can use in your theme, which displays
the current `$AWS_PROFILE`. It uses two variables to control how that is shown:
- ZSH_THEME_AWS_PREFIX: sets the prefix of the AWS_PROFILE. Defaults to `<aws:`.
* ZSH_THEME_AWS_PREFIX: sets the prefix of the AWS_PROFILE. Defaults to `<aws:`.
- ZSH_THEME_AWS_SUFFIX: sets the suffix of the AWS_PROFILE. Defaults to `>`.
* ZSH_THEME_AWS_SUFFIX: sets the suffix of the AWS_PROFILE. Defaults to `>`.
......@@ -39,60 +39,73 @@ function acp() {
return 1
fi
local exists="$(aws configure get aws_access_key_id --profile $1)"
local aws_access_key_id="$(aws configure get aws_access_key_id --profile $1)"
local aws_secret_access_key="$(aws configure get aws_secret_access_key --profile $1)"
local aws_session_token="$(aws configure get aws_session_token --profile $1)"
local mfa_serial="$(aws configure get mfa_serial --profile $1)"
local role_arn="$(aws configure get role_arn --profile $1)"
local aws_access_key_id=""
local aws_secret_access_key=""
local aws_session_token=""
if [[ -n $exists || -n $role_arn ]]; then
if [[ -n $role_arn ]]; then
local mfa_serial="$(aws configure get mfa_serial --profile $1)"
local mfa_token=""
local mfa_opt=""
if [[ -n $mfa_serial ]]; then
echo "Please enter your MFA token for $mfa_serial:"
read mfa_token
echo "Please enter the session duration in seconds (900-43200; default: 3600, which is the default maximum for a role):"
read sess_duration
if [[ -z $sess_duration ]]; then
sess_duration="3600"
fi
mfa_opt="--serial-number $mfa_serial --token-code $mfa_token --duration-seconds $sess_duration"
fi
local ext_id="$(aws configure get external_id --profile $1)"
local extid_opt=""
if [[ -n $ext_id ]]; then
extid_opt="--external-id $ext_id"
fi
local profile=$1
local source_profile="$(aws configure get source_profile --profile $1)"
if [[ -n $source_profile ]]; then
profile=$source_profile
fi
echo "Assuming role $role_arn using profile $profile"
local assume_cmd=(aws sts assume-role "--profile=$profile" "--role-arn $role_arn" "--role-session-name "$profile"" "$mfa_opt" "$extid_opt")
local JSON="$(eval ${assume_cmd[@]})"
aws_access_key_id="$(echo $JSON | jq -r '.Credentials.AccessKeyId')"
aws_secret_access_key="$(echo $JSON | jq -r '.Credentials.SecretAccessKey')"
aws_session_token="$(echo $JSON | jq -r '.Credentials.SessionToken')"
else
aws_access_key_id="$(aws configure get aws_access_key_id --profile $1)"
aws_secret_access_key="$(aws configure get aws_secret_access_key --profile $1)"
aws_session_token="$(aws configure get aws_session_token --profile $1)"
# First, if the profile has MFA configured, lets get the token and session duration
local mfa_opt=""
if [[ -n $mfa_serial ]]; then
local mfa_token=""
echo "Please enter your MFA token for $mfa_serial:"
read -r mfa_token
echo "Please enter the session duration in seconds (900-43200; default: 3600, which is the default maximum for a role):"
read -r sess_duration
if [[ -z $sess_duration ]]; then
sess_duration="3600"
fi
mfa_opt="--serial-number $mfa_serial --token-code $mfa_token --duration-seconds $sess_duration"
fi
# Now see whether we need to just MFA for the current role, or assume a different one
local credentials_output=""
if [[ -n $role_arn ]]; then
# Means we need to assume a specified role
# Check whether external_id is configured to use while assuming the role
local ext_id="$(aws configure get external_id --profile $1)"
local extid_opt=""
if [[ -n $ext_id ]]; then
extid_opt="--external-id $ext_id"
fi
# Get source profile to use to assume role
local profile=$1
local source_profile="$(aws configure get source_profile --profile "$1")"
if [[ -n $source_profile ]]; then
profile=$source_profile
fi
echo "Assuming role $role_arn using profile $profile"
local assume_cmd=(aws sts assume-role "--profile=$profile" "--role-arn $role_arn" "--role-session-name $profile" "$mfa_opt" "$extid_opt"
"--query '[Credentials.AccessKeyId,Credentials.SecretAccessKey,Credentials.SessionToken]' --output text | tr '\t' '\n'")
credentials_output="$(eval "${assume_cmd[@]}")"
elif [[ -n $mfa_opt ]]; then
# Means we only need to do MFA
echo "Obtaining session token for profile $profile"
local get_token_cmd=(aws sts get-session-token "--profile=$profile" "$mfa_opt"
"--query '[Credentials.AccessKeyId,Credentials.SecretAccessKey,Credentials.SessionToken]' --output text | tr '\t' '\n'")
credentials_output="$(eval "${get_token_cmd[@]}")"
fi
if [[ -n $credentials_output ]]; then
local credentials=("${(f)credentials_output}")
aws_access_key_id=${credentials[1]}
aws_secret_access_key=${credentials[2]}
aws_session_token=${credentials[3]}
fi
if [[ -n $aws_access_key_id && -n $aws_secret_access_key ]]; then
export AWS_DEFAULT_PROFILE=$1
export AWS_PROFILE=$1
export AWS_EB_PROFILE=$1
export AWS_ACCESS_KEY_ID=$aws_access_key_id
export AWS_SECRET_ACCESS_KEY=$aws_secret_access_key
[[ -z "$aws_session_token" ]] && unset AWS_SESSION_TOKEN || export AWS_SESSION_TOKEN=$aws_session_token
echo "Switched to AWS Profile: $1";
echo "Switched to AWS Profile: $1"
fi
}
......@@ -120,8 +133,7 @@ function aws_profiles() {
function _aws_profiles() {
reply=($(aws_profiles))
}
compctl -K _aws_profiles asp aws_change_access_key
compctl -K _aws_profiles acp aws_change_access_key
compctl -K _aws_profiles asp acp aws_change_access_key
# AWS prompt
function aws_prompt_info() {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment