I have setup a CloudFront distribution and a Lambda@Edge function as described in this article:
https://aws.amazon.com/blogs/networking-and-content-delivery/resizing-images-with-amazon-cloudfront-lambdaedge-aws-cdn-blog/
I now want to limit the S3 bucket to be private and only allow the CloudFront distribution access to the bucket. I've added an Origin Access Identity to the S3 Origin configuration, and updated the bucket policy to allow this OAI GetObject access to the bucket. I have removed the statement from the bucket policy that made it publicly readable, and changed the ACL to be private. If I do not include any query string parameters on the request to CloudFront, the image is returned as expected and the S3 link is not directly accessible.
However, the solution relies on passing in query parameters to resize the images on the fly (via 2 Lambda@Edge functions) and after making the bucket private I get an Access Denied 403 response from CloudFront.
I tried disabling forwarding of query strings which had no effect. I also tried only updating the bucket policy to remove public read access, and leave the ACL as PublicRead and it worked. So it makes me think something is up with the ACL being set to private
I was wondering if perhaps S3 is returning a 403 instead of a 404 when the bucket is made private? But then I don’t understand why adding the whitelisted query string param yields a different result to the request for the same image with no query string
Update
Example of working URL: http://<my_distro>.cloudfront.net/images/house.jpeg
Example of broken URL: http://<my_distro>.cloudfront.net/images/house.jpeg?size=1200
If your distribution doesn't have a default root object defined, and a requester doesn't have s3:ListBucket access, then the requester receives an Access Denied error. The requester gets this error instead of a 404 Not Found error when they request the root of your distribution.
If you're denied permissions, then use another IAM identity that has bucket access, and edit the bucket policy. Or, delete and recreate the bucket policy if no one has access to it. If you're trying to add a public read policy, then disable the bucket's S3 Block Public Access.
If you're getting Access Denied errors on public read requests that are allowed, check the bucket's Amazon S3 block public access settings. Review the S3 Block Public Access settings at both the account and bucket level. These settings can override permissions that allow public read access.
Step 1: enable CORS on your S3 bucketGo to your S3 bucket in the AWS (Amazon Web Services) console and select it. Click the Properties tab then open the Permissions area. You should see a button labelled 'Edit CORS Configuration' or something similar. Click it.
After investigating it turns out that if a bucket is private, then S3 will return a 403 instead of a 404 if an object does not exist in the bucket which makes sense from a security point of view (prevents object enumeration etc.).
The viewer request code in the Lambda from the blog post transformed the image url when the query string was present. If this image doesn't exist, it generates it on the fly. The origin response functino from the blog post is checking for a status of 404 in order to trigger the image resizing. However when the bucket is made private, the response is 403 so instead the Lambda@Edge just forwards the response. The fix is to either handle the 403 or make the bucket public. I've gone with the former
Lambda@Edge works with s3 via special user. So, you have to add rules in your s3 bucket policy, like this:
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity XXXXX"
},
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::xxx/*"
},
{
"Sid": "2",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity XXXX"
},
"Action": [
"s3:ListBucket"
],
"Resource": "arn:aws:s3:::xxxx"
}
]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With