One of the downsides of the default AWS command line set up is that by default, it stores credentials in plaintext in the
~/.aws/credentials file on the local disk.
It’s always bothered me, but recently I found https://github.com/99designs/aws-vault.
aws-vault uses a password manager to store credentials instead. By default, on MacOS, it uses MacOS Keychain, but it can also be configured to use alternative password backends via environment variables.
One of the supported secret backends is https://www.passwordstore.org/ - that’s great for me, because it supports GPG encryption, and I use
pass for everything else anyway, along with a Nitrokey security key to encrypt everything.
To switch from the default to
pass I just had to set an extra environment variable in my
Once I installed
aws-vault (I used the Nix package manager, but it’s available on loads of package managers), I had to tell it to store my AWS credentials.
aws-vault supports multiple profiles, so when you’re adding credentials, you need to give it a profile name, for example “personal” for your personal account, or the name of your client.
$ aws-vault add profile_name Enter Access Key ID: xxxxxxxxxxxxxxxxxxxxxx Enter Secret Access Key: xxxxxxxxxxxxxxxxxxxxxxx
Once I’d done this, I was able to delete the credentials from my
Best practice on AWS is that your base credentials don’t give you much in the way of permissions, and then you assume a role that requires MFA. This step of assuming a role creates temporary credentials, so that if they’re leaked, there’s a much smaller window of opportunity to exploit them.
aws-vault uses the
~/.aws/config file to determine which MFA device to use and the role to assume. To learn how to migrate from static credentials to a role, check out this post.
If you don’t want to migrate to using MFA and temporary credentials, you can skip adding anything to
~/.aws/config file, but I don’t recommend working that way. When I’d finished editing, my
~/.aws/config file looked like this:
[default] region = "eu-west-2" output = "json" [profile personal] mfa_serial = "arn:aws:iam::xxxxxxxxx:mfa/AdrianH" role_arn = "arn:aws:iam::xxxxxxxxxxx:role/Developer"
If you’re looking for the right value to put in
mfa_serial, you can use
aws iam list-mfa-devices or you can find it in the AWS console.
To use my personal AWS account and assume the “Developer” role, I can execute the command:
$ aws-vault exec profile_name Enter token for arn:aws:iam::xxxxxxxxxxx:mfa/AdrianH: xxxx
This looks up my base IAM credentials from my password manager, assumes the “Developer” role using STS, and drops the temporary credentials as environment variables into a new shell (I can see them with
env | grep AWS). Because the
AWS_* environment variables are set, I’m able to use CLI tools or AWS SDKs with appropriate permissions set.
When I’m finished, I can then use the exit command to terminate the shell and return back to not having any AWS permissions. Much better than what I was doing before.