Skip to main content

Getting a boto3 Session for an IAM role using Python

Why I use Sessions in boto3, and the Python function I use to create them.

When I worked at Wellcome, I was doing a lot of work with AWS, and I was a frequent user of boto3, the Python SDK for AWS. There were a lot of IAM roles, spread across multiple accounts, and I was writing Python scripts that would work with specific roles.

I was persuaded to use boto3 Sessions in an article by Ben Kehoe. Although most of my Python code was one-off scripts where there’s not much difference, I thought it was a good habit to get into so I switched everywhere. On the rare occasions I wrote Python in prod, I had the habit ingrained.

The following snippet became a common element in my scripts:

import boto3


def get_aws_session(*, role_arn: str) -> boto3.Session:
    """
    Create a boto3 Session authenticated with the given IAM role ARN.
    """
    sts_client = boto3.client("sts")
    assumed_role_object = sts_client.assume_role(
        RoleArn=role_arn, RoleSessionName="AssumeRoleSession1"
    )
    credentials = assumed_role_object["Credentials"]

    return boto3.Session(
        aws_access_key_id=credentials["AccessKeyId"],
        aws_secret_access_key=credentials["SecretAccessKey"],
        aws_session_token=credentials["SessionToken"],
    )

Ben reviews this code in his article, and points out a couple of shortcomings: it’s not so readable, and it doesn’t handle credential expiry. He has a library aws-assume-role-lib that he suggests using as an alternative.

I only used this snippet in one-off scripts. For me, wrapping it in a function fixed the readability issue, and I wasn’t concerned about expiring credentials. At Wellcome, credentials would expire after 4 hours. It was unusual for me to have scripts that ran longer than that, and when I did it wasn’t too arduous to restart the script every so often.

In prod code, I’d just create the session directly:

sess = boto3.Session()

and let the AWS environment work out how to retrieve credentials (e.g. if I was running in a Lambda function, I’d let it use the execution role).

I’m not currently using AWS for anything, so this code may get out of date.