Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cloudfront signed urls ip address

I have Signed URLs on Cloudfront working fine in PHP. Bucket policies work with HTTP referrers on S3 but because Cloudfront doesn't support HTTP referrer checks I need to serve a file to one IP address only (the client that requested the file and generated the signed URL or my web server ideally).

Can someone please help me add the IP Address element to the JSON code so it works?

"IpAddress":{"AWS:SourceIp":"192.0.2.0/24"},

I'm lost with the PHP and Policy Statement but think it might be easy for someone who knows: http://tinyurl.com/9czr5lp

It does encoding/signing a bit differently for a custom policy: http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/private-content-creating-signed-url-custom-policy.html#private-content-custom-policy-statement

The below is an AWS example and works except not for the IP Address lock in.

I can test this very quickly if someone can please give me a hand for two minutes!

Thanks MASSIVELY for any help :)

Jon

    function getSignedURL($resource, $timeout)
    {
        $keyPairId = "XXXXXXXXXXXX";
        $expires = time() + $timeout;
        $json = '{"Statement":[{"Resource":"'.$resource.'","Condition":{"DateLessThan":     {"AWS:EpochTime":'.$expires.'}}}]}';
        $fp=fopen("pk-XXXXXXXX.pem","r");

        $priv_key=fread($fp,8192);
        fclose($fp);

        $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://s675765.cloudfront.net/filename.mp4", 600);
print $url;
like image 882
Jon Ross Avatar asked Oct 29 '12 12:10

Jon Ross


1 Answers

{"Statement":[{"Resource":"testRes","Condition":{"DateLessThan":{"AWS:EpochTime":1357034400},"IpAddress":{"AWS:SourceIp":"192.0.2.0\/24"}}}]}

This is a valid JSON string with filled and escaped values. If you pass the IP address as a variable make sure you escape the /

e.g.

$escapedIp = str_replace( '/', '\/', $ipAddress );

Have a look at the php json extension This would make things quite easier:

example statement as php array

$statement = array( 
    'Statement' => array( 
        array(
            'Resource' => $resource, 
            'Condition' => array( 
                'DateLessThan' => array( 
                    'AWS:EpochTime' => $expires 
                ),
                'IpAddress' => array( 
                    'AWS:SourceIp' => $ipAddress 
                ) 
            ) 
        )
    ) 
);

$json = json_encode( $statement );
like image 190
Michel Feldheim Avatar answered Nov 01 '22 22:11

Michel Feldheim