Module: WAZ::Storage::SharedKeyCoreService
- Included in:
- Blobs::Service, Queues::Service, Tables::Service
- Defined in:
- lib/waz/storage/core_service.rb
Overview
This module is imported by the specific services that use Shared Key authentication profile. On the current implementation this module is imported from WAZ::Queues::Service and WAZ::Blobs::Service.
Instance Attribute Summary collapse
-
#access_key ⇒ Object
Returns the value of attribute access_key.
-
#account_name ⇒ Object
Returns the value of attribute account_name.
-
#base_url ⇒ Object
Returns the value of attribute base_url.
-
#retry_count ⇒ Object
Returns the value of attribute retry_count.
-
#sharedaccesssignature ⇒ Object
Returns the value of attribute sharedaccesssignature.
-
#type_of_service ⇒ Object
Returns the value of attribute type_of_service.
-
#use_devenv ⇒ Object
Returns the value of attribute use_devenv.
-
#use_sas_auth_only ⇒ Object
Returns the value of attribute use_sas_auth_only.
-
#use_ssl ⇒ Object
Returns the value of attribute use_ssl.
Instance Method Summary collapse
-
#canonicalize_headers(headers) ⇒ Object
Canonicalizes the request headers by following Microsoft’s specification on how those headers have to be sorted and which of the given headers apply to be canonicalized.
-
#canonicalize_message(url) ⇒ Object
Creates a canonical representation of the message by combining account_name/resource_path.
- #canonicalize_message20090919(url) ⇒ Object
-
#execute(verb, path, query = {}, headers = {}, payload = nil) ⇒ Object
Generates a Windows Azure Storage call, it internally calls url generation method and the request generation message.
-
#generate_request(verb, url, headers = {}, payload = nil) ⇒ Object
Generates a request based on Adam Wiggings’ rest-client, including all the required headers for interacting with Windows Azure Storage API (except for Tables).
-
#generate_request_uri(path = nil, options = {}) ⇒ Object
Generates the request uri based on the resource path, the protocol, the account name and the parameters passed on the options hash.
-
#generate_signature(options = {}) ⇒ Object
Generates the signature based on Micosoft specs for the REST API.
- #generate_signature20090919(options = {}) ⇒ Object
-
#initialize(options = {}) ⇒ Object
Creates an instance of the implementor service (internally used by the API).
Instance Attribute Details
#access_key ⇒ Object
Returns the value of attribute access_key.
6 7 8 |
# File 'lib/waz/storage/core_service.rb', line 6 def access_key @access_key end |
#account_name ⇒ Object
Returns the value of attribute account_name.
6 7 8 |
# File 'lib/waz/storage/core_service.rb', line 6 def account_name @account_name end |
#base_url ⇒ Object
Returns the value of attribute base_url.
6 7 8 |
# File 'lib/waz/storage/core_service.rb', line 6 def base_url @base_url end |
#retry_count ⇒ Object
Returns the value of attribute retry_count.
7 8 9 |
# File 'lib/waz/storage/core_service.rb', line 7 def retry_count @retry_count end |
#sharedaccesssignature ⇒ Object
Returns the value of attribute sharedaccesssignature.
6 7 8 |
# File 'lib/waz/storage/core_service.rb', line 6 def sharedaccesssignature @sharedaccesssignature end |
#type_of_service ⇒ Object
Returns the value of attribute type_of_service.
6 7 8 |
# File 'lib/waz/storage/core_service.rb', line 6 def type_of_service @type_of_service end |
#use_devenv ⇒ Object
Returns the value of attribute use_devenv.
6 7 8 |
# File 'lib/waz/storage/core_service.rb', line 6 def use_devenv @use_devenv end |
#use_sas_auth_only ⇒ Object
Returns the value of attribute use_sas_auth_only.
6 7 8 |
# File 'lib/waz/storage/core_service.rb', line 6 def use_sas_auth_only @use_sas_auth_only end |
#use_ssl ⇒ Object
Returns the value of attribute use_ssl.
6 7 8 |
# File 'lib/waz/storage/core_service.rb', line 6 def use_ssl @use_ssl end |
Instance Method Details
#canonicalize_headers(headers) ⇒ Object
Canonicalizes the request headers by following Microsoft’s specification on how those headers have to be sorted and which of the given headers apply to be canonicalized.
55 56 57 58 |
# File 'lib/waz/storage/core_service.rb', line 55 def canonicalize_headers(headers) cannonicalized_headers = headers.keys.select {|h| h.to_s.start_with? 'x-ms'}.map{ |h| "#{h.downcase.strip}:#{headers[h].strip}" }.sort{ |a, b| a <=> b }.join("\x0A") return cannonicalized_headers end |
#canonicalize_message(url) ⇒ Object
Creates a canonical representation of the message by combining account_name/resource_path.
61 62 63 64 65 66 67 |
# File 'lib/waz/storage/core_service.rb', line 61 def (url) uri_component = url.gsub(/https?:\/\/[^\/]+\//i, '').gsub(/\?.*/i, '') comp_component = url.scan(/comp=[^&]+/i).first() uri_component << "?#{comp_component}" if comp_component = "/#{self.account_name}/#{uri_component}" return end |
#canonicalize_message20090919(url) ⇒ Object
106 107 108 109 110 111 112 113 |
# File 'lib/waz/storage/core_service.rb', line 106 def (url) uri_component = url.gsub(/https?:\/\/[^\/]+\//i, '').gsub(/\?.*/i, '') query_component = (url.scan(/\?(.*)/i).first() or []).first() query_component = query_component.split('&').sort{|a, b| a <=> b}.map{ |p| CGI::unescape(p.split('=').join(':')) }.join("\n") if query_component = "/#{self.account_name}/#{uri_component}" << "\n#{query_component}" if query_component return end |
#execute(verb, path, query = {}, headers = {}, payload = nil) ⇒ Object
Generates a Windows Azure Storage call, it internally calls url generation method and the request generation message.
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/waz/storage/core_service.rb', line 117 def execute(verb, path, query = {}, headers = {}, payload = nil) escaped_path = (path || "").split("/").map{ | part | CGI.escape(part) }.join("/") url = generate_request_uri(escaped_path, query) request = generate_request(verb, url, headers, payload) errors = 0 begin request.execute() rescue Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::ECONNRESET => e errors += 1 if errors > self.retry_count raise e.class, e., e.backtrace end retry end end |
#generate_request(verb, url, headers = {}, payload = nil) ⇒ Object
Generates a request based on Adam Wiggings’ rest-client, including all the required headers for interacting with Windows Azure Storage API (except for Tables). This methods embeds the authorization key signature on the request based on the given access_key.
28 29 30 31 32 33 34 35 36 |
# File 'lib/waz/storage/core_service.rb', line 28 def generate_request(verb, url, headers = {}, payload = nil) http_headers = {} headers.each{ |k, v| http_headers[k.to_s.gsub(/_/, '-')] = v} unless headers.nil? http_headers.merge!("x-ms-Date" => Time.new.httpdate) http_headers.merge!("Content-Length" => (payload or "").bytesize) request = {:headers => http_headers, :method => verb.to_s.downcase.to_sym, :url => url, :payload => payload} request[:headers].merge!("Authorization" => "SharedKey #{account_name}:#{generate_signature(request)}") unless self.use_sas_auth_only return RestClient::Request.new(request) end |
#generate_request_uri(path = nil, options = {}) ⇒ Object
Generates the request uri based on the resource path, the protocol, the account name and the parameters passed on the options hash.
40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/waz/storage/core_service.rb', line 40 def generate_request_uri(path = nil, = {}) protocol = use_ssl ? "https" : "http" query_params = .keys.sort{ |a, b| a.to_s <=> b.to_s}.map{ |k| "#{k.to_s.gsub(/_/, '')}=#{CGI.escape([k].to_s)}"}.join("&") unless .nil? or .empty? uri = "#{protocol}://#{base_url}/#{path.start_with?(account_name) ? "" : account_name }#{((path or "").start_with?("/") or path.start_with?(account_name)) ? "" : "/"}#{(path or "")}" if !self.use_devenv.nil? and self.use_devenv uri ||= "#{protocol}://#{account_name}.#{base_url}#{(path or "").start_with?("/") ? "" : "/"}#{(path or "")}" if self.use_sas_auth_only uri << "?#{self.sharedaccesssignature.gsub(/\?/,'')}" else uri << "?#{query_params}" if query_params end return uri end |
#generate_signature(options = {}) ⇒ Object
Generates the signature based on Micosoft specs for the REST API. It includes some special headers, the canonicalized header line and the canonical form of the message, all of the joined by n character. Encoded with Base64 and encrypted with SHA256 using the access_key as the seed.
72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/waz/storage/core_service.rb', line 72 def generate_signature( = {}) return generate_signature20090919() if [:headers]["x-ms-version"] == "2011-08-18" signature = [:method].to_s.upcase + "\x0A" + ([:headers]["Content-MD5"] or "") + "\x0A" + ([:headers]["Content-Type"] or "") + "\x0A" + ([:headers]["Date"] or "")+ "\x0A" signature += canonicalize_headers([:headers]) + "\x0A" unless self.type_of_service == 'table' signature += ([:url]) signature = signature.toutf8 if(signature.respond_to? :toutf8) Base64.encode64(HMAC::SHA256.new(Base64.decode64(self.access_key)).update(signature).digest) end |
#generate_signature20090919(options = {}) ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/waz/storage/core_service.rb', line 86 def generate_signature20090919( = {}) signature = [:method].to_s.upcase + "\x0A" + ([:headers]["Content-Encoding"] or "") + "\x0A" + ([:headers]["Content-Language"] or "") + "\x0A" + ([:headers]["Content-Length"] or "").to_s + "\x0A" + ([:headers]["Content-MD5"] or "") + "\x0A" + ([:headers]["Content-Type"] or "") + "\x0A" + ([:headers]["Date"] or "")+ "\x0A" + ([:headers]["If-Modified-Since"] or "")+ "\x0A" + ([:headers]["If-Match"] or "")+ "\x0A" + ([:headers]["If-None-Match"] or "")+ "\x0A" + ([:headers]["If-Unmodified-Since"] or "")+ "\x0A" + ([:headers]["Range"] or "")+ "\x0A" + canonicalize_headers([:headers]) + "\x0A" + ([:url]) signature = signature.toutf8 if(signature.respond_to? :toutf8) Base64.encode64(HMAC::SHA256.new(Base64.decode64(self.access_key)).update(signature).digest) end |
#initialize(options = {}) ⇒ Object
Creates an instance of the implementor service (internally used by the API).
10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/waz/storage/core_service.rb', line 10 def initialize( = {}) # Flag to define the use of shared access signature only self.use_sas_auth_only = [:use_sas_auth_only] or false self.sharedaccesssignature = [:sharedaccesssignature] self.account_name = [:account_name] self.access_key = [:access_key] self.type_of_service = [:type_of_service] self.use_ssl = [:use_ssl] or false self.use_devenv = !![:use_devenv] self.base_url = "#{[:type_of_service] or "blobs"}.#{[:base_url] or "core.windows.net"}" unless self.use_devenv self.base_url ||= ([:base_url] or "core.windows.net") self.retry_count = ([:retry_count] or 5) end |