Blog

One Vault to Access Them All

Secure Multi-Account AWS Access

Yev Dytyniuk

Yev Dytyniuk

February 27, 2026
8 minutes

Managing access to multiple AWS accounts is a daily reality of a cloud engineer - and often a source of friction: short-lived credentials, roles switching and chaining, multi-factor authentication or single-sign-ons. The list is not definitive and varies between workflows.

The number of accounts multiplies the moment you get a full-fledged DTAP (Development/Test/Acceptance/Production) environment. Working on 3 DTAP-enabled projects? Congratulations, you've got 9 AWS accounts to deal with. How often do you catch yourself thinking, "What account am I in now?" and then run aws sts get-caller-identity for a quick sanity check? If this slowed you down, as it did me, read on. I will share my perspective on managing access to multiple accounts without growing any grey hair.

AWS CLI profiles are not enough

The AWS CLI configuration file lets you define multiple profiles to switch between accounts. Usually, you have something like this in your $HOME/.aws/config:

# $HOME/.aws/config

[default]
output = json
region = eu-west-1

[profile personal]
region = eu-west-1

# And so on

I will deliberately skip configuring static access keys because, at best, you shouldn't use them, especially in an enterprise-grade environment.

If you rely on AWS Identity Centre, the successor of AWS SSO, you usually have a few of the following configuration blocks:

# $HOME/.aws/config

[sso-session EvilCorp]
sso_start_url = https://evilcorp.awsapps.com/start/
sso_region = eu-west-1
sso_registration_scopes = sso:account:access

[profile evilcorp-dev]
sso_session = EvilCorp
sso_account_id = 112233445566
sso_role_name = Poweruser

[profile evilcorp-acc]
sso_session = EvilCorp
# ...

[profile evilcorp-prod]
sso_session = EvilCorp
# ...

To use a profile, you pass its name as a --profile argument for AWS CLI commands:

# Development
$ aws s3 ls --profile evilcorp-dev

# Acceptance/UAT
$ aws s3 ls --profile evilcorp-acc

Works? Yes. Convenient? Secure? Questionable.

What is the chance that you mistype the name of the profile? Or, in case of autocomplete, press [Tab] too little or too many times and choose the wrong option?

