S3 Access Denied - Bucket owner can't download objects owned by CloudFront - amazon-web-services

I have an IAM user that owns the the S3 bucket.
Also, I've been using CloudFront to upload some files to S3.
I just reliased that the Bucket Owner IAM User can't download the objects that are created by CloudFront - It says Access Denied.
Some potential solutions might be:
Is there a way to enforce bucket owner to be able to download all files?
Is there a way to give IAM user a permission to own CloudFront CloudFront Origin Access Identity EY******** user?
My bucket policy looks like this:
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity EY********"
},
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListMultipartUploadParts",
"s3:AbortMultipartUpload",
"s3:PutObjectAcl",
"s3:PutObjectVersionAcl"
],
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
IAM user can't download this:
IAM user can download this

Seems like there was a settings for enforcing object ownership to be Bucket owner.

Related

Accessing a S3 bucket through client code is denied

I am trying to access and modify my s3 bucket through my web client. To do so, I've created a bucket and modified it in a way that it would allow public access.
My bucket policy:
{
"Version": "2012-10-17",
"Id": "Policy1646559824301",
"Statement": [
{
"Sid": "Stmt1646559821897",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::airsoftarmory-user-inventory/*"
}
]}
My CORS setting:
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"PUT",
"HEAD",
"GET"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": []
}]
ACL is enabled and looks like this:
For uploading an image to bucket, I created a new IAM user and a specific policy for putObject as follows:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::airsoftarmory-user-inventory/*"
}
]
}
Used access keys of this user with policy attached inside my code.
The problem is, I am getting access denied response while both uploading and downloading. Can someone help me, what am I missing?
For me to troubleshoot this problem.
I will check if aws has been configured properly. You could follow this guide, and could try aws sts get-caller-identity to check if credentials works properly.
The IAM role for the user is only given for PutObject, so this will not allow user to be able get any object out from the bucket. Try adding more permission to this user such as GetObject permission. This will give the user authority to pull out data from the bucket.
The bucket policy at the bucket only allow for GetObject and does not allow for any PutObject. Again try adding the PutObject action to the bucket policy. This might also be the problem facing now of not able to upload object to the bucket.
If you are confused with IAM and bucket policy. Try reading these blogs:
https://aws.amazon.com/blogs/security/iam-policies-and-bucket-policies-and-acls-oh-my-controlling-access-to-s3-resources/
https://binaryguy.tech/aws/s3/iam-policies-vs-s3-policies-vs-s3-bucket-acls/
Hope this helps!

access denied when I attempt to upload to s3 with a signed post could it be the bucket policy?

I have a s3 bucket which does not have public access. I have a bucket policy but it was automatically generated when I connected a CDN to the bucket for a origin access Identity.
But thats all the policy has.
Bucket polices are dicks for me. Im wondering if this is in fact the problem or if it may be something else.
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::shofi-mod/*"
}
]
}
for comparison here is the bucket policy of my other bucket that does have public access. I am looking at the two for clues of what it is I should do
{
"Version": "2012-10-17",
"Id": "",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam:::user/shofi-stuff-bucket-user"
},
"Action": [
"s3:ListBucket",
"s3:ListBucketVersions",
"s3:GetBucketLocation",
"s3:Get*",
"s3:Put*"
],
"Resource": "arn:aws:s3:::shofi-stuff"
}
]
}
thank you so much kings
There's a few topics here.
The first bucket policy you have shown simply grants access to CloudFront via an Allow policy. It would not interfere with the pre-signed URL.
The second bucket policy (while not being directly relevant to your question) has an error in it. When using GetObject and PutObject, access must be granted to the contents of the bucket, no the bucket itself. (Whereas ListBucket does apply to the bucket.)
Therefore, the Resource should grant access to the bucket and the contents of the bucket:
"Resource": ["arn:aws:s3:::shofi-stuff", "arn:aws:s3:::shofi-stuff/*"]
As to why your pre-signed URL is not working, it would either be due to:
The underlying credentials (IAM User, IAM Role) that was used to generate the pre-signed URL does not have permission to perform the upload (perhaps due to a similar Resource problem), or
The pre-signed URL is being incorrectly generated

Disallow a user to list directory contents of S3 bucket

I am attempting to allow multiple users access to a single S3 bucket. However they should only have access to a particular directory in that bucket.
Imagine the following
my-bucket
- client-1
- important-doc.txt
- client-2
- somefile.jpg
- my-own-file.js
With that in mind (allowing say, client-1 access to only that directory) I have the following policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::my-bucket"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::my-bucket/client-1/*"
}
]
}
This works as you would expect, client-1 can connect to the bucket, go to their particular directory and download. However it appears they have the ability to list the directory of the entire bucket, I assume due to the s3:ListBucket permission being allowed. But if I restrict that to only the folder my Transmit app notifies me that permission is denied.
Can anyone advise me how to correctly write this permission?
The first choice is how to track and authenticate the users.
Option 1: IAM Users
Normally, IAM User credentials are given to employees and applications. Policies can be applied directly against IAM Users to grant them access to resources.
In the case of granting IAM Users access to specific folders within an Amazon S3 bucket, the easiest method would be to put these users into an IAM Group and then author a policy that uses IAM Policy Variables that can automatically insert the name of the IAM User into the policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": ["s3:ListBucket"],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::mybucket"],
"Condition": {"StringLike": {"s3:prefix": ["${aws:username}/*"]}}
},
{
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::mybucket/${aws:username}/*"]
}
]
}
There is a limit of 5000 IAM Users in an AWS Account.
Option 2: Temporary credentials
Rather than giving IAM User 'permanent' credentials, the AWS Security Token Service (STS) can issue temporary credentials with an assigned permission policy.
The flow would typically be:
Users authenticate themselves to your app (eg using your own database of users, or federated access from Active Directory, or even an OpenID service)
Your back-end app then generates temporary credentials with the appropriate permissions (such as the policy you have shown in #jellcsc's answer)
The app provides these credentials to the users (or their app)
The users use these credentials to access the permitted AWS services
The credentials expire after a period of time and the users must reconnect to your app to obtain a new set of temporary credentials.
This is more secure because the app is responsible for ensuring authentication and granting permissions. There is less risk of accidentally granting permissions to a set of users.
Option 3: Pre-signed URLs
When a web application wishes to allow access to private objects in Amazon S3, it can generate an Amazon S3 pre-signed URLs, which is a time-limited URL that provides temporary access to a private object. It works like this:
Users authenticate to the web app
When the back-end is rendering an HTML page and wants to include a reference to a private object (eg <img src='...'>, it generates a pre-signed URL that grants temporary access to a private object
When the user's browser sends the URL to S3, the signature is verified and the expiry time is checked. If it is valid, then S3 returns the object.
This is common in applications like photo-sharing systems where users might want to share photos with other users, so that the security is more complex than simply looking at the directory where the image is stored.
Bottom line
If you are using IAM Users, then use Option 1 and take advantage of IAM Policy Variables to write one policy that will grant appropriate access to each user. However, consider carefully whether giving IAM User access to external people is acceptable within your security posture.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::my-bucket",
"Condition": {
"StringEquals": {
"s3:prefix": [
"client-1"
],
"s3:delimiter": [
"/"
]
}
}
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::my-bucket",
"Condition": {
"StringLike": {
"s3:prefix": [
"client-1/*"
]
}
}
},
{
"Sid": "VisualEditor2",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::my-bucket/client-1/*"
}
]
}

AWS: Could not able to give s3 access via s3 bucket policy

I am the root user of my account and i created one new user and trying to give access to s3 via s3 bucket policy:
Here is my policy details :-
{  "Id": "Policy1542998309644",  "Version": "2012-10-17",  "Statement": [    {      "Sid": "Stmt1542998308012",      "Action": [        "s3:ListBucket"      ],      "Effect": "Allow",      "Resource": "arn:aws:s3:::aws-bucket-demo-1",      "Principal": {        "AWS": [          "arn:aws:iam::213171387512:user/Dave"        ]      }    }  ]}
in IAM i have not given any access to the new user. I want to provide him access to s3 via s3 bucket policy. Actually i would like to achieve this : https://aws.amazon.com/premiumsupport/knowledge-center/s3-console-access-certain-bucket/ But not from IAM , I want to use only s3 bucket policy.
Based on the following AWS blog post (the blog shows IAM policy, but it can be adapted to a bucket policy):
How can I grant a user Amazon S3 console access to only a certain bucket?
you can make the following bucket policy:
{
"Id": "Policy1589632516440",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1589632482887",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::aws-bucket-demo-1",
"Principal": {
"AWS": [
"arn:aws:iam::213171387512:user/Dave"
]
}
},
{
"Sid": "Stmt1589632515136",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::aws-bucket-demo-1/*",
"Principal": {
"AWS": [
"arn:aws:iam::213171387512:user/Dave"
]
}
}
]
}
This will require user to url directly to the bucket:
https://s3.console.aws.amazon.com/s3/buckets/aws-bucket-demo-1/
The reason is that the user does not have permissions to list all buckets available. Thus he/she has to go directly to the one you specify.
Obviously the IAM user needs to have AWS Management Console access enabled when you create him/her in the IAM service. With Programmatic access only, IAM users can't use console and no bucket policy can change that.
You will need to use ListBuckets.
It seems like you want this user to only be able to see your bucket but not access anything in it.

Remove AWS S3 bucket having Read by Everyone permission through Bucket policy

Suppose I have an S3 bucket that has "Everyone Read" permission. Bucket is not public. Means anyone can access objects by typing its url in the browser. Now I want to remove this access from URL thing in browser. One option is to go to each images and remove "Read" from "Everyone" section. But since there are huge amount of images so this is not feasible.
So can I put such bucket policy which allows access only from one IAM user and not from browser thing? I tried adding such bucket policy that allow access to all resources for only specific user but still images are accessible from browsing through URL. Any thoughts?
Edit: Adding policy that I tried
{
"Id": "Policy1",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1",
"Action": "s3:*",
"Effect": "Allow",
"Resource": "arn:aws:s3:::test-bucket-public-issue",
"Principal": {
"AWS": [
"arn:aws:iam::AccounId:user/Username"
]
}
}
]
}
Ok #Himanshu Mohan I will explain you what i have done. I have created a S3 bucket and then i added the below bucket policy
{
"Version": "2012-10-17",
"Id": "Policy1534419239074",
"Statement": [
{
"Sid": "Stmt1534419237657",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::xxx-xxx-test/*"
}
]
}
While adding this policy the bucket will automatically public
Then i have uploaded an image as what you referred and i was able to access the same image via browser.
Now I changed the policy back to as what you said
Now i was not able to access the image, will show the access denied xml response. The only difference i see is i have added the /* after the bucket name "Resource": "arn:aws:s3:::xxx-xxx-test/*".