Reputation: 1753
i've have a folder named private
in my s3 bucket and the contents in that folder only accessed by authorised user (ie Public read access is disabled).
So i am generating sigened url's for accessing one of the object in that folder it works fine.
Here is the signed URL format
s3-<region>.amazonaws.com/<folder>/<imagename>??X-Amz-Content-Sha256=.......
Also i have created cloudfront distribution for the above s3 bucket for better performance.
here is the cloudfront url xxxxjjjj.cloudfront.net
So how can i serve my signed url with this cloudfront distribution??
When i try with this url
xxxxjjjj.cloudfront.net/<folder>/<imagename>??X-Amz-Content-Sha256=.......
I will get access denied error,i think this is not the right way to deliver the s3 signed url content with cloudfront distribution.
Using php laravel framework
Upvotes: 0
Views: 3131
Reputation: 1269
There is an easiest way to generate cloudfront Signed URL. There is a cloudfront signed URL signer on GitHub, edit the config and use it.
The package can be installed via Composer:
composer require dreamonkey/laravel-cloudfront-url-signer
2.The configuration file can optionally be published via:
php artisan vendor:publish --provider="Dreamonkey\CloudFrontUrlSigner\CloudFrontUrlSignerServiceProvider"
URL's can be signed with the sign method:
use CloudFrontUrlSigner;
CloudFrontUrlSigner::sign('https://myapp.com/resource');
Upvotes: 0
Reputation: 739
There is an example for what you are asking using PHP SDK in this link https://docs.aws.amazon.com/aws-sdk-php/v3/guide/service/cloudfront-signed-url.html
and here's the equivalent code in Larave (5.3) using custom policy:
public static function signedUrl($resourceKey) {
//$resourceKey = 'videos/example.mp4'
$baseUrl = 'https://xxxxjjjj.cloudfront.net';
$fullUrl = $baseUrl . '/' . $resourceKey;
$expires = time() + 300;
$customSigningPolicy = <<<POLICY
{
"Statement": [
{
"Resource": "{$fullUrl}",
"Condition": {
"DateLessThan": {"AWS:EpochTime": {$expires}}
}
}
]
}
POLICY;
// CloudFront Signed Urls
/** @var CloudFrontClient $cloudFront */
$cloudFront = \AWS::createClient('CloudFront');
$url = $cloudFront->getSignedUrl([
'url' => $fullUrl,
'policy' => $customSigningPolicy,
'key_pair_id' => 'YOUR_KEY_PAIR_ID',
'private_key' => '/path/to/your/cloudfront-private-key.pem'
]);
return $url;
}
P.S. I found a mistake in the aws example, since they used the $resourceKey as the Resource value in the policy which is not woking, what worked with me is to use the full url of the file.
Their code:
$resourceKey = 'videos/example.mp4';
$customPolicy = <<<POLICY
{
"Statement": [
{
"Resource": "{$resourceKey}",
"Condition": {
"IpAddress": {"AWS:SourceIp": "{$_SERVER['REMOTE_ADDR']}/32"},
"DateLessThan": {"AWS:EpochTime": {$expires}}
}
}
]
}
POLICY;
What Worked:
$resourceKey = 'videos/example.mp4'; // or $resourceKey = 'videos/*'; or $resourceKey = '*';
$fullUrl = $baseUrl . '/' . $resourceKey;
$customPolicy = <<<POLICY
{
"Statement": [
{
"Resource": "{$fullUrl}",
"Condition": {
"IpAddress": {"AWS:SourceIp": "{$_SERVER['REMOTE_ADDR']}/32"},
"DateLessThan": {"AWS:EpochTime": {$expires}}
}
}
]
}
POLICY;
Upvotes: 1
Reputation: 178956
Signed URLs for CloudFront use a different format and different credentials than signed URLs for S3.
Read Serving Private Content through CloudFront.
There is a laravel-url-signer on GitHub or you can write your own code from this example in the CloudFront docs.
For testing your CloudFront and S3 settings, you can use aws cloudfront sign ...
in aws-cli to generate a test signed URL.
Upvotes: 5