Sitemap

AWS Hands-On | S3 Security | S3 CORS

8 min readJun 4, 2025

--

📌 Notice

This is a hands-on tutorial accompanying the blog post:

Pass the AWS Certified Solutions Architect Associate Certification SAA-C03-(Episode 12: S3 Security)

🔹 Focus: Practical implementation of Amazon S3.
🔹 For theoretical concepts and exam-style questions, please refer to the main blog post (link to parent blog).

Here’s a step-by-step guide to practicing CORS (Cross-Origin Resource Sharing) with Amazon S3, based on the provided content:

Objective: Understand how CORS prevents cross-origin requests by default in web browsers and how to configure S3 bucket CORS policies to allow such requests.

Prerequisites:

✔ An AWS account with access to Amazon S3.
✔ Two HTML files:

  • index.html: Contains a script to fetch another HTML file. (You'll need to modify it as described in Step 1).
  • extra-page.html: A simple HTML file with content like "This extra page has been successfully loaded."

Step 1: Prepare Your index.html File for CORS Demo

  1. Open index.html: Open your index.html file in a text editor.
  2. Uncomment CORS Demo Section:
<!DOCTYPE html>
<html>
<body>
<h1>I Really love coffee!</h1>
<p>Hello world!</p>
<img src="coffee.jpg" width="300">
</body>

<!-- CORS DEMO -->
<div id="tofetch">
<script>
var tofetch = document.getElementById("tofetch");

fetch('extra-page.html')
.then((response) => {
return response.text();
})
.then((html) => {
tofetch.innerHTML = html
});
</script>
</html>

3. Save index.html: Save the modified file.

Step 2: Create Your “Origin” S3 Bucket and Host index.html

  1. Create S3 Bucket: In the AWS S3 console, click “Create bucket”.
  2. Configure Bucket Details (Origin):
  • Bucket name: Choose a unique name (e.g., demo-cors-mino-v2).
  • AWS Region: Choose a region (e.g., ap-southeast-1 - Singapore, as the example used Canada for the "other origin," and I'm in Sri Lanka, making a region like Singapore a good alternative to demonstrate cross-region).
  • Block Public Access settings: Uncheck “Block all public access” (you’ll make this bucket public). Acknowledge the warning.
  • Leave other settings as default.

3. Create Bucket: Click “Create bucket”.

4. Enable Static Website Hosting:

  • Go into your newly created “Origin” bucket.
  • Click the “Properties” tab.
  • Scroll down to “Static website hosting” and click “Edit”.
  • Select “Enable”.
  • Hosting type: “Host a static website”.
  • Index document: index.html.
  • Click “Save changes”.

5. Set Bucket Policy for Public Access:

  • Click the “Permissions” tab.
  • Under “Bucket policy”, click “Edit”.
  • Paste the following policy, replacing YOUR_ORIGIN_BUCKET_NAME with the actual name of your origin bucket:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::YOUR_ORIGIN_BUCKET_NAME/*"
}
]
}
  • Click “Save changes”.

6. Upload Files to Origin Bucket:

  • Go to the “Objects” tab. * Click “Upload”, then “Add files”.
  • Select both your modified index.html and extra-page.html files.
  • Click "Upload".

7. Test Initial Setup (Same Origin):

  • Go to the "Properties" tab of your origin bucket.
  • Copy the "Bucket website endpoint" URL.
  • Paste it into your browser.

Observation: You should see "I love coffee, Hello world! The coffee image." followed by "This extra page has been successfully loaded." This confirms the fetch request worked within the same origin.

Step 3: Create Your “Other Origin” S3 Bucket and Host extra-page.html

  1. Create S3 Bucket: In the AWS S3 console, click “Create bucket”.
  2. Configure Bucket Details (Other Origin):
  • Bucket name: demo-other-origin-mino (or a unique name).
  • AWS Region: Choose a different region from your origin bucket (e.g., us-east-1 - N. Virginia).
  • Block Public Access settings: Uncheck “Block all public access”. Acknowledge the warning.
  • Leave other settings as default.

3. Create Bucket: Click “Create bucket”.

4. Enable Static Website Hosting:

  • Go into your new “Other Origin” bucket.
  • Click the “Properties” tab.
  • Scroll down to “Static website hosting” and click “Edit”.
  • Select “Enable”.
  • Hosting type: “Host a static website”.
  • Index document: index.html (even though we're only putting extra-page.html).
  • Click “Save changes”.

5. Set Bucket Policy for Public Access:

  • Click the “Permissions” tab.
  • Under “Bucket policy”, click “Edit”.
  • Paste the following policy, replacing YOUR_OTHER_ORIGIN_BUCKET_NAME with the actual name of this other origin bucket:
 {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::YOUR_OTHER_ORIGIN_BUCKET_NAME/*"
}
]
}
  • Click “Save changes”.

6. Upload extra-page.html to Other Origin:

  • Go to the "Objects" tab.
  • Click "Upload", then "Add files".
  • Select only your extra-page.html file.
  • Click "Upload".

7. Verify extra-page.html is Public:

  • Click on the extra-page.html object in the "Other Origin" bucket.
  • Copy its "Object URL".
  • Paste it into your browser.
  • You should see "This extra page has been successfully loaded."

Step 4: Modify index.html to Fetch from the "Other Origin"

  1. Remove extra-page.html from Origin Bucket:
  • Go back to your first (“Origin”) bucket.
  • Select extra-page.html and delete it.

Reason: This ensures the fetch request must go to the other bucket, demonstrating the cross-origin scenario.

  • Go back to your webpage (the one using the origin bucket’s endpoint) and refresh. You should now see a “404 Not Found” for the extra-page.html in the browser's console, as it can't find it locally.

2. Get the “Other Origin” extra-page.html URL:

  • Go to your demo-other-origin-mino bucket.
  • Go to the “Properties” tab.
  • Copy the “Bucket website endpoint” URL.
  • Append /extra-page.html to it (e.g., http://demo-other-origin-mino.s3-website.us-east-1.amazonaws.com/extra-page.html). This is the full URL to the extra-page.html in the other bucket.
<!DOCTYPE html>
<html>
<body>
<h1>I Really love coffee!</h1>
<p>Hello world!</p>
<img src="coffee.jpg" width="300">
</body>

<!-- CORS DEMO -->
<div id="tofetch">
<script>
var tofetch = document.getElementById("tofetch");

fetch('http://demo-other-origin-mino.s3-website.us-east-1.amazonaws.com/extra-page.html')
.then((response) => {
return response.text();
})
.then((html) => {
tofetch.innerHTML = html
});
</script>
</html>

3. Edit index.html to Point to Other Origin:

  • Open your index.html file in a text editor again.
  • Find the fetch('extra-page.html') line.
  • Replace 'extra-page.html' with the full URL you just copied for the extra-page.html in the "Other Origin" bucket.
  • Example: fetch('http://demo-other-origin-stephane.s3-website.ca-central-1.amazonaws.com/extra-page.html')
  • Save the modified index.html.

4. Upload Updated index.html to Origin Bucket:

  • Go back to your first (“Origin”) bucket.
  • Click “Upload”, then “Add files”, and select your newly modified index.html.
  • Click “Upload”. (It will overwrite the existing index.html.)

Step 5: Observe CORS Blockage (Before CORS Policy)

  1. Open Developer Tools: Go to your browser (Chrome recommended). Navigate to the webpage hosted on your origin bucket’s endpoint. Right-click anywhere on the page, select “Inspect” (or “More tools” > “Developer tools”).
  2. Go to “Console” Tab: In the Developer Tools, click on the “Console” tab.
  3. Refresh Page: Refresh the webpage.

Observation: You will see “Hello world! I love coffee” and the image. However, the “This extra page has been successfully loaded.” text will not appear. More importantly, in the Console tab of your developer tools, you will see an error message similar to:

Access to fetch at 'http://demo-other-origin-stephane.s3-website.ca-central-1.amazonaws.com/extra-page.html' from origin 'http://YOUR_ORIGIN_BUCKET_ENDPOINT' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Explanation: The browser is preventing your index.html (from Origin A) from fetching extra-page.html (from Origin B) because Origin B has not explicitly allowed requests from Origin A.

Step 6: Add CORS Policy to the “Other Origin” Bucket

  1. Navigate to “Other Origin” Bucket Permissions: Go to your demo-other-origin-mino bucket.
  2. Go to “Permissions” Tab: Click on the “Permissions” tab.
  3. Edit CORS Policy: Scroll down to “Cross-origin resource sharing (CORS)” and click “Edit”.
  4. Paste CORS Configuration: Paste the following JSON configuration into the editor.
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET"
],
"AllowedOrigins": [
"http://YOUR_ORIGIN_BUCKET_ENDPOINT"
],
"ExposeHeaders": [],
"MaxAgeSeconds": 3000
}
]

5. Save Changes: Click “Save changes”.

Explanation: This CORS policy tells the “Other Origin” bucket that it’s allowed to receive GET requests from your “Origin” bucket’s domain.

Step 7: Verify CORS Success

  1. Refresh Webpage: Go back to your webpage (the one hosted on your origin bucket’s endpoint) in the browser with Developer Tools open.
  2. Refresh the page again.

Observation: The “This extra page has been successfully loaded.” text should now appear on your webpage!

  • Verify in Developer Tools:
  • In the “Network” tab, find the request for extra-page.html.
  • Click on it, then go to the “Headers” tab.
  • Under “Response Headers”, you should now see Access-Control-Allow-Origin: http://YOUR_ORIGIN_BUCKET_ENDPOINT (or similar) and Access-Control-Allow-Methods: GET.

Conclusion:

You have successfully demonstrated CORS in Amazon S3. You’ve learned that:

  • Web browsers enforce a Same-Origin Policy for security.
  • By default, cross-origin requests are blocked.
  • You must configure a CORS policy on the receiving S3 bucket (the one serving the resource) to explicitly allow requests from specified origins.
  • The Access-Control-Allow-Origin header is key to enabling these requests.

To stay informed on the latest technical insights and tutorials, connect with me on Medium and LinkedIn. For professional inquiries or technical discussions, please contact me via email. I welcome the opportunity to engage with fellow professionals and address any questions you may have.

--

--

Paul issack minoltan
Paul issack minoltan

Written by Paul issack minoltan

I am a Professional Software Engineer

No responses yet