title: AWS CloudFront Returns Access Denied from S3 Origin with Query String
body: <p>I have setup a CloudFront distribution and a Lambda@Edge function as described in this article:</p>
  
  <p><a href="https://aws.amazon.com/blogs/networking-and-content-delivery/resizing-images-with-amazon-cloudfront-lambdaedge-aws-cdn-blog/" rel="noreferrer">https://aws.amazon.com/blogs/networking-and-content-delivery/resizing-images-with-amazon-cloudfront-lambdaedge-aws-cdn-blog/</a></p>
  
  <p>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.</p>
  
  <p>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.</p>
  
  <p>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</p>
  
  <p>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</p>
  
  <p><strong>Update</strong></p>
  
  <p>Example of working URL: <code>http://&lt;my_distro&gt;.cloudfront.net/images/house.jpeg</code></p>
  
  <p>Example of broken URL: <code>http://&lt;my_distro&gt;.cloudfront.net/images/house.jpeg?size=1200</code></p>