Using aws-vault with Linux

~/.aws/credentials sucks - but don't worry, you have options.

There are lots of purported "best practices" out there on the internet regarding AWS API keypairs. In this author's opinion, the term best practices is in many cases either a dubious claim or a concept that isn't actually real, since "best" is often subjective or situation dependent. However, with regard to AWS API keypairs and developer machines, I'll argue that there really is a best way.

I was recently introduced to aws-vault by an acquaintance from the HangOps slack team. Succinctly put, it solves two significant problems:

  • Leaving a keypair lying around on disk, accessible in plain text from your ~/.aws/credentials file, really sucks. It's not necessarily terrible if you're enforcing role assumption and 2fa, and if your disk is encrypted at rest, and if you never walk away from your machine without locking it - but that's several ifs.
  • The 1h timeout on credentials gained from assuming a role sucks.

Enter aws-vault - which stores credentials and session data in your keychain and is capable of handling renewal transparently. Usage is well documented for OSX and outside the scope of this article, which tells you how to do it with Gnome (or Cinnamon - which is what I use). I've used the same process on both Ubuntu 16.04 and Fedora 27 with success. While simply using an encrypted file works just fine, I prefer to use the keychain!


  • Ensure that gnome-keyring is installed.
  • Ensure that that gnome-keyring-daemon is running - I put these lines in my ~/.bash_profile:
if [ -n "$DESKTOP_SESSION" ];then  
    eval $(gnome-keyring-daemon --start)
    export SSH_AUTH_SOCK

Under Linux, aws-vault defaults to using encrypted files. Therefore, you'll need to specify a backend via env var. In ~/.bash_profile:

export AWS_VAULT_BACKEND=secret-service  

You're set to begin adding credentials:

  • source ~/.bash_profile
  • aws-vault add $someprofilename - This will prompt you for an AWS Access Key ID and AWS Secret Access Key pair

You now have a keypair stored in aws-vault - however, a little more setup is required for assuming roles. This is done a bit like how the ~/.aws/credentials file normally functions, only it's done in ~/.aws/config - aws-vault adds the [profile someprofile], you just need to add profiles which use its keypair for assuming a role:

[profile someprofile]

[profile ops]
role_arn = arn:aws:iam::12345678910:role/some-role  
source_profile = someprofile  
mfa_serial = arn:aws:iam::23456789101:mfa/connor_rielly

[profile k8s]
role_arn = arn:aws:iam::34567891011:role/another-role  
source_profile = someprofile  
mfa_serial = arn:aws:iam::23456789101:mfa/connor_rielly

[profile blog]
role_arn = arn:aws:iam::456789101112:role/third-role  
source_profile = someprofile  
mfa_serial = arn:aws:iam::23456789101:mfa/connor_rielly  

Now you can see that aws-vault retrieves any linked profiles:

$ aws-vault list
Profile                  Credentials              Sessions  
=======                  ===========              ========                 
someprofile              someprofile              -  
ops                      someprofile              -  
k8s                      someprofile              -  
blog                     someprofile              -  

And you're ready grab some credentials with a nice, long TTL:

$ aws-vault exec --server --session-ttl=8h ops
Enter token for arn:aws:iam::23456789101:mfa/connor_rielly: 549236

$ aws-vault list
Profile                  Credentials              Sessions  
=======                  ===========              ========                 
someprofile              someprofile              86743437993111653036  
ops                      someprofile              -  
k8s                      someprofile              -  
blog                     someprofile              - 

$ aws s3 ls
2017-12-15 20:49:38 some-bucket-1  
2017-12-09 23:08:47 some-bucket-2  
2017-07-18 22:59:37 some-bucket-3  

Or to execute subprocesses with AWS credentials injected as Environment Variables:

aws-vault exec k8s -- ansible-playbook standup-asg-cluster.yml -i inventories/dev -e "namespace=tcdev" -e "region=us-west-2"  

Or to login to the console (this opens a browser tab):

$ aws-vault --debug login tck8s
2018/03/08 13:01:34 Loading config file /home/crielly/.aws/config  
2018/03/08 13:01:34 Parsing config file /home/crielly/.aws/config  
2018/03/08 13:01:34 Skipping session token and using master credentials directly  
2018/03/08 13:01:34 Looking up keyring for tc  
Enter token for arn:aws:iam::ACCTNUMBER:mfa/connor_rielly: 976384  
2018/03/08 13:01:41 Assuming role arn:aws:iam::ACCTNUMBER:role/org-admin with iam credentials  

You also now have no keypair stored in anything resembling a readable fashion on-disk.