AWS Vault is a tool to securely store and access AWS credentials in a development environment.

AWS Vault stores IAM credentials in your operating system’s secure keystore and then generates temporary credentials from those to expose to your shell and applications. It’s designed to be complementary to the AWS CLI tools, and is aware of your profiles and configuration in ~/.aws/config.

https://github.com/99designs/aws-vault

 

Typical Authentication Flow


When you configure your IAM user using the AWS CLI, it stores your credentials in plain text on your machine by default in an .aws directory on your home directory. This is common knowledge and can be exploited in cases where your computer gets compromised and all of this can happen without your knowledge. With your credentials, an attacker can use them to do almost anything in your AWS account based on the permissions set on the associated IAM user.

Pros:

  • Simple to configure for a single AWS Account
  • Authentication to AWS can be entirely transparent to the end-user

Cons:

  • Long-term credentials are stored on the local disk of your laptop in plain-text, which can lead to credential leakage and present a security risk
  • Complex to configure when you are Well-Architected and have more than one AWS Account

AWS Vault securely stores and access AWS credentials in our local setup using our operating system’s secure keystore. It then generates temporary credentials from the keystore and exposes it to our shell and applications, making sure we do not store these credentials in plain text.

 

Quick start


# Setup a New Profile
# Store AWS credentials for the "jonsmith" profile
$ aws-vault add jonsmith
Enter Access Key Id: ABDCDEFDASDASF
Enter Secret Key: %%%

# Execute a command (using temporary credentials)
$ aws-vault exec jonsmith -- aws s3 ls
bucket_1
bucket_2

# open a browser window and login to the AWS Console
$ aws-vault login jonsmith

# List credentials
$ aws-vault list
Profile                  Credentials              Sessions
=======                  ===========              ========
jonsmith                 jonsmith                 -

 

Environment variables


To configure the default flag values of aws-vault and its subcommands:

  • AWS_VAULT_BACKEND: Secret backend to use (see the flag --backend)
  • AWS_VAULT_KEYCHAIN_NAME: Name of macOS keychain to use (see the flag --keychain)
  • AWS_VAULT_PROMPT: Prompt driver to use (see the flag --prompt)
  • AWS_VAULT_PASS_PASSWORD_STORE_DIR: Pass password store directory (see the flag --pass-dir)
  • AWS_VAULT_PASS_CMD: Name of the pass executable (see the flag --pass-cmd)
  • AWS_VAULT_PASS_PREFIX: Prefix to prepend to the item path stored in pass (see the flag --pass-prefix)
  • AWS_VAULT_FILE_DIR: Directory for the “file” password store (see the flag --file-dir)
  • AWS_VAULT_FILE_PASSPHRASE: Password for the “file” password store
  • AWS_CONFIG_FILE: The location of the AWS config file

To override the AWS config file (used in the exec, login and rotate subcommands):

  • AWS_REGION: The AWS region
  • AWS_DEFAULT_REGION: The AWS region, applied only if AWS_REGION isn’t set
  • AWS_STS_REGIONAL_ENDPOINTS: STS endpoint resolution logic, must be “regional” or “legacy”
  • AWS_MFA_SERIAL: The identification number of the MFA device to use
  • AWS_ROLE_ARN: Specifies the ARN of an IAM role in the active profile
  • AWS_ROLE_SESSION_NAME: Specifies the name to attach to the role session in the active profile

To override session durations (used in exec and login):

  • AWS_SESSION_TOKEN_TTL: Expiration time for the GetSessionToken credentials. Defaults to 1h
  • AWS_CHAINED_SESSION_TOKEN_TTL: Expiration time for the GetSessionToken credentials when chaining profiles. Defaults to 8h
  • AWS_ASSUME_ROLE_TTL: Expiration time for the AssumeRole credentials. Defaults to 1h
  • AWS_FEDERATION_TOKEN_TTL: Expiration time for the GetFederationToken credentials. Defaults to 1h
  • AWS_MIN_TTL: The minimum expiration time allowed for a credential. Defaults to 5m

Note: that the session durations above expect a unit after the number (e.g. 12h or 43200s).

To override or set session tagging (used in exec):

  • AWS_SESSION_TAGS: Comma separated key-value list of tags passed with the AssumeRole call, overrides session_tags profile config variable
  • AWS_TRANSITIVE_TAGS: Comma separated list of transitive tags passed with the AssumeRole call, overrides transitive_session_tags profile config variable

To override or set the source identity (used in exec and login):

  • AWS_SOURCE_IDENTITY: Specifies the source identity for assumed role sessions

 

Backends


You can choose among different pluggable secret storage backends. You can set the backend using the --backend flag or the AWS_VAULT_BACKEND environment variable. Run aws-vault --help to see what your --backend flag supports.

The supported vaulting backends are:

  • macOS Keychain
  • Windows Credential Manager
  • Secret Service (Gnome Keyring, KWallet)
  • KWallet
  • Pass
  • Encrypted file

 

