← Home

Migrating to aws-vault

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 [0]

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 [1] 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 ~/.zshrc.

export AWS_VAULT_BACKEND=pass

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 ~/.aws/credentials file.

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, see [2]

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.