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

Last updated: 2020-02-06

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. For more information, see Resource-Based Policies and Using Resource-based Policies for AWS Lambda.

Resolution

If you haven't already, configure these 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.

Then, follow these instructions:

1.    Attach the following 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-execution-role with the name of the execution role.

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

3.    Update your Lambda function code to add the AWS Security Token Service (AWS STS) AssumeRole API 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 acts as if it belongs to account B. For more information, see assume_role in the AWS SDK for Python (Boto 3) documentation.

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

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"

Did this article help you?

Anything we could improve?


Need more help?