Managing credentials


Using multiple profiles

In addition to using IAM roles to assume temporary privileges as described in README.md, aws-vault can also be used with multiple profiles directly. This allows you to use multiple separate AWS accounts that have no relation to one another, such as work and home.

# Store AWS credentials for the "home" profile
$ aws-vault add home
Enter Access Key Id: ABDCDEFDASDASF
Enter Secret Key: %

# Execute a command using temporary credentials
$ aws-vault exec home -- aws s3 ls
bucket_1
bucket_2

# store credentials for the "work" profile
$ aws-vault add work
Enter Access Key Id: ABDCDEFDASDASF
Enter Secret Key: %

# Execute a command using temporary credentials
$ aws-vault exec work -- aws s3 ls
another_bucket

Here is an example ~/.aws/config file, to help show the configuration. It defines two AWS accounts: “home” and “work”, both of which use MFA. The work account provides two roles, allowing the user to become either profile.

[default]
region = us-east-1

[profile home]
mfa_serial = arn:aws:iam::111111111111:mfa/home-account

[profile work]
mfa_serial = arn:aws:iam::111111111111:mfa/work-account
role_arn = arn:aws:iam::111111111111:role/ReadOnly

[profile work-admin]
role_arn = arn:aws:iam::111111111111:role/Administrator
source_profile = work

Listing profiles and credentials

You can use the aws-vault list command to list out the defined profiles, and any session associated with them.

$ aws-vault list
Profile                  Credentials              Sessions
=======                  ===========              ========
home                     home
work                     work                     1525456570
work-read-only           work
work-admin               work

Removing credentials

The aws-vault remove command can be used to remove credentials. It works similarly to the aws-vault add command.

# Remove AWS credentials for the "work" profile
$ aws-vault remove work
Delete credentials for profile "work"? (y|N) y
Deleted credentials.

Rotating credentials

Regularly rotating your access keys is a critical part of credential management. You can do this with the aws-vault rotate <profile> command as often as you like.

The minimal IAM policy required to rotate your own credentials is:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:CreateAccessKey",
                "iam:DeleteAccessKey",
                "iam:GetUser"
            ],
            "Resource": [
                "arn:aws:iam::*:user/${aws:username}"
            ]
        }
    ]
}

 

Managing Sessions


Executing a command

Running aws-vault exec will run a command with AWS credentials.

When using exec, you may find it useful to use the builtin -- feature in bash, zsh and other POSIX shells. For example

aws-vault exec myprofile -- aws s3 ls

Using -- signifies the end of the aws-vault options, and allows the shell autocomplete to kick in and offer autocompletions for the proceeding command.

If you use exec without specifying a command, AWS Vault will create a new interactive subshell. Note that when creating an interactive subshell, bash, zsh and other POSIX shells will execute the ~/.bashrc or ~/.zshrc file. If you have local variables, functions or aliases (for example your PS1 prompt), ensure that they are defined in the rc file so they get executed when the subshell begins.

Logging into AWS console

You can use the aws-vault login command to open a browser window and login to AWS Console for a given account:

$ aws-vault login work

If you have temporary STS credentials already available in your environment, you can have aws-vault use these credentials to sign you in. This is useful when you had to use something else than aws-vault to retrieve temporary credentials:

# AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN must be set in your environment prior to running the below
$ aws-vault login

Removing stored sessions


If you want to remove sessions managed by aws-vault before they expire, you can do this with aws-vault clear command.

You can also specify a profile to remove sessions for this profile only.

aws-vault clear [profile]

Using –no-session


AWS Vault will typically create temporary credentials using a combination of GetSessionToken and AssumeRole, depending on the config. The GetSessionToken call is made with MFA if available, and the resulting session is cached in the backend vault and can be used to assume roles from different profiles without further MFA prompts.

If you wish to skip the GetSessionToken call, you can use the --no-session flag.

However, consider that if you use --no-session with a profile using IAM credentials and NO role_arn, then your IAM credentials will be directly exposed to the terminal/application you are running. This is the opposite of what you are normally trying to achieve by using AWS Vault. You can easily witness that by doing

aws-vault exec <iam_user_profile> -- env | grep AWS

You’ll see an AWS_ACCESS_KEY_ID of the form ASIAxxxxxx which is a temporary one. Doing

aws-vault exec <iam_user_profile> --no-session -- env | grep AWS

You’ll see your IAM user AWS_ACCESS_KEY_ID of the form AKIAxxxxx directly exposed, as well as the corresponding AWS_SECRET_KEY_ID.

Session duration

If you try to assume a role from a temporary session or another role, AWS considers that as role chaining and limits your ability to assume the target role to 1h. Trying to use a duration longer than 1h may result in an error:

