Skip to content

Instantly share code, notes, and snippets.

@tomtaylor
Created September 5, 2013 14:08
Show Gist options
  • Select an option

  • Save tomtaylor/6450580 to your computer and use it in GitHub Desktop.

Select an option

Save tomtaylor/6450580 to your computer and use it in GitHub Desktop.
Class to sign private CloudFront URLs, supporting passing Cache-Control and Content-Disposition headers through to S3.
class CloudfrontSigner
def initialize(distribution, private_key, key_pair_id)
@distribution = distribution
@private_key = OpenSSL::PKey::RSA.new(private_key)
@key_pair_id = key_pair_id
end
def signed_url(path, expires_at, options = {})
# AWS operates in UNIX time
expires_unix_time = expires_at.to_i.to_s
host = "#{@distribution}.cloudfront.net"
request_options = {}
request_options["response-cache-control"] = options[:cache_control] if options[:cache_control].present?
request_options["response-content-disposition"] = options[:content_disposition] if options[:content_disposition].present?
source_uri = Addressable::URI.new(
:host => host,
:path => path,
:scheme => "https"
)
source_uri.query_values = request_options if request_options.length > 0
signed_query = request_options.merge(
"Signature" => signature(source_uri.to_s, expires_unix_time),
"Expires" => expires_unix_time,
"Key-Pair-Id" => @key_pair_id,
)
signed_uri = source_uri.dup
signed_uri.query_values = signed_query
signed_uri.to_s
end
private
def signature(url, expires_unix_time)
policy = %Q[{"Statement":[{"Resource":"#{url}","Condition":{"DateLessThan":{"AWS:EpochTime":#{expires_unix_time}}}}]}]
sig = 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?
sig.tr!("+=/", "-_~")
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment