Skip to main content
BackAnt projects ship with a pre-built AWSClient wrapper in api/apis/aws/AWSClient.py. It wraps a boto3.Session and supports all three authentication methods: IAM credentials, AWS profiles, and ECS task role credentials.

AWSClient

# api/apis/aws/AWSClient.py
import boto3

class AWSClient:
    def __init__(
        self,
        aws_access_key_id=None,
        aws_secret_access_key=None,
        aws_session_token=None,
        region_name=None,
        profile_name=None,
    ):
        if profile_name:
            self.session = boto3.Session(profile_name=profile_name, region_name=region_name)
        elif aws_access_key_id and aws_secret_access_key:
            self.session = boto3.Session(
                aws_access_key_id=aws_access_key_id,
                aws_secret_access_key=aws_secret_access_key,
            )
        else:
            # Falls back to ECS task role / instance profile credentials
            self.session = boto3.Session(region_name=region_name)

Authentication methods

IAM credentials (from environment)

Set the S3 credentials in your .env:
S3_ACCESS_KEY=AKIA...
S3_SECRET_KEY=abc123...
Then instantiate with them from Environment.py:
from startup.Environment import myEnvironment
from apis.aws.AWSClient import AWSClient

aws = AWSClient(
    aws_access_key_id=myEnvironment.S3_ACCESS_KEY,
    aws_secret_access_key=myEnvironment.S3_SECRET_KEY,
    region_name="eu-central-1",
)

ECS task role (production)

When running on ECS, leave credentials empty and boto3 picks up the task role automatically:
aws = AWSClient(region_name="eu-central-1")
No credentials needed in .env — IAM permissions are attached to the ECS task definition.

AWS profile (local development)

aws = AWSClient(profile_name="my-profile", region_name="eu-central-1")

Using AWS services

Call self.session.client() to get a service client:

S3

class StorageService:
    def __init__(self):
        self.aws = AWSClient(
            aws_access_key_id=myEnvironment.S3_ACCESS_KEY,
            aws_secret_access_key=myEnvironment.S3_SECRET_KEY,
            region_name="eu-central-1",
        )
        self.s3 = self.aws.session.client("s3")

    def upload_file(self, file_bytes: bytes, bucket: str, key: str):
        self.s3.put_object(Body=file_bytes, Bucket=bucket, Key=key)

    def get_file_url(self, bucket: str, key: str, expires_in: int = 3600):
        return self.s3.generate_presigned_url(
            "get_object",
            Params={"Bucket": bucket, "Key": key},
            ExpiresIn=expires_in,
        )

    def delete_file(self, bucket: str, key: str):
        self.s3.delete_object(Bucket=bucket, Key=key)

SES (email)

ses = aws.session.client("ses", region_name="eu-central-1")
ses.send_email(
    Source="no-reply@yourapp.com",
    Destination={"ToAddresses": ["user@example.com"]},
    Message={
        "Subject": {"Data": "Welcome"},
        "Body": {"Text": {"Data": "Hello!"}},
    },
)

Cognito

cognito = aws.session.client("cognito-idp", region_name=myEnvironment.COGNITO_REGION)

cognito.admin_create_user(
    UserPoolId=myEnvironment.COGNITO_USERPOOL_ID,
    Username="user@example.com",
    TemporaryPassword="Temp1234!",
)

Adding a new external API

To add a new third-party API (e.g. Stripe, Google, Twilio):
  1. Create a client wrapper in api/apis/<name>/:
api/apis/
├── aws/
│   └── AWSClient.py
└── stripe/
    └── StripeClient.py
  1. Instantiate it as a singleton and inject it into the service that needs it.
  2. Add any required credentials to Environment.py and .env.