aws-vault: error: Failed to get credentials for default: ValidationError: The requested DurationSeconds exceeds the MaxSessionDuration set for this role.
        status code: 400, request id: aa58fa50-4a5e-11e9-9566-293ea5c350ee

For that reason, AWS Vault will not use GetSessionToken if --duration or the role’s duration_seconds is longer than 1h.

MFA


To enable MFA for a profile, specify the mfa_serial in ~/.aws/config. You can retrieve the MFA’s serial (ARN) in the web console, or you can usually derive it pretty easily using the format arn:aws:iam::[account-id]:mfa/[your-iam-username]. If you have an account with an MFA associated, but you don’t provide the IAM, you are unable to call IAM services, even if you have the correct permissions to do so.

AWS Vault will attempt to re-use a GetSessionToken between profiles that share a common mfa_serial. In the following example, aws-vault will cache and re-use sessions between role1 and role2. This means you don’t have to continually enter MFA codes if the user is the same.

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.

[profile tom]
mfa_serial = arn:aws:iam::111111111111:mfa/tom

[profile role1]
source_profile = tom
role_arn = arn:aws:iam::22222222222:role/role1
mfa_serial = arn:aws:iam::111111111111:mfa/tom

[profile role2]
source_profile = tom
role_arn = arn:aws:iam::33333333333:role/role2
mfa_serial = arn:aws:iam::111111111111:mfa/tom

AWS Single Sign-On (AWS SSO)


If your organization uses AWS Single Sign-On (AWS SSO), AWS Vault provides a method for using the credential information defined by AWS SSO CLI v2. The configuration options are as follows:

  • sso_start_url The URL that points to the organization’s AWS SSO user portal.
  • sso_region The AWS Region that contains the AWS SSO portal host. This is separate from, and can be a different region than the default CLI region parameter.
  • sso_account_id The AWS account ID that contains the IAM role that you want to use with this profile.
  • sso_role_name The name of the IAM role that defines the user’s permissions when using this profile.

Here is an example configuration using AWS SSO.

[profile Administrator-123456789012]
sso_start_url=https://aws-sso-portal.awsapps.com/start
sso_region=eu-west-1
sso_account_id=123456789012
sso_role_name=Administrator

 

Integration with ZSH and oh-my-zsh


I use the iTerm2 terminal configured with the ZSH shell. I also use the oh-my-zsh framework for my ZSH shell. This should work in any terminal that uses ZSH not just iTerm2. So any Unix-like operating system, MacOS, Linux, BSD and WSL2 on Windows. ‘Oh My Zsh’ is an open source community-driven framework for managing your ZSH configurations. Think of it as a community supported alias package for your terminal.

‘Oh My Zsh’ supports plugins and the plugin we will add is called zsh-aws-vault. It provides many convenient aliases to use when running commands that interact with the configured AWS profiles.

The first step in installing the above plugin is to clone and download it to the plugins directory:

$ cd ~/.oh-my-zsh/custom/plugins
$ git clone git@github.com:blimmer/zsh-aws-vault.git

Next, edit your ~/.zshrc file and add the new plugin to the plugins line. We will be adding a plugin for AWS Vault. So edit your plugins line to look something like this: (Here, I’m adding AWS Vault in addition to git and dotenv plugins):

plugins=(
  git
  dotenv
  zsh-aws-vault
)

 

Usage with zsh-aws-vault


Here are the aliases that are added after you install the plugin for zsh:

Alias Expression
av aws-vault
ave aws-vault exec
avl aws-vault login
avll aws-vault login -s
avli aws-vault login in private browsing window
avs aws-vault server
avsh aws-vault exec $1 — zsh
avp list aws config / role ARNs

We will use the following command to run the example above where we listed all S3 buckets in our account:

$ ave s3-read-user -- aws s3 ls
account_bucket-a
account_bucket-b
account_bucket-c

Sometimes you might not want to type extra commands each time you want to interact with your AWS account through the CLI. In such cases use the nifty avsh command to create a shell for a given profile. Then any command you run in that shell will use the associated profile. Using the example above, we can create a shell with the s3-read-user profile, then run any command without using the ave or aws-vault prefixes like we did above:

$ avsh s3-read-user

Now any command you run in that shell will use the associated profile from the previous command:

$ aws s3 ls
account_bucket-a
account_bucket-b
account_bucket-c

If you run the env command at this point, you will see all the AWS environment variables created in your terminal. You can use the exit command to go back to your regular shell and remove these variables from your shell environment.

$ env | grep AWS
AWS_VAULT=s3-read-user
AWS_DEFAULT_REGION=us-east-1
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=%%%
AWS_SECRET_ACCESS_KEY=%%%
AWS_SESSION_TOKEN=%%%
AWS_SECURITY_TOKEN=%%%
AWS_SESSION_EXPIRATION=2020-12-29T11:00:00Z

To exit from the temporary shell and back to your normal shell without the AWS environment variables, use the exit command:

$ exit