Account level
- S3 Block Public Access at the account level (and in the organisation via SCP/Control Tower control).
aws s3control put-public-access-block --account-id 111122223333 \
--public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
Public websites should be served through CloudFront with Origin Access Control, not public buckets.
Bucket level
- Object Ownership: Bucket owner enforced (ACLs disabled, the default for new buckets).
- Default encryption SSE-S3, or SSE-KMS with a customer-managed key and S3 Bucket Keys enabled (reduces KMS costs).
- Bucket policy denying non-TLS requests:
{
"Sid": "DenyInsecureTransport",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": ["arn:aws:s3:::cust-data-prod", "arn:aws:s3:::cust-data-prod/*"],
"Condition": { "Bool": { "aws:SecureTransport": "false" } }
}
- Access restricted to specific roles, and to your VPC endpoint where appropriate (
aws:SourceVpce).
Data protection
- Versioning enabled.
- Lifecycle: expire noncurrent versions after N days; abort incomplete multipart uploads after 7 days.
- Object Lock (compliance or governance mode) for backups and audit data that must not be deleted or encrypted by ransomware. Must be enabled at bucket creation (or later for existing buckets via support/API where allowed).
- MFA delete for highly sensitive buckets (root-only configuration; consider Object Lock instead).
aws s3api put-bucket-versioning --bucket cust-data-prod --versioning-configuration Status=Enabled
aws s3api put-bucket-lifecycle-configuration --bucket cust-data-prod --lifecycle-configuration file://lifecycle.json
Visibility
- Server access logging or CloudTrail data events for sensitive buckets.
- IAM Access Analyzer for S3 to find buckets shared outside the account/organisation.
- Amazon Macie for buckets that may hold personal data.
- Storage Lens dashboard for growth and cost.
Availability notes
S3 Standard stores data across at least three AZs in the region, so a single bucket is already AZ-resilient. Region resilience needs replication (see the S3 cross-region replication post). One Zone-IA and S3 Express One Zone store data in a single AZ: don't use them for the only copy of important data.