What you'll learn
- Access is allowed only if a policy allows it and nothing denies it; an explicit Deny always wins.
- New buckets have Block Public Access on and ACLs disabled; keep it that way and grant access with IAM and bucket policies.
- Every new object is encrypted (SSE-S3 by default); use SSE-KMS when you need key-level control and audit.
Section 01
Who can do what
| Mechanism | Attached to | Use it for |
|---|---|---|
| IAM policy | A role or user | What your own functions and people can do — the default choice |
| Bucket policy | The bucket | Rules for everyone: deny non-TLS, require encryption, allow another account or a CloudFront distribution |
| Access points | A named endpoint on the bucket | Separate policies per application or team on a shared bucket |
| ACLs | Buckets and objects | Legacy. Disabled by default (Object Ownership: BucketOwnerEnforced) — leave them off |
Within one account, either an IAM policy or the bucket policy can allow access. Across accounts, both sides must allow it.
Section 02
Block Public Access
Four settings stop buckets from becoming public through ACLs or policies. Since April 2023 they're all on for new buckets, and you can enforce them for the whole account. With BlockPublicPolicy on, S3 rejects any bucket policy that grants public access — the intern's “public read” statement fails with AccessDenied.
Need public images for a website? Serve them through CloudFront with origin access control, and keep the bucket private.
Section 03
Encryption
- SSE-S3 — the default since January 2023. S3 manages the keys; nothing to configure.
- SSE-KMS — keys in AWS KMS: separate permission to decrypt, CloudTrail records of key use. Turn on S3 Bucket Keys to cut KMS request costs.
- DSSE-KMS — two layers of encryption for workloads that require it.
- SSE-C — you send your own key with every request. Since April 2026 it's disabled by default for new buckets.
In transit, deny plain HTTP with a bucket-policy statement on aws:SecureTransport — the practice below.
Practice
Your turn
An intern wrote a bucket policy to "make sprites load faster" by making every object public. Block Public Access rejects it. Replace that statement with one that keeps the archive private and denies any request that doesn't use TLS.
Allow; add a Deny for s3:* when aws:SecureTransport is "false", on the bucket and its objects.Check
Check your understanding
Quick Quiz · one question, as many tries as you need.
s3:GetObject on the bucket. The bucket policy denies s3:* when aws:SecureTransport is false. The role calls GetObject over HTTP. Result?Choose one answer.