Dev.to Security 🔐 Cybersecurity 👁 1 📖 3 min read

🔒 Secure Amazon S3 Access using VPC Endpoint and IAM Role (Hands-on AWS Lab)

One of the most common security mistakes in AWS is exposing Amazon S3 buckets to the public. While public access may be useful for testing, production workloads should always access S3 privately through AWS networking an

🔒 Secure Amazon S3 Access using VPC Endpoint and IAM Role (Hands-on AWS Lab)

One of the most common security mistakes in AWS is exposing Amazon S3 buckets to the public. While public access may be useful for testing, production workloads should always access S3 privately through AWS networking and IAM.

In this hands-on lab, we'll start with a publicly accessible S3 bucket, verify that anyone can access its contents, and then progressively secure it using:

  • Amazon S3
  • VPC Gateway Endpoint
  • IAM Role for EC2
  • Bucket Policy with VPC Endpoint restriction

By the end of this tutorial, your S3 bucket will only be accessible from resources inside your VPC.

Architecture

                Internet
                    |
          (Access Denied)
                    X
                    |
         -----------------------
         |     Amazon S3       |
         -----------------------
                    ^
                    |
          Gateway VPC Endpoint
                    |
             ----------------
             |     VPC      |
             |              |
             |   EC2 + IAM  |
             ----------------

Step 1: Create an S3 Bucket

Navigate to Amazon S3 from the AWS Console.

Click Create bucket.

Use the bucket name:

ml-lab-bucket-secure-ml-101

For this lab:

  • Disable Block all public access

accept

  • Accept the warning
  • Create the bucket

At this point the bucket is capable of serving public objects.

Step 2: Allow Public Read Access

Open the bucket and navigate to:

Permissions → Bucket Policy

Paste the following policy.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadAccess",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::ml-lab-bucket-secure-ml-101/*"
    }
  ]
}

bucket policy

Save the policy.

This policy allows anyone on the internet to download objects from the bucket.

Step 3: Upload a Test File

Open the Objects tab.

Upload:

raw_v1.csv

upload

After uploading:

  1. Open the object.
  2. Copy its Object URL.
  3. Paste it into a browser.

The CSV downloads successfully without authentication.

✅ This confirms the bucket is publicly accessible.

Step 4: Create a VPC Gateway Endpoint for Amazon S3

Search for VPC in the AWS Console.

Navigate to:

Endpoints

Click Create endpoint.

Configuration:

Name

my-ps-lab-endpoint-01

Service:

com.amazonaws.us-east-1.s3

select service

Type:

Gateway

Choose:

  • Your VPC
  • Your Route Table

Create the endpoint.

Step 5: Verify the Route Table

Navigate to:

VPC → Route Tables

Open the selected route table.

Under Routes, verify a route similar to:

vpce-xxxxxxxx

endpoint id

Copy the endpoint ID.

You'll use it later in the bucket policy.

Step 6: Launch an EC2 Instance

Open EC2.

Launch a new instance.

Example name:

my-ps-lab-instance-01

Choose:

  • Your VPC
  • Your subnet
  • Default key pair

ec2 instance

Launch the instance.

Step 7: Create an IAM Role

Navigate to IAM → Roles.

Create a new role.

Configuration:

Trusted Entity

AWS Service

Use Case

EC2

Permissions:

AmazonS3FullAccess

s3 access

Role Name

my-iam-role-lab-01

Create the role.

Step 8: Add an Inline IAM Policy

Open the IAM role.

Choose:

Add permissions
→ Create Inline Policy
→ JSON

Paste:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:ListBucket"],
      "Resource": "arn:aws:s3:::ml-lab-bucket-secure-ml-101"
    },
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject"],
      "Resource": "arn:aws:s3:::ml-lab-bucket-secure-ml-101/*"
    }
  ]
}

Policy name:

my-secure-policy

policy

Create the policy.

Although the role already has AmazonS3FullAccess, this inline policy demonstrates how to grant least-privilege permissions for a specific bucket.

Step 9: Attach the IAM Role to EC2

Go to the EC2 console.

Select the instance.

Choose:

Actions
→ Security
→ Modify IAM Role

Attach:

my-iam-role-lab-01

role update

Update the role.

Step 10: Test Access from EC2

Connect to the EC2 instance using EC2 Instance Connect.

Run:

aws s3 ls s3://ml-lab-bucket-secure-ml-101

bucket access

Expected output:

raw_v1.csv

You can also test another bucket:

aws s3 ls s3://your-s3-bucket-name

At this stage, EC2 can access the bucket successfully.

Step 11: Block Public Access

Return to the S3 bucket.

Navigate to:

Permissions

Edit Block Public Access.

Enable:

Block all public access

block access

Save the settings.

Type:

confirm

to apply the changes.

The bucket is no longer publicly accessible.

Step 12: Restrict Access to the VPC Endpoint

Now we'll ensure that only requests coming through our VPC Endpoint are allowed.

Replace the bucket policy with:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyIfNotFromVPCE",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::ml-lab-bucket-secure-ml-101",
        "arn:aws:s3:::ml-lab-bucket-secure-ml-101/*"
      ],
      "Condition": {
        "StringNotEquals": {
          "aws:sourceVpce": "vpce-xxxxxxxx"
        }
      }
    }
  ]
}

Replace:

vpce-xxxxxxxx

with your own VPC Endpoint ID.

Save the policy.

Step 13: Validate the Security

Test from Browser

Open the Object URL again.

Expected result:

Access Denied

denied

The internet can no longer reach your bucket.

Test from EC2

Return to the EC2 terminal.

Run:

aws s3 ls s3://ml-lab-bucket-secure-ml-101

Expected output:

raw_v1.csv

bucket access

The EC2 instance continues to access the bucket successfully because traffic flows through the VPC Gateway Endpoint.

What We Achieved

In this lab, we transformed an insecure S3 bucket into a private, production-ready storage solution.

✔ Created an Amazon S3 bucket

✔ Allowed public object access

✔ Verified public accessibility

✔ Created a Gateway VPC Endpoint

✔ Launched an EC2 instance

✔ Assigned an IAM Role

✔ Granted least-privilege bucket permissions

✔ Enabled Block Public Access

✔ Restricted S3 access using a VPC Endpoint policy

✔ Verified that only workloads inside the VPC could access the bucket

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.