Can't download objects from S3 using the URL link - amazon-web-services

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.

Related

s3 bucket policy to access object url

What is s3 bucket policy permission to provide an IAM user to access object url which is basically an HTTPs url for the object that i have uploaded to S3 bucket.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListBucket",
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": "arn:aws:s3:::bucket"
},
{
"Sid": "GetObject",
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::bucket/*"
}
]
}
With above policy i can download the object into my local , but i cant access it with object url which includes Https link. If i keep the s3 bucket full public , only then i can have the https access to the object url.
I dont want to provide full public access and how to provide access to this with bucket policy?
You can get https url by generating s3 pre-signed urls for the objects. This will allow for temporary access using the urls generated.
Other than that, a common choice is to share your s3 objects with an outside world without making your bucket public using CloudFront as explained in:
Amazon S3 + Amazon CloudFront: A Match Made in the Cloud
Objects in Amazon S3 are private by default. They are not accessible via an anonymous URL.
If you want a specific IAM User to be able to access the bucket, then you can add permissions to the IAM User themselves. Then, when accessing the bucket, they will need to identify themselves and prove their identity. This is best done by making API calls to Amazon S3, which include authentication.
If you must access the private object via a URL, then you can create an Amazon S3 pre-signed URL, which is a time-limited URL that provides temporary access to a private object. This proves your ownership and will let S3 serve the content to you. A pre-signed URL can be generated with a couple of lines of code.

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?

How to create correct S3 bucket policy to enable read access to a file only if they know the path

My web app allows different user to upload different files. Currently putting them all in one bucket, something like:
A12345-Something.zip
B67890-Lorem.zip
A12345-... is file uploaded by user id A12345.
B67890-... is file uploaded by user id B67890.
This is my S3 bucket policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::xxxx/*"
}
]
}
So far, this is all good, user A12345 can download the zip file by accessing https://xxxx.s3.ap-south-1.amazonaws.com/A12345-Something.zip
But the AWS interface gives me a warning that this bucket is a public bucket and it is highly recommended to not set it to public.
I am not sure but it is indeed very wrong if the policy above allows someone to list all objects from all users in my bucket and then access them one by one.
I think I need a policy that only allows reading a specific object if the full path is provided (assuming only that user will have access to that full path), but disallow listing of objects?
How should the policy looks like?
The policy you've specified allows someone to get all objects which means if they have the path they can retrieve that file publicly in the browser.
The permission ListObjects would be the permission that allows people to list all of the objects in your S3 bucket, this is not included.
If only specific users should be accessing this content, you should take a look at using signed URLs instead, this would prevent someone guessing or somehow gaining access to a link you do not want them to have.
This warning is in place to protect sensitive data being left exposed to the world, which is recent times has caused large volumes of private company data to be leaked.

My AS3 Bucket Policy only applies to some Objects

I'm having a really hard time setting up my bucket policy, it looks like my bucket policy only applies to some objects in my bucket.
What I want is pretty simple: I store video files in the bucket and I want them to be exclusively downloadable from my webiste.
My approach is to block everything by default, and then add allow rules:
Give full rights to root and Alice user.
Give public access to files in my bucket from only specific referers (my websites).
Note:
I manually made all the objects 'public' and my settings for Block Public Access are all set to Off.
Can anyone see any obvious errors in my bucket policy?
I don't understand why my policy seems to only work for some files.
Thank you so much
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::MY_BUCKET/*",
"Condition": {
"StringNotLike": {
"aws:Referer": [
"https://mywebsite1.com/*",
"https://mywebsite2.com/*"
]
}
}
},
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::MY_BUCKET/*",
"Condition": {
"StringLike": {
"aws:Referer": [
"https://mywebsite1.com/*",
"https://mywebsite2.com/*"
]
}
}
},
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::426873019732:root",
"arn:aws:iam::426873019732:user/alice"
]
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::MY_BUCKET",
"arn:aws:s3:::MY_BUCKET/*"
]
}
]
}
Controlling access via aws:Referer is not secure. It can be overcome quite easily. A simple web search will provide many tools that can accomplish this.
The more secure method would be:
Keep all objects in your Amazon S3 bucket private (do not "Make Public")
Do not use a Bucket Policy
Users should authenticate to your application
When a user wishes to access one of the videos, or when your application creates an HTML page that refers/embeds a video, the application should determine whether the user is entitled to access the object.
If the user is entitled to access the object, the application creates an Amazon S3 pre-signed URL, which provides time-limited access to a private object.
When the user's browser requests to retrieve the object via the pre-signed URL, Amazon S3 will verify the contents of the URL. If the URL is valid and the time limit has not expired, Amazon S3 will return the object (eg the video). If the time has expired, the contents will not be provided.
The pre-signed URL can be created in a couple of lines of code and does not require and API call back to Amazon S3.
The benefit of using pre-signed URLs is that your application determines who is entitled to view objects. For example, a user could choose to share a video with another user. Your application would permit the other user to view this shared video. It would not require any changes to IAM or bucket policies.
See: Amazon S3 pre-signed URLs
Also, if you wish to grant access to an Amazon S3 bucket to specific IAM Users (that is, users within your organization, rather than application users), it is better to grant access on the IAM User rather than via an Amazon S3 bucket. If there are many users, you can create an IAM Group that contains multiple IAM Users, and then put the policy on the IAM Group. Bucket Policies should generally be used for granting access to "everyone" rather than specific IAM Users.
In general, it is advisable to avoid using Deny policies since they can be difficult to write correctly and might inadvertently deny access to your Admin staff. It is better to limit what is being Allowed, rather than having to combine Allow and Deny.

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.