Block Public S3 Bucket Access with CloudFront OAI
S3 stands for Simple Storage Service. S3 is like a virtual drive to store and retrieve data. According to the AWS definition:
“You can use Amazon S3 to store and retrieve any amount of data at any time, from anywhere on the web”
Meaning you need to have Internet 🤷🏻♀️
One of the AWS most amazing services is serving a static website from an S3 bucket. Many people use it for this purpose.
The service provided by S3 Bucket also has loads of vulnerabilities if S3 is not configured properly.
I am going to discuss one of those here.
A bucket is considered public if any user can list the contents of the bucket, and private if the bucket’s contents can only be listed or written by certain S3 users.
If you own an AWS account, try running the following command:
aws s3 ls s3://bucket-name/
The bucket is PUBLIC if it displays the content of the bucket
This bucket is a public Amazon S3 bucket. This is not recommended, as this bucket will list all files and directories to any user that asks.
Remediation
Make sure all the Amazon S3 buckets you are using are marked as private.
But if the bucket is made private, how will you be able to host a static website?
AWS Cloudfront to the rescue.
Cloudfront is a content delivery network (CDN) of AWS. It is a fully managed, fast CDN service that speeds up the distribution of static, dynamic web, or streaming content to end-users.
Yes! It has a lot of power but this is not the one we are talking about. The one we are talking about is OAI (Origin Access Identity).
The Origin Access Identity (OAI) is the primary way to make CloudFront access private content stored in S3. Without it, CloudFront is like an anonymous user, it only has access to content everybody else has access to.
When you make the bucket private, you forbid even CloudFront from accessing it. In many real-world scenarios, you want your visitors to access the content only through the distribution, and not directly. This is where OAI helps.
Follow the steps below to configure OAI Power
Step 1: Create a bucket. Make sure ‘Block all public access’ is enabled.
Step 2: Upload your files to the S3 bucket.
You can also see under Properties > Static Hosting that it is disabled.
Also under Bucket’s Permission > Bucket Policy, that bucket is blocked from public access.
Step 3: Go to CloudFront and create a Distribution
Enter the Fields with the Values provided below:
It will take some time to deploy. Meanwhile you can checkout the Updated Bucket Policy
{
“Version”: “2008–10–17”,
“Id”: “PolicyForCloudFrontPrivateContent”,
“Statement”: [
{
“Sid”: “1”,
“Effect”: “Allow”,
“Principal”: {
“AWS”: “arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity EB5UFU7XS9ASB”
},
“Action”: “s3:GetObject”,
“Resource”: “arn:aws:s3:::secure-bucket-here/*”
}
]
}
The OAI created in the above step can be seen under the Cloudfront > Security (Object Access Identity):
Step 4: Click on the cloud front distribution just created. Go to Edit Settings.
In the Edit settings search for the Default root object, enter the starting page of the web application. (For me it is index.html 🙆🏻♀️)
Once everything is deployed you can see the status Enabled. Copy the Domain name and paste it in a new tab to view the website.
Voila!
Note : Step 4 is necessary, you might get ‘Access Denied’ error in absence of it.
As you do not have S3 publicly accessible and don’t have a static URL created for the bucket, it can only be accessed via CloudFront OAI.