title: AWS Lambda Access Denied on Pre-Signed CloudFront URL
body: <p>I was following the guide from <a href="https://docs.aws.amazon.com/solutions/latest/serverless-image-handler/deployment.html" rel="nofollow noreferrer">https://docs.aws.amazon.com/solutions/latest/serverless-image-handler/deployment.html</a> to create a new Lambda Function over my CloudFront distribution. However, I have an extra requirement to only use the <strong>pre-signed URLs</strong>. The idea is that my service generates the <code>CloudFront pre-signed URL</code> and gives that URL to the client to access it. However, client should be able to invoke the Lambda Function on that URL.</p>
  
  <p>For example the following should be possible:</p>
  
  <ul>
  <li>Service returns the URL <code>https://dfg565mo4z0svb.cloudfront.net/portrait.jpeg?Expires=1540724061&amp;Signature=VLfwYdHrLM91wzFyOg0S3C6PKkKWghfOiZzt1-ew~gt0HPK~Sap0~5PHVHCEDHgHIQfwb0~oAZQ1igOOiRigzMTQ-ew~uSIR7-dsd~QJlAuceO5f2cDB2hopC5~trEgRTMnQSozPlbrFSwthveVBlZPVI3s2YapZgC7pqZB08IKIYtcXKjRfMPkxgumV5P-~Dj7rK5fdfvLyvTUTxIwrt3WLndOydBjxxUsL-6D-Hkdz8uWi6u59-sg__&amp;Key-Pair-Id=BPKDVBLKFPWSDLIAXN8I
  </code></li>
  <li>The client should be able to invoke Lambda like this: <code>https://dfg565mo4z0svb.cloudfront.net/fit-in/100x100/portrait.jpeg?Expires=1540724061&amp;Signature=VLfwYdHrLM91wzFyOg0S3C6PKkKWghfOiZzt1-ew~gt0HPK~Sap0~5PHVHCEDHgHIQfwb0~oAZQ1igOOiRigzMTQ-ew~uSIR7-dsd~QJlAuceO5f2cDB2hopC5~trEgRTMnQSozPlbrFSwthveVBlZPVI3s2YapZgC7pqZB08IKIYtcXKjRfMPkxgumV5P-~Dj7rK5fdfvLyvTUTxIwrt3WLndOydBjxxUsL-6D-Hkdz8uWi6u59-sg__&amp;Key-Pair-Id=BPKDVBLKFPWSDLIAXN8I
  </code> where <strong>/fit-in/100x100/</strong> is the Lambda Function.</li>
  </ul>
  
  <p>All of that works by the default, but if I set the <strong>Restrict Viewer Access
  (Use Signed URLs or Signed Cookies)</strong> option under Origin Behaviour to <strong>Yes</strong>, then suddenly any call to my Lambda Function returns the <strong>Access Denied</strong> response.</p>
  
  <p><strong>IAM Policy of the Role that my Lambda Function is using</strong></p>
  
  <pre><code>    {
      "Version": "2012-10-17",
      "Statement": [
          {
              "Effect": "Allow",
              "Action": [
                  "logs:CreateLogGroup",
                  "logs:CreateLogStream",
                  "logs:PutLogEvents"
              ],
              "Resource": "arn:aws:logs:*:*:*"
          },
          {
              "Effect": "Allow",
              "Action": [
                  "s3:PutObject",
                  "s3:GetObject"
              ],
              "Resource": "arn:aws:s3:::myBucket/*"
          }
      ]
  }
  </code></pre>
  
  <p><strong>Bucket Policy</strong></p>
  
  <pre><code>    {
      "Version": "2008-10-17",
      "Id": "PolicyForCloudFrontPrivateContent",
      "Statement": [
          {
              "Sid": "1",
              "Effect": "Allow",
              "Principal": {
                  "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity EN2PJ6YY7V8EE"
              },
              "Action": "s3:GetObject",
              "Resource": "arn:aws:s3:::myBucket/*"
          },
          {
              "Sid": "2",
              "Effect": "Allow",
              "Principal": {
                  "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E2EM2OLBKAK85T"
              },
              "Action": "s3:GetObject",
              "Resource": "arn:aws:s3:::myBucket/*"
          }
      ]
  }
  </code></pre>
  
  <p>How can I use the presigned URLs with Lambda?</p>