Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Jun 9th, 2012  |  syntax: None  |  size: 2.79 KB  |  hits: 23  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. require 'cgi'
  2. require 'openssl'
  3. require 'net/https'
  4. require 'rubygems'
  5. require 'activesupport'
  6.  
  7. module AWS
  8.   class API
  9.     def initialize(access_key, secret_key, uri='/')
  10.       prefix = self.class.name.split('::').last.downcase!
  11.       @host = "#{prefix}.amazonaws.com"
  12.       @access_key = access_key
  13.       @secret_key = secret_key
  14.       @uri = uri
  15.       @signature_version = '2'
  16.       @signature_method = 'HmacSHA256'
  17.     end
  18.  
  19.     def method_missing(symbol, args={})
  20.       send_request(format_method(symbol.to_s), args)
  21.     end
  22.  
  23.     private
  24.       def format_method(string)
  25.         string.gsub!(/^[a-z]|_+[a-z]/) { |a| a.upcase }
  26.         string.gsub!(/_/, '')
  27.       end
  28.  
  29.       def format_params(params)
  30.         param_array = Array.new
  31.         params.sort_by { |k, v| k}.each do |param|
  32.           param_array << "#{CGI.escape(param[0]).gsub('+', '%20')}=#{CGI.escape(param[1]).gsub('+', '%20')}"
  33.         end
  34.  
  35.         flat_params = "#{param_array.join('&')}"
  36.  
  37.         # make the proper string to sign
  38.         string_to_sign = "#{@request_method}\n#{@host}\n#{@uri}\n#{flat_params}"
  39.         digest = OpenSSL::Digest::Digest.new('sha256')
  40.         b64_hmac = [OpenSSL::HMAC.digest(digest, @secret_key, string_to_sign)].pack("m").strip
  41.         signature = CGI.escape(b64_hmac)
  42.         "#{flat_params}&Signature=#{signature}"
  43.       end
  44.  
  45.       def add_default_params
  46.         {
  47.           'Timestamp'         => Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
  48.           'AWSAccessKeyId'    => @access_key,
  49.           'Version'           => @api_version,
  50.           'SignatureVersion'  => @signature_version,
  51.           'SignatureMethod'   => @signature_method
  52.         }
  53.       end
  54.  
  55.       def send_request(method, params={}, request_method=:get)
  56.         @request_method = 'GET' if request_method == :get # TODO: add POST support
  57.         params.merge! add_default_params
  58.         params['Action'] = method
  59.         canonical_string = format_params(params)
  60.  
  61.         http = Net::HTTP.new(@host, 443)
  62.         http.use_ssl = true
  63.         http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  64.         response, xml_data = http.get("#{@uri}?#{canonical_string}")
  65.         data = Hash.from_xml(xml_data)
  66.         case response
  67.         when Net::HTTPOK
  68.           data
  69.         else
  70.           raise Error.new(data)
  71.         end
  72.       end
  73.  
  74.   end
  75.  
  76.   class Error < Exception
  77.     attr_reader :message
  78.     def initialize(data)
  79.       @message = "#{data['Response']['Errors']['Error']['Code']}: #{data['Response']['Errors']['Error']['Message']}"
  80.     end
  81.   end
  82.  
  83.   class EC2 < AWS::API
  84.     def initialize(access_key, secret_key)
  85.       @api_version = '2010-11-15'
  86.       super
  87.     end
  88.   end
  89.   class IAM < AWS::API
  90.     def initalize(access_key, secret_key)
  91.       @api_version = '2010-05-08'
  92.       super
  93.     end
  94.   end
  95. end