#------------------------------------------------------------------------- # # Copyright (c) Microsoft and contributors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #-------------------------------------------------------------------------- # TODO: extract common SAS logic, add support for the other SAS types require "azure/core/configuration" require "azure/core/auth/signer" # This will break if used against API version prior to 2013-08-15 as the format # changed # See https://msdn.microsoft.com/library/azure/dn140255.aspx for more information on construction module Azure module Blob module Auth class SharedAccessSignature < Core::Auth::Signer DEFAULTS = { resource: 'b', permissions: 'r', version: '2013-08-15' } KEY_MAPPINGS = { permissions: :sp, start: :st, expiry: :se, resource: :sr, identifier: :si, version: :sv, cache_control: :rscc, content_disposition: :rscd, content_encoding: :rsce, content_language: :rscl, content_type: :rsct } OPTIONAL_QUERY_PARAMS = [:sp, :si, :rscc, :rscd, :rsce, :rscl, :rsct] attr :path attr :options attr :account_name # Public: Initialize the Signer. # # ==== Attributes # # * +path+ - the container or blob path # * +options+ - Hash. Required and optional parameters # * +account_name+ - The account name. Defaults to the one in the # global configuration. # * +access_key+ - The access_key encoded in Base64. Defaults to the # one in the global configuration. # # ==== Options # # * +:resource+ - String. Resource type, either 'b' (blob) or 'c' (container). Default 'b' # * +:permissions+ - String. Combination of 'r','w','d','l' (container only) in this order. Default 'r' # * +:start+ - String. UTC Date/Time in ISO8601 format. Optional. # * +:expiry+ - String. UTC Date/Time in ISO8601 format. Required. # * +:identifier+ - String. Identifier for stored access policy. Optional # * +:version+ - String. API version. Default '2013-08-15' # # * +:cache_control - String. Response header override. Optional. # * +:content_disposition - String. Response header override. Optional. # * +:content_encoding - String. Response header override. Optional. # * +:content_language - String. Response header override. Optional. # * +:content_type - String. Response header override. Optional. def initialize(path, options, account_name=Azure.config.storage_account_name, access_key=Azure.config.storage_access_key) @path = path @account_name = account_name @options = DEFAULTS.merge(options) super(access_key) end # Public: Construct the plaintext to the spec required for signatures def signable_string # Order is significant # The newlines from empty strings here are required [ options[:permissions], options[:start], options[:expiry], canonicalized_resource, options[:identifier], options[:version], options[:cache_control], options[:content_disposition], options[:content_encoding], options[:content_language], options[:content_type] ].join("\n") end def canonicalized_resource "/#{account_name}/#{path}" end # Public: A customised URI reflecting options for the resource signed with the Shared Access Signature def signed_uri query_params = URI.encode_www_form(query_hash) "https://#{account_name}.blob.core.windows.net/#{path}?#{query_params}" end def to_s signed_uri end private def signature sign(signable_string) end def query_hash Hash[options.map { |k, v| [KEY_MAPPINGS[k], v] }].reject { |k,v| OPTIONAL_QUERY_PARAMS.include?(k) && v.to_s == '' }.merge( sig: signature ) end end end end end