amazon-web-servicesamazon-s3boto3stsaws-regions

STS assume role returns invalid credentials (InvalidToken)


When I call sts:AssumeRole from account A eu-west-1 on role in account B and with those returned credentials I call list objects from s3 bucket located in eu-south-1 it fails with following error.

botocore.exceptions.ClientError: An error occurred (InvalidToken) when calling the ListObjectsV2 operation: The provided token is malformed or otherwise invalid.

code

import boto3

role_arn = "..."
bucket_name = "..."

sts_client = boto3.client(
    "sts",
    region_name="eu-west-1",
)
sts_response = sts_client.assume_role(
    RoleArn=role_arn,
    RoleSessionName="test-session-name",
)

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

s3_client = session.client(
    "s3",
    region_name="eu-south-1",
)

res = s3_client.list_objects_v2(Bucket=bucket_name)
# botocore.exceptions.ClientError

Solution

  • Two issues here

    STS region

    Even though I used region_name it still calls global sts endpoint https://sts.amazonaws.com which may be quite unexpected. It can be overriden by endpoint_url

    sts_client = boto3.client(
        "sts",
        endpoint_url="https://sts.eu-west-1.amazonaws.com",
    )
    

    or set environment variable AWS_STS_REGIONAL_ENDPOINTS=regional see docs

    export AWS_STS_REGIONAL_ENDPOINTS=regional
    

    Issue two

    eu-south-1 is one of so called opt-in region. It means you have to manually activate this region in your account to use it. And that is the root cause of credentials being invalid for some services/api calls.

    https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html

    Session tokens from Regional AWS STS endpoints are valid in all AWS Regions. Session tokens from the global STS endpoint are valid only in AWS Regions that are enabled by default