AWS: How to make cross account aws cli calls by assuming role on behalf of instance profile.

Hi folks,

In this article, we are going learn how we can assume IAM role on behalf of EC2 instance profile and leverage AWS STS service in order to run cross account AWS cli commands.

Background:

Most of the organizations try to keep segregation when it comes to AWS infrastructure by managing different linked AWS accounts based on the functionality.  For example, one account to run all the shared tools/servers required. Such as Jenkins etc. A separate account to run actual non production workloads, a separate account for running Database workloads, a separate for production workloads etc etc.

Need:

So you need to run AWS cli commands targeting your application servers running in one AWS account(say ‘Y’),from your Jenkins server running in another AWS account (say ‘X’).

blog1

Problem:

As you know, AWS cli commands originated from any EC2 instance are always targeted to AWS account in which that server is running. So, if your Jenkins server is running in account ‘X’, all AWS commands originated from Jenkins server will always be targeted to account ‘X’.

So, how can we target resources present in account ‘Y’ whilst still using Jenkins server running in account ‘X’?

Solution:

To achieve cross account access, AWS has provided assume role concept in conjunction with AWS STS. Read in details here about assume role.

I am not going in to details of how to create role and give cross accounts access for now. So I am considering here that my Jenkins server running in account ‘X’ has instance profile and its been granted assume role access on account ‘Y’.

Here are the set of commands that you can use to achieve this.

Please note, I am running a Jenkins slave on Linux and scripts are written in Groovy.

  • Clear all AWS environment variables.

env.AWS_ACCESS_KEY_ID = “”
env.AWS_SECRET_ACCESS_KEY = “”
env.AWS_SESSION_TOKEN = “”

  • Call STS service with assume role details and write output to file.

sh “aws sts assume-role –role-arn ‘put_here_assumerole_arn‘ –role-session-name ‘test-session’ > temp_role.txt”

  • Echo output file

sh “cat temp_role.txt”

  • Extract output file and set AWS environmental variables.

env.AWS_ACCESS_KEY_ID = sh (script:”cat temp_role.txt | jq .Credentials.AccessKeyId | xargs”, returnStdout: true).trim()

env.AWS_SECRET_ACCESS_KEY = sh (script:”cat temp_role.txt | jq .Credentials.SecretAccessKey | xargs”, returnStdout: true).trim()

env.AWS_SESSION_TOKEN = sh (script:”cat temp_role.txt | jq .Credentials.SessionToken | xargs”, returnStdout: true).trim()

I am using jq to extract/filter data from json output file. Read more about jq here.

  • Run your AWS CLI commands.

def output = sh (script: “put_your_aws_cli_command_here“, returnStdout: true).trim()

echo output

  • Unset the credentials.

env.AWS_ACCESS_KEY_ID = “”
env.AWS_SECRET_ACCESS_KEY = “”
env.AWS_SESSION_TOKEN = “”

The last step is needed to make sure that Jenkins slave wont get confused in making any subsequent calls within same account.

Hope, this will save your time someday…

Happy learning… 🙂