Beginner · Compute and storage: EC2 and S3 · topic 13 of 50 · 30 min
Securing and sharing S3 data
Explanation
Why S3 security matters
Many well-known data leaks were not clever hacks. Someone made a bucket public "just for a test" and forgot, and search tools found millions of customer records, ID card scans or medical files. S3 is safe by default today, so most leaks come from people switching the safety off. Your job is to keep it private and grant only the access each app needs.
Safe defaults since 2023
- Since April 2023, new buckets have S3 Block Public Access turned on and ACLs disabled.
- Since January 2023, every new object is encrypted at rest with SSE-S3 by default, at no extra cost.
Block Public Access is a set of four switches that override any policy or ACL that would make data public. You can set it per bucket and for the whole account. Keep it on at the account level unless you have a strong, reviewed reason.
Who can do what: IAM policies and bucket policies
An IAM policy is attached to a user, group or role and says what that identity may do, for example "this app role may read objects in invoices-bucket". A bucket policy is a resource-based policy attached to the bucket and names who may access it, which can include other AWS accounts or AWS services. Inside one account, an allow in either place is enough, as long as nothing denies it. For another account, both sides must allow: the bucket policy and the other account's IAM policy. An explicit Deny anywhere always wins.
ACLs (access control lists) are an older, per-object way to grant access. With Object Ownership set to "Bucket owner enforced" (the default for new buckets), ACLs are disabled and the bucket owner owns every object. Use policies instead of ACLs.
A bucket policy for CloudFront
To serve website files publicly but keep the bucket private, put CloudFront (the AWS CDN) in front and use Origin Access Control (OAC). The bucket policy then lets only your CloudFront distribution read objects.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCloudFrontRead",
"Effect": "Allow",
"Principal": { "Service": "cloudfront.amazonaws.com" },
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::news-site-assets/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/EDFDVBD6EXAMPLE"
}
}
},
{
"Sid": "DenyPlainHttp",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": ["arn:aws:s3:::news-site-assets", "arn:aws:s3:::news-site-assets/*"],
"Condition": { "Bool": { "aws:SecureTransport": "false" } }
}
]
}Static website hosting, and why CloudFront is better
S3 has a "static website hosting" feature that serves index.html from a website endpoint. But that endpoint uses plain HTTP only, and the bucket must allow public reads. CloudFront with OAC gives you HTTPS with your own domain, caching close to users, lower data transfer cost to the internet, and a private bucket. For anything real, use CloudFront.
Encryption choices
| Option | Who manages the key | When to use |
|---|---|---|
| SSE-S3 | S3, fully automatic | The default; fine for most data |
| SSE-KMS | AWS KMS key you control | You need key policies, audit of key use in CloudTrail, or separate keys per team. Turn on S3 Bucket Keys to cut KMS request costs |
| Client-side | You, before upload | Data must be encrypted before it ever reaches AWS |
Pre-signed URLs: share one file for a short time
A pre-signed URL is a normal S3 link with a signature and an expiry time added. Anyone with the link can download (or upload, if you sign a PUT) that one object until it expires, without an AWS account, and the bucket stays private. The link carries the permissions of whoever signed it, so sign with a role that can only read the needed prefix. With the CLI the default expiry is one hour and the maximum is seven days; links signed with temporary role credentials stop working when those credentials expire.
aws s3 presign s3://lab-reports-ap-south-1/2026/10/report-88231.pdf --expires-in 900Logging and checking
Turn on S3 server access logs or CloudTrail data events to record who read or changed objects. IAM Access Analyzer can list buckets that are shared outside your account. AWS Config rules and Security Hub can alert you when a bucket becomes public or unencrypted.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Securing and sharing S3 data · 1/7
Most S3 data leaks happen because someone made a bucket public and forgot. Today buckets are private by default.
Prefer a video by a teacher? Find free videos on “aws s3 security block public access bucket policy presigned url cloudfront oac” on YouTube ↗
In real life: A hospital shares lab reports with patients
A diagnostic lab chain in Pune stores PDF reports in a private bucket with SSE-KMS and versioning. When a report is ready, the app generates a pre-signed URL valid for 15 minutes and sends it by SMS after the patient logs in. If the SMS is forwarded tomorrow, the link no longer works. The bucket policy denies plain HTTP, Block Public Access stays on at account level, and CloudTrail data events record every download for audits.
import boto3
s3 = boto3.client("s3", region_name="ap-south-1")
url = s3.generate_presigned_url(
"get_object",
Params={"Bucket": "lab-reports-ap-south-1", "Key": "2026/10/report-88231.pdf"},
ExpiresIn=900,
)
print(url)Practice (0/3 done)
A teammate gets Access Denied reading a private bucket from an EC2 app. What is the right fix?
Write checkBucket(config) that returns a list of risk codes, in this order, for a simplified bucket config: "BLOCK_PUBLIC_ACCESS_OFF" if config.blockPublicAccess is false; "ACLS_ENABLED" if config.objectOwnership is not "BucketOwnerEnforced"; "PUBLIC_POLICY" if any statement in config.policy.Statement has Effect "Allow", a Principal of "*" (or { AWS: "*" }) and no Condition; "VERSIONING_OFF" if config.versioning is false. config.policy may be missing. A safe bucket returns [].
Write a bucket policy for the bucket "college-results-2026" that (1) lets only the IAM role arn:aws:iam::111122223333:role/results-app read and write objects, and (2) denies every request that is not over HTTPS. Then explain in two sentences why you did not need to turn off Block Public Access.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Block and file storage: EBS, instance store and EFSCompute and storage: EC2 and S3 · same module
- EC2: virtual servers in the cloudCompute and storage: EC2 and S3 · same module
- Encryption, keys and secretsCloud security and compliance
- Cloud identity and access managementCyber Security: from zero to SOC analyst · Cloud security basics
- Identity is the new perimeterCloud security and compliance
- Portfolio projects that get interviewsCertifications and cloud careers
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
What is the default Object Ownership setting for new buckets?
Answer: Bucket owner enforced (ACLs disabled)
Since April 2023 new buckets use Bucket owner enforced, which disables ACLs.
You need an audit trail of every use of the encryption key for a bucket. Which option fits?
Answer: SSE-KMS
With SSE-KMS, key use is logged in CloudTrail and controlled by a key policy.
Why is CloudFront preferred over the S3 website endpoint for a public site?
Answer: CloudFront gives HTTPS, caching and lets the bucket stay private
The website endpoint is HTTP only and needs public read. CloudFront with OAC keeps the bucket private and adds HTTPS and caching.
A pre-signed URL was created with a 15 minute expiry. What happens if someone uses it after 20 minutes?
Answer: S3 refuses the request because the link has expired
The signature includes the expiry. After that time S3 rejects the request.
Which bucket policy statement makes data public?
Answer: Allow, Principal "*", s3:GetObject, no Condition
Allow to Principal "*" without a limiting condition grants access to anyone on the internet.
Can you sign in to AWS as an IAM group?Related
Answer: No, a group only holds users and their shared permissions
Groups have no credentials of their own; they only collect users.
A user has no policies at all and tries s3:ListAllMyBuckets. What happens?Related
Answer: Implicit deny
With no Allow, the default implicit deny applies.
Which statement about Amazon S3 encryption is true for new objects today?Related
Answer: They are encrypted at rest by default with SSE-S3
Since January 2023, S3 applies SSE-S3 to all new objects by default.
What does a cloud IAM policy define?Related
Answer: Which actions are allowed or denied on which resources
Policies are the permission rules.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- This is the last topic of “Compute and storage: EC2 and S3”. The module exam comes next.
- Module 3 exam: Compute and storage, EC2 and S3 · 12 questions · 20 min, without help. 4 topics of this module still to finish first.
- Then the next module, Networking and databases: VPC and RDS. 50 topics left in the course before the final exam.