Skip to content

Instantly share code, notes, and snippets.

@brianredbeard
Last active October 3, 2022 02:18
Show Gist options
  • Star 24 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save brianredbeard/035ee1419bc38a0e2d854fb828d585d7 to your computer and use it in GitHub Desktop.
Save brianredbeard/035ee1419bc38a0e2d854fb828d585d7 to your computer and use it in GitHub Desktop.
aws, sts, and bash

About

AWS provides a mechanism for temporarily assuming another role within their API system. While it is not a technically hard process it can be convoluted and hard to understand. This document aims to both make it easier to follow along with as well as give an in depth explanation of some of the underpinnings of the Bourne Again Shell (aka BASH) which can make this easier to utilize on a day to day basis.

Explanation

Below is an overexplained version of the following process:

  1. Using credentials stored in ~/.aws/credentials as a "profile" which are then understood by the AWS command line tools
  2. Using those AWS credentials, temporarily assume a role using the AWS Security Token Service (STS) to get temporary credentials corresponding to a role in another account
  3. Taking the JSON output of that AWS STS API response and parsing out the relevant values to create a series of Bourne Again Shell (bash) commands to provide access to the role via the AWS CLI commands
  4. Placing the generated bash commands into a temporary file using a "first in first out special file" (FIFO, also known as a "named pipe"). We are doing this because the subsequent command (source) cannot take input via a pipeline and should use a file argument.
  5. Read and execute the commands from the temporary file descriptor in our current environment, thus exporting the following variables, which (similar to AWS_PROFILE are understood by the underlying libraries used by the aws command):
    • AWS_SESSION_TOKEN
    • AWS_ACCESS_KEY_ID
    • AWS_SECRET_ACCESS_KEY
               Using process substitution[sub] create a temporary file descriptor which will hold the output of our "aws" command then pipelined[pipe] through jq
        ----------------------------------------------------------------------------------------------------------------------------------------------------------------
       |                                                                                                                                                                |
       |   AWS Profile from                                                  Target            Name of the role to assume                        Friendly               |
       |  ~/.aws/credentials                                                Account #           in the target account #                            Name                 |
       |  ------------------                                                ----------       ----------------------------                       ---------               |
       | |                  |                                              |          |      |                           |                     |         |              |             
source <(AWS_PROFILE=redbeard  aws sts assume-role --role-arn arn:aws:iam::123456789123:role/OrganizationAccountAccessRole --role-session-name "DevAccount"  | \        |
   jq -r  '.Credentials | @sh "export AWS_SESSION_TOKEN=\(.SessionToken)\nexport AWS_ACCESS_KEY_ID=\(.AccessKeyId)\nexport AWS_SECRET_ACCESS_KEY=\(.SecretAccessKey) "')
   

After this has occurred you will have received a set of temporary credentials what are good for one hour, one can validate this using the command echo $AWS_ACCESS_KEY_ID. Due to the nature of STS tokens, it should be different each time you acquire one

Copy Paste Version:

source <(AWS_PROFILE=redbeard  aws sts assume-role --role-arn arn:aws:iam::123456789123:role/OrganizationAccountAccessRole --role-session-name "DevAccount"  | jq -r  '.Credentials | @sh "export AWS_SESSION_TOKEN=\(.SessionToken)\nexport AWS_ACCESS_KEY_ID=\(.AccessKeyId)\nexport AWS_SECRET_ACCESS_KEY=\(.SecretAccessKey) "')

To unset these values:

Manual Command

source <(env | awk -F= '/AWS/ {print "unset ", $1}')

BASH Alias

What follows is a BASH alias which can be added to .bash_profile. Once in place, using the alias UNSET_AWS will unset all AWS environment variables. This uses a special quoting syntax which allows for the use of backslash escaped characters as per the ANSI C standard (see the QUOTING section of man 1 bash for more details).

alias UNSET_AWS=$'source <(env | awk -F= \' /AWS/ {print "unset ", $1} \')'

Links

sub: http://wiki.bash-hackers.org/syntax/expansion/proc_subst

pipe: http://wiki.bash-hackers.org/syntax/basicgrammar#pipelines

@scotttam
Copy link

Thanks for putting this together. Using source on my Mac wasn't working but eval seemed to do the trick.

eval $(AWS_PROFILE=redbeard aws sts assume-role --role-arn arn:aws:iam::123456789123:role/OrganizationAccountAccessRole --role-session-name "DevAccount" | jq -r '.Credentials | @sh "export AWS_SESSION_TOKEN=\(.SessionToken)\nexport AWS_ACCESS_KEY_ID=\(.AccessKeyId)\nexport AWS_SECRET_ACCESS_KEY=\(.SecretAccessKey) "')

@bbhenry
Copy link

bbhenry commented Mar 6, 2019

Very nice. Thanks for sharing it.

@dragon788
Copy link

The reason source probably didn't work on macOS is that you maybe have your default shell as zsh and source is a bash-ism, using . instead of source should allow it to work with most other shells like zsh(macOS) or dash(Ubuntu).

@russellballestrini
Copy link

russellballestrini commented Oct 6, 2020

I wrote a small Python tool called sts2env: https://gist.github.com/russellballestrini/bfae477ef36b36e8803fb4a2d241fc78

Usage:

eval $(aws sts assume-role --role-arn arn:aws:iam::01234:role/the-role-name --role-session-name my-role-session | ./sts2env)

@chrisgilbert
Copy link

This is really useful, thanks!

@russellballestrini
Copy link

@chrisgilbert welcome. <3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment