Class: Aws::AwsUtils

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

Overview

:nodoc:

Constant Summary collapse

HEX =
[
        "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07",
        "%08", "%09", "%0A", "%0B", "%0C", "%0D", "%0E", "%0F",
        "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17",
        "%18", "%19", "%1A", "%1B", "%1C", "%1D", "%1E", "%1F",
        "%20", "%21", "%22", "%23", "%24", "%25", "%26", "%27",
        "%28", "%29", "%2A", "%2B", "%2C", "%2D", "%2E", "%2F",
        "%30", "%31", "%32", "%33", "%34", "%35", "%36", "%37",
        "%38", "%39", "%3A", "%3B", "%3C", "%3D", "%3E", "%3F",
        "%40", "%41", "%42", "%43", "%44", "%45", "%46", "%47",
        "%48", "%49", "%4A", "%4B", "%4C", "%4D", "%4E", "%4F",
        "%50", "%51", "%52", "%53", "%54", "%55", "%56", "%57",
        "%58", "%59", "%5A", "%5B", "%5C", "%5D", "%5E", "%5F",
        "%60", "%61", "%62", "%63", "%64", "%65", "%66", "%67",
        "%68", "%69", "%6A", "%6B", "%6C", "%6D", "%6E", "%6F",
        "%70", "%71", "%72", "%73", "%74", "%75", "%76", "%77",
        "%78", "%79", "%7A", "%7B", "%7C", "%7D", "%7E", "%7F",
        "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87",
        "%88", "%89", "%8A", "%8B", "%8C", "%8D", "%8E", "%8F",
        "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97",
        "%98", "%99", "%9A", "%9B", "%9C", "%9D", "%9E", "%9F",
        "%A0", "%A1", "%A2", "%A3", "%A4", "%A5", "%A6", "%A7",
        "%A8", "%A9", "%AA", "%AB", "%AC", "%AD", "%AE", "%AF",
        "%B0", "%B1", "%B2", "%B3", "%B4", "%B5", "%B6", "%B7",
        "%B8", "%B9", "%BA", "%BB", "%BC", "%BD", "%BE", "%BF",
        "%C0", "%C1", "%C2", "%C3", "%C4", "%C5", "%C6", "%C7",
        "%C8", "%C9", "%CA", "%CB", "%CC", "%CD", "%CE", "%CF",
        "%D0", "%D1", "%D2", "%D3", "%D4", "%D5", "%D6", "%D7",
        "%D8", "%D9", "%DA", "%DB", "%DC", "%DD", "%DE", "%DF",
        "%E0", "%E1", "%E2", "%E3", "%E4", "%E5", "%E6", "%E7",
        "%E8", "%E9", "%EA", "%EB", "%EC", "%ED", "%EE", "%EF",
        "%F0", "%F1", "%F2", "%F3", "%F4", "%F5", "%F6", "%F7",
        "%F8", "%F9", "%FA", "%FB", "%FC", "%FD", "%FE", "%FF"
]
TO_REMEMBER =
'AZaz09 -_.!~*\'()'
ASCII =

‘Z’=>90, ‘a’=>97, ‘z’=>122, ‘0’=>48, ‘9’=>57, ‘ ’=>32, ‘-’=>45, ‘_’=>95, ‘.’=>

{}
@@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:



218
219
220
221
222
# File 'lib/awsbase/right_awsbase.rb', line 218

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



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/awsbase/right_awsbase.rb', line 136

def self.amz_escape(param)

    param = param.to_s
#            param = param.force_encoding("UTF-8")

    e = "x" # escape2(param.to_s)
#            puts 'ESCAPED=' + e.inspect


    #return CGI.escape(param.to_s).gsub("%7E", "~").gsub("+", "%20") # from: http://umlaut.rubyforge.org/svn/trunk/lib/aws_product_sign.rb

    #param.to_s.gsub(/([^a-zA-Z0-9._~-]+)/n) do
    #  '%' + $1.unpack('H2' * $1.size).join('%').upcase
    #end

#            puts 'e in=' + e.inspect
#            converter = Iconv.new('ASCII', 'UTF-8')
#            e = converter.iconv(e) #.unpack('U*').select{ |cp| cp < 127 }.pack('U*')
#            puts 'e out=' + e.inspect

    e2 = CGI.escape(param)
    e2 = e2.gsub("%7E", "~")
    e2 = e2.gsub("+", "%20")
    e2 = e2.gsub("*", "%2A")

#            puts 'E2=' + e2.inspect
#            puts e == e2.to_s

    e2

end

.caller_methodObject



230
231
232
233
# File 'lib/awsbase/right_awsbase.rb', line 230

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

.escape2(s) ⇒ Object



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/awsbase/right_awsbase.rb', line 168

def self.escape2(s)
    # home grown
    ret = ""
    s.unpack("U*") do |ch|
#                puts 'ch=' + ch.inspect
        if ASCII['A'] <= ch && ch <= ASCII['Z'] # A to Z
            ret << ch
        elsif ASCII['a'] <= ch && ch <= ASCII['z'] # a to z
            ret << ch
        elsif ASCII['0'] <= ch && ch <= ASCII['9'] # 0 to 9
            ret << ch
        elsif ch == ASCII[' '] # space
            ret << "%20" # "+"
        elsif ch == ASCII['-'] || ch == ASCII['_'] || ch == ASCII['.'] || ch == ASCII['~']
            ret << ch
        elsif ch <= 0x007f # other ascii
            ret << HEX[ch]
        elsif ch <= 0x07FF # non-ascii
            ret << HEX[0xc0 | (ch >> 6)]
            ret << HEX[0x80 | (ch & 0x3F)]
        else
            ret << HEX[0xe0 | (ch >> 12)]
            ret << HEX[0x80 | ((ch >> 6) & 0x3F)]
            ret << HEX[0x80 | (ch & 0x3F)]
        end

    end
    ret

end

.escape_sig(raw) ⇒ Object



199
200
201
# File 'lib/awsbase/right_awsbase.rb', line 199

def self.escape_sig(raw)
    e = CGI.escape(raw)
end

.fix_service_params(service_hash, signature) ⇒ Object

Set a timestamp and a signature version



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

def self.fix_service_params(service_hash, signature)
    service_hash["Timestamp"] ||= Time.now.utc.strftime("%Y-%m-%dT%H:%M:%S.000Z") unless service_hash["Expires"]
    service_hash["SignatureVersion"] = signature
    service_hash
end

.mandatory_arguments(required_args, params) ⇒ Object

Raises:



224
225
226
227
228
# File 'lib/awsbase/right_awsbase.rb', line 224

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



39
40
41
# File 'lib/awsbase/right_awsbase.rb', line 39

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)



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

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)



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

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


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/awsbase/right_awsbase.rb', line 73

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 = escape_sig(Base64.encode64(OpenSSL::HMAC.digest(digest, aws_secret_access_key, string_to_sign)).strip)
    ret = "#{canonical_string}&Signature=#{signature}"
#            puts 'full=' + ret.inspect
    ret
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.



212
213
214
215
# File 'lib/awsbase/right_awsbase.rb', line 212

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