Amazon Cloudfront URL Signing, Rails, and JWPlayer
Most folks are aware of Amazon S3’s file system storage. One use case for S3 (Cloudfront) that we found handy was streaming video content. Now, if you use a provider such as Vimeo (and a handful of others that we tested) they work well but unfortunately security isn’t necessarily their strong suit. If you were to say, secure the video by only allowing embedding by a specific domain, a user can spoof the Referer header as originating from the “secure” domain and bypass those restrictions. There were other security issues we found with those services and suffice it to say, this was the best alternative for our needs.
Once again, we want to stream videos but we would like to do this with a reasonable level of security. For our use case, we needed this functionality within a Rails application so that JWPlayer had an endpoint to stream from. We leveraged the aws_cf_signer gem to accomplish this goal.
First, we’ll make an entry inside of our Gemfile:
Next, we need to have our private key leveraged for signing URL(s), more information can be found on Amazon’s site. Once you have designated your trusted signer and obtained the private key, we can configure our
Create a configuration file under config/initializers:
After doing this, we can leverage the constant (SIGNER) when signing Cloudfront URL(s).
The trick with Cloudfront is that it is really a distribution center for content housed on S3. We want to restrict access by the general public to that S3 bucket while still allowing Cloudfront to grab content.
Why RTMP and Web? The answer is simple, sometimes you feel like Flash, sometimes you don’t. In our case, we use both (to support Flash-incapable devices). This means not only do you need to setup two separate distribution centers but it also requires you to sign the URLs for each distro center differently.
After this step, your distribution center is created and Amazon gives you instructions on a 2-step process for securing your S3 bucket.
Assuming you’ve done everything correctly, you should now be able to access your content via signed URL(s).
Lets create some methods for signing URL(s):
The key part of this is understanding that the signing is different between RTMP and Web. Quick breakdown:
RTMP - The path portion (not the full URL) is signed Web - The entire URL is signed
Last bit is that you need to have JWPlayer (or some other player) stream this content: