How can I configure a Lambda function to assume a role from another AWS account?

Last updated: 2019-06-25

I need my AWS Lambda function to assume a role from another AWS account to perform a specific task. How can I configure that?

Short Description

You can give a Lambda function created in one account ("account A") permissions to assume a role from another account ("account B") to access resources such as an Amazon Simple Storage Service (Amazon S3) bucket, or to do tasks such as starting and stopping instances.

To do this, configure two AWS Identity and Access Management (IAM) roles:

  • Execution role – The primary role in account A that gives the Lambda function permission to do its work.
  • Assumed role – A role in account B that the Lambda function in account A assumes to gain access to cross-account resources.

For more information, see AWS Lambda Permissions.

Resolution

1.    Attach this IAM policy to your Lambda function's execution role in account A to assume the role in account B:

Note: Replace 222222222222 with the AWS account ID of account B. Replace role-on-source-account with the name of the assumed role.

{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "arn:aws:iam::222222222222:role/role-on-source-account"
    }
}

2.    Modify the trust policy of the assumed role in account B to the following:

Note: Replace 111111111111 with the AWS account ID of account A. Replace my-lambda-executionrole-source-account with the name of the execution role.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111111111111:role/my-lambda-executionrole-source-account"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

3.    Update your Lambda function code to add the AWS Security Token Service (AWS STS) AssumeRole call. This call returns a set of credentials that you can use to create a service client. When using this client, your function has the permissions conferred to it by the assumed role, and it acts as if it belongs to account B.

For more information on using the assume_role call, see the Amazon Web Services (AWS) SDK for Python documentation.

This function code in Python is provided as-is. You can use it as an example for your own use case.

Note: Replace 222222222222 with the AWS account ID of account B. Replace role-on-source-account with the name of the assumed role.

import boto3

def lambda_handler(context, event):

    sts_connection = boto3.client('sts')
    acct_b = sts_connection.assume_role(
        RoleArn="arn:aws:iam::222222222222:role/role-on-source-account",
        RoleSessionName="cross_acct_lambda"
    )
    
    ACCESS_KEY = acct_b['Credentials']['AccessKeyId']
    SECRET_KEY = acct_b['Credentials']['SecretAccessKey']
    SESSION_TOKEN = acct_b['Credentials']['SessionToken']

    # create service client using the assumed role credentials, e.g. S3
    client = boto3.client(
        's3',
        aws_access_key_id=ACCESS_KEY,
        aws_secret_access_key=SECRET_KEY,
        aws_session_token=SESSION_TOKEN,
    )

    return "Hello from Lambda"