class Aws::CF::Signer
Attributes
Public: Provides a configuration option that sets the default_expires
in milliseconds
Examples
Aws::CF::Signer.configure do |config| config.default_expires = 3600 end
Returns nothing.
Public: Provides a configuration option to set the key_pair_id
if it has not been inferred from the key_path
Examples
Aws::CF::Signer.configure do |config| config.key_pair_id = "XXYYZZ" end
Returns a String value indicating the current setting
Public: Provides an accessor to the key_path
Returns a String value indicating the current setting
Public Class Methods
Public: Builds a signed url or stream resource name with optional configuration and policy options
Returns a String
# File lib/cloudfront-signer.rb, line 180 def self.build_url(original_subject, configuration_options = {}, policy_options = {}) subject = original_subject.dup # If the url or stream path already has a query string parameter - # append to that. separator = subject =~ /\?/ ? '&' : '?' subject.gsub!(/\s/, '%20') if configuration_options[:remove_spaces] subject = URI.escape(subject) if configuration_options[:uri_escape] result = subject + separator + signed_params(subject, policy_options).collect do |key, value| "#{key}=#{value}" end.join('&') if configuration_options[:html_escape] return html_encode(result) else return result end end
Public: Provides a simple way to configure the signing class.
Yields self.
Examples
Aws::CF::Signer.configure do |config| config.key_path = "/path/to/yourkeyfile.pem" config.key_pair_id = "XXYYZZ" config.default_expires = 3600 end
Returns nothing.
# File lib/cloudfront-signer.rb, line 104 def self.configure yield self if block_given? unless key_path || private_key fail ArgumentError, 'You must supply the path to a PEM format RSA key pair.' end unless @key_pair_id @key_pair_id = extract_key_pair_id(key_path) fail ArgumentError, 'The Cloudfront signing key id could not be inferred from ' \ "#{key_path}. Please supply the key pair id as a " \ 'configuration argument.' unless @key_pair_id end end
Public: Provides an accessor to the default_expires
value
Returns an Integer value indicating the current setting
# File lib/cloudfront-signer.rb, line 77 def default_expires @default_expires ||= 3600 end
Public: Provides a configuration check method which tests to see that the key_path
, key_pair_id
and private key values have all been set.
Returns a Boolean value indicating that settings are present.
# File lib/cloudfront-signer.rb, line 125 def self.is_configured? (key_pair_id.nil? || private_key.nil?) ? false : true end
Public: Provides a configuration option to set the key directly as a string e.g. as an ENV var
Examples
Aws::CF::Signer.configure do |config| config.key = ENV.fetch('KEY') end
Returns nothing.
# File lib/cloudfront-signer.rb, line 53 def key=(key) @key = OpenSSL::PKey::RSA.new(key) end
Public: Provides a configuration option that sets the key_path
Examples
Aws::CF::Signer.configure do |config| config.key_path = "/path/to/your/keyfile.pem" end
Returns nothing.
# File lib/cloudfront-signer.rb, line 35 def key_path=(path) unless File.exist?(path) fail ArgumentError, "The signing key could not be found at #{path}" end @key_path = path self.key = File.readlines(path).join('') end
Public: Sign a stream path part or filename (spaces are allowed in stream paths and so are not removed).
Returns a String
# File lib/cloudfront-signer.rb, line 156 def self.sign_path(subject, policy_options = {}) build_url subject, { remove_spaces: false }, policy_options end
Public: Sign a stream path or filename but URI encode the string first
Returns a String
# File lib/cloudfront-signer.rb, line 172 def self.sign_path_escaped(subject, policy_options = {}) build_url subject, { uri_escape: true }, policy_options end
Public: Sign a stream path or filename and HTML encode the result.
Returns a String
# File lib/cloudfront-signer.rb, line 163 def self.sign_path_safe(subject, policy_options = {}) build_url subject, { remove_spaces: false, html_escape: true }, policy_options end
Public: Sign a url - encoding any spaces in the url before signing. CloudFront stipulates that signed URLs must not contain spaces (as opposed to stream paths/filenames which CAN contain spaces).
Returns a String
# File lib/cloudfront-signer.rb, line 134 def self.sign_url(subject, policy_options = {}) build_url subject, { remove_spaces: true }, policy_options end
Public: Sign a url (as above) but URI encode the string first.
Returns a String
# File lib/cloudfront-signer.rb, line 148 def self.sign_url_escaped(subject, policy_options = {}) build_url subject, { uri_escape: true }, policy_options end
Public: Sign a url (as above) and HTML encode the result.
Returns a String
# File lib/cloudfront-signer.rb, line 141 def self.sign_url_safe(subject, policy_options = {}) build_url subject, { remove_spaces: true, html_escape: true }, policy_options end
Public: Sign a subject url or stream resource name with optional policy options. It returns raw params to be used in urls or cookies
Returns a Hash
# File lib/cloudfront-signer.rb, line 206 def self.signed_params(subject, policy_options = {}) result = {} if policy_options[:policy_file] policy = IO.read(policy_options[:policy_file]) result['Policy'] = encode_policy(policy) else policy_options[:expires] = epoch_time(policy_options[:expires] || Time.now + default_expires) if policy_options.keys.size <= 1 # Canned Policy - shorter URL expires_at = policy_options[:expires] policy = %{{"Statement":[{"Resource":"#{subject}","Condition":{"DateLessThan":{"AWS:EpochTime":#{expires_at}}}}]}} result['Expires'] = expires_at else # Custom Policy resource = policy_options[:resource] || subject policy = generate_custom_policy(resource, policy_options) result['Policy'] = encode_policy(policy) end end result.merge 'Signature' => create_signature(policy), 'Key-Pair-Id' => @key_pair_id end
Private Class Methods
# File lib/cloudfront-signer.rb, line 273 def self.create_signature(policy) url_encode Base64.encode64( private_key.sign(OpenSSL::Digest::SHA1.new, (policy)) ) end
# File lib/cloudfront-signer.rb, line 269 def self.encode_policy(policy) url_encode Base64.encode64(policy) end
# File lib/cloudfront-signer.rb, line 258 def self.epoch_time(timelike) case timelike when String then Time.parse(timelike).to_i when Time then timelike.to_i when Integer then timelike else fail ArgumentError, 'Invalid argument - String, Integer or Time required - ' \ "#{timelike.class} passed." end end
# File lib/cloudfront-signer.rb, line 279 def self.extract_key_pair_id(key_path) File.basename(key_path) =~ /^pk-(.*).pem$/ ? Regexp.last_match[1] : nil end
# File lib/cloudfront-signer.rb, line 235 def self.generate_custom_policy(resource, options) conditions = { 'DateLessThan' => { 'AWS:EpochTime' => epoch_time(options[:expires]) } } conditions['DateGreaterThan'] = { 'AWS:EpochTime' => epoch_time(options[:starting]) } if options[:starting] conditions['IpAddress'] = { 'AWS:SourceIp' => options[:ip_range] } if options[:ip_range] { 'Statement' => [{ 'Resource' => resource, 'Condition' => conditions }] }.to_json end
# File lib/cloudfront-signer.rb, line 288 def self.html_encode(s) s.gsub('?', '%3F').gsub('=', '%3D').gsub('&', '%26') end
Private: Provides an accessor to the RSA key value
Returns an RSA key pair.
# File lib/cloudfront-signer.rb, line 86 def private_key @key end
# File lib/cloudfront-signer.rb, line 283 def self.url_encode(s) s.gsub('+', '-').gsub('=', '_').gsub('/', '~').gsub(/\n/, '') .gsub(' ', '') end