3e6ee85a161c8089955c19364728e167025a911d

Author
Maksym <maksyms@users.noreply.github.com>
Committer
GitHub <noreply@github.com>
Date

Message

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.

Diff

This diff is truncated to protect this page.

  1diff --git a/plugins/aws/README.md b/plugins/aws/README.md
  2index 851f586ddd12935da9037af3539327fd2a250bb4..4c2ae96e57340593acc0ddb6987fc7ba1b874a8b 100644
  3--- a/plugins/aws/README.md
  4+++ b/plugins/aws/README.md
  5@@ -3,7 +3,7 @@
  6 This plugin provides completion support for [awscli](https://docs.aws.amazon.com/cli/latest/reference/index.html)
  7 and a few utilities to manage AWS profiles and display them in the prompt.
  8 
  9-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.
 10+To use it, add `aws` to the plugins array in your zshrc file.
 11 
 12 ```zsh
 13 plugins=(... aws)
 14@@ -40,6 +40,6 @@ plugins=(... aws)
 15 The plugin creates an `aws_prompt_info` function that you can use in your theme, which displays
 16 the current `$AWS_PROFILE`. It uses two variables to control how that is shown:
 17 
 18-- ZSH_THEME_AWS_PREFIX: sets the prefix of the AWS_PROFILE. Defaults to `<aws:`.
 19+* ZSH_THEME_AWS_PREFIX: sets the prefix of the AWS_PROFILE. Defaults to `<aws:`.
 20 
 21-- ZSH_THEME_AWS_SUFFIX: sets the suffix of the AWS_PROFILE. Defaults to `>`.
 22+* ZSH_THEME_AWS_SUFFIX: sets the suffix of the AWS_PROFILE. Defaults to `>`.
 23diff --git a/plugins/aws/aws.plugin.zsh b/plugins/aws/aws.plugin.zsh
 24index 8149ba12116f65635d479aa074f7d91f0887a0e6..e6959759e38868fa785a8a17f4e486796f36f23c 100644
 25--- a/plugins/aws/aws.plugin.zsh
 26+++ b/plugins/aws/aws.plugin.zsh
 27@@ -39,60 +39,73 @@ function acp() {
 28     return 1
 29   fi
 30 
 31-  local exists="$(aws configure get aws_access_key_id --profile $1)"
 32+  local aws_access_key_id="$(aws configure get aws_access_key_id --profile $1)"
 33+  local aws_secret_access_key="$(aws configure get aws_secret_access_key --profile $1)"
 34+  local aws_session_token="$(aws configure get aws_session_token --profile $1)"
 35+  local mfa_serial="$(aws configure get mfa_serial --profile $1)"
 36   local role_arn="$(aws configure get role_arn --profile $1)"
 37-  local aws_access_key_id=""
 38-  local aws_secret_access_key=""
 39-  local aws_session_token=""
 40-  if [[ -n $exists || -n $role_arn ]]; then
 41-    if [[ -n $role_arn ]]; then
 42-      local mfa_serial="$(aws configure get mfa_serial --profile $1)"
 43-      local mfa_token=""
 44-      local mfa_opt=""
 45-      if [[ -n $mfa_serial ]]; then
 46-        echo "Please enter your MFA token for $mfa_serial:"
 47-        read mfa_token
 48-        echo "Please enter the session duration in seconds (900-43200; default: 3600, which is the default maximum for a role):"
 49-        read sess_duration
 50-        if [[ -z $sess_duration ]]; then
 51-          sess_duration="3600"
 52-        fi
 53-        mfa_opt="--serial-number $mfa_serial --token-code $mfa_token --duration-seconds $sess_duration"
 54-      fi
 55-
 56-      local ext_id="$(aws configure get external_id --profile $1)"
 57-      local extid_opt=""
 58-      if [[ -n $ext_id ]]; then
 59-        extid_opt="--external-id $ext_id"
 60-      fi
 61-
 62-      local profile=$1
 63-      local source_profile="$(aws configure get source_profile --profile $1)"
 64-      if [[ -n $source_profile ]]; then
 65-        profile=$source_profile
 66-      fi
 67-
 68-      echo "Assuming role $role_arn using profile $profile"
 69-      local assume_cmd=(aws sts assume-role "--profile=$profile" "--role-arn $role_arn" "--role-session-name "$profile"" "$mfa_opt" "$extid_opt")
 70-      local JSON="$(eval ${assume_cmd[@]})"
 71-
 72-      aws_access_key_id="$(echo $JSON | jq -r '.Credentials.AccessKeyId')"
 73-      aws_secret_access_key="$(echo $JSON | jq -r '.Credentials.SecretAccessKey')"
 74-      aws_session_token="$(echo $JSON | jq -r '.Credentials.SessionToken')"
 75-    else
 76-      aws_access_key_id="$(aws configure get aws_access_key_id --profile $1)"
 77-      aws_secret_access_key="$(aws configure get aws_secret_access_key --profile $1)"
 78-      aws_session_token="$(aws configure get aws_session_token --profile $1)"
 79+
 80+  # First, if the profile has MFA configured, lets get the token and session duration
 81+  local mfa_opt=""
 82+
 83+  if [[ -n $mfa_serial ]]; then
 84+    local mfa_token=""
 85+    echo "Please enter your MFA token for $mfa_serial:"
 86+    read -r mfa_token
 87+    echo "Please enter the session duration in seconds (900-43200; default: 3600, which is the default maximum for a role):"
 88+    read -r sess_duration
 89+    if [[ -z $sess_duration ]]; then
 90+      sess_duration="3600"
 91     fi
 92+    mfa_opt="--serial-number $mfa_serial --token-code $mfa_token --duration-seconds $sess_duration"
 93+  fi
 94+
 95+  # Now see whether we need to just MFA for the current role, or assume a different one
 96+  local credentials_output=""
 97+  if [[ -n $role_arn ]]; then
 98+    # Means we need to assume a specified role
 99 
100+    # Check whether external_id is configured to use while assuming the role
101+    local ext_id="$(aws configure get external_id --profile $1)"
102+    local extid_opt=""
103+    if [[ -n $ext_id ]]; then
104+      extid_opt="--external-id $ext_id"
105+    fi
106+
107+    # Get source profile to use to assume role
108+    local profile=$1
109+    local source_profile="$(aws configure get source_profile --profile "$1")"
110+    if [[ -n $source_profile ]]; then
111+      profile=$source_profile
112+    fi
113+
114+    echo "Assuming role $role_arn using profile $profile"
115+    local assume_cmd=(aws sts assume-role "--profile=$profile" "--role-arn $role_arn" "--role-session-name $profile" "$mfa_opt" "$extid_opt"
116+      "--query '[Credentials.AccessKeyId,Credentials.SecretAccessKey,Credentials.SessionToken]' --output text | tr '\t' '\n'")
117+    credentials_output="$(eval "${assume_cmd[@]}")"
118+  elif [[ -n $mfa_opt ]]; then
119+    # Means we only need to do MFA
120+    echo "Obtaining session token for profile $profile"
121+    local get_token_cmd=(aws sts get-session-token "--profile=$profile" "$mfa_opt"
122+      "--query '[Credentials.AccessKeyId,Credentials.SecretAccessKey,Credentials.SessionToken]' --output text | tr '\t' '\n'")
123+    credentials_output="$(eval "${get_token_cmd[@]}")"
124+  fi
125+
126+  if [[ -n $credentials_output ]]; then