Painlessly assume IAM roles in CLI scripts with dynamic AWS CLI profiles

Soenke Ruempler
superluminar
Published in
3 min readJul 26, 2020

--

Often, it’s necessary to assume another IAM role in AWS CLI scripts — apart from the current IAM role, e.g., in CI systems like AWS CodeBuild. For example:

  • Cross AWS account access: In a multi-account AWS Setup, several tasks require assuming an IAM role in another AWS account.
  • Functional roles: To scope down privileges or to gain privileged access, sometimes AWS users have to assume another IAM role for a temporary session.

In a local/static environment, one would preferably use AWS CLI profiles with source_profile.

But what about more dynamic environments with no AWS CLI config and profiles previously set up, for example, a CI environment? Or, situations, when the IAM role to assume is not yet known and dynamically synthesized based on input to the CI build step? Then (e.g., without AWS CLI profiles at hand) assuming another IAM role usually works like this:

  • Call aws sts assume-role
  • Export the credentials into the environment.

Such assume-role “hacks” with more or less messy scripts involving jq or bash array magic can be found in the wild as the defacto solution. Additional difficulties with this way are changing back to the original IAM role, or even having to deal with several different IAM roles to assume. One usually ends up with setting/unsetting ENV variables and eventually might get confused about the currently assumed IAM role.

A cleaner and more native way would be great.

Luckily, there is a native way with AWS CLI, since it’s able to create CLI profiles on the fly dynamically.

Let’s have a look at the following (for demo purposes simple) example: Imagine you want to list all S3 buckets in another AWS Account within an AWS CodeBuild buildspec. The sample IAM role to assume in the S3 bucket has the ARN arn:aws:iam::123456789012:role/S3Access

Two lines of AWS CLI setup code allow us to use dynamically assume and use this role:

$ aws configure --profile s3access set role_arn arn:aws:iam::123456789012:role/S3Access
$ aws configure --profile s3access set credential_source EcsContainer

The first line instructs the AWS CLI to create a new CLI profile s3access on the fly, and to use the desired IAM role arn:aws:iam::123456789012:role/S3Access.
(You might already use this for your local/dev machine in combination with source_profile.

The “magic sauce” is the second line: credentials_source tells the AWS CLI where to look for the source credentials for the iam assume-role call which it implicitly does when calling it with the s3access profile. For CodeBuild, it’s EcsContainer since CodeBuild itself seems to use ECS under the hood. (Currently, it’s also possible to use Environment for environment variables, or Ec2InstanceMetadata for EC2 instances.)

Now, you can seamlessly use the AWS CLI with the profile, and it will handle all the assume-role stuff invisible to the user:

$ aws --profile s3access s3api list-buckets

That’s it. No environment variables or jq and friends have been harmed. You could also add more temporary/dynamic environments based on your use case.

For your reference a complete sample CodeBuild buildspec:

version: 0.2
phases:
build:
commands:
- aws configure --profile s3access set role_arn arn:aws:iam::123456789012:role/S3Access
- aws configure --profile s3access set credential_source EcsContainer
- aws --profile s3access s3api list-buckets

Summary

In this post, I showed how to dynamically create AWS CLI profiles within dynamic environments like, for example, AWS CodeBuild.

These dynamically created AWS CLI profiles allow seamless switching between IAM roles without messing around with e.g. jq and environment variables.

--

--

Soenke Ruempler
superluminar

co-founder superluminar. AWS, Cloud, Serverless, Wardley Maps, Toyota Kata. AWS Partner Ambassador and Community Builder. Co-Org ServerlessDays Hamburg.