Skip to content

michaelthomasletts/boto3-refresh-session

Repository files navigation


A simple Python package for refreshing the temporary security credentials in a boto3.session.Session object automatically.

😛 Features

  • Drop-in replacement for boto3.session.Session
  • Supports automatic credential refresh for:
    • STS
    • IoT Core
      • X.509 certificates w/ role aliases over mTLS (PEM files and PKCS#11)
      • MQTT actions are available!
    • Custom authentication methods
  • Natively supports all parameters supported by boto3.session.Session
  • Tested, documented, and published to PyPI
  • Future releases will include support for IoT (coming soon)

😌 Recognition and Testimonials

Featured in TL;DR Sec.

Featured in CloudSecList.

Recognized during AWS Community Day Midwest on June 5th, 2025.

A testimonial from a Cyber Security Engineer at a FAANG company:

Most of my work is on tooling related to AWS security, so I'm pretty choosy about boto3 credentials-adjacent code. I often opt to just write this sort of thing myself so I at least know that I can reason about it. But I found boto3-refresh-session to be very clean and intuitive [...] We're using the RefreshableSession class as part of a client cache construct [...] We're using AWS Lambda to perform lots of operations across several regions in hundreds of accounts, over and over again, all day every day. And it turns out that there's a surprising amount of overhead to creating boto3 clients (mostly deserializing service definition json), so we can run MUCH more efficiently if we keep a cache of clients, all equipped with automatically refreshing sessions.

💻 Installation

pip install boto3-refresh-session

📝 Usage

Core Concepts (click to expand)

Core Concepts

  1. RefreshableSession is the intended interface for using boto3-refresh-session. Whether you're using this package to refresh temporary credentials returned by STS, the IoT credential provider (which is really just STS, but I digress), or some custom authentication or credential provider, RefreshableSession is where you ought to be working when using boto3-refresh-session.

  2. You can use all of the same keyword parameters normally associated with boto3.session.Session! For instance, suppose you want to pass region_name to RefreshableSession as a parameter, whereby it's passed to boto3.session.Session. That's perfectly fine! Just pass it like you normally would when initializing boto3.session.Session. These keyword parameters are completely optional, though. If you're confused, the main idea to remember is this: if initializing boto3.session.Session requires a particular keyword parameter then pass it to RefreshableSession; if not, don't worry about it.

  3. To tell RefreshableSession which AWS service you're working with for authentication and credential retrieval purposes (STS vs. IoT vs. some custom credential provider), you'll need to pass a method parameter to RefreshableSession. Since the service_name namespace is already occupied by boto3.sesssion.Session, boto3-refresh-session uses method instead of "service" so as to avoid confusion. If you're using RefreshableSession for STS, however, then method is set to "sts" by default. You don't need to pass the method keyword argument in that case.

  4. Using RefreshableSession for STS, IoT, or custom flows requires different keyword parameters that are unique to those particular methods. For instance, STSRefreshableSession, which is the engine for STS in boto3-refresh-session, requires assume_role_kwargs and optionally allows sts_client_kwargs whereas CustomRefreshableSession and IoTX509RefreshableSession do not. To familiarize yourself with the keyword parameters for each method, check the documentation for each of those engines in the Refresh Strategies section here.

  5. Irrespective of whatever method you pass as a keyword parameter, RefreshableSession accepts a keyword parameter named defer_refresh. Basically, this boolean tells boto3-refresh-session either to refresh credentials the moment they expire or to wait until credentials are explicitly needed. If you are working in a low-latency environment then defer_refresh = False might be helpful. For most users, however, defer_refresh = True is most desirable. For that reason, defer_refresh = True is the default value. Most users, therefore, should not concern themselves too much with this feature.

  6. Some developers struggle to imagine where boto3-refresh-session might be helpful. To figure out if boto3-refresh-session is for your use case, or whether credential_process satisfies your needs, check out this blog post. boto3-refresh-session is not for every developer or use-case; it is a niche tool.

Clients and Resources (click to expand)

Clients and Resources

Most developers who use boto3 interact primarily with boto3.client or boto3.resource instead of boto3.session.Session. But many developers may not realize that boto3.session.Session belies boto3.client and boto3.resource! In fact, that's precisely what makes boto3-refresh-session possible!

To use the boto3.client or boto3.resource interface, but with the benefits of boto3-refresh-session, you have a few options!

In the following examples, let's assume you want to use STS for retrieving temporary credentials for the sake of simplicity. Let's also focus specifically on client. Switching to resource follows the same exact idioms as below, except that client must be switched to resource in the pseudo-code, obviously. If you are not sure how to use RefreshableSession for STS (or custom auth flows) then check the usage instructions in the following sections!

RefreshableSession.client (Recommended)

So long as you reuse the same session object when creating client and resource objects, this approach can be used everywhere in your code. It is very simple and straight-forward!

from boto3_refresh_session import RefreshableSession

assume_role_kwargs = {
  "RoleArn": "<your-role-arn>",
  "RoleSessionName": "<your-role-session-name>",
  "DurationSeconds": "<your-selection>",
  ...
}
session = RefreshableSession(assume_role_kwargs=assume_role_kwargs)
s3 = session.client("s3")
DEFAULT_SESSION

This technique can be helpful if you want to use the same instance of RefreshableSession everywhere in your code without reference to boto3_refresh_session!

from boto3 import DEFAULT_SESSION, client
from boto3_refresh_session import RefreshableSession

assume_role_kwargs = {
  "RoleArn": "<your-role-arn>",
  "RoleSessionName": "<your-role-session-name>",
  "DurationSeconds": "<your-selection>",
  ...
}
DEFAULT_SESSION = RefreshableSession(assume_role_kwargs=assume_role_kwargs)
s3 = client("s3")
botocore_session
from boto3 import client
from boto3_refresh_session import RefreshableSession

assume_role_kwargs = {
  "RoleArn": "<your-role-arn>",
  "RoleSessionName": "<your-role-session-name>",
  "DurationSeconds": "<your-selection>",
  ...
}
s3 = client(
  service_name="s3",
  botocore_session=RefreshableSession(assume_role_kwargs=assume_role_kwargs)
)
STS (click to expand)

STS

Most developers use AWS STS to assume an IAM role and return a set of temporary security credentials. boto3-refresh-session can be used to ensure those temporary credentials refresh automatically. For additional information on the exact parameters that RefreshableSession takes for STS, check this documentation.

import boto3_refresh_session as brs

# OPTIONAL - you can pass all of the params normally associated with boto3.session.Session
profile_name = "<your-profile-name>"
region_name = "us-east-1"
...

# REQUIRED - as well as all of the params associated with STS.Client.assume_role
assume_role_kwargs = {
  "RoleArn": "<your-role-arn>",
  "RoleSessionName": "<your-role-session-name>",
  "DurationSeconds": "<your-selection>",
  ...
}

# OPTIONAL - as well as all of the params associated with STS.Client, except for 'service_name'
sts_client_kwargs = {
  "region_name": region_name,
  ...
}

# basic initialization of boto3.session.Session
session = brs.RefreshableSession(
  assume_role_kwargs=assume_role_kwargs, # required
  sts_client_kwargs=sts_client_kwargs,   # optional
  region_name=region_name,               # optional
  profile_name=profile_name,             # optional
  ...                                    # misc. params for boto3.session.Session
)
Custom Authentication Flows (click to expand)

Custom

If you have a highly sophisticated, novel, or idiosyncratic authentication flow not included in boto3-refresh-session then you will need to provide your own custom temporary credentials callable object. RefreshableSession accepts custom credentials callable objects, as shown below. For additional information on the exact parameters that RefreshableSession takes for custom authentication flows, check this documentation.

# create (or import) your custom credential method
def your_custom_credential_getter(...):
    ...
    return {
        "access_key": ...,
        "secret_key": ...,
        "token": ...,
        "expiry_time": ...,
    }

# and pass it to RefreshableSession
session = RefreshableSession(
    method="custom",                                         # required
    custom_credentials_method=your_custom_credential_getter, # required
    custom_credentials_method_args=...,                      # optional
    region_name=region_name,                                 # optional
    profile_name=profile_name,                               # optional
    ...                                                      # misc. params for boto3.session.Session
)
IoT Core X.509 (click to expand)

IoT Core X.509

AWS IoT Core can vend temporary AWS credentials through the credentials provider when you connect with an X.509 certificate and a role alias. boto3-refresh-session makes this flow seamless by automatically refreshing credentials over mTLS.

For additional information on the exact parameters that IOTX509RefreshableSession takes, check this documentation.

PEM file

import boto3_refresh_session as brs

# PEM certificate + private key example
session = brs.RefreshableSession(
    method="iot",
    endpoint="<your-credentials-endpoint>.credentials.iot.<region>.amazonaws.com",
    role_alias="<your-role-alias>",
    certificate="/path/to/certificate.pem",
    private_key="/path/to/private-key.pem",
    thing_name="<your-thing-name>",       # optional, if used in policies
    duration_seconds=3600,                # optional, capped by role alias
    region_name="us-east-1",
)

# Now you can use the session like any boto3 session
s3 = session.client("s3")
print(s3.list_buckets())

PKCS#11

session = brs.RefreshableSession(
    method="iot",
    endpoint="<your-credentials-endpoint>.credentials.iot.<region>.amazonaws.com",
    role_alias="<your-role-alias>",
    certificate="/path/to/certificate.pem",
    pkcs11={
        "pkcs11_lib": "/usr/local/lib/softhsm/libsofthsm2.so",
        "user_pin": "1234",
        "slot_id": 0,
        "token_label": "MyToken",
        "private_key_label": "MyKey",
    },
    thing_name="<your-thing-name>",
    region_name="us-east-1",
)

MQTT

After initializing a session object, you can can begin making actions with MQTT using the mqtt method! You can reuse the same certificate, private key, et al as that used to initialize RefreshableSession. Or, alternatively, you can provide separate PKCS#11 or certificate information, whether those be file paths or bytes values. Either way, at a minimum, you will need to provide the endpoint and client identifier (i.e. thing name).

from awscrt.mqtt.QoS import AT_LEAST_ONCE
conn = session.mqtt(
  endpoint="<your endpoint>-ats.iot.<region>.amazonaws.com",
  client_id="<your thing name or client ID>",
)
conn.connect()
conn.connect().result()
conn.publish(topic="foo/bar", payload=b"hi", qos=AT_LEAST_ONCE)
conn.disconnect().result()

⚠️ Changes

Browse through the various changes to boto3-refresh-session over time.

😥 v3.0.0

The changes introduced by v3.0.0 will not impact ~99% of users who generally interact with boto3-refresh-session by only RefreshableSession, which is the intended usage for this package after all.

Advanced users, however, particularly those using low-level objects such as BaseRefreshableSession | refreshable_session | BRSSession | utils.py, may experience breaking changes.

Please review this PR for additional details.

✂️ v4.0.0

The ecs module has been dropped. For additional details and rationale, please review this PR.

😛 v5.0.0

Support for IoT Core via X.509 certificate-based authentication (over HTTPS) is now available!

➕ v5.1.0

MQTT support added for IoT Core via X.509 certificate-based authentication.

Sponsor this project

 

Contributors 3

  •  
  •  
  •  

Languages