Automation with Boto3 (Python)

Boto3 is the official AWS SDK for Python — the tool ZEUS uses to read AWS under the hood. This lesson shows the patterns we use for safe, scalable inventory of a customer's environment.

Sessions, clients and resources

Boto3 has two interfaces:

  • client — low level, maps 1:1 onto the AWS API (all operations),
  • resource — higher level, object-oriented (available for some services).
import boto3

# Sesja czytająca credentiale z roli/profilu
session = boto3.Session(region_name="eu-central-1")
ec2 = session.client("ec2")

resp = ec2.describe_instances()
for r in resp["Reservations"]:
    for inst in r["Instances"]:
        print(inst["InstanceId"], inst.get("PublicIpAddress", "—"))

Credentials — never in code

Boto3 looks for credentials in order: environment variables → profile → instance/task IAM role. In production always use roles, not keys in files.

# Przyjęcie roli cross-account (wzorzec ZEUS)
sts = boto3.client("sts")
creds = sts.assume_role(
    RoleArn="arn:aws:iam::111122223333:role/zeus-readonly",
    RoleSessionName="zeus-scan",
)["Credentials"]

scoped = boto3.client(
    "s3",
    aws_access_key_id=creds["AccessKeyId"],
    aws_secret_access_key=creds["SecretAccessKey"],
    aws_session_token=creds["SessionToken"],
)

Tip: assume_role returns temporary credentials (1h by default). This is safer than long-term access keys — and it is exactly the mechanism the ZEUS connector to AWS uses.

Paginators — because results can be large

The AWS API returns results in pages. Looping over NextToken by hand is error-prone; use paginators:

s3 = session.client("s3")
paginator = s3.get_paginator("list_objects_v2")

for page in paginator.paginate(Bucket="zeus-data"):
    for obj in page.get("Contents", []):
        print(obj["Key"], obj["Size"])

Example: auditing public buckets

s3 = session.client("s3")
for b in s3.list_buckets()["Buckets"]:
    name = b["Name"]
    try:
        pab = s3.get_public_access_block(Bucket=name)
        cfg = pab["PublicAccessBlockConfiguration"]
        if not all(cfg.values()):
            print(f"[UWAGA] {name}: Block Public Access niepełny")
    except s3.exceptions.ClientError:
        print(f"[UWAGA] {name}: brak konfiguracji Block Public Access")

Best practices

PrincipleWhy
Roles instead of access keysno long-term secrets
Paginatorscomplete results, no errors
Handling ClientErrorthe API raises exceptions, not error codes
Throttling / retryAWS rate-limits requests (exponential backoff)

How ZEUS sees it

The ZEUS connector to AWS is built precisely on Boto3. It assumes a read-only role via assume_role, uses paginators for a complete inventory and queries services in parallel (EC2, S3, RDS, IAM, GuardDuty). Temporary credentials and exclusively Describe/List/Get operations guarantee the scan never modifies the customer's environment.

In the next lesson: security — GuardDuty, Security Hub and IAM Access Analyzer.