Presenting: aws-identity for Amazon Web Services

2012-07-23 16:07

We rely on Amazon Web Services at work. I spend a lot of time with the AWS command line tools but find myself juggling AWS accounts for various clients. This necessitates re-setting the EC2_CERT, EC2_PRIVATE_KEY, and AWS_CREDENTIAL_FILE environment variables each time I need to work on a different client. I put together a small shell script, aws-identity, to automate away that tedium.

To start, gather your certificates and credentials. Some AWS tools require an X.509 pair that can be created by Amazon via the “security credentials” web interface or created locally using the IAM tools. Other tools rely on a textual credential file specifying an access key and secret key, again available via “security credentials”.

aws-credentials
  1. AWSAccessKeyId=accesskeyhere
  2. AWSSecretKey=isureamtellingyoumysecretkeyrightnow

Create a directory layout to store certificates, keys, and credential files. I use ~/aws-identities/ with a subdirectory for each client. In this example, client1 has both an X.509 pair and a credential file, and client2 has only an X.509 pair.

tree ~/aws-identities
  1. aws-identities
  2. ├── client1
  3. │   ├── aws-credentials
  4. │   ├── cert-ARFCVP24OJED4KQP2WXYPDX7XYV62UYJ.pem
  5. │   └── pk-ARFCVP24OJED4KQP2WXYPDX7XYV62UYJ.pem
  6. └── client2
  7. ├── cert-YHGL5M3BBXFTMRYP3R42VNT32B634ESH.pem
  8. └── pk-YHGL5M3BBXFTMRYP3R42VNT32B634ESH.pem
  9. 2 directories, 5 files

A child process can’t modify the parent shell’s environment directly, so the aws-identity script will generate the proper commands for your shell. Its output can be evaled to alter the environment. It supports Bourne-style shells such as sh, zsh, bash, and ksh, as well as CSH-style shells like csh and tcsh.

bin/aws-identity client1 sh
  1. export EC2_CERT=/Users/nreid/aws-identities/client1/cert-ARFCVP24OJED4KQP2WXYPDX7XYV62UYJ.pem &&
  2. export EC2_PRIVATE_KEY=/Users/nreid/aws-identities/client1/pk-ARFCVP24OJED4KQP2WXYPDX7XYV62UYJ.pem &&
  3. export AWS_CREDENTIAL_FILE=/Users/nreid/aws-identities/client1/aws-credentials
bin/aws-identity client2 csh
  1. setenv EC2_CERT /Users/nreid/aws-identities/client2/cert-YHGL5M3BBXFTMRYP3R42VNT32B634ESH.pem &&
  2. setenv EC2_PRIVATE_KEY /Users/nreid/aws-identities/client2/pk-YHGL5M3BBXFTMRYP3R42VNT32B634ESH.pem &&
  3. unsetenv AWS_CREDENTIAL_FILE

Omitting the shell type argument will produce human-readable descriptive text about the variables it will set or unset.

bin/aws-identity client1
  1. Switched EC2 and AWS identity to client1
bin-aws-identity client2
  1. Switched EC2 identity to client2

I combine the two modes in a function in my .zshrc:

~/.zshrc
  1. aws() {eval `bin/aws-identity $1 sh` && bin/aws-identity $1}

The aws command now allows me to painlessly switch accounts! To client1:

aws client1
  1. Switched EC2 and AWS identity to client1
export | grep -E 'EC2_CERT|EC2_PRIV|AWS_CRED'
  1. AWS_CREDENTIAL_FILE=/Users/nreid/aws-identities/client1/aws-credentials
  2. EC2_CERT=/Users/nreid/aws-identities/client1/cert-ARFCVP24OJED4KQP2WXYPDX7XYV62UYJ.pem
  3. EC2_PRIVATE_KEY=/Users/nreid/aws-identities/client1/pk-ARFCVP24OJED4KQP2WXYPDX7XYV62UYJ.pem
as-describe-auto-scaling-instances
  1. INSTANCE i-effb1d573 client1-promo us-east-1a InService HEALTHY client1-promo
  2. INSTANCE i-afd343ce3 client1-promo us-east-1d InService HEALTHY client1-promo

Or to client2:

aws client2
  1. Switched EC2 identity to client2
export | grep -E 'EC2_CERT|EC2_PRIV|AWS_CRED'
  1. EC2_CERT=/Users/nreid/aws-identities/client2/cert-YHGL5M3BBXFTMRYP3R42VNT32B634ESH.pem
  2. EC2_PRIVATE_KEY=/Users/nreid/aws-identities/client2/pk-YHGL5M3BBXFTMRYP3R42VNT32B634ESH.pem
as-describe-auto-scaling-instances
  1. INSTANCE i-8c5733f5 Client2FB us-east-1d InService HEALTHY Client2FB
  2. INSTANCE i-c45ed870 Client2FB us-east-1b InService HEALTHY Client2FB