class Aws::CloudFront::UrlSigner


)
policy: policy.to_json
url = signer.signed_url(url,
)
private_key_path: “./cf_private_key.pem”
key_pair_id: “cf-keypair-id”,
signer = Aws::CloudFront::UrlSigner.new(
Allows you to create signed URLs for Amazon CloudFront resources

def canned_policy(resource, expires)

create canned policy that used for signing
def canned_policy(resource, expires)
  json_hash = {
    'Statement' => [
      'Resource' => resource,
        'Condition' => {
          'DateLessThan' => {'AWS:EpochTime' => expires}
        }
    ]
  }
  json_hash.to_json
end

def encode(policy)

def encode(policy)
  Base64.encode64(policy).gsub(/[+=\/]/, '+' => '-', '=' => '_', '/' => '~')
end

def initialize(options = {})

Options Hash: (**options)
  • :private_key_path (String) --
  • :private_key (String) --
  • :key_pair_id (String) --
def initialize(options = {})
  @key_pair_id = key_pair_id(options)
  @private_key = private_key(options)
end

def key_pair_id(options)

def key_pair_id(options)
  if options[:key_pair_id].nil? or options[:key_pair_id] == ''
    raise ArgumentError, ":key_pair_id must not be blank"
  else
    options[:key_pair_id]
  end
end

def private_key(options)

def private_key(options)
  if options[:private_key]
    options[:private_key]
  elsif options[:private_key_path]
    File.open(options[:private_key_path], 'rb') { |f| f.read }
  else
    msg = ":private_key or :private_key_path should be provided"
    raise ArgumentError, msg
  end
end

def resource(scheme, url)

prepare resource for signing
def resource(scheme, url)
  case scheme
  when 'http', 'http*', 'https' then url
  when 'rtmp'
    url_info = URI.parse(url)
    path = url_info.path
    path[0] = ''
    resource_content = "#{File.dirname(path)}/#{File.basename(path)}".gsub(' ', '/')
    if url_info.query
      "#{resource_content}?#{uri.query}"
    else
      resource_content
    end
  else
    msg = "Invaild URI scheme:#{scheme}.Scheme must be one of: http, https or rtmp."
    raise ArgumentError, msg
  end
end

def rtmp_url(uri)

create a relative signed URL for RTMP distribution
def rtmp_url(uri)
  result = uri.path.gsub(' ', '/')
  result[0] = ''
  if uri.query
    "#{result}?#{uri.query}"
  else
    result
  end
end

def sign_policy(policy)

create the signature string with policy signed
def sign_policy(policy)
  key = OpenSSL::PKey::RSA.new(@private_key)
  key.sign(OpenSSL::Digest::SHA1.new, policy)
end

def signature(params = {})

Options Hash: (**param)
  • :policy (String) --
  • :expires (Integer) --
  • :resource (String) --
def signature(params = {})
  signature_content = []
  if params[:policy]
    policy = params[:policy].gsub('/\s/s', '')
    signature_content << "Policy=#{encode(policy)}"
  elsif params[:resource] && params[:expires]
    policy = canned_policy(params[:resource], params[:expires])
    signature_content << "Expires=#{params[:expires]}"
  else
    msg = "Either a policy or a resource with an expiration time must be provided."
    raise ArgumentError, msg
  end
  signature_content << "Signature=#{encode(sign_policy(policy))}"
  signature_content << "Key-Pair-Id=#{@key_pair_id}"
  signature_content.join('&').gsub("\n", '')
end

def signed_url(url, params = {})

Options Hash: (**params)
  • :policy (String) --
  • :expires (Time, DateTime, Date, String, Integer) --

Parameters:
  • url (String) --
def signed_url(url, params = {})
  url_sections = url.split('://')
  if url_sections.length < 2
    raise ArgumentError, "Invaild URL:#{url}"
  end
  # removing wildcard character to get real scheme
  scheme = url_sections[0].gsub('*', '')
  uri = "#{scheme}://#{url_sections[1]}"
  signed_content = signature(
    :resource => resource(scheme, uri),
    :expires => time(params[:expires]),
    :policy => params[:policy]
  )
  start_flag = URI.parse(uri).query ? '&' : '?'
  uri = "#{uri}#{start_flag}#{signed_content}"
  if scheme == 'rtmp'
    rtmp_url(URI(uri))
  else
    uri
  end
end

def time(expires)

def time(expires)
  case expires
  when Time then expires.to_i
  when DateTime, Date then expires.to_time.to_i
  when String then Time.parse(expires).to_i
  when Integer, NIL then expires
  else
    msg = "expected a time value for :expires, got `#{expires.class}'"
    raise ArgumentError, msg
  end
end