boto3 — AssumeRole, then use the scoped session
import boto3
sts = boto3.client("sts", endpoint_url="https://your-gateway:9000",
aws_access_key_id="AKIA...", aws_secret_access_key="...")
# 1. Assume a role scoped to one bucket, 1-hour session
resp = sts.assume_role(
RoleArn="arn:aws:iam::acct:role/read-only-reports",
RoleSessionName="agent-session-1",
DurationSeconds=3600,
)
creds = resp["Credentials"]
# 2. Use the temporary session — X-Amz-Security-Token is enforced
s3 = boto3.client(
"s3", endpoint_url="https://your-gateway:9000",
aws_access_key_id=creds["AccessKeyId"],
aws_secret_access_key=creds["SecretAccessKey"],
aws_session_token=creds["SessionToken"],
)
s3.list_objects_v2(Bucket="reports")
# 3. Hand out a time-limited link without sharing any credential
url = s3.generate_presigned_url(
"get_object", Params={"Bucket": "reports", "Key": "q3.pdf"}, ExpiresIn=3600
)
# 4. Or federate via OIDC — no static key at all
resp = sts.assume_role_with_web_identity(
RoleArn="arn:aws:iam::acct:role/ci-pipeline",
RoleSessionName="ci-run-482",
WebIdentityToken=oidc_id_token, # JWKS-verified: sig, iss, aud, sub, exp
)