Class: RightAws::AwsUtils

Inherits:
Object
  • Object
show all
Defined in:
lib/awsbase/right_awsbase.rb

Overview

:nodoc:

Constant Summary collapse

TOKEN_GENERATOR_CHARSET =

Generates a token in format of:

1. "1dd8d4e4-db6b-11df-b31d-0025b37efad0 (if UUID gem is loaded)
2. "1287483761-855215-zSv2z-bWGj2-31M5t-ags9m" (if UUID gem is not loaded)
('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a
@@digest1 =
OpenSSL::Digest::Digest.new("sha1")
@@digest256 =

Some installation may not support sha256

OpenSSL::Digest::Digest.new("sha256") rescue nil

Class Method Summary collapse

Class Method Details

.allow_only(allowed_keys, params) ⇒ Object

Raises:



139
140
141
142
143
# File 'lib/awsbase/right_awsbase.rb', line 139

def self.allow_only(allowed_keys, params)
  bogus_args = []
  params.keys.each {|p| bogus_args.push(p) unless allowed_keys.include?(p) }
  raise AwsError.new("The following arguments were given but are not legal for the function call #{caller_method}: #{bogus_args.inspect}") if bogus_args.length > 0
end

.amz_escape(param) ⇒ Object



53
54
55
56
57
58
# File 'lib/awsbase/right_awsbase.rb', line 53

def self.amz_escape(param)
  param = param.flatten.join('') if param.is_a?(Array) # ruby 1.9.x Array#to_s fix
  param.to_s.gsub(/([^a-zA-Z0-9._~-]+)/n) do
    '%' + $1.unpack('H2' * $1.size).join('%').upcase
  end
end

.caller_methodObject



151
152
153
154
# File 'lib/awsbase/right_awsbase.rb', line 151

def self.caller_method
  caller[1]=~/`(.*?)'/
  $1
end

.content_md5(content) ⇒ Object

Calculates ‘Content-MD5’ header value for some content



47
48
49
# File 'lib/awsbase/right_awsbase.rb', line 47

def self.content_md5(content)
  Base64.encode64(Digest::MD5::new.update(content).digest).strip
end

.fix_headers(headers) ⇒ Object



75
76
77
78
79
80
81
82
83
# File 'lib/awsbase/right_awsbase.rb', line 75

def self.fix_headers(headers)
  result = {}
  headers.each do |header, value|
    next if !header.is_a?(String) || value.nil?
    header = header.downcase
    result[header] = value if result[header].right_blank?
  end
  result
end

.fix_service_params(service_hash, signature) ⇒ Object

Set a timestamp and a signature version



69
70
71
72
73
# File 'lib/awsbase/right_awsbase.rb', line 69

def self.fix_service_params(service_hash, signature)
  service_hash["Timestamp"] ||= utc_iso8601(Time.now) unless service_hash["Expires"]
  service_hash["SignatureVersion"] = signature
  service_hash
end

.generate_unique_tokenObject



166
167
168
169
170
171
172
173
174
# File 'lib/awsbase/right_awsbase.rb', line 166

def self.generate_unique_token
  time  = Time.now
  token = "%d-%06d" % [time.to_i, time.usec]
  4.times do
    token << "-"
    5.times { token << TOKEN_GENERATOR_CHARSET[rand(TOKEN_GENERATOR_CHARSET.size)] }
  end
  token
end

.mandatory_arguments(required_args, params) ⇒ Object

Raises:



145
146
147
148
149
# File 'lib/awsbase/right_awsbase.rb', line 145

def self.mandatory_arguments(required_args, params)
  rargs = required_args.dup
  params.keys.each {|p| rargs.delete(p)}
  raise AwsError.new("The following mandatory arguments were not provided to #{caller_method}: #{rargs.inspect}") if rargs.length > 0
end

.sign(aws_secret_access_key, auth_string) ⇒ Object



42
43
44
# File 'lib/awsbase/right_awsbase.rb', line 42

def self.sign(aws_secret_access_key, auth_string)
  Base64.encode64(OpenSSL::HMAC.digest(@@digest1, aws_secret_access_key, auth_string)).strip
end

.sign_request_v0(aws_secret_access_key, service_hash) ⇒ Object

Signature Version 0 A deprecated guy (should work till septemper 2009)



87
88
89
90
91
92
# File 'lib/awsbase/right_awsbase.rb', line 87

def self.sign_request_v0(aws_secret_access_key, service_hash)
  fix_service_params(service_hash, '0')
  string_to_sign = "#{service_hash['Action']}#{service_hash['Timestamp'] || service_hash['Expires']}"
  service_hash['Signature'] = AwsUtils::sign(aws_secret_access_key, string_to_sign)
  service_hash.to_a.collect{|key,val| "#{amz_escape(key)}=#{amz_escape(val.to_s)}" }.join("&")
end

.sign_request_v1(aws_secret_access_key, service_hash) ⇒ Object

Signature Version 1 Another deprecated guy (should work till septemper 2009)



96
97
98
99
100
101
# File 'lib/awsbase/right_awsbase.rb', line 96

def self.sign_request_v1(aws_secret_access_key, service_hash)
  fix_service_params(service_hash, '1')
  string_to_sign = service_hash.sort{|a,b| (a[0].to_s.downcase)<=>(b[0].to_s.downcase)}.to_s
  service_hash['Signature'] = AwsUtils::sign(aws_secret_access_key, string_to_sign)
  service_hash.to_a.collect{|key,val| "#{amz_escape(key)}=#{amz_escape(val.to_s)}" }.join("&")
end

.sign_request_v2(aws_secret_access_key, service_hash, http_verb, host, uri) ⇒ Object

Signature Version 2 EC2, SQS and SDB requests must be signed by this guy. See: docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/index.html?REST_RESTAuth.html

http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1928


107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/awsbase/right_awsbase.rb', line 107

def self.sign_request_v2(aws_secret_access_key, service_hash, http_verb, host, uri)
  fix_service_params(service_hash, '2')
  # select a signing method (make an old openssl working with sha1)
  # make 'HmacSHA256' to be a default one
  service_hash['SignatureMethod'] = 'HmacSHA256' unless ['HmacSHA256', 'HmacSHA1'].include?(service_hash['SignatureMethod'])
  service_hash['SignatureMethod'] = 'HmacSHA1'   unless @@digest256
  # select a digest
  digest = (service_hash['SignatureMethod'] == 'HmacSHA256' ? @@digest256 : @@digest1)
  # form string to sign
  canonical_string = service_hash.keys.sort.map do |key|
    "#{amz_escape(key)}=#{amz_escape(service_hash[key])}"
  end.join('&')
  string_to_sign = "#{http_verb.to_s.upcase}\n#{host.downcase}\n#{uri}\n#{canonical_string}"
  # sign the string
  signature      = amz_escape(Base64.encode64(OpenSSL::HMAC.digest(digest, aws_secret_access_key, string_to_sign)).strip)
  "#{canonical_string}&Signature=#{signature}"
end

.split_items_and_params(array) ⇒ Object



156
157
158
159
160
# File 'lib/awsbase/right_awsbase.rb', line 156

def self.split_items_and_params(array)
  items  = Array(array).flatten.compact
  params = items.last.kind_of?(Hash) ? items.pop : {}
  [items, params]
end

.URLencode(raw) ⇒ Object

From Amazon’s SQS Dev Guide, a brief description of how to escape: “URL encode the computed signature and other query parameters as specified in RFC1738, section 2.2. In addition, because the + character is interpreted as a blank space by Sun Java classes that perform URL decoding, make sure to encode the + character although it is not required by RFC1738.” Avoid using CGI::escape to escape URIs. CGI::escape will escape characters in the protocol, host, and port sections of the URI. Only target chars in the query string should be escaped.



134
135
136
137
# File 'lib/awsbase/right_awsbase.rb', line 134

def self.URLencode(raw)
  e = URI.escape(raw)
  e.gsub(/\+/, "%2b")
end

.utc_iso8601(time) ⇒ Object



35
36
37
38
39
40
# File 'lib/awsbase/right_awsbase.rb', line 35

def self.utc_iso8601(time)
  if    time.is_a?(Fixnum) then time = Time::at(time)
  elsif time.is_a?(String) then time = Time::parse(time)
  end
  time.utc.strftime("%Y-%m-%dT%H:%M:%S.000Z")
end

.xml_escape(text) ⇒ Object

:nodoc:



60
61
62
# File 'lib/awsbase/right_awsbase.rb', line 60

def self.xml_escape(text) # :nodoc:
  REXML::Text::normalize(text)
end

.xml_unescape(text) ⇒ Object

:nodoc:



64
65
66
# File 'lib/awsbase/right_awsbase.rb', line 64

def self.xml_unescape(text) # :nodoc:
  REXML::Text::unnormalize(text)
end