aws.plugin.zsh 6.69 KB
Newer Older
1
function agp() {
2
  echo $AWS_PROFILE
3
}
4

5
# AWS profile selection
6
function asp() {
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  if [[ -z "$1" ]]; then
    unset AWS_DEFAULT_PROFILE AWS_PROFILE AWS_EB_PROFILE
    echo AWS profile cleared.
    return
  fi

  local -a available_profiles
  available_profiles=($(aws_profiles))
  if [[ -z "${available_profiles[(r)$1]}" ]]; then
    echo "${fg[red]}Profile '$1' not found in '${AWS_CONFIG_FILE:-$HOME/.aws/config}'" >&2
    echo "Available profiles: ${(j:, :)available_profiles:-no profiles found}${reset_color}" >&2
    return 1
  fi

  export AWS_DEFAULT_PROFILE=$1
  export AWS_PROFILE=$1
  export AWS_EB_PROFILE=$1
}

# AWS profile switch
function acp() {
David Kane's avatar
David Kane committed
28
  if [[ -z "$1" ]]; then
29
    unset AWS_DEFAULT_PROFILE AWS_PROFILE AWS_EB_PROFILE AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
David Kane's avatar
David Kane committed
30
    echo AWS profile cleared.
31
    return
David Kane's avatar
David Kane committed
32
  fi
33

34
35
  local -a available_profiles
  available_profiles=($(aws_profiles))
36
37
38
39
40
41
  if [[ -z "${available_profiles[(r)$1]}" ]]; then
    echo "${fg[red]}Profile '$1' not found in '${AWS_CONFIG_FILE:-$HOME/.aws/config}'" >&2
    echo "Available profiles: ${(j:, :)available_profiles:-no profiles found}${reset_color}" >&2
    return 1
  fi

42
43
44
45
  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)"
46
  local role_arn="$(aws configure get role_arn --profile $1)"
47
48
49
50
51
52
53
54
55
56
57
58

  # 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"
59
    fi
60
61
62
63
64
65
66
    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
67

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
    # 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
102
103
104
105
106
107
    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
108
    echo "Switched to AWS Profile: $1"
109
  fi
110
}
111

112
function aws_change_access_key() {
113
  if [[ -z "$1" ]]; then
114
    echo "usage: $0 <profile>"
115
116
    return 1
  fi
117
118

  echo Insert the credentials when asked.
119
  asp "$1" || return 1
120
121
  AWS_PAGER="" aws iam create-access-key
  AWS_PAGER="" aws configure --profile "$1"
122
123
124

  echo You can now safely delete the old access key running \`aws iam delete-access-key --access-key-id ID\`
  echo Your current keys are:
125
  AWS_PAGER="" aws iam list-access-keys
126
127
}

128
function aws_profiles() {
129
  [[ -r "${AWS_CONFIG_FILE:-$HOME/.aws/config}" ]] || return 1
130
  grep --color=never -Eo '\[.*\]' "${AWS_CONFIG_FILE:-$HOME/.aws/config}" | sed -E 's/^[[:space:]]*\[(profile)?[[:space:]]*([-_[:alnum:]\.@]+)\][[:space:]]*$/\2/g'
131
}
132

133
function _aws_profiles() {
134
135
  reply=($(aws_profiles))
}
136
compctl -K _aws_profiles asp acp aws_change_access_key
137

David Kane's avatar
David Kane committed
138
# AWS prompt
139
function aws_prompt_info() {
David Kane's avatar
David Kane committed
140
141
142
143
144
  [[ -z $AWS_PROFILE ]] && return
  echo "${ZSH_THEME_AWS_PREFIX:=<aws:}${AWS_PROFILE}${ZSH_THEME_AWS_SUFFIX:=>}"
}

if [ "$SHOW_AWS_PROMPT" != false ]; then
145
  RPROMPT='$(aws_prompt_info)'"$RPROMPT"
David Kane's avatar
David Kane committed
146
147
148
fi


149
150
# Load awscli completions

151
# AWS CLI v2 comes with its own autocompletion. Check if that is there, otherwise fall back
152
if command -v aws_completer &> /dev/null; then
153
  autoload -Uz bashcompinit && bashcompinit
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
  complete -C aws_completer aws
else
  function _awscli-homebrew-installed() {
    # check if Homebrew is installed
    (( $+commands[brew] )) || return 1

    # speculatively check default brew prefix
    if [ -h /usr/local/opt/awscli ]; then
      _brew_prefix=/usr/local/opt/awscli
    else
      # ok, it is not in the default prefix
      # this call to brew is expensive (about 400 ms), so at least let's make it only once
      _brew_prefix=$(brew --prefix awscli)
    fi
  }

  # get aws_zsh_completer.sh location from $PATH
  _aws_zsh_completer_path="$commands[aws_zsh_completer.sh]"

  # otherwise check common locations
  if [[ -z $_aws_zsh_completer_path ]]; then
    # Homebrew
    if _awscli-homebrew-installed; then
      _aws_zsh_completer_path=$_brew_prefix/libexec/bin/aws_zsh_completer.sh
    # Ubuntu
    elif [[ -e /usr/share/zsh/vendor-completions/_awscli ]]; then
      _aws_zsh_completer_path=/usr/share/zsh/vendor-completions/_awscli
181
182
183
    # NixOS
    elif [[ -e "${commands[aws]:P:h:h}/share/zsh/site-functions/aws_zsh_completer.sh" ]]; then
      _aws_zsh_completer_path="${commands[aws]:P:h:h}/share/zsh/site-functions/aws_zsh_completer.sh"
184
185
186
187
    # RPM
    else
      _aws_zsh_completer_path=/usr/share/zsh/site-functions/aws_zsh_completer.sh
    fi
188
189
  fi

190
191
  [[ -r $_aws_zsh_completer_path ]] && source $_aws_zsh_completer_path
  unset _aws_zsh_completer_path _brew_prefix
192
fi