How can I make sure I fully secured my AWS S3 Bucket? - amazon-web-services

I am trying to make sure I have my S3 bucket secure. I need to allow some sort of public access due to my website displays the images that are uploaded to my S3 bucket.
My Public Access settings look sleek this:
I then set up my Cross-origin resource sharing (CORS) to look like this:
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET",
"PUT",
"POST"
],
"AllowedOrigins": [
"https://example.com",
"https://www.example.com"
],
"ExposeHeaders": [],
"MaxAgeSeconds": 3000
}
]
And my S3 ACLs look like this:
After doing this my images are still visible on my website hosted on AWS. My question here is am I missing anything?
I don't think I fully understand the Cross-origin resource sharing (CORS) of this. I assumed the AllowedOrigins tag would only allow the images to be viewed on my domain? So I took the address to one of my images and threw it in my web browser and it loaded. Is this correct behavior or am I misunderstanding this?
Any more suggestions on how to secure my S3 bucket? I basically just want user on my website to be able to view my images and upload images from only my site. Thanks!
Updates
For a more full view, my bucket policy is:
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "AllowPublicRead",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::example.com.storage/*"
}
]
}
My ACLs in S3 are configured as:

You asked "how to secure my S3 bucket?"
Buckets in Amazon S3 are private by default, so they are automatically 'secure'. However, you want to make the objects (eg images) accessible to users on your website, so you need to open sufficient access to permit this (as you have successfully done!).
In fact, the only elements you actually needed were:
On "Block Public Access", allow Bucket Polices (Done!)
Create a Bucket Policy that grants GetObject to anyone (Done!)
You only need the CORS settings if you are experiencing a particular problem, and there is no need to change the Bucket ACLs from their default values.
The bucket policy is only allowing people to download objects, and only if they know the name of the object. They are not permitted to upload objects, delete objects or even list the objects in the bucket. That's pretty secure!
Your settings are fine for publicly-accessible content that you are happy for anyone to access. If you have any personal or confidential content (eg documents, or items requiring login) then you would need an alternate way of granting access only to appropriately authorized people. However, this doesn't seem to be a requirement in your situation.
Bottom line: You are correctly configured for granting public read-only access to anyone, without providing any additional access. Looks good!

Amazon CloudFront (CF) is often used for serving content from S3 buckets without needing the buckets to be public. This way your website would server your images from CF, rather than directly from the bucket. CF would fetch and cache the images from the bucket privately.
The way it works is that in your bucket, you would setup a special bucket policy which would allow a CF user, called origin access identity (OAI), to access your bucket.
The use of CF and OAI to serve your images from your bucket not only keeps your bucket fully private, but also reduces load times as CF caches the images in its edge locations.
More details on this are in:
Restricting Access to Amazon S3 Content by Using an Origin Access Identity
Amazon S3 + Amazon CloudFront: A Match Made in the Cloud
How do I use CloudFront to serve HTTPS requests for my Amazon S3 bucket?

Related

Amazon S3 - is it possible to restrict users to scan folders of public folders?

I have an Amazon S3 bucket with several files with randomized file names. The file names are very difficult to guess (for example: id84hBDs4g0a73nb0Ms9.png) and I would only want users who know the file name to access them. This means that the Amazon S3 bucket is technically public, but I have to restrict users from "scanning" / "listing" the folder. The user should only be able to access the files they know the file name to and not other files. Is this a possible setting in Amazon S3?
You are wanting to implement Security through obscurity - Wikipedia. Please note that it is not a form of complete security, as anyone who knows the names of the objects can access them.
You can simply add a Bucket Policy that makes all objects in the bucket (or a path within the bucket) 'public'. This policy allows access to the objects, but not listing of the bucket.
From Bucket policy examples - Amazon Simple Storage Service:
{
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::YOUR-BUCKET/*"
}
]
}
You will first need to disable Block Public Access on the bucket to be able to store this bucket policy.

What combination of Block Public Access settings makes my s3 bucket viewable to everyone?

I am new to AWS and created an s3 bucket for static site hosting. I want to allow Read-Only access to everyone so they can access the website. What combination of settings gives me this scenario? Do I need to uncheck all 4 settings in the Block Public Access settings? Do I even need to add a bucket policy if all 4 settings are set to off? I just want to make sure the bucket is never written to but the account holder. Thanks.
Block Public Access acts as an additional layer of protection to prevent Amazon S3 buckets from being made public accidentally.
By default, all content in Amazon S3 is private. You can then make content accessible in several different ways:
At the bucket-level, by creating a Bucket Policy on the desired bucket. The rules added to this bucket can be used to grant access to objects (GetObject), list contents, upload, delete, etc. The policies can also get quite specific, such as allowing access only to specific IP addresses.
At the object-level, by configuring Access Control Lists (ACLs) on each individual object. For example, an object can be made publicly accessible.
At the IAM User or IAM Group level, by adding an IAM Policy directly the to the user/group. This is great for granting access to only specific sets of IAM users (as opposed to publicly).
By using Pre-Signed URLs that are generated programmatically and provide time-limited access to a specific object. This is typically used by applications to grant access to private objects. For example, a photo-sharing website would keep all photos private, but an authorized user would be able to view their own pictures, or pictures shared with them via the application.
So, in your question, you say you would like to "allow Read-Only access to everyone so they can access the website". This would normally be done by creating a Bucket Policy such as:
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"MakeItPublic",
"Effect":"Allow",
"Principal": "*",
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::my-bucket/*"]
}
]
}
You should first deactivate the two Block Public Access settings that refer to Bucket Policies (the bottom two).
You need Amazon CloudFront distribution. In addition to providing the benefits of an integrated CDN, you can configure an Origin Access Identity that ensures that the bucket can only be accessed through CloudFront, not through public S3.
Client -> Route53 -> Cloudfront -> S3 (blocked public access)
In Cloudfront
Create cloudfront function (from left menu), this will redirect any
request with index.html appended. For ex: example.com/home to
example.com/home/index.html
'use strict';
function handler(event) {
var request = event.request;
var uri = request.uri;
// Check whether the URI is missing a file name.
if (uri.endsWith('/')) {
request.uri += 'index.html';
}
// Check whether the URI is missing a file extension.
else if (!uri.includes('.')) {
request.uri += '/index.html';
}
return request;
}
Create the origin access (from left menu), this will be used in
distribution's origin
In Distributions
In origin tab
Create origin as S3 type, by choosing the s3 bucket
Click on origin access control settings that create at first step
Edit general settings and put index.html in default root object.
Edit Behaviours, In Function associations, select cloudfront function
in viewer request. Don’t need to go with lambda function
In S3
In properties, disable static s3 website hosting
In permissions
Block all public access
Edit the bucket policy with below:
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipal",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::BUCKET_NAME/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::ACC_NUMBER:distribution/DISTRIBUTION_ID"
}
}
}
]
}
In Route53
Create A record by selecting cloudfront distribution

How to revoke public permissions from a Amazon S3 Bucket

I created a Amazon S3 Bucket to store only images from my website. I have more than 1 million images all with public read access. Everytime I make a login, Amazon gives me this warning:
"This bucket has public access
You have provided public access to this bucket. We highly recommend that you never grant any kind of public access to your S3 bucket. "
I'm using the following Bucket Policy to only allow images to be shown just in my site:
{
"Version": "2012-10-17",
"Id": "http referer policy example",
"Statement": [
{
"Sid": "Allow get requests originated from www.example.com and example.com.br",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::examplebucket.com/*",
"Condition": {
"StringLike": {
"aws:Referer": [
"http://www.example.com/*",
"http://www.example.com.br/*",
"https://www.example.com/*",
"https://www.example.com.br/*"
]
}
}
}
]
}
How can I revoke the public access to the bucket and to my files and grant it only to my sites?
Thank you!
It's a scary warning meant to prevent people from leaking data unintentionally. There have been lots of cases in the news lately about companies accidentally setting permissions to allow public reads.
In your case you really do want these to be publicly readable so you can just ignore the warning. Your security policy looks fine and still matches the documentation for public hosting.
You could theoretically put these images behind another server that streams them to the user if you really don't want someone to be able to download them directly. That's not really any more secure though.
If you do not want to have these publicly available at all just delete this policy from your bucket. In that case your website will not be able to serve the images.
Your policy looks good. You are providing a higher level of security then just public thru the referer header and not allowing the listing of objects.
Using S3 to provide common files such as CSS, JS and Images is just so easy. However, with all of the accidental security problems I usually recommend one of these approaches:
Turn on static web site hosting for the bucket. This makes it very clear to future admins that this bucket is intended for public files. Also I do not see big warning messages for these buckets. Enable redirect requests.
Better, turn off all public access and use CloudFront. Enable Origin Access Identity. You receive all the benefits of CloudFront, tighter security, etc.
Using an Origin Access Identity to Restrict Access to Your Amazon S3 Content

Can't download objects from S3 using the URL link

I have a policy like below which I've attached to several users:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:*"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::foo-bar",
"arn:aws:s3:::foo-bar/*"
]
}
]
}
The intent of this policy is that these users would have full control over the bucket foo-bar. However, I'm noticing that even though the users can download the objects in these buckets using Accesskey and Secretkey. They can not download the objects via a URL e.g. https://s3.amazonaws.com/foo-bar/test.docx
I am currently logged in as a IAMManager user and also have AmazonS3FullAccess. I can see the list of objects in this bucket but when I click the URL I can't download them. I can, however, download them via clicking the Download button.
Question
Is there anything I need to change in my policy OR the objects can only be downloaded via the URL when they are publicly available?
By using your IAM policy on your users, you are granting S3 API access to the bucket for those users only. However, when accessing the bucket via the URL, you are not using the S3 APIs and no authentication information is being sent.
In order to download objects from an S3 bucket directly via the URL, the bucket needs to be made public, which you may or may not want to do.

S3 Bucket Still Public Despite CloudFront Origin Identity Access Policy

I have followed the documentation on setting up a CloudFront (CF) web distribution to serve private content from my s3 bucket, but despite adjusting the settings in my distribution to do so, my s3 bucket files are still accessible via s3.amazonaws.com/bucket-name/file-name.ext. I was curious why this is still occurring because when I created a CF Origin Access Identity, I selected Yes, Update Bucket Policy, which I thought would take care of closing off the read access via my s3 bucket url, but it hasn't. Did I miss an adjustment that should be make? I assumed that settings I make on CF should adjust my s3 bucket and make it not accessible via GET requests.
Here is my s3 Bucket Policy:
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity *My-Key-ID*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucket-name/*"
}
]
}
However, I noticed permissions on the individual files, but wasn't sure what they were related to.
Here are my CF settings:
Distribution:
Origin: (On initial identity creation I picked "Yes, Update Bucket Policy")
Behavior (Top Half):
Behavior (Bottom Half):
The bucket policy and object ACLs work together.
Anything allowed by either policy or object ACL is still allowed... except when explicitly denied by the bucket policy.
Your policy allows downloads through CloudFront.
Your object ACLs allow "Everyone" to "open/download" them, thus, anonymous direct access to objects in the bucket will still be allowed.
The most correct solution is to modify the object ACLs to remove the ability for "Everyone" to "open/download," which is clearly not correct if you do not want the objects to be accessible from S3 by anonymous users. In the console, click the × on that "Everyone" entry for an object, and click Save. You should find that this solves the problem.
Future objects should not be uploaded as publicly-readable.
This could also be accomplished using a custom bucket policy to override the object ACLs, but this is an advanced configuration that will break your ability to manipulate objects in the console if done incorrectly and will unnecessarily complicate things.