简体   繁体   中英

Signed URLs in CloudFront with wildcards

I'm using PHP to sign URLs to access my S3 bucket through CloudFront, signing individual files works fine using the code below. But after generating the string with a wildcard with is substituted for the the actual filename, eg index.html or main.css in the URL (according to the documentation here ) but access is denied.

<?php 

function getSignedURL($resource, $timeout)
{
//This comes from key pair you generated for cloudfront
$keyPairId = "MYKEYPAIR";

$expires = time() + $timeout; //Time out in seconds
$json = '{"Statement":[{"Resource":"'.$resource.'","Condition":{"DateLessThan":{"AWS:EpochTime":'.$expires.'}}}]}';     

//Read Cloudfront Private Key Pair
$fp=fopen("aws.pem","r"); 
$priv_key=fread($fp,8192); 
fclose($fp); 

//Create the private key
$key = openssl_get_privatekey($priv_key);
if(!$key)
{
    echo "<p>Failed to load private key!</p>";
    return;
}

//Sign the policy with the private key
if(!openssl_sign($json, $signed_policy, $key, OPENSSL_ALGO_SHA1))
{
    echo '<p>Failed to sign policy: '.openssl_error_string().'</p>';
    return;
}

//Create url safe signed policy
$base64_signed_policy = base64_encode($signed_policy);
$signature = str_replace(array('+','=','/'), array('-','_','~'), $base64_signed_policy);

//Construct the URL
$url = $resource.'?Expires='.$expires.'&Signature='.$signature.'&Key-Pair-Id='.$keyPairId;

return $url;
}

$url = getSignedURL("http://cdn.mydomain.com/path/*", 3000);
print_r($url);

?>

My bucket policy is as follows:

{
"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:::bucketname/*"
    }
]
}

Any help would be appreciated.

Are you using a canned or a custom policy? I found that you cannot use wildcard URLs unless you're using a custom policy, so give that a try.

This is way old, but I found it through a Google search and eventually figured out the answer based off of a hint in Mark's answer so I figured I'd share in case some other future person stumbles across this question.

I went back to the CF docs ( https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-creating-signed-url-custom-policy.html ) and read a little more carefully for a policy to be a "custom policy" you have to include the actual base64-encoded policy as its own kv-pair in the query string.

I'm not super experienced in php, but probably editing your code to be something like:

$url = $resource.'?Expires='.$expires.'&Policy='.$base64_signed_policy.'&Signature='.$signature.'&Key-Pair-Id='.$keyPairId;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM