11
votes

I'm configuring an environment with a Amazon S3 Bucket for storage of media files and Amazon CloudFront for restricted distribution purposes.

The access to those media files needs to be private and should be done via a signed URL. So I created the S3 Bucket on South America (São Paulo) region and uploaded some test files. Then I created a CloudFront Distribution with that previous bucket as Origin and it's Bucket Access is restricted. I created a new OAI (Origin Access Identity) and also selected the option Yes, Update Bucket Policy so that it auto-configures the S3 Bucket Policies. I'm only using the default Behavior and it's configured with HTTP and HTTPS viewer protocol policy and GET, HEAD allowed methods. Restrict Viewer Access (Use Signed URLs or Signed Cookies) is set and the Trusted Signer is set to Self.

Here's some images to clarify the setup:

S3 Bucket Policy S3 Bucket Policy

Distribution's Origin Distribution's Origin

Distribution's Behavior Distribution's Behavior

I'm getting a HTTP 403 while trying to access the signed URL generated with either awscli or cfsign.pl

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

Is there something missing that I don't know? It looks like I made everything the docs said to do.

4

4 Answers

5
votes

I received the same Access Denied error and spent the last couple hours trying to figure out what was going on. I finally realized that the Expires parameter was set in the past since I was using my local time instead of UTC. Make sure to set the Expires in the future according to UTC.

4
votes

In my case the problem was with URL I was passing to URL signing code (I was using AWS SDK for Node.js).

cloudFront.getSignedUrl({
  url: `${distributionUrl}/${encodeURI(key)}`,
  expires: Math.floor(new Date().getTime() / 1000) + 60 * 60
})

Note encodeURI. I was not doing that. The resulting signed URL would still have URI components encoded, BUT would have invalid signature, thus causing 403 error.

EDIT: ...And you have to wrap it into url.format() like this:

cloudFront.getSignedUrl({
  url: url.format(`${distributionUrl}/${encodeURI(key)}`),
  expires: Math.floor(new Date().getTime() / 1000) + 60 * 60
})

I guess they should be doing that in SDK.

3
votes

After recreating both the Amazon S3 Bucket and Amazon CloudFront Distribution I was still experiencing the issue. After a session with my rubber duck I found out that the Private Key file that I was using belongs to a deleted CloudFront Key-pair.

Now that I'm using the correct key to encrypt things everything is working fine. That doesn't explain why the first bucket and distribution weren't working because in that specific case I was using the same set of configurations and the right Private Key file.

1
votes

I also encountered the same issue. Probably, we have to re-generate Clouf Front key-pair.