aws s3 presign: Generate a Temporary S3 URL
aws s3 presign produces a signed URL that grants time-limited access to an object without handing over AWS credentials.
A presigned URL lets a downstream job, a browser, or a partner fetch or upload an object with a link that expires. In CI it is a clean way to hand a build artifact to a step or system that has no AWS credentials of its own.
What it does
aws s3 presign generates a URL that embeds a signature derived from your credentials, valid until it expires. Anyone with the URL can perform the operation (GET by default) until then, with no further authentication. The default expiry is 3600 seconds.
Common usage
aws s3 presign s3://my-bucket/artifacts/build.tar.gz --expires-in 900
# capture the URL for a later job to download
URL=$(aws s3 presign s3://my-bucket/reports/coverage.html --expires-in 3600)
echo "coverage=$URL" >> "$GITHUB_OUTPUT"Options
| Flag | What it does |
|---|---|
| --expires-in <seconds> | Lifetime of the URL (default 3600, max 604800) |
| --region <region> | Region for the signature |
| --endpoint-url <url> | Presign against an S3-compatible endpoint |
In CI
Keep --expires-in as short as the workflow needs; a presigned URL is a bearer token, so a long expiry in logs is a leak. If you presign with temporary role credentials (OIDC/STS), the URL stops working when those credentials expire, even if --expires-in is longer, so the STS session length is the real cap.
Common errors in CI
A URL that returns "The request signature we calculated does not match" (SignatureDoesNotMatch) usually means the region used to sign differs from the bucket region; pass --region. "(AccessDenied)" from the URL means the signing identity lacked s3:GetObject. A URL that suddenly 403s before --expires-in elapsed means the temporary STS credentials that signed it expired first.