At my current job, I have a need to be access multiple AWS accounts. Generally we follow the AWS best practices for security and set up IAM accounts with restricted functionality that can access only the resources that are appropriate for the completion of the task at hand. At this point we've looked at federation technologies (such as SAML), but haven't yet implemented this.

Generally, I like to make sure that whatever I do using the AWS console on the web I can also achieve using the AWS cli (which is now based on boto, it appears they have phase out the Java based CLI). So I tend to at least document what equivalent AWS CLI commands are for whatever functionality I'm working on. However, I have multiple AWS API keys, depending on what I am working on and which account the work is associated with. So, those keys are associated with different AWS accounts, e.g. when using an AWS lab in a class, I might end up with access keys for that class, which I can use during the lab.

The AWS environment provides quite a convenient setup for this, using configuration files in your ~/.aws directory. They also allow you to use a ~/.awsrc file, which I use for my autocompletion.

So, I've set up a directory with a set of config files, named awscfg-whatever.cfg containing the key and secrets for the various accounts, as follows:

  ls -l ~/.awsrc ~/.aws
  lrwxrwxrwx. 1 vmic vmic  22 Apr  4 09:21 /home/vmic/.awsrc >
  .aws/awsrc-es-vmic.cfg
  -rw-------. 1 vmic vmic  75 Jun 11 2014 awsrc-account1.cfg
  -rw-------. 1 vmic vmic  75 Nov 25 2014 awsrc-es-vmic.cfg
  -rw-------. 1 vmic vmic  75 May 27 2015 awsrc-qwiklab.cfg
  lrwxrwxrwx. 1 vmic vmic   9 May  5 2015 config > config-es
  -rw-------. 1 vmic vmic 203 May  7 2015 config-es
  # cat ~/.aws/awsrc-qwiklab.cfg
  key AKIAJSP5SAXQHBUVQYLA
  password sv5RTXCRrd4YFgGvdbbdM52GMttXa3X_xN.J4gww

The config file just contains the various defaults I want to use, such as the region. I haven't included this in the switching process, though I could add that.

What this allows me to do is to write a simple bash auto-completion script that look in the ~/.aws directory and enumerates all the files with the pattern awsrc-*.cfg. And then I can simply use that information to link the specified file to the ~/.awsrc file, resulting in the AWS CLI using a different account:

  # switch-aws
  current config: es-vmic
  configs:
    account1
    es-vmic
    qwiklab
  # switch-aws qwiklab
  switched to qwikab
  # ls -l ~/.awsrc
  lrwxrwxrwx. 1 vmic vmic 22 Apr  6 10:19 /home/vmic/.awsrc >
  .aws/awsrc-qwiklab.cfg

And if you have multiple accounts starting with the same name, the autocompletion script will show what options there are for switching.

It's worth noting that the AWS cli comes with it's own autocompletion script written in python that works quite amazingly.

The two scripts involved are:

switch-aws

#!/bin/bash

#
# A simple bash shell script to setup AWS environments. The
# idea is to have a a number of aws configurations in ~/.aws
# (with appropriate file permissions) using a standard nameing
# convention 'awsrc-*.cfg'. This script simply finds those and
# sets up the environment variables for use by both the CLI and
# the command tools. Please note that the CLI and the command
# line tools use different environment variables (what!?). Also
# note that the CLI has more extensive configurations that can be
# configured in a ~/.aws/config file which I do not address here.
#
# I also have a small bash autocompletion script which will
# allow me to use 'switch-aws ' to show all configured AWS
# configurations.
#

AWS_LOC="$HOME/.aws"
CONFIGS=

get_cfgs () {
   if [ -z "$CONFIGS" ]; then
       l=`/bin/ls -1 $AWS_LOC/awsrc-*.cfg`
       for f in $l; do
           f=${f##*/awsrc-}
           f=${f%.cfg}
           CONFIGS="$CONFIGS $f"
       done
   fi
}

list_cfgs () {
    get_cfgs
    echo "configs:"
    for f in $CONFIGS; do
        echo "  $f"
    done
}

list_current_cfg () {
    if [ -h "$HOME/.awsrc" ]; then
        f=`readlink "$HOME/.awsrc"`
        f=${f##*/awsrc-}
        f=${f%.cfg}
        echo "current config: $f"
    else
        echo "no current config"
    fi
}

set_cfg () {
    get_cfgs
    for f in $CONFIGS; do
        if [ "$f" == "$1" ]; then
            rm -f "$HOME/.awsrc"
            /bin/ln -s ".aws/awsrc-${f}.cfg" "$HOME/.awsrc"
            echo "switched to $f"
            return 0
        fi
    done
    echo "no config called $1"
}

set_env () {
    k=`/bin/egrep "^key " "$HOME/.awsrc" | awk '{print $2}'`
    export AWS_ACCESS_KEY="$k"
    export AWS_ACCESS_KEY_ID="$k"
    p=`/bin/egrep "^password " "$HOME/.awsrc" | awk '{print $2}'`
    export AWS_SECRET_KEY="$p"
    export AWS_SECRET_ACCESS_KEY="$p"
}

if [ "$#" -ne "1" ]; then
    list_current_cfg
    list_cfgs
else
    set_cfg $1
    set_env
fi

switch-aws_completion

#!/bin/bash

function _awsrc_completion_()
{
    local word=${COMP_WORDS[COMP_CWORD]}
    local aws_loc="$HOME/.aws"
    local l
    
    l=`/bin/ls -1 $aws_loc/awsrc-${word}*.cfg 2>/dev/null`
    for f in $l; do
        f=${f##*/awsrc-}
        f=${f%.cfg}
        COMPREPLY+=($f)
    done
}

complete -F _awsrc_completion_ switch-aws

And you need to include alias switch-aws=". script-location/switch-aws" in your .bashrc somewhere as well as running the autocompletion script out of your .bashrc.