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:



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

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



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
167
# File 'lib/awsbase/right_awsbase.rb', line 137

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



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

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

.escape2(s) ⇒ Object



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
198
# File 'lib/awsbase/right_awsbase.rb', line 169

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



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

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

.fix_service_params(service_hash, signature) ⇒ Object

Set a timestamp and a signature version



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

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:



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

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



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

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)



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

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)



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

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


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

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.



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

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