Created
May 4, 2011 14:57
-
-
Save iHiD/955355 to your computer and use it in GitHub Desktop.
Ruby Signed Expiring Cloudfront URL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# A simple function to return a signed, expiring url for Amazon Cloudfront. | |
# As it's relatively difficult to figure out exactly what is required, I've posted my working code here. | |
# This will require openssl, digest/sha1, base64 and maybe other libraries. | |
# In my rails app, all of these are already loaded so I'm not sure of the exact dependencies. | |
module CloudFront | |
def get_signed_expiring_url(path, expires_in, private_key_filename, key_pair_id) | |
# AWS works on UTC, so make sure you are not using local time | |
expires = (Time.now.getutc + expires_in).to_i.to_s | |
private_key = OpenSSL::PKey::RSA.new(File.read(private_key_filename)) | |
# path should be your S3 path without a leading slash and without a file extension. | |
# e.g. files/private/52 | |
policy = %Q[{"Statement":[{"Resource":"#{path}","Condition":{"DateLessThan":{"AWS:EpochTime":#{expires}}}}]}] | |
signature = Base64.strict_encode64(private_key.sign(OpenSSL::Digest::SHA1.new, policy)) | |
# I'm not sure exactly why this is required, but it's in Amazon's perl script and seems necessary | |
# Different base64 implementations maybe? | |
signature.tr!("+=/", "-_~") | |
"#{path}?Expires=#{expires}&Signature=#{signature}&Key-Pair-Id=#{key_pair_id}" | |
end | |
end | |
# Sample implementation for returning either a publicly accessibly or a time-limited url | |
class Video | |
def get_url | |
if public? | |
self.path | |
else | |
CloudFront.get_signed_expiring_url(self.path, 45.seconds, "#{Rails.root}/config/cloudfront.pem", "xxxKEYPAIRIDxxx") | |
end | |
end | |
end |
Amazon uses their own version of URL-safe Base64 that also accounts for "=", the spec only accounts for "+" and "/", so you have to do the replacement yourself.
Also, this worked great, but only if I used the entire URL, not just the path - extension. Thanks!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@wweidendorf
urlsafe_encode64
complies with RFC 4648And actually looks like this in the source ... (see here) ... seems it doesn't replace '=' with '_'. I'll also point out that Amazon's sample PHP code replaces all three as well so I think it's safer to stick with what they do though I must admit I've not tested if it fails.