S3 Operations Reference
Core S3 Commands
# List buckets
aws s3 ls
# List objects with size and date
aws s3 ls s3://my-bucket/ --human-readable --summarize
# Copy local to S3
aws s3 cp ./report.pdf s3://my-bucket/reports/report.pdf
aws s3 cp s3://src-bucket/file.txt s3://dst-bucket/file.txt # bucket to bucket
# Sync directory (only changed files)
aws s3 sync ./dist s3://my-bucket/web --delete --exact-timestamps
# Make / remove bucket
aws s3 mb s3://my-new-bucket --region ap-southeast-1
aws s3 rb s3://my-empty-bucket
# Move (copy + delete)
aws s3 mv s3://my-bucket/old.txt s3://my-bucket/new.txt
Lifecycle Rules
# lifecycle.json
{
"Rules": [
{
"ID": "MoveToIA",
"Status": "Enabled",
"Filter": {"Prefix": "logs/"},
"Transitions": [
{"Days": 30, "StorageClass": "STANDARD_IA"},
{"Days": 90, "StorageClass": "GLACIER"}
],
"Expiration": {"Days": 365}
},
{
"ID": "CleanupIncomplete",
"Status": "Enabled",
"Filter": {},
"AbortIncompleteMultipartUpload": {"DaysAfterInitiation": 7}
}
]
}
# Apply lifecycle configuration
aws s3api put-bucket-lifecycle-configuration \
--bucket my-bucket \
--lifecycle-configuration file://lifecycle.json
Presigned URLs
# Generate presigned GET URL (expires in 1 hour)
aws s3 presign s3://my-bucket/private/doc.pdf --expires-in 3600
# Generate presigned PUT URL via SDK (CLI only supports GET)
# Python boto3 example:
# import boto3
# s3 = boto3.client('s3')
# url = s3.generate_presigned_url(
# 'put_object',
# Params={'Bucket': 'my-bucket', 'Key': 'upload/file.txt'},
# ExpiresIn=3600
# )
# Use presigned URL with curl
curl -o downloaded.pdf "https://my-bucket.s3.amazonaws.com/private/doc.pdf?X-Amz-..."
Bucket Policies
# Public read policy (static website hosting)
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-website-bucket/*"
}]
}
# Restrict to specific VPC endpoint
{
"Statement": [{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": ["arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*"],
"Condition": {
"StringNotEquals": {"aws:sourceVpce": "vpce-1a2b3c4d"}
}
}]
}
# Apply bucket policy
aws s3api put-bucket-policy --bucket my-bucket --policy file://policy.json
CORS Configuration
# cors.json
{
"CORSRules": [
{
"AllowedHeaders": ["Authorization", "Content-Type"],
"AllowedMethods": ["GET", "PUT", "POST"],
"AllowedOrigins": ["https://example.com", "https://app.example.com"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3600
}
]
}
# Apply CORS configuration
aws s3api put-bucket-cors \
--bucket my-bucket \
--cors-configuration file://cors.json
# Get current CORS config
aws s3api get-bucket-cors --bucket my-bucket
Storage Classes
| Class | Use Case | Retrieval |
|---|---|---|
| STANDARD | Frequently accessed data | Immediate |
| STANDARD_IA | Infrequently accessed, rapid retrieval needed | Immediate |
| ONEZONE_IA | Non-critical, reproducible data | Immediate |
| INTELLIGENT_TIERING | Unknown/changing access patterns | Immediate |
| GLACIER_IR | Archive with milliseconds retrieval | Milliseconds |
| GLACIER | Long-term archive | Minutes to hours |
| DEEP_ARCHIVE | Regulatory archive | Up to 12 hours |