Back

Assume roles

Recently i've needed to use the Assume Role functionality with AWS. This allows a user to temporarily impersonate another AWS user/role and therefore inherit their permissions. In my use case, I wanted to set up our our CI servers to be able to deploy to both our production and staging environments, which are on seperate AWS accounts.

Yes, that means that a user on one account can actually assume the role of a user on another account - pretty powerful.

To get this setup I read through a few tutorials but I found the terminology quite confusing as it's easy to get lost when you refer to the accounts as 'Account A' and 'Account B.' In this tutorial I will refer to these accounts as Production and Staging.

My EC2 CI fleet lives on my production account, and I want them to be able to deploy some AWS Lambda code on the staging account.

AWS Setup

Staging Account Changes (account I want to assume)

  1. Created a new role that can carry out the deployment changes I need
  2. In the same role, setup a Trust Relationship with the JSON file and add the following, ensuring to add the production account ID.

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "AWS": "arn:aws:iam::<PRODUCTION ACCOUNT ID>:root"
          },
          "Action": "sts:AssumeRole"
        }
      ]
    }
    
  3. Take note of the Role/User ARN for this newly created IAM user, you will need this later.

This essentially establishes trust between the two accounts, allowing the production account to be able to delegate the AssumeRole permission further. But we aren't quite done...

Production Account Changes (account that does the assuming)

So essentially the production account is trusted, but we still need it to delegate the assume role privelege down to the role doing the assuming. In my case, it was the role that my CI boxes use.

I added the below IAM permission, being sure to add the newly created User ARN created on the staging account.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor0",
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": "< STAGING ROLE/USER ARN >"
    }
  ]
}

So thats the AWS Setup complete, time to try it out using the AWS CLI. I added these commands to the CI fleet:

temp_role=$(aws sts assume-role --role-arn < STAGING ROLE/USER ARN > --role-session-name upload-staging)
export AWS_ACCESS_KEY_ID=$(echo $temp_role | jq .Credentials.AccessKeyId | xargs)
export AWS_SECRET_ACCESS_KEY=$(echo $temp_role | jq .Credentials.SecretAccessKey | xargs)
export AWS_SESSION_TOKEN=$(echo $temp_role | jq .Credentials.SessionToken | xargs)

The AssumeRole CLI command returns a temporary set of credentials in JSON format, so I was able to use the jq library to be able pull those out of the JSON and add them to instance variables.