Another downside is that all your credentials are in the same basket now - for SSO-enabled profiles, temporary credentials are stored on the disk, in $HOME/.aws/sso/cache/*.json:

$ cat ~/.aws/sso/cache/974...66f330.json | jq -r
{
  "startUrl": "https://evilcorp.awsapps.com/start/",
  "region": "eu-west-1",
  "accessToken": "...",
  "expiresAt": "2026-02-12T19:46:13Z",
  "clientId": "...",
  "clientSecret": "...",
  "registrationExpiresAt": "2026-05-13T18:45:59Z",
  "refreshToken": "..."
}

MFA, with bare profiles, feels like an afterthought and makes the process even clunkier. There has to be a better, more convenient way.

Enter the aws-vault

aws-vault is a tool designed to solve a lot of the mentioned problems.

First, it picks up your $HOME/.aws/config file, so you don't have to migrate your profiles to yet another tool. Second, instead of files, it uses your system's keychain or other backend of your choice to store AWS access credentials:

  • macOS Keychain
  • Secret Service (Gnome Keyring, KWallet)
  • 1Password
  • and others

So, if you use static access keys, this is a better way to store them than the good old $HOME/.aws/credentials file. However, don't forget to still use roles, preferably, with MFA. And, yes, aws-vault supports all these scenarios.

Identity Centre (SSO) Integration

The aws-vault will pick up your SSO-backed profiles without any extra configuration.

To check a list of profiles recognised by the aws-vault, run the list command:

$ aws-vault list
Profile                  Credentials              Sessions
=======                  ===========              ========
default                  -                        -
personal                 personal                 -
localstack               localstack               -
evilcorp-dev             -                        sso.GetRoleCredentials:-10m45s
evilcorp-acc             -                        -
evilcorp-prod            -                        -
-                        -                        oidc:https://evilcorp.awsapps.com/start/

The columns are:

  • Your AWS profile name.
  • If the profile uses a static access key, you'll see its name in the Credentials column.
  • Information about an active profile session.

In the example above, aws-vault assumed a role in the evilcopr-dev profile almost 11 minutes ago. Profile with dashes instead of names and sessions starting with oidc: are your configured SSO sessions ([sso-session] from the $HOME/.aws/config).

aws-vault in action

The conventional way to run a command barely differs from AWS CLI:

$ aws s3 ls --profile evilcorp-dev
# VS
$ aws-vault exec evilcorp-dev -- aws s3 ls

The -- signifies the end of aws-vault options and enables shell autocomplete for the AWS CLI command. But I find this tiresome -- typing the whole thing just to run one command, then again for another, and again.

So, instead, you can start a new shell session by omitting the command part: aws-vault exec $PROFILE.

Using an SSO-based profile will open your default browser if you don't have an active SSO session. Once signed in, the aws-vault will get you a set of temporary credentials and inject them into a subshell:

$ aws-vault exec evilcorp-dev
Opening the SSO authorization page in your default browser (use Ctrl-C to abort)
https://evil-sso.awsapps.com/start/#/device?user_code=ABCD-EFGH
Starting subshell /bin/zsh, use `exit` to exit the subshell
$ printenv | grep AWS
AWS_VAULT=evilcord-dev
AWS_REGION=eu-west-1
AWS_DEFAULT_REGION=eu-west-1
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
AWS_SESSION_TOKEN=...
AWS_CREDENTIAL_EXPIRATION=2026-02-25T22:30:17Z

Signing in to the AWS Console is as simple as swapping the exec command with the login command: aws-vault login $PROFILE. You can omit $PROFILE if you want to open the console for the current session:

$ aws-vault exec evilcorp-acc
Starting subshell /bin/zsh, use `exit` to exit the subshell
$ aws-vault login

Mixed with the multi-session support feature of the AWS Console, I find this an incredible improvement for my workflows.

Metadata server

In scenarios where you need temporary credentials for an extended period of time, aws-vault can run a background server to imitate the metadata endpoint you have in an EC2 instance of an ECS task. This server will continue to generate temporary credentials any time the application requests them. For example, when you manage your infrastructure with Terraform, you need the AWS credentials for the entire duration of the apply phase.

The server also enables a local development environment to connect to AWS services. Are you developing a multi-container system with Docker Compose? Not a problem, your containers can retrieve temporary credentials from aws-vault running on the host! The default credentials chain of the AWS SDK automatically connects to the server to fetch credentials. The process is similar to amazon-ecs-local-container-endpoints. The difference is that credentials are sourced from the keychain via aws-vault.

Other use cases

You can also turn the tables around and make aws-vault your "master credentials vault" through the credential_process configuration in your AWS config file. This aligns with the AWS SDK and other tools that recognise the AWS_PROFILE environment variable:

# Master credentials added with `aws-vault add master-profile`
# ~/.aws/config
[profile master-profile]
credentials_process = aws-vault export --format=json --no-session master-profile

[profile my-role]
source_profile = master-profile
role_arn = ...

Now, you can either use aws-vault as an executor:

aws-vault exec my-role aws s3 ls

Or run the command with a pre-set environment variable:

AWS_PROFILE=my-role aws s3 ls

With just a few lines added, you can turn your aws-vault into an MFA session cache:

# ~/.aws/config

[profile master-profile]
credential_process = aws-vault export --format=json --no-session master-profile
mfa_serial = arn:aws:iam::123456789012:mfa/johndoe

[profile my-role]
source_profile = master-profile
role_arn = ...
mfa_serial ... 

Or, even a cache for alternative credential sources:

# ~/.aws/config

[profile custom-cred-profile]
credential_process = custom-creds-cmd
# via aws-vault as cache
$ aws-vault exec custom-cred-profile aws s3 ls

# skip aws-vault, so, no cache
$ AWS_PROFILE=custom-cred-profile aws s3 ls

I'm sure that you'll find your recipe after checking the documentation

Bonus

I usually start several sessions with aws-vault exec. You can easily get lost trying to remember which tab or panel has which account. Try running 2 or 3 accounts with a decent amount of commands...

So, to help myself, I wrote a simple Bash function to display the current session name in my zsh shell prompt:

# ~/.zshrc

function aws_profile_info() {
    local _info=""
    local _profile="${AWS_VAULT:-$AWS_PROFILE}"
    if [[ "$_profile" != "" ]]; then
        _info="(%{$fg[yellow]%}\u2601%{$reset_color%} $_profile)"
    fi
    echo -e "$_info"
}

PROMPT='$(aws_profile_info)'
PROMPT+='[the rest of your PROMPT config]'

The moment I start a session:

~ $ aws-vault exec evilcorp-dev
Opening the SSO authorization page in your default browser (use Ctrl-C to abort)
https://evilcorp.awsapps.com/start/#/device?user_code=ABCD-EFGH
Starting subshell /bin/zsh, use `exit` to exit the subshell
(☁ evilcorp-dev) ~ $

I get my shell prompt prefixed with an active AWS profile and a small cloud icon on its left. Handy, isn't it?

Wrapping Up

I like to optimise my routines without losing oversight on the automation. aws-vault gives me this with a pinch of Bash scripting to spice up my ZSH prompt.

I've used several different tools to manage access to my AWS accounts, but haven't found something more productive than aws-vault. Let's be honest, what can be better than cranking up your terminal and getting into the account with a single command? It does not matter whether you are running an AWS CLI command or navigating through the Console.

Give it a try. Life is too short to waste it on credentials management :)

Photo by Brett Sayles.

Written by

Yev Dytyniuk

Yev Dytyniuk

AWS Cloud Consultant/Engineer

A software/cloud engineer who has seen enough to go and fix things before the damage is done. I've built various web applications, integrated enterprise systems, run migrations, etc. I like simple, effective, and robust architectures and am always on the lookout for another interesting challenge: optimise a wonky database, turn an hour-long batch process into a blazingly event-based pipeline, or just talk about the quirks of another AWS service.

Contact

Let’s discuss how we can support your journey.