S3 Bucket Still Public Despite CloudFront Origin Identity Access Policy - amazon-web-services

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.

Related

Restricting access to S3 objects unless url is signed

I've created a unique bucket for my private files on S3. This bucket is configured to block all public access. My application is configured to upload files to this s3 bucket with no public read access and I can confirm that the permissions on the objects reflect that this is working (i.e. there are no permissions given to the public on the objects that are uploaded).
Despite all of these measures to restrict public access to these files, these files are still visible to the public. I think that my IAM settings may be overriding the ACL setting as well as the bucket settings. I'm not sure which IAM setting to change or if changes may negatively impact other parts of my application, so I'd like to restrict access to this 'private bucket' with a bucket policy if possible.
This is what I've started with for a bucket policy:
{
"Version": "2012-10-17",
"Id": "My Special Bucket Policy",
"Statement": [
{
"Sid": "DenyAccesstoAllFiles",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my_private_bucket/*"
}
]
}
Unfortunately, this blocks access to objects in this 'private bucket' even with a signed url.
Please note that I've been able to generate signed urls successfully. They expire in 60 seconds just as I've configured them.
Thanks for your help!
Edit: All my files are being uploaded like this:
All buckets and objects are private by default. So normally you don't need any policy on them. In your case any access is denied, because Deny always wins over any Allow:
Remember, an explicit deny in any of these policies overrides the allow.
Thus, there is no way to enable any public access to your objects due to your Deny, and no pre-signed url will change that.
Normally what you do is that you get rid of your policy, and rely on default behavior that the buckets and objects are private. In that case, the pre-signed url will work.
Two things to note:
Buckets created in AWS in default settings are always private and their objects are not accessible via their links. I think you have mixed up some links that make you believe that your objects are still visible :)
You do not need to have an explicit policy to deny all the access to
your S3 objects.
I would recommend you to remove the policy that you have attached to your bucket and then test again if the public links to your objects work (they shouldn't if your bucket is made via default settings). Once that part is clear, your pre-signed URLs should work!

Make every object in an Amazon S3 bucket publicly accessible

I have a S3 bucket on AWS to which I am uploading images from the frontend.
After successfully uploading an image to S3, this is the URL I get -
https://cewa-foundation-2020.s3.amazonaws.com/image8_%281%29.webp-1628768330444.webp
I want to make this URL public so that anyone with this link can view the image.
How can I achieve this?
To make every object public you should add a Bucket Policy to the bucket.
Go to the bucket's Permissions tab
Go to the Block public access options
Turn off the two options that mention Bucket Policies:
Below that, add a Bucket Policy that grants access to anonymous users:
{
"Version":"2012-10-17",
"Statement":[
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::YOUR-BUCKET-NAME/*"
}
]
}
All objects in the bucket can now be accessed by anyone on the Internet. However, they will not be able to list the contents of the bucket, so they will need to know the exact name of the object they want to access.
You can make an object public by doing these below steps:
Open the object by choosing the link on the object name.
Choose the Permissions tab.
Choose Edit.
In the Everyone section, select Objects Read.
Select I understand the effects of these changes on this object.
Choose Save changes.
This is just one of the ways of doing it. Check the below link for more such ways.
Source: https://aws.amazon.com/premiumsupport/knowledge-center/read-access-objects-s3-bucket/

How can I make sure I fully secured my AWS S3 Bucket?

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?

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

Amazon S3 access control-Who can upload files?

I have a static website created with Amazon S3. The only permissions I have set are through the bucket policy provided in Amazons tutorial:
{
"Version":"2012-10-17",
"Statement": [{
"Sid": "Allow Public Access to All Objects",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::example.com/*"
}
]
}
Clearly, this policy enables the public to view any file stored on my bucket, which I want. My question is, is this policy alone enough to prevent other people from uploading files and/or hijacking my website? I wish for the public to be able to access any file on the bucket, but I want to be the only one with list, upload, and delete permissions. Is this the current behavior of my bucket, given that my bucket policy only addresses view permissions?
Have a look at this: http://docs.aws.amazon.com/IAM/latest/UserGuide/AccessPolicyLanguage_EvaluationLogic.html#policy-eval-basics
From that document:
When a request is made, the AWS service decides whether a given
request should be allowed or denied. The evaluation logic follows
these rules:
By default, all requests are denied. (In general, requests made using
the account credentials for resources in the account are always
allowed.)
An explicit allow overrides this default.
An explicit deny overrides any allows.
So as long as you don't explicitly allow other access you should be fine. I have a static site hosted on S3 and I have the same access policy.