Restricting access to S3 objects unless url is signed - amazon-web-services

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!

Related

Make one S3 bucket public

Currently I have 5 S3 buckets in my account, and all of them are Block all public access -> ON and the same setting is also there for Block Public Access settings for this account -> ON.
Now I want to create a new bucket that should be public, and I don't want to change any of my existing buckets. So for the newly created bucket I have set Block all public access = OFF. But when I try to save below policy, it gives Access denied error. So I guess I have to Turn Off Block Public Access settings for this account.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Action": "s3:GetObject",
"Effect": "Allow",
"Resource": "arn:aws:s3:::MyNewImageBucketS3/*",
"Principal": "*"
}
]
}
I want to know that if I turn off account level setting, then will it affect my existing buckets?
As a second option I can configure CloudFront and serve files publicly but want to know about the public access change at the account level.
Block all public access = OFF; this setting is for individual s3 buckets provided you are doing it from bucket settings, so for that specific bucket you can turn this off and you are good to go.
If you want specific objects to be publicly accessible then this can be achieved via similar IAM policy you shared but to make this work turn on public access on that bucket and then you can apply IAM policy to allow specific objects and deny remaining.
Below image describes that if you change it in bucket setting, its going to effect on that specific bucket and the objects within bucket only
For more guidelines please check below AWS doc
https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-policy-alternatives-guidelines.html

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

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.

Amazon S3: Restricting access to a specific object to an assigned HTTP referrer

I understand it's possible to restrict file access to a specified HTTP referrer with a bucket policy, but is it possible to do this on a per-object basis? We want most of the images in our bucket to be publicly accessible; If you have the link, then you should be able to copy and past it into your browser to view.
Our application has come to a point where we'd like to limit some of these images so that they can only be dished out by us from our site. However, I've only seen this functionality through setting an all encompassing bucket policy. Is it possible to set this on specific objects during their lifetime and not everything in a bucket?
Thanks!
Yes, you can restrict to prefix paths and objects. All you need to do is specify the correct rules in the Resource field of your bucket policy. For example:
{
"Version":"2012-10-17",
"Statement":[{
"Sid":"AddPerm",
"Effect":"Allow",
"Principal": "*",
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::examplebucket/public/path/public-image.jpg"
]
}
]
}
But as you grow more complex in your security requirements, take a look at signed urls and IAM identity
federation, as those can be more flexible and easier to maintain than bucket policy rules.