Skip to main content
  1. Posts/

AWS CLI - Dealing with Multiple Profiles

·5 mins
devops security networking aws aws cli aws sso bash zsh tips & tricks
Table of Contents

TL;DR
#

Working with multiple AWS CLI profiles can be a hassle. It also might not be obvious that authenticating with an AWS CLI profile doesn’t automatically tell AWS CLI which profile to use for commands. I wrote a Bash/ZSH function to automate logging in and setting the AWS_PROFILE environment variable for a specified profile.

Want to skip straight to the solution? Jump to Automating Profile Switching.

A Faulty Assumption
#

I’ve had multiple profiles set up in my .aws/config file for a while, but apparently I’ve never actually used any of them other than the one I have set as default.

This became evident recently as I was working with AWS CLI and needed to switch between different accounts (i.e., profiles). I use SSO for AWS authentication with AWS CLI and always start with aws sso login. Up until now, I haven’t had any problems as it uses my default profile. In this case, however, I started with aws sso login --profile <profileName> instead. After authenticating successfully, I immediately ran into a problem.

Maybe it’s paranoia (though I like to think of it as a good practice), but I’ve always been in a habit of running the aws sts get-caller-identity command any time I authenticate with AWS CLI. If you’re not familiar with this command, it outputs info about the IAM user you’re authenticated as and which account you’re logged into. For me it’s a good visual indicator that I’m in the correct account before running any actual commands. In this case, running the command showed that I was logged into my default profile account and not the one I intended to use. Weird. I then logged out of both accounts to ensure there was no session caching, etc. After that, I made sure to re-authenticate with aws sso login --profile <profileName> to be sure I was only using the desired profile. Running aws sts get-caller-identity again gave a different result. It instead returned Unable to locate credentials. You can configure credentials by running "aws configure". This made no sense - I knew the profile was already configured and I had authenticated with it.

Helpful Commands: aws configure list and aws configure list-profiles are useful commands for referencing & troubleshooting AWS CLI profiles.

This seems obvious in hindsight, but it certainly wasn’t at the time - it never occurred to me that there was a difference between authenticating multiple profiles in AWS CLI vs. telling AWS CLI which profile to actually use when running commands. I was aware of, and had used, the --profile <profileName> argument for commands, but I had always assumed that was just an override - which technically it is. At any rate, I made the faulty assumption that authenticating with an AWS CLI profile also automatically sets it as the profile to use for subsequent commands.

After a bit of searching, I found the answer in the AWS CLI docs

If no profile is explicitly defined, the default profile is used…
To use a named profile for multiple commands, you can avoid specifying the profile in every command by setting the AWS_PROFILE environment variable as the default profile. You can override this setting by using the –profile parameter.

Bingo - the AWS_PROFILE environment variable tells AWS CLI to use a specific profile. Sure enough, a quick export AWS_PROFILE=<profileName> worked beautifully.

That’s great and all, but I really don’t want to mess with setting and unsetting the environment variable every time I use AWS CLI. This problem is a prime candidate for an automated solution.

Automating Profile Switching
#

While thinking about how to automate this, I remembered something a friend had recently shown me. They had written a Bash function, for a specific task, that displayed a numbered list of options to choose from. So I borrowed their idea and wrote a Bash/ZSH function to automate the AWS login process and set the environment variable.

The Bash/ZSH function can be added to .bashrc or .zshrc and, in my opinion, simplifies the AWS CLI login process. While technically two separate functions - aws-login and aws-logout - they work together to serve a single purpose.

Running the aws-login function displays a list of the configured AWS CLI profiles and prompts you to choose one. Once a profile is selected, it goes through the normal AWS SSO login process and then, if authentication is successful, sets the AWS_PROFILE environment variable to the selected profile.

Snippet from the aws-login function…

    # AWS SSO login with the specified profile
    echo "AWS SSO login for profile: $profile"
    aws sso login --profile "$profile"
    
    # Check if login was successful
    if [ $? -eq 0 ]; then
        # Set the AWS_PROFILE environment variable
        export AWS_PROFILE="$profile"
        echo "AWS SSO login successful"
        echo "AWS_PROFILE set to: $profile"
    else
        echo "AWS SSO login failed"
        return 1
    fi

AWS CLI Login Function Screenshot
aws-login function example

Running the aws-logout function goes through the AWS SSO logout process and then unsets the environment variable.

Snippet from the aws-logout function…

    # AWS SSO logout for the current profile
    aws sso logout --profile "$AWS_PROFILE"
    
    # Check if logout was successful
    if [ $? -eq 0 ]; then
        echo "Successfully logged out of profile: $AWS_PROFILE"
        # Unset the AWS_PROFILE environment variable
        unset AWS_PROFILE
        echo "AWS_PROFILE environment variable cleared"
    else
        echo "AWS SSO logout failed"
        return 1

AWS CLI Logout Function Screenshot
aws-logout function example

The full script/function is available here…
aws-sso-login-logout.sh

Also, if you have an alternative solution to this problem, I’d love to hear about it in the comments!

Terminal Prompt Customization
#

In the screenshots above, you may have noticed the AWS context in the terminal prompt. I’ve been using the Wezterm terminal emulator along with Starship for a bit. Both are cross-platform so I get the same look and feel regardless of which machine I’m working on. In this case, Starship pulls the AWS context from the AWS_PROFILE environment variable and displays it directly in the prompt. This provides an awesome additional visual indicator!

The configs used in the screenshots above are available in my GitHub dotfiles repo. That said, there are plenty of great (read better) resources out there for configuring Wezterm and/or Starship.
wezterm.lua
starship.toml

Josh Jaggard
Author
Josh Jaggard