1
votes

I am trying to serve content using a Cloudfront private distribution with a S3 bucket as my origin.

I have an image file in my bucket for testing purposes with it's permissions set to private. I have set up my bucket policy so the Cloudfront Origin Access Identity has get permissions

{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
    {
        "Sid": "1",
        "Effect": "Allow",
        "Principal": {
            "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity **************"
        },
        "Action": "s3:GetObject",
        "Resource": "arn:aws:s3:::studeersnel.{{my-bucket}}/*"
    }
]
}

When I have set my Cloudfront distribution to public (without using signed urls) it works fine. The object can't be accessed with the direct S3 link, but it can be accessed using the Cloudfront url.

Now when I set "Restrict Viewer Access (Use Signed URLs)" to "Yes" under "Default Cache Behavior Settings", it doesn't work anymore. I get a 403 error. If I follow the signed url I get this message:

<Error>
  <Code>AccessDenied</Code>
  <Message>Access denied</Message>
</Error>

I am using the php-sdk to create my signed url's using the following code:

require '../vendor/autoload.php';

use Aws\CloudFront\CloudFrontClient;

$cloudFront = CloudFrontClient::factory(array(
    'key' => '********************',
    'secret' => '****************************************',
    'private_key' => '../pk-********************.pem',
    'key_pair_id' => '********************',
));

$hostUrl = 'http://**************.cloudfront.net';
$resourceKey = 'desert.jpg';
$expires = time() + 300;

$signedUrl = $cloudFront->getSignedUrl(array(
    'url'     => $hostUrl . '/' . $resourceKey,
    'expires' => $expires,
));

echo $signedUrl.'<br><br>';
echo '<img src="' . $signedUrl . '">';

Any ideas what I'm doing wrong?

1
Is the bucket owner the owner of the object? The reason I ask is bucket policies only apply if the bucket owner is the owner of the object.imperalix
On both the bucket and the object it says "Owner: Me". I have used the same IAM account to create both, not the root account. I have also tried giving CloudFront Origin Access Identity ************** explicit Open/Download permission on the object, but that didn't help either.Lucas H
You didn't mention you have added Trusted Signers in CloudFront settings (take a look here: docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/…). You need to do it to let CloudFront know which signatures to trustAlex Z
I left the "Trusted Signers" setting on "Self". I used the root account to make the CloudFront Key Pairs. I tried adding the account number to the trusted signers anyway, but it appears that it recognizes that this number is my own account and the setting just reverts to Self.Lucas H

1 Answers

1
votes

Fixed the problem today, so thought I'd post the solution here if anyone runs into the same issue.

I figured that it must be a problem with the generation of the url itself, so went over the credentials once more. After checking everything I decided to try and create a new Cloudfront key pair. For some reason this has fixed the problem.