5

Here is my sign URL function:

private function signUrl($lesson) {
        $cloudFrontClient = AWS::createClient('CloudFront', [
          'region'  => '<my-region>',
          'version' => '2017-03-25' 
        ]);

        $streamHostUrl = 'https://<mydomain>.cloudfront.net';
        $resourceKey = $object->s3_video;
        $expires = time() + 300;

        // Create a signed URL for the resource using the canned policy
        $signedUrlCannedPolicy = $cloudFrontClient->getSignedUrl([
            'url'         => $streamHostUrl . '/' . $resourceKey,
            'expires'     => $expires,
            'private_key' => '<MY_PEM_FILE_PATH>',
            'key_pair_id' => '<KEY_PAIR_ID>'
        ]);

        return $signedUrlCannedPolicy;
    }

When clicking on the link I get this ambiguous error message, which can't really help me debug the problem:

 <Error><Code>AccessDenied</Code><Message>Access
 Denied</Message><RequestId>SOME_ID_HERE</RequestId><HostId>SOME_BASE64_HERE_NOT_READABLE</HostId></Error>

I wondered if there is some way to debug this, maybe in the AWS console or some API call?

funerr
  • 7,212
  • 14
  • 81
  • 129

2 Answers2

8

There's more in that error than you see. Your CloudFront signed URL is actually working. <HostId> and <RequestId> are not components in an Access Denied error from CloudFront. This error is coming from S3, after CloudFront accepts your signed request.

In the HTTP response headers, you should see...

Server: Amazon S3
x-amz-request-id: (same value as the XML RequestId)
x-amz-id-2: (same value as the XML HostId)

S3 is not allowing CloudFront to fetch your content.

See Using an Origin Access Identity to Restrict Access to Your Amazon S3 Content and verify your configuration.

Also review the steps in Amazon CloudFront Latency to set your Error Caching Minimim TTL for 403 errors to 0 seconds, otherwise you will continue to see the error for up to 5 minutes (the default) after you fix the issue.

If everything looks correct, you may want to review your S3 bucket logs to ensure that you are requesting the object that you intend to. In CloudFront origin settings, there is a value called Origin Path that should almost always be left blank. Putting a value there will cause CloudFront to ask for a different object than the URL makes it appear you are requesting, so this value is not commonly something that you should set to anything.

Michael - sqlbot
  • 169,571
  • 25
  • 353
  • 427
  • 1
    The problem was that my URL was pointing to a nonexistent file. But your answer may help other people who don't understand this error. If there will be a more easy way to check any error logs (maybe in the console) then I would love that update. – funerr Apr 09 '18 at 21:09
  • 1
    @funerr there isn't anything for this in the console. You have to enable logging and access the log files. You can change the nonexistent object reply from 403 `AccessDenied` to 404 `NoSuchKey` if you grant the Origin Access Identity the `s3:ListBucket` privilege, but that isn't recommended unless you also set create a [Default Root Object](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DefaultRootObject.html) -- otherwise accessing `/` returns a list of all your objects in the bucket, which is rarely something you would want. – Michael - sqlbot Apr 10 '18 at 00:10
  • I added a similar problem [here](https://stackoverflow.com/questions/51888056/how-long-does-an-s3-origin-take-to-allow-cloudfront-to-access) – Efren Aug 17 '18 at 03:37
  • @Michael-sqlbot omg you saved me a bunch of time! Just ran into this issue myself. My issue was that i needed to click Update Bucket policy radio button – 4308 Jan 26 '21 at 15:49
0

try

$signedUrlCannedPolicy = $cloudFrontClient->getSignedUrl([
        'url'  => "{$streamHostUrl} / {$resourceKey}",
        'expires'     => $expires,
        'private_key' => '<MY_PEM_FILE_PATH>',
        'key_pair_id' => '<KEY_PAIR_ID>'
    ]);
Anoop Babu
  • 178
  • 12