1

I have followed these steps so far.

Setup a cloudfront distribution for web/http and its enabled.

Then i generated my CloudFront Key Pairs saved the file and uploaded to my server.

I have my Amazon SDK all setup to generate getSignedUrl and have the following code.

<?php
use Aws\CloudFront\CloudFrontClient;

$client = CloudFrontClient::factory(array(
    'private_key'    => dirname(__FILE__) . '/cloudfront/pk- my key here -.pem',
    'key_pair_id' => 'AWS Key'
));

$distributionUrl = '- my url here -.cloudfront.net';

$url = $client->getSignedUrl(array(
    'url'     => 'https://' . $distributionUrl . '/video.mp4',
    'expires' => time() + 3600
));

?>

<video width="320" height="240" controls>
  <source src="<?php echo $url; ?>" type="video/mp4">
  Your browser does not support the video tag.
</video>

Ok so it is generating a url but it wont play in the video player and if i view console in chrome it shows this error.

UPDATE i know have the ability to stream directly from cloudfront as long as my files are set to public i cannot get the getSignedUrl to work at all so frustrating.

Could someone help with this been trying to get something working for hours?

Thanks

user1503606
  • 3,872
  • 13
  • 44
  • 78

1 Answers1

1

The documentation from CloudFront found here gives an example on how to use cloudfront to serve streamable private content.

Create a URL Signature Using PHP

Any web server that runs PHP can use the PHP demo code to create policy statements and signatures for private CloudFront RTMP distributions. The sample creates a functioning web page with signed URL links that play a video stream using CloudFront streaming. To get the sample, download Signature Code for Video Streaming in PHP.


See this question for reference.


/**
 * Create a signed URL
 *
 * This method accepts an array of configuration options:
 * - url:       (string)  URL of the resource being signed (can include query string and wildcards). For example:
 *                        rtmp://s5c39gqb8ow64r.cloudfront.net/videos/mp3_name.mp3
 *                        http://d111111abcdef8.cloudfront.net/images/horizon.jpg?size=large&license=yes
 * - policy:    (string)  JSON policy. Use this option when creating a signed URL for a custom policy.
 * - expires:   (int)     UTC Unix timestamp used when signing with a canned policy. Not required when passing a
 *                        custom 'policy' option.
 *
 * @param array $options Array of configuration options used when signing
 *
 * @return string                   The file URL with authentication parameters.
 * @throws InvalidArgumentException if key_pair_id and private_key have not been configured on the client
 */
public function getSignedUrl(array $options)
{
    if (!$this->getConfig('key_pair_id') || !$this->getConfig('private_key')) {
        throw new InvalidArgumentException(
            'An Amazon CloudFront keypair ID (key_pair_id) and an RSA private key (private_key) is required'
        );
    }

    // Initialize the configuration data and ensure that the url was specified
    $options = Collection::fromConfig($options, null, array('url'));
    // Determine the scheme of the policy
    $urlSections = explode('://', $options['url']);
    // Ensure that the URL contained a scheme and parts after the scheme
    if (count($urlSections) < 2) {
        throw new InvalidArgumentException('Invalid URL: ' . $options['url']);
    }

    // Get the real scheme by removing wildcards from the scheme
    $scheme = str_replace('*', '', $urlSections[0]);
    $policy = $options['policy'] ?: $this->createCannedPolicy($scheme, $options['url'], $options['expires']);
    // Strip whitespace from the policy
    $policy = str_replace(' ', '', $policy);

    $url = Url::factory($scheme . '://' . $urlSections[1]);
    if ($options['policy']) {
        // Custom policies require that the encoded policy be specified in the URL
        $url->getQuery()->set('Policy', strtr(base64_encode($policy), '+=/', '-_~'));
    } else {
        // Canned policies require that the Expires parameter be set in the URL
        $url->getQuery()->set('Expires', $options['expires']);
    }

    // Sign the policy using the CloudFront private key
    $signedPolicy = $this->rsaSha1Sign($policy, $this->getConfig('private_key'));
    // Remove whitespace, base64 encode the policy, and replace special characters
    $signedPolicy = strtr(base64_encode($signedPolicy), '+=/', '-_~');

    $url->getQuery()
        ->useUrlEncoding(false)
        ->set('Signature', $signedPolicy)
        ->set('Key-Pair-Id', $this->getConfig('key_pair_id'));

    if ($scheme != 'rtmp') {
        // HTTP and HTTPS signed URLs include the full URL
        return (string) $url;
    } else {
        // Use a relative URL when creating Flash player URLs
        $url->setScheme(null)->setHost(null);
        // Encode query string variables for flash players
        $url = str_replace(array('?', '=', '&'), array('%3F', '%3D', '%26'), (string) $url);

        return substr($url, 1);
    }
}

/**
 * Sign a policy string using OpenSSL RSA SHA1
 *
 * @param string $policy             Policy to sign
 * @param string $privateKeyFilename File containing the OpenSSL private key
 *
 * @return string
 */
protected function rsaSha1Sign($policy, $privateKeyFilename)
{
    $signature = '';
    openssl_sign($policy, $signature, file_get_contents($privateKeyFilename));

    return $signature;
}

/**
 * Create a canned policy for a particular URL and expiration
 *
 * @param string $scheme  Parsed scheme without wildcards
 * @param string $url     URL that is being signed
 * @param int    $expires Time in which the signature expires
 *
 * @return string
 * @throws InvalidArgumentException if the expiration is not set
 */
protected function createCannedPolicy($scheme, $url, $expires)
{
    if (!$expires) {
        throw new InvalidArgumentException('An expires option is required when using a canned policy');
    }

    // Generate a canned policy
    if ($scheme == 'http' || $scheme == 'https') {
        $resource = $url;
    } elseif ($scheme == 'rtmp') {
        $parts = parse_url($url);
        $pathParts = pathinfo($parts['path']);
        // Add path leading to file, strip file extension, and add a query string if present
        $resource = ltrim($pathParts['dirname'] . '/' . $pathParts['filename'], '/')
            . (isset($parts['query']) ? "?{$parts['query']}" : '');
    } else {
        throw new InvalidArgumentException("Invalid URI scheme: {$scheme}. Must be one of http or rtmp.");
    }

    return sprintf(
        '{"Statement":[{"Resource":"%s","Condition":{"DateLessThan":{"AWS:EpochTime":%d}}}]}',
        $resource,
        $expires
    );
}
Community
  • 1
  • 1
majidarif
  • 18,694
  • 16
  • 88
  • 133