AWS Cheatsheet

S3

Use this AWS reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Bucket Operations

aws s3 mb s3://my-bucket                          # make bucket
aws s3 mb s3://my-bucket --region eu-west-1       # in specific region
aws s3 rb s3://my-bucket                          # remove empty bucket
aws s3 rb s3://my-bucket --force                  # remove + delete all objects
aws s3 ls                                         # list all buckets
aws s3 ls s3://my-bucket                          # list bucket root
aws s3 ls s3://my-bucket/prefix/ --recursive      # list recursively
aws s3 ls s3://my-bucket --recursive --human-readable --summarize

Object Copy / Move / Delete

CommandWhat it does
aws s3 cp file.txt s3://bucket/keyUpload local file
aws s3 cp s3://bucket/key file.txtDownload object
aws s3 cp s3://src/key s3://dst/keyServer-side copy
aws s3 mv file.txt s3://bucket/keyUpload + delete local
aws s3 mv s3://bucket/old s3://bucket/newRename object
aws s3 rm s3://bucket/keyDelete object
aws s3 rm s3://bucket/prefix/ --recursiveDelete all under prefix
# Upload with metadata + storage class
aws s3 cp file.txt s3://bucket/file.txt \
  --storage-class INTELLIGENT_TIERING \
  --metadata '{"project":"web"}'

# Sync directory (only changed/new files)
aws s3 sync ./dist s3://bucket/dist/
aws s3 sync s3://bucket/dist/ ./dist             # download sync
aws s3 sync ./dist s3://bucket/ --delete         # mirror (remove extra)
aws s3 sync ./dist s3://bucket/ --exclude "*.log" --include "*.html"

Presigned URLs

# Generate download URL valid for 1 hour (default 3600s)
aws s3 presign s3://bucket/secret-file.pdf

# Custom expiry (max 7 days for v4)
aws s3 presign s3://bucket/file.pdf --expires-in 86400

The CLI can only presign GET — there is no s3api generate-presigned-url command. Presigned PUT (upload) URLs require an SDK:

# Presigned PUT with boto3
import boto3

url = boto3.client("s3").generate_presigned_url(
    "put_object",
    Params={"Bucket": "my-bucket", "Key": "uploads/file.zip"},
    ExpiresIn=3600,
)
# then: curl -X PUT --upload-file file.zip "$url"

Bucket Policy & ACL

# Apply bucket policy from file
aws s3api put-bucket-policy --bucket my-bucket --policy file://policy.json

# Get current policy
aws s3api get-bucket-policy --bucket my-bucket

# Delete bucket policy
aws s3api delete-bucket-policy --bucket my-bucket

Legacy — ACLs: new buckets default to BucketOwnerEnforced (ACLs disabled) since April 2023, so aws s3api put-object-acl --acl public-read errors unless you first change the bucket's Object Ownership setting. Use bucket policies instead.

Example public-read bucket policy (policy.json)

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": "*",
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::my-bucket/*"
  }]
}

Static Website Hosting

aws s3 website s3://my-bucket \
  --index-document index.html \
  --error-document error.html

# Endpoint: http://my-bucket.s3-website-<region>.amazonaws.com

Versioning

aws s3api put-bucket-versioning \
  --bucket my-bucket \
  --versioning-configuration Status=Enabled

aws s3api get-bucket-versioning --bucket my-bucket

# List versions of an object
aws s3api list-object-versions --bucket my-bucket --prefix my-file.txt

# Restore specific version
aws s3api get-object \
  --bucket my-bucket --key file.txt \
  --version-id abc123 restored.txt

Lifecycle Rules

aws s3api put-bucket-lifecycle-configuration \
  --bucket my-bucket \
  --lifecycle-configuration file://lifecycle.json

lifecycle.json — move to IA after 30d, Glacier after 90d, delete after 365d:

{
  "Rules": [{
    "ID": "archive-rule",
    "Status": "Enabled",
    "Filter": { "Prefix": "logs/" },
    "Transitions": [
      { "Days": 30,  "StorageClass": "STANDARD_IA" },
      { "Days": 90,  "StorageClass": "GLACIER" }
    ],
    "Expiration": { "Days": 365 }
  }]
}

Storage Classes

ClassUse CaseMin Duration
STANDARDFrequent access
INTELLIGENT_TIERINGUnknown/changing access
STANDARD_IAInfrequent access, rapid retrieval30 days
ONE_ZONE_IAInfrequent, single-AZ30 days
GLACIER_IRArchive, instant retrieval90 days
GLACIERArchive, minutes-to-hours retrieval90 days
GLACIER_DEEP_ARCHIVELong-term archive, 12h retrieval180 days

Encryption

# Server-side encryption with S3-managed keys (SSE-S3)
aws s3 cp file.txt s3://bucket/ --sse AES256

# SSE-KMS (AWS managed key)
aws s3 cp file.txt s3://bucket/ --sse aws:kms

# SSE-KMS with specific key
aws s3 cp file.txt s3://bucket/ \
  --sse aws:kms \
  --sse-kms-key-id arn:aws:kms:us-east-1:123:key/abc-123

# Enforce encryption on bucket (via policy)
aws s3api put-bucket-encryption \
  --bucket my-bucket \
  --server-side-encryption-configuration '{
    "Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"}}]
  }'

CORS Configuration

aws s3api put-bucket-cors --bucket my-bucket --cors-configuration file://cors.json

cors.json:

{
  "CORSRules": [{
    "AllowedOrigins": ["https://myapp.com"],
    "AllowedMethods": ["GET", "PUT"],
    "AllowedHeaders": ["*"],
    "MaxAgeSeconds": 3000
  }]
}

Replication

# Enable versioning on both source and destination first, then:
aws s3api put-bucket-replication \
  --bucket source-bucket \
  --replication-configuration file://replication.json