TGuimond TGuimond - 6 days ago 5
PHP Question

Access Denied - S3 resource using Pre Signed URL - PHP SDK

I am generating a Pre Signed URL to allow users to download files from an S3 Bucket. I am generating the URL's via the PHP SDK using the following code:

public static function get_content_link( $bucket, $key ) {

//check response code from AWS
require_once 'aws/aws-autoloader.php';

$s3 = new Aws\S3\S3Client([
'version' => 'latest',
'region' => 'eu-west-1',
'credentials' => [
'key' => 'MY-KEY',
'secret' => 'MY-SECRET',
],
]);

$cmd = $s3->getCommand('GetObject', [
'Bucket' => $bucket,
'Key' => $key
]);

$request = $s3->createPresignedRequest($cmd, '+500 minutes');

// Get the actual presigned-url
$presignedUrl = (string) $request->getUri();

return $presignedUrl;
}


The URLs are being returned as expected, for example:

https://s3-eu-west-1.amazonaws.com/MY-BUCKET-NAME/product/3166_1480009917388.mov?x-amz-content-sha256=unsigned-payload&x-amz-algorithm=aws4-hmac-sha256&x-amz-credential=akiaiqrmkn276hcpjkaq%2f20161127%2feu-west-1%2fs3%2faws4_request&x-amz-date=20161127t145603z&x-amz-signedheaders=host&x-amz-expires=30000&x-amz-signature=98eaef504f053ca56908ac49c6539c4a8b8e250d7d3a4a12460f4a806ec41c19


When I try to open any of the returned links in the browser I am getting an access denied error from S3:

<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>A37839BB23186F72</RequestId>
<HostId>
yvKTN+CN1TTNk2tqoxxm3MPOGTUSMaRYtbbEFeCzGP7ou5IYf37Z9uBESwUQWDIUR1GUuPbZyuM=
</HostId>
</Error>


The files that I want to provide access to are in a bucket which contains folders allowing public access, by the folder I am trying to access is private (called /product/). Our bucket policy looks like this:

{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "AllowPublicReadProxies",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::MY-BUCKET-NAME/proxies*"
},
{
"Sid": "AllowPublicReadThumbs",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::MY-BUCKET-NAME/thumbs*"
}
]
}


It is my understanding that the purpose of creating a Pre Signed URL is to allow unauthenticated users temporary access to protected files without having to modify the bucket or folder permissions.

Has anyone got any ideas as to what I have missed or done wrong?

Thanks!

Answer

Many thanks to @Michael-sqlbot for figuring this out for me.

It turns out I was forcing the entire URL to be lowercase when outputting the pre signed URL to the page, so AWS was returning an Access Denied error due to the fact that the resource technically didn't exist.

Comments