Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't access through S3 to files updated through CloudFront

I was using Cloud-Front to access files in my S3 bucket and update the files. I disable Cloud-Front now, however i cannot access those files directly through S3 now.

Also, when i try to set permissions on items in the bucket i receive a message that access was denied. I don't have such problem with items updated directly through S3.

How can i enable access to files in my bucket directly though s3?

like image 940
Erik Sapir Avatar asked Dec 20 '22 07:12

Erik Sapir


2 Answers

I had the same problem: Files created with Origin Access Identity weren't readable by the host account (or any user accounts) and couldn't be accessed via CLI, Lambda or the Console.

Solution

My solution was to set a header on the client request that allows control of the files by the bucket owner.

x-amz-acl=bucket-owner-full-control

This shouldn't require changes to your Cloudfront distribution. All x-amz-* headers should be passed through automatically.

I complemented this solution with a bucket policy that requires this header. So, people can't hack my client and upload files that I can't manage. The following is added to the policy statement object allowing s3:PutObject by the Origin Access Identity:

"Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": [
                        "bucket-owner-full-control"
                    ]
                }
            }

Explanation

The cause is described in Managing Access with ACLs.

For example, if a bucket owner allows other AWS accounts to upload objects, permissions to these objects can only be managed using object ACL by the AWS account that owns the object.

The only way I found to manage ACLs created by the Origin Access Identity is to set the x-amz-acl header at object creation time.

like image 53
Waylon Flinn Avatar answered Dec 21 '22 19:12

Waylon Flinn


An alternative to Waylon Flinn's answer is to add / overwrite the x-amz-acl header in a Lambda@Edge function. Something along these lines in nodejs:

exports.handler = (event, context, callback) => {
    const { request } = event.Records[0].cf;
    const { headers } = request;
    headers['x-amz-acl'] = [{key: 'x-amz-acl', value: 'bucket-owner-full-control'}];    
    callback(null, request);
};

The advantage is that you no longer need that policy Waylon writes in his answer since you always set the x-amz-acl header yourself in your own trusted environment. The downside is that Lambda@Edge comes with its own complexity, quirks, and extra costs. It is up to you to decide which approach is better for your use case.

Lambda@Edge was not available at all when Waylon wrote his answer back in 2016. It became generally available on Jul 17, 2017 (almost an year later): Lambda@Edge now Generally Available.

like image 39
Ali Avatar answered Dec 21 '22 21:12

Ali