Courses / Hands-on Cloud for Freshers
Session 3 of 8
Storage you can see: S3 and a static website
Overview
Unit 3 — Storage You Can See: S3 and a Static Website
Course: Hands-on Cloud for Freshers
Prerequisites: You have an AWS account with an everyday administrator identity (not the root
user) and a budget alert in place, and you can sign in to the AWS Management Console with it. You
have the AWS CLI version 2 installed and signed in with short-lived credentials, as set up in
Unit 2 — version 2.32.0 or later if you sign in with aws login. If you are starting here, the notes’
Before you start gives the setup path. You can write a small HTML file in a text editor.
No prior knowledge of Amazon S3, bucket policies or website hosting is assumed.
What the reader can do after this unit:
- Create an S3 general purpose bucket in a chosen Region, tag it, upload objects to it, and explain why an object’s “folder” is only the first part of its key name.
- Publish a static website from a bucket by enabling website hosting, relaxing Block Public Access
for that one bucket, and writing a bucket policy that grants public read access to its objects —
and say which of those two locks produced a given
403. - Remove everything the unit created, from the console or with one CLI command, and confirm from the bucket list that nothing is left.
Core question this unit answers: To let anyone on the internet read a page stored in S3, which two separate locks must you open, and what do you give up by opening them instead of putting a content delivery network in front of a private bucket?
Connections:
- Builds on: Unit 2’s identities and policies — a bucket policy is the same JSON policy language, attached to the bucket instead of to a user or role — and Unit 1’s habit of checking cost before building.
- Leads into: Unit 4, which runs a web server on a virtual machine you manage yourself. Putting the two side by side is the point: the same page can be served by a storage service with no server, or by a server you have to patch, open a firewall for, and remember to switch off. Unit 8 comes back to this unit’s static-site skill for the front end of its full deployment.
Your answers are scored
This unit is assessed. The quiz is marked against a key held separately from your materials. Questions 1–8 are multiple choice and are marked by comparing your letter. Questions 9–10 ask you to write something — a bucket policy and a CLI command — and each is marked by running it: the policy is attached to a test bucket and probed with unsigned requests, and the command is run against a small fixture of files.
Two consequences worth knowing before you start:
- You can test your constructed answers yourself before you submit them. Each question says what your answer must achieve — who may read the pages, what the bucket must hold afterwards — and you can try it in your own account. The marking checks themselves are in the separate answer key.
- Only outcomes are marked. Extra whitespace in a JSON document or a different order of keys does not change your score; a policy that also lets anyone delete your pages does.
Notes
Hands-on Cloud for Freshers — Unit 3: Storage You Can See: S3 and a Static Website
Before you start
Sign in to the AWS Management Console with your everyday administrator identity, not the root user,
and check in the top-right corner that you are in the Region you chose in Unit 1. These notes use
Asia Pacific (Mumbai), ap-south-1 in every example; pick a Region near you if you prefer, but
stay in that one Region for the whole unit, because a bucket’s Region is fixed when you create it and
it decides the bucket’s website address.
Have a terminal open with the AWS CLI version 2 signed in, and a folder on your computer holding two
small HTML files, index.html and error.html. Any content will do; a heading and one sentence each
is enough.
If you are starting here without the earlier units, set up three things first:
- A console sign-in that is not the root user and can create and delete S3 buckets — an identity with administrator permissions is enough.
- The AWS CLI version 2.32.0 or later. Install or update it by following Installing or updating
to the latest version of the AWS CLI (Sources), then run
aws --version; the output startsaws-cli/<version>. The version matters because the sign-in command in the next step,aws login, needs at least 2.32.0. - The CLI signed in. Run
aws login, finish the sign-in in the browser it opens, and choose your Region when it asks. The sign-in guide lists theSignInLocalDevelopmentAccessmanaged policy among its prerequisites for the identity. Then runaws sts get-caller-identity: it prints your account ID and the ARN of the identity you signed in as. An error means step 3 is not done.
Every resource in this course carries the tag project = hands-on-cloud, so that the teardown at the
end of each unit can find everything it made. The bucket you create here is named
hoc-site-<your-initials>-<random-digits> — for example hoc-site-ab-4821. That example name is used
throughout; replace it with yours everywhere you see it.
Every statement here about how Amazon S3 behaves is taken from the Amazon S3 User Guide and the AWS CLI User Guide, fetched 2026-10-02; the pages are listed under Sources at the end.
Summary
Amazon S3 stores files — called objects — inside containers called buckets, and by default nothing
you put there can be read by anyone outside your account. Publishing a static website from S3 means
deliberately opening that up, and S3 makes you do it in two separate places: you relax the bucket’s
Block Public Access settings, which exist only to stop public access, and then you write a
bucket policy that actually grants it. Most first attempts fail at one of those two locks and
return the same 403 Forbidden, which is why this unit teaches you to tell them apart. It also
teaches the honest trade-off: S3’s website endpoint serves only HTTP, never HTTPS, and requires a
public bucket, so AWS’s own documentation recommends putting a content delivery service in front of
a private bucket for anything real. You will build the simple public version, prove it works, and
then delete it.
Key concepts
| Term | Definition |
|---|---|
| Bucket | A container for objects in Amazon S3. A general purpose bucket’s name must be unique across every AWS account in the partition, and its name and Region cannot be changed after it is created |
| Object | One stored item: its data (any sequence of bytes), its key, and metadata about it |
| Key | The full name of an object inside its bucket, such as images/logo.png. You use the key to retrieve the object |
| Prefix | The leading part of a key up to a /, such as images/. S3 has a flat structure; the console shows a prefix as a folder, but there is no real directory |
| Region | The AWS location a bucket lives in. Objects stay in that Region unless you explicitly move them |
| Block Public Access | Four settings, on by default for a new bucket, that override any policy or access control list that would make the bucket or its objects public. They can be set on the account and on each bucket; S3 applies the most restrictive combination |
| Bucket policy | A JSON policy attached to a bucket, in the same policy language as Unit 2, that grants or denies access to the bucket and its objects |
| Object Ownership | A bucket setting. Its default, Bucket owner enforced, disables access control lists, so the bucket owner owns every object and access is controlled only by policies |
| Static website hosting | A bucket property that makes S3 answer browser requests at a website endpoint, returning an index document for the root and an error document for missing pages |
| Website endpoint | The HTTP-only address S3 gives a bucket configured as a website, such as http://hoc-site-ab-4821.s3-website.ap-south-1.amazonaws.com |
| Index document | The object returned when a visitor requests the root of the site or a folder, usually index.html. The name is case sensitive |
| Error document | The object returned for a 4XX error such as a missing page, for example error.html |
Explanations
The failure, before the explanation
You create a bucket, upload index.html, turn on static website hosting, and open the website
endpoint in a browser. You get this:
403 Forbidden
Code: AccessDenied
The file is there — you can see it in the console. The website hosting setting is on. Nothing is
misspelt. Here is the part that surprises people: if you had asked for a page that does not
exist, you would have got a 404 Not Found instead. The S3 documentation spells this out: on the
website endpoint, a request for an object that does not exist returns 404, and a request for an
object that exists but that you have not granted read permission on returns 403.
So a 403 on your own homepage is good news of a kind. It says S3 found the object and refused to
hand it over. The rest of this section is about why, and about the two locks that both have to be
open before it will.
Buckets, objects and keys: storage you can see
Think of a bucket as a single, enormous shelf of labelled boxes. Each box is an object; the label on
the box is its key. There are no shelves inside the shelf — just one long row of labels. If you label
three boxes logs/day1.txt, logs/day2.txt and logs/day3.txt, the console will draw you a folder
called logs containing three files, because they share the prefix logs/. Nothing called logs
exists on its own.
A second way to see it: a key is a full file path written on a single sticky note. When you upload
logo.png into a console folder named images, S3 stores one object whose key is
images/logo.png. When you create an empty folder in the console, S3 actually creates a zero-byte
object whose key ends in /, purely so that the console has something to show.
This matters immediately for a website: the browser asks for /images/logo.png, and S3 looks for an
object whose key is exactly images/logo.png. Keys are case sensitive, so Images/logo.png is a
different object.
Creating a bucket asks for very little. In the S3 console, under General purpose buckets, choose Create bucket, enter the Bucket name, and check the Region shown in the navigation bar. The rest of the page shows the defaults that matter for this unit:
| Setting on the Create bucket page | Default | What it means for you |
|---|---|---|
| Object Ownership | Bucket owner enforced (ACLs disabled) | Access is controlled only by policies; leave it |
| Block Public Access settings for this bucket | All four settings on | Nothing in the bucket can be made public until you change this |
| Bucket Versioning | Disabled | Overwriting a file replaces it; deleting the bucket later is simpler |
| Tags | None | Add project = hands-on-cloud here: enter the Key and Value and choose Add Tag |
| Default encryption | Server-side encryption with Amazon S3 managed keys (SSE-S3) | Every new object is encrypted at rest; AWS states this costs nothing extra (SSE-S3 source below) |
Bucket names follow strict rules: 3 to 63 characters; only lowercase letters, numbers, full stops and
hyphens; starting and ending with a letter or number; no two full stops in a row; not shaped like an
IP address; and not starting with reserved prefixes such as xn-- or amzn-s3-demo-. AWS recommends
avoiding full stops in names except for buckets used only for website hosting, and avoiding aws or
amazon in a name. hoc-site-ab-4821 passes every rule.
From the terminal, the same uploads look like this. aws s3 cp copies one file; aws s3 sync makes
the bucket match a local folder, and with --delete it also removes objects that no longer exist
locally:
aws s3 cp index.html s3://hoc-site-ab-4821
aws s3 sync . s3://hoc-site-ab-4821 --delete
aws s3 ls s3://hoc-site-ab-4821
Two locks, not one
Making a page public in S3 is like getting into a building that has a security barrier at the gate and a locked front door. The barrier exists only to stop people; it never lets anyone in by itself. The door is what you unlock for a specific visitor. Lift the barrier and leave the door locked, and nobody gets in. Unlock the door and leave the barrier down, and nobody gets in either — and from the pavement both failures look identical.
In S3:
- The barrier is Block Public Access. Its four settings —
BlockPublicAcls,IgnorePublicAcls,BlockPublicPolicyandRestrictPublicBuckets— override any policy or access control list that would make the bucket public. All four are on for a new bucket. They also exist at account level, and S3 always applies the most restrictive combination of the account and bucket settings. - The door is the bucket policy. Turning Block Public Access off grants nothing. You still need a policy that says everyone may read the objects.
The policy the S3 documentation gives for a public website is this, with your bucket name in the
Resource:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": ["s3:GetObject"],
"Resource": ["arn:aws:s3:::hoc-site-ab-4821/*"]
}
]
}
Read it with the Unit 2 eyes you already have. Principal: "*" means anyone, signed in or not.
Action is a single action, reading an object — not listing the bucket, not writing, not deleting.
Resource ends in /*, which means every object inside the bucket. Without the /* the ARN names
the bucket itself rather than the objects in it, so the statement no longer covers the files you want
people to read. If the console rejects the policy with Policy has invalid resource, the
documentation’s advice is to check that the bucket name in the ARN matches your bucket’s name.
The order matters, and it produces the second failure people meet. If you paste that policy while
Block Public Access is still on, the save fails: BlockPublicPolicy rejects any bucket policy that
would grant public access. If it still fails after you have cleared Block all public access on
the bucket, look at the account-level settings: the most restrictive combination wins. You find them
in the S3 console’s navigation pane under Account and organization settings, in Block Public
Access settings for this account. If your account belongs to an organization that sets Block Public
Access centrally, the S3 documentation says the account-level settings cannot be changed there at all.
A table to keep for diagnosis:
| What you see | Which lock | What to check |
|---|---|---|
| Saving the bucket policy fails | Barrier (Block Public Access) | Bucket-level settings, then account-level settings |
Policy has invalid resource |
Neither — a typo | The bucket name in the ARN matches the bucket |
403 on a page that exists |
Door (no public read) | Is there a bucket policy granting s3:GetObject on bucket/*? |
404 on a page you expected |
Neither | The key: spelling, case, and the folder prefix |
Static website hosting: the endpoint and its documents
Picture a shop that has a stockroom and a shop window. The stockroom (the bucket) holds every box; the shop window (the website endpoint) shows a chosen box to anyone walking past, and when someone asks for something that is not there, the window shows a “not found” card instead of a blank wall. Turning on static website hosting is building that window — it does not decide who may look through it, which is still the job of the two locks.
Website hosting is a property of the bucket. In the console, open the bucket, choose Properties,
and under Static website hosting choose Edit, then Enable. Enter the Index document
— index.html — and the Error document — error.html — and choose Save changes. The
Bucket website endpoint then appears at the bottom of the Properties page.
The endpoint has one of two forms, depending on the Region: a dash before the Region
(s3-website-<Region>) or a dot (s3-website.<Region>). The S3 documentation lists
s3-website.ap-south-1.amazonaws.com as a website endpoint domain, so the example bucket’s site is:
http://hoc-site-ab-4821.s3-website.ap-south-1.amazonaws.com
Copy yours from the console rather than typing it; the console always shows the right form for your Region.
Two details catch people:
- The index document name is case sensitive and must match exactly. If you enter
index.htmlin the setting and uploadIndex.html, S3 has no object with the key it was told to return. - The website endpoint is not the same as the bucket’s ordinary address. The ordinary (REST API)
endpoint returns errors as XML, and a request for the bucket root there is a request to list the
bucket, which succeeds only for a caller granted
s3:ListBucket— the public-read policy in this unit does not grant it. The website endpoint returns HTML error pages, returns your index document at the root, supports onlyGETandHEADrequests, and serves only publicly readable content.
The trade-off: HTTP only, and a public bucket
Here is the sentence from the S3 documentation that decides whether you would use this for real: Amazon S3 website endpoints do not support HTTPS. Your site is served over plain HTTP, and the documentation’s own tutorial notes that it requires disabling Block Public Access while recommending that you keep it enabled.
Think of it as the difference between pinning a notice to a public noticeboard and handing copies out through a reception desk. The noticeboard (the public bucket) is simple and works immediately, but anyone can read the board directly and there is no envelope around what you hand over. The reception desk (a content delivery network in front of a private bucket) keeps the original locked away and hands out sealed copies over HTTPS.
AWS documents two ways to get the reception desk:
- AWS Amplify Hosting — the S3 documentation’s recommended option for static website content stored in S3. It deploys your files to a managed content delivery network powered by Amazon CloudFront and gives you a public HTTPS address.
- Amazon CloudFront with origin access control (OAC) — lets you keep all four Block Public Access settings on, because CloudFront, not the public, reads the bucket.
This unit does not build either: both add moving parts that are worth learning only once the plain
version makes sense. What you must be able to do now is say why the plain version is fine for a
learning exercise and not for a site you care about: HTTP only, a publicly readable bucket, and the
403/404 difference, which lets anyone probe whether a given key exists.
Taking it down: empty, then delete
Think of returning a rented storage unit: you cannot hand back the key while boxes are still inside. S3 works the same way — a bucket can be deleted only when it is empty. In the console, choose the bucket under General purpose buckets and choose Delete; if it still holds objects, the console shows a This bucket is not empty alert with an Empty bucket button, and once that is done you confirm by typing the bucket name and choosing Delete bucket.
From the terminal, one command does both steps for a bucket without versioning:
aws s3 rb s3://hoc-site-ab-4821 --force
--force deletes every object and then the bucket. It does not work on a versioned bucket that still
holds old versions, which is one reason this unit leaves versioning off.
One thing the documentation warns about, which surprises people: after you delete a bucket, its name returns to the shared pool and another AWS account can create a bucket with the same name. For a learning bucket with random digits in its name, that is harmless. For a name other people’s browsers or code still point at, it is a real risk, and the documentation’s advice is to empty such a bucket and keep it rather than delete it.
Flashcards
Say the answer aloud before revealing it. Speaking it is what exposes the gaps that reading past a written answer hides. Choose a question to reveal its answer.
What is the difference between a bucket and an object?
A bucket is the container, with a name unique across the partition and a fixed Region. An object is one stored item inside it: its data, its key, and its metadata.
You upload logo.png into a console folder called images. What is the object's key?
images/logo.png. The folder is only the prefix images/; S3 itself has a flat structure.
What are the two locks you open to make a website public?
Block Public Access, which only ever blocks, and a bucket policy, which actually grants public read. Opening only one of them leaves the site unreadable.
Your homepage returns 403 but a made-up page returns 404. What does that tell you?
The homepage object exists but public read is not in effect. Look at the locks — Block Public Access, then the bucket policy and any deny — not at the file.
Why might saving a public bucket policy fail even after you cleared Block Public Access on the bucket?
The account-level Block Public Access settings are still on, and S3 applies the most restrictive combination of account and bucket settings.
Why does the policy's Resource end in /*?
s3:GetObject acts on objects, and arn:aws:s3:::bucket/* means every object in the bucket. The bare bucket ARN names the bucket, which GetObject never applies to.
Can you open your S3 website endpoint with https://?
No. S3 website endpoints support only HTTP. For HTTPS, AWS documents Amplify Hosting or CloudFront in front of the bucket.
What does Object Ownership's default, Bucket owner enforced, change?
It disables access control lists, so the bucket owner owns every object and access is controlled only by policies.
You set the index document to index.html and uploaded Index.html. What happens?
The root of the site does not return your page: the index document name is case sensitive and must match the object’s key exactly.
What does aws s3 sync . s3://bucket --delete do that aws s3 cp does not?
It copies every new or changed file in the folder, recursively, and with --delete it also removes objects from the bucket that no longer exist locally.
When does aws s3 rb s3://bucket --force fail?
When versioning is enabled and old object versions remain; --force removes current objects but not retained versions, so the bucket is not empty.
Why would you keep an empty bucket rather than delete it?
After deletion, another account can create a bucket with the same name and receive requests meant for yours.
Model answer
The question: “We want to put a one-page site for an event on S3 by this afternoon. Talk me through how you would make it public, and what you would warn me about.”
An examiner listens for five beats, in this order: setup, both locks, verify, trade-off, take-down. Missing any one of them is a failure state, not a stylistic gap: the first three are what make the site work, and the last two separate someone who got it working from someone who understands what they built. Say the answer aloud; the beat names in brackets are there for you to check yourself against, not to be spoken.
[Setup] “First I would create a bucket in our usual Region, upload the page and its images so that each object’s key matches the link in the HTML exactly — keys are case sensitive — and turn on static website hosting with
index.htmlas the index document anderror.htmlas the error document.[Both locks] Then there are two separate locks to open, and both have to be opened. The first is Block Public Access: I would turn it off for this one bucket, and check the account-level setting too, because the most restrictive combination wins. The second is a bucket policy that actually grants the read —
s3:GetObjectfor everyone, onarn:aws:s3:::our-bucket/*. Turning off Block Public Access on its own makes nothing public; it only stops blocking a policy that does.[Verify] Before I tell anyone it is live, I would open the website endpoint and request two things: the homepage, which must load, and a page that does not exist, which must return our error page. If the homepage gives a
403, the object is there but public read is not in effect, so I would check Block Public Access at bucket and account level, check that the policy exists and namesbucket/*, and check that nothing denies the read. If it gives a404, a key is wrong.[Trade-off] The warning is that this endpoint serves only HTTP, never HTTPS, and it only works because the bucket is publicly readable. That is fine for a short-lived event page. For anything that outlives the event, I would put Amplify Hosting or CloudFront in front, so visitors get HTTPS and the bucket can stay private.
[Take-down] And when the event is over, I would empty the bucket and delete it — unless links to that name will keep circulating, in which case I would empty it and keep it, because once a bucket name is deleted it can be claimed by another account, and the old links would then point there.“
The trade-off beat is the one most answers drop. It is also the beat an interviewer is listening for, because it shows you know the difference between it works and it is fit to keep.
Why this matters
- A portfolio site that should have been quick. A first attempt returns
403and the natural reaction is to re-upload the file, then delete and recreate the bucket. Knowing that403means “found, but not allowed” sends you straight to the bucket policy instead. - One wrong policy should not publish private files. Block Public Access overrides any policy that would make a bucket public, which is why it is on by default for every new bucket and why the S3 documentation recommends keeping it on unless public access is the point, as it is for this site.
- A team demo that stopped working after cleanup. Someone deleted a bucket whose name was still hard-coded in an app. The name became available to anyone, which is exactly the risk the S3 documentation warns about.
- A login form on an HTTP-only page. A static site is fine for public information. The moment a page asks for anything private, plain HTTP is the wrong transport, and the S3 website endpoint cannot offer anything else.
After this unit
The project for this unit is Publish, Probe and Remove a Static Site (project.md). You will
publish a three-page site from a tagged bucket, prove each lock by turning it off and watching the
status code change, record the status codes as evidence, and then delete everything and show the
bucket list is clean. Keep your local site folder: Unit 8 reuses it as the front end of its full
deployment.
Unit 4 serves a web page from a different kind of resource — a virtual server, Amazon EC2 — where you will meet the network firewall equivalent of this unit’s two locks, and a resource you must remember to remove when you are done.
Sources
Every page below was fetched 2026-10-02.
- Hosting a static website using Amazon S3 — https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteHosting.html (fetched 2026-10-02)
- Tutorial: Configuring a static website on Amazon S3 — https://docs.aws.amazon.com/AmazonS3/latest/userguide/HostingWebsiteOnS3Setup.html (fetched 2026-10-02)
- Setting permissions for website access — https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteAccessPermissionsReqd.html (fetched 2026-10-02)
- Website endpoints — https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteEndpoints.html (fetched 2026-10-02)
- Configuring a custom error document (website endpoint response codes) — https://docs.aws.amazon.com/AmazonS3/latest/userguide/CustomErrorDocSupport.html (fetched 2026-10-02)
- Blocking public access to your Amazon S3 storage — https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-control-block-public-access.html (fetched 2026-10-02)
- Configuring block public access settings for your account — https://docs.aws.amazon.com/AmazonS3/latest/userguide/configuring-block-public-access-account.html (fetched 2026-10-02)
- Installing or updating to the latest version of the AWS CLI — https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html (fetched 2026-10-02)
- Login for AWS local development using console credentials — https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sign-in.html (fetched 2026-10-02)
- get-caller-identity, AWS CLI Command Reference — https://docs.aws.amazon.com/cli/latest/reference/sts/get-caller-identity.html (fetched 2026-10-02)
- Creating a general purpose bucket — https://docs.aws.amazon.com/AmazonS3/latest/userguide/create-bucket-overview.html (fetched 2026-10-02)
- General purpose bucket naming rules — https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html (fetched 2026-10-02)
- Amazon S3 objects overview — https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingObjects.html (fetched 2026-10-02)
- Using server-side encryption with Amazon S3 managed keys (SSE-S3) — https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingServerSideEncryption.html (fetched 2026-10-02)
- Organizing objects in the Amazon S3 console by using folders — https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-folders.html (fetched 2026-10-02)
- Deleting a general purpose bucket — https://docs.aws.amazon.com/AmazonS3/latest/userguide/delete-bucket.html (fetched 2026-10-02)
- Using tags with S3 general purpose buckets — https://docs.aws.amazon.com/AmazonS3/latest/userguide/buckets-tagging.html (fetched 2026-10-02)
- Using high-level (s3) commands in the AWS CLI — https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html (fetched 2026-10-02)
Project
Hands-on Project — Publish, Probe and Remove a Static Site
Objective
Publish a small static website from a tagged S3 bucket, test each of the two locks by closing it on purpose and recording what the website endpoint returns, and then remove everything and show that the bucket is gone. You finish holding a working local site, an evidence table you produced yourself, and a record that the bucket no longer exists — the three things that separate “I clicked through a tutorial” from “I can do this again and take it down safely”.
What you need: your AWS account, signed in to the console as your everyday administrator
identity; the AWS CLI version 2, signed in — version 2.32.0 or later if you sign in with
aws login, because the AWS CLI User Guide gives that as the minimum for the command (check yours
with aws --version); a text editor; and curl (or a browser’s developer tools) to read HTTP status
codes. Everything here uses Amazon S3 only and needs no paid feature.
- Cost. AWS’s billing guide states that on the Free account plan you incur no charges until you upgrade to a paid plan, and that eligible usage draws on your Free Tier credits. A few small HTML files and a few dozen requests are a very small amount of usage; check your Free Tier and Credits pages in the Billing and Cost Management console if you want to see it.
- If you are starting here. You need an AWS account and a console sign-in that is not the root
user and can create and delete S3 buckets; an identity with administrator permissions is enough.
Then set up the CLI in three steps:
- Install or update the AWS CLI version 2 by following Installing or updating to the latest
version of the AWS CLI (Sources), then run
aws --version. The first word of the output isaws-cli/<version>; it must read2.32.0or higher. - Run
aws loginand complete the sign-in in the browser it opens. The sign-in guide’s prerequisites say the identity needs theSignInLocalDevelopmentAccessmanaged policy; if the browser step is refused, that is the first thing to check. - Run
aws sts get-caller-identity. It must print your account ID and the ARN of the identity you signed in as. If it prints an error, repeat step 2.
- Install or update the AWS CLI version 2 by following Installing or updating to the latest
version of the AWS CLI (Sources), then run
Throughout, replace hoc-site-ab-4821 with your own bucket name — hoc-site-<your-initials>-<random-digits>
— and ap-south-1 with your Region if you chose a different one.
Task 1 — Build the site locally
Scope: three files, plain HTML, no framework, no build step. Stop when all three open correctly from your own disk.
Create a folder called hoc-site holding:
index.html— a heading with your name and a link toabout.html;about.html— one paragraph and a link back toindex.html;error.html— a heading that says the page was not found, and a link toindex.html.
Use relative links (href="about.html", not a full address), because the same files will later be
served from your website endpoint. Open each file in a browser from disk and click every link.
Time budget: 20 minutes
Output: the hoc-site folder with three HTML files whose links all work when opened from disk.
Keep this folder after the project — Unit 8 reuses it.
Task 2 — Publish it, then probe both locks
Scope: one bucket, one policy, four probes. Stop once your evidence table has four rows.
-
Create the bucket. In the S3 console, check the Region in the navigation bar, choose General purpose buckets, then Create bucket. Enter your bucket name. Leave Object Ownership, Block Public Access, versioning and encryption at their defaults. Under Tags, enter the Key
projectand the Valuehands-on-cloud, choose Add Tag, then choose Create bucket. -
Upload the site. From inside the
hoc-sitefolder, run:aws s3 sync . s3://hoc-site-ab-4821 --delete aws s3 ls s3://hoc-site-ab-4821Compare the listing with your folder before going on: it should name the same three files.
-
Enable website hosting. Open the bucket, choose Properties, and under Static website hosting choose Edit, then Enable. Set Index document to
index.htmland Error document toerror.html, and choose Save changes. Copy the Bucket website endpoint from the bottom of the Properties page. -
Probe 1 — both locks closed. Request the homepage and print only the status code:
curl -s -o /dev/null -w "%{http_code}\n" http://<your-endpoint>/Replace
<your-endpoint>with the endpoint you copied (it looks likehoc-site-ab-4821.s3-website.ap-south-1.amazonaws.com). Record the code. -
Open the barrier — at both levels. Block Public Access exists for the whole account as well as for each bucket, and S3 applies the most restrictive combination of the two. Clearing only the bucket’s setting therefore opens nothing while the account’s setting is still on.
- a. Check the account level first. In the S3 console’s navigation pane choose Account and organization settings, and read Block Public Access settings for this account. Write down whether Block all public access shows On or Off.
- b. If it is On, choose Edit, clear Block all public access, choose Save changes, type confirm and choose Confirm. This setting covers every bucket you own, which is why the Teardown turns it back on. If the console refuses with a message about an organizational S3 Block Public Access policy, your account is managed by an organization and you cannot change it: record the message, leave the account column at on for every probe, and carry on — your Probes 2–4 will show what a closed barrier does.
- c. Then the bucket level. Open your bucket, choose Permissions; under Block public access (bucket settings) choose Edit, clear Block all public access, choose Save changes, and confirm.
-
Probe 2 — barrier opened, no policy yet. Run the same request again and record the code.
-
Open the door — the bucket policy. Under Bucket policy choose Edit, paste this policy with your bucket name in place of
hoc-site-ab-4821, and choose Save changes:{ "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": ["s3:GetObject"], "Resource": ["arn:aws:s3:::hoc-site-ab-4821/*"] } ] }If the save fails, record the error message in your table.
-
Probe 3 and Probe 4. Request the homepage, then a page that does not exist:
curl -s -o /dev/null -w "%{http_code}\n" http://<your-endpoint>/ curl -s -o /dev/null -w "%{http_code}\n" http://<your-endpoint>/no-such-page.htmlOpen both addresses in a browser too, and note which of your three pages, if any, each one shows.
Time budget: 45 minutes
Output: an evidence table with exactly four rows and these seven columns, filled from what you set and saw, not from what you expected:
| Probe | Bucket BPA | Account BPA | Policy | Address | Code | Closed lock |
|---|
- Bucket BPA and Account BPA —
onoroff: whether Block all public access was on at that level when you probed. - Policy —
presentif a public-read bucket policy was saved at that moment, otherwiseabsent(a save that failed counts asabsent). - Address —
/or/no-such-page.html. Code — the three digitscurlprinted. - Closed lock — one word, worked out from the three columns before it, never from the code:
barrierif either BPA column isonand Policy ispresent;doorif both BPA columns areoffand Policy isabsent;bothif either BPA column isonand Policy isabsent;noneif both BPA columns areoffand Policy ispresent.
For Probe 1, the Account BPA value is the one you read in step 5a, since nothing had changed it yet.
A row can read none and still show a code other than 200: no lock is closed, so the code has a
cause other than permission — the diagnosis table in the notes says which.
Task 3 — Close each lock again and predict first (optional extension)
Scope: two experiments, each written as a prediction before you run it. Stop when both predictions are checked.
- Experiment A. Write down the status code you expect from the homepage if you delete the bucket policy but leave Block Public Access off. Then remove the policy from the bucket’s Permissions tab, under Bucket policy, probe, and record the code.
- Experiment B. Put the policy back, then turn Block all public access back on for the bucket. Before probing, write down your prediction and which of the four settings you think is responsible. Probe, and record the code.
Time budget: 30 minutes
Output: a two-row table — experiment, predicted code, observed code, and matched or missed — plus, for each row marked missed, one sentence that uses the words barrier and door.
Teardown — required
Do this whether or not you finished every task. A public bucket left behind is the one thing in this unit that can cause real trouble later.
-
Delete the bucket and every object in it:
aws s3 rb s3://hoc-site-ab-4821 --forceIf it reports that the bucket is not empty, use the console instead: select the bucket, choose Empty, confirm, then choose Delete and type the bucket name to confirm.
-
Prove this bucket is gone by name:
aws s3api head-bucket --bucket hoc-site-ab-4821Record the command’s output and its exit status (
echo $?in a Unix-like shell). Then runaws s3 lsand check thathoc-site-ab-4821is not among the names it prints; other buckets you own may be listed and are not part of this check. -
Put the account-level Block Public Access setting back as you found it. If you turned it off in Task 2, step 5b, open Account and organization settings, choose Edit under Block Public Access settings for this account, select Block all public access, choose Save changes, type confirm and choose Confirm.
-
Keep your local
hoc-sitefolder.
Output: a teardown record holding the head-bucket output and exit status, one line stating
whether hoc-site-ab-4821 appeared in aws s3 ls, and one line giving the account-level Block
all public access value you left in place (on or off).
What this feeds
Unit 4’s project opens by checking that you are starting from a clean slate: it asks for this
teardown record as evidence before you launch anything new. Its notes compare its own “barrier” — a
security group rule on a server — with the two locks you probed here, so keep your Task 2 evidence
table too. Unit 8 reuses your hoc-site folder as its front end.
Sources
Every page below was fetched 2026-10-02.
- Explore AWS services with AWS Free Tier (Free account plan, credits, no charges until you upgrade) — https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/free-tier.html
- Tutorial: Configuring a static website on Amazon S3 (create, enable hosting, Block Public Access, policy) — https://docs.aws.amazon.com/AmazonS3/latest/userguide/HostingWebsiteOnS3Setup.html
- Setting permissions for website access (the public-read bucket policy) — https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteAccessPermissionsReqd.html
- Website endpoints (endpoint form, 403 and 404 responses) — https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteEndpoints.html
- Blocking public access to your Amazon S3 storage (bucket and account settings) — https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-control-block-public-access.html
- Configuring block public access settings for your account (Account and organization settings; organization-managed accounts) — https://docs.aws.amazon.com/AmazonS3/latest/userguide/configuring-block-public-access-account.html
- Installing or updating to the latest version of the AWS CLI (
aws --version) — https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html - Using tags with S3 general purpose buckets — https://docs.aws.amazon.com/AmazonS3/latest/userguide/buckets-tagging.html
- Deleting a general purpose bucket (Empty, then Delete) — https://docs.aws.amazon.com/AmazonS3/latest/userguide/delete-bucket.html
- Using high-level (s3) commands in the AWS CLI (
sync --delete,rb --force) — https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html - head-bucket, AWS CLI Command Reference — https://docs.aws.amazon.com/cli/latest/reference/s3api/head-bucket.html
- Login for AWS local development using console credentials (
aws login, minimum version 2.32.0, prerequisites) — https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sign-in.html - get-caller-identity, AWS CLI Command Reference — https://docs.aws.amazon.com/cli/latest/reference/sts/get-caller-identity.html
Quiz
Online marking is not open yet. Work through the questions and check the written ones against the criteria printed with each question. The answer key is kept back for now.
Quiz — Unit 3: Storage You Can See: S3 and a Static Website
Instructions: Ten questions in two parts, and both parts are scored.
- Questions 1–8 are multiple choice. Pick one option per question. They are marked by comparing your letter against the key.
- Questions 9–10 ask you to write something: a bucket policy and a CLI command. Each is marked on what your answer does when it is run, not on how it is worded; any answer that behaves as the question asks earns full credit.
Work closed-book on questions 1–8. On questions 9–10 you may test your answer in your own account as often as you like before submitting it. The answer key, including how questions 9–10 are marked, is held separately.
Every question uses the example bucket hoc-site-ab-4821 in the Asia Pacific (Mumbai) Region,
ap-south-1.
1. Website hosting is enabled on hoc-site-ab-4821 and index.html is in the bucket, but there
is no bucket policy. A browser requests the website endpoint’s root. What happens?
a) S3 returns 404 Not Found, because without a policy the object cannot be located
b) S3 returns 403 Forbidden, because the object exists but nobody has been granted read access
c) S3 returns the page, because enabling website hosting grants public read access by itself
d) S3 returns the error document, because a missing policy is treated as a missing page
2. You cleared Block all public access on the bucket, but saving a bucket policy that grants
s3:GetObject to * still fails. What is the most likely cause?
a) The policy needs s3:ListBucket as well before S3 will accept a public read statement
b) Website hosting must be enabled first, or S3 rejects every policy that names * as principal
c) Object Ownership is set to Bucket owner enforced, which forbids any policy granting public read
d) Block Public Access is still on at account level, and S3 applies the most restrictive combination
3. In the S3 console you open a folder named images and upload logo.png into it. What is the
key of the object you created?
a) images/logo.png
b) logo.png, stored inside a directory object named images
c) /images/logo.png
d) logo.png, with images recorded as a tag on the object
4. A classmate types https://hoc-site-ab-4821.s3-website.ap-south-1.amazonaws.com and the page
will not load, although the same address with http:// works. Why?
a) The bucket policy grants s3:GetObject only to requests that arrive over plain HTTP
b) The certificate is issued only a while after website hosting is first enabled on a bucket
c) S3 website endpoints do not support HTTPS; AWS documents Amplify Hosting or CloudFront for it
d) Block Public Access treats any HTTPS request from outside the account as a cross-account call
5. You create a bucket and accept every default on the Create bucket page. Which statement is true of the new bucket?
a) Versioning is enabled, so every overwrite keeps the previous copy of the object b) Access control lists are enabled, so each object can be made public individually c) Objects are stored unencrypted until you choose an encryption type for the bucket d) All four Block Public Access settings are on, so nothing in it can be made public
6. You run aws s3 rb s3://hoc-site-ab-4821 --force and it fails, saying the bucket is not empty.
What explains this?
a) --force only works on buckets that have never had website hosting enabled
b) Versioning is enabled, and --force does not remove the retained object versions
c) The bucket still has a bucket policy, which must be deleted before the bucket can be
d) --force deletes objects only under the prefix you name, and you named no prefix
7. Your team wants a static site served over HTTPS while all four Block Public Access settings stay on for the bucket. Which approach does the S3 documentation describe for that?
a) Serve the site through Amazon CloudFront using origin access control
b) Enable website hosting and add a bucket policy limited to s3:GetObject
c) Turn on access control lists and grant READ to the AllUsers group
d) Switch the bucket’s default encryption to SSE-KMS so that requests are signed
8. In Static website hosting you entered index.html as the index document, and you uploaded
your homepage as Index.html. What do visitors to the root of the site get?
a) Your homepage, because S3 ignores case when it looks up an index document b) A list of the keys in the bucket, because no index document could be found c) Not your homepage: index document names are case sensitive and must match exactly d) Your homepage, but only after S3 renames the object to match the configured name
Part 2 — Constructed response
Submit only the requested text — no explanation, no surrounding quotes.
9. Write the bucket policy for hoc-site-ab-4821 that lets anyone on the internet read the site’s
pages, and grants nothing else.
Assume Block Public Access is off for the bucket and that it holds the pages index.html and
about.html. Submit the policy as JSON.
10. Write one AWS CLI command, run from inside your local site folder, that makes the bucket
hoc-site-ab-4821 hold exactly the files in that folder.
Before you run it, the local folder holds index.html (edited today) and about.html (new). The
bucket holds index.html (an older copy) and old.html (a page you have since deleted locally). The
bucket’s Object Ownership setting is Bucket owner enforced.
Sources
These questions are taught in this unit’s notes, which draw on these pages:
- Website endpoints — https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteEndpoints.html (fetched 2026-10-02)
- Configuring a custom error document — https://docs.aws.amazon.com/AmazonS3/latest/userguide/CustomErrorDocSupport.html (fetched 2026-10-02)
- Hosting a static website using Amazon S3 — https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteHosting.html (fetched 2026-10-02)
- Tutorial: Configuring a static website on Amazon S3 — https://docs.aws.amazon.com/AmazonS3/latest/userguide/HostingWebsiteOnS3Setup.html (fetched 2026-10-02)
- Blocking public access to your Amazon S3 storage — https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-control-block-public-access.html (fetched 2026-10-02)
- Creating a general purpose bucket — https://docs.aws.amazon.com/AmazonS3/latest/userguide/create-bucket-overview.html (fetched 2026-10-02)
- Organizing objects in the Amazon S3 console by using folders — https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-folders.html (fetched 2026-10-02)
- Deleting a general purpose bucket — https://docs.aws.amazon.com/AmazonS3/latest/userguide/delete-bucket.html (fetched 2026-10-02)
- Using high-level (s3) commands in the AWS CLI — https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html (fetched 2026-10-02)
TechEazy Consulting training material — not affiliated with or endorsed by Amazon Web Services (AWS).