Class: Azure::Storage::Common::Core::Auth::SharedAccessSignature

Inherits:
Object
  • Object
show all
Defined in:
lib/azure/storage/common/core/auth/shared_access_signature_generator.rb

Constant Summary collapse

DEFAULTS =
{
  permissions: "r",
  version: Azure::Storage::Common::Default::STG_VERSION
}
SERVICE_TYPE_MAPPING =
{
  b: Azure::Storage::Common::ServiceType::BLOB,
  t: Azure::Storage::Common::ServiceType::TABLE,
  q: Azure::Storage::Common::ServiceType::QUEUE,
  f: Azure::Storage::Common::ServiceType::FILE
}
ACCOUNT_KEY_MAPPINGS =
{
  version:              :sv,
  service:              :ss,
  resource:             :srt,
  permissions:          :sp,
  start:                :st,
  expiry:               :se,
  protocol:             :spr,
  ip_range:             :sip
}
SERVICE_KEY_MAPPINGS =
{
  version:              :sv,
  permissions:          :sp,
  start:                :st,
  expiry:               :se,
  identifier:           :si,
  protocol:             :spr,
  ip_range:             :sip
}
BLOB_KEY_MAPPINGS =
{
  resource:             :sr,
  cache_control:        :rscc,
  content_disposition:  :rscd,
  content_encoding:     :rsce,
  content_language:     :rscl,
  content_type:         :rsct
}
TABLE_KEY_MAPPINGS =
{
  table_name:           :tn,
  startpk:              :spk,
  endpk:                :epk,
  startrk:              :srk,
  endrk:                :erk
}
FILE_KEY_MAPPINGS =
{
  resource:             :sr,
  cache_control:        :rscc,
  content_disposition:  :rscd,
  content_encoding:     :rsce,
  content_language:     :rscl,
  content_type:         :rsct
}
SERVICE_OPTIONAL_QUERY_PARAMS =
[:sp, :si, :sip, :spr, :rscc, :rscd, :rsce, :rscl, :rsct, :spk, :srk, :epk, :erk]
ACCOUNT_OPTIONAL_QUERY_PARAMS =
[:st, :sip, :spr]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(account_name = "", access_key = "") ⇒ SharedAccessSignature

Public: Initialize the SharedAccessSignature generator

Parameters:

  • account_name (String) (defaults to: "")

    The account name. Defaults to the one in the global configuration.

  • access_key (String) (defaults to: "")

    The access_key encoded in Base64. Defaults to the one in the global configuration.



106
107
108
109
110
111
112
113
114
# File 'lib/azure/storage/common/core/auth/shared_access_signature_generator.rb', line 106

def initialize( = "", access_key = "")
  if .empty? || access_key.empty?
    client = Azure::Storage::Common::Client.create_from_env
     = client. if .empty?
    access_key = client.storage_access_key if access_key.empty?
  end
  @account_name = 
  @signer = Azure::Core::Auth::Signer.new(access_key)
end

Instance Attribute Details

#account_nameObject (readonly)

Returns the value of attribute account_name.



100
101
102
# File 'lib/azure/storage/common/core/auth/shared_access_signature_generator.rb', line 100

def 
  @account_name
end

Instance Method Details

#canonicalize_time(options) ⇒ Object



284
285
286
287
288
# File 'lib/azure/storage/common/core/auth/shared_access_signature_generator.rb', line 284

def canonicalize_time(options)
  options[:start] = Time.parse(options[:start]).utc.iso8601 if options[:start]
  options[:expiry] = Time.parse(options[:expiry]).utc.iso8601 if options[:expiry]
  options[:expiry] ||= (Time.now + 60 * 30).utc.iso8601
end

#canonicalized_resource(service_type, path) ⇒ String

Return the cononicalized resource representation of the blob resource

Returns:



280
281
282
# File 'lib/azure/storage/common/core/auth/shared_access_signature_generator.rb', line 280

def canonicalized_resource(service_type, path)
  "/#{service_type}/#{}#{path.start_with?('/') ? '' : '/'}#{path}"
end

#generate_account_sas_token(options = {}) ⇒ Object

Account Shared Access Signature Token for the given options

Options

  • :service - String. Required. Accessible services. Combination of ‘b’ (blob), ‘q’ (queue), ‘t’ (table), ‘f’ (file).

  • :resource - String. Required. Accessible resource types. Combination of ‘s’ (service), ‘c’ (container-level), ‘o’(object-level).

  • :permissions - String. Required. Permissions. Combination of ‘r’ (read), ‘w’ (write), ‘d’(delete), ‘l’(list), ‘a’(add),

    'c'(create), 'u'(update), 'p'(process). Permissions are only valid if they match
    the specified signed resource type; otherwise they are ignored.
    
  • :start - String. Optional. UTC Date/Time in ISO8601 format.

  • :expiry - String. Optional. UTC Date/Time in ISO8601 format. Default now + 30 minutes.

  • :protocol - String. Optional. Permitted protocols.

  • :ip_range - String. Optional. An IP address or a range of IP addresses from which to accept requests.

    When specifying a range, note that the range is inclusive.
    

Parameters:

  • account_name (String)

    storage account name

  • options (Hash) (defaults to: {})

Raises:



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/azure/storage/common/core/auth/shared_access_signature_generator.rb', line 241

def (options = {})
  raise Azure::Storage::Common::InvalidOptionsError, "SAS version cannot be set" if options[:version]

  options = DEFAULTS.merge(options)
  valid_mappings = ACCOUNT_KEY_MAPPINGS

  invalid_options = options.reject { |k, _| valid_mappings.key?(k) }
  raise Azure::Storage::Common::InvalidOptionsError, "invalid options #{invalid_options} provided for SAS token generate" if invalid_options.length > 0

  canonicalize_time(options)

  query_hash = Hash[options.map { |k, v| [ACCOUNT_KEY_MAPPINGS[k], v] }]
  .reject { |k, v| ACCOUNT_OPTIONAL_QUERY_PARAMS.include?(k) && v.to_s == "" }
  .merge(sig: @signer.sign((options)))

  URI.encode_www_form(query_hash)
end

#generate_service_sas_token(path, options = {}) ⇒ Object

Service Shared Access Signature Token for the given path and options

Options

  • :service - String. Required. Service type. ‘b’ (blob) or ‘q’ (queue) or ‘t’ (table) or ‘f’ (file).

  • :resource - String. Required. Resource type, ‘b’ (blob) or ‘c’ (container) or ‘f’ (file) or ‘s’ (share).

  • :permissions - String. Optional. Combination of ‘r’, ‘a’, ‘c’, w’,‘d’,‘l’ in this order for a container.

    Combination of 'r', 'a', 'c', 'w', 'd' in this order for a blob.
    Combination of 'r', 'c', 'w', 'd', 'l' in this order for a share.
    Combination of 'r', 'c', 'w', 'd' in this order for a file.
    Combination of 'r', 'a', 'u', 'p' in this order for a queue.
    Combination of 'r', 'a', 'u', 'd' in this order for a table.
    This option must be omitted if it has been specified in an associated stored access policy.
    
  • :start - String. Optional. UTC Date/Time in ISO8601 format.

  • :expiry - String. Optional. UTC Date/Time in ISO8601 format. Default now + 30 minutes.

  • :identifier - String. Optional. Identifier for stored access policy.

  • :protocol - String. Optional. Permitted protocols.

  • :ip_range - String. Optional. An IP address or a range of IP addresses from which to accept requests.

Below options for blob serivce only

  • :cache_control - String. Optional. Response header override.

  • :content_disposition - String. Optional. Response header override.

  • :content_encoding - String. Optional. Response header override.

  • :content_language - String. Optional. Response header override.

  • :content_type - String. Optional. Response header override.

Below options for table service only

  • :startpk - String. Optional but must accompany startrk. The start partition key of a specified partition key range.

  • :endpk - String. Optional but must accompany endrk. The end partition key of a specified partition key range.

  • :startrk - String. Optional. The start row key of a specified row key range.

  • :endrk - String. Optional. The end row key of a specified row key range.

Parameters:

  • path (String)

    Path of the URI or the table name

  • options (Hash) (defaults to: {})

Raises:



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/azure/storage/common/core/auth/shared_access_signature_generator.rb', line 149

def generate_service_sas_token(path, options = {})
  if options.key?(:service)
    service_type = SERVICE_TYPE_MAPPING[options[:service].to_sym]
    options.delete(:service)
  end

  raise Azure::Storage::Common::InvalidOptionsError, "SAS version cannot be set" if options[:version]

  options = DEFAULTS.merge(options)
  valid_mappings = SERVICE_KEY_MAPPINGS
  if service_type == Azure::Storage::Common::ServiceType::BLOB
    if options[:resource]
      options.merge!(resource: options[:resource])
    else
      options.merge!(resource: "b")
    end
    valid_mappings.merge!(BLOB_KEY_MAPPINGS)
  elsif service_type == Azure::Storage::Common::ServiceType::TABLE
    options.merge!(table_name: path)
    valid_mappings.merge!(TABLE_KEY_MAPPINGS)
  elsif service_type == Azure::Storage::Common::ServiceType::FILE
    if options[:resource]
      options.merge!(resource: options[:resource])
    else
      options.merge!(resource: "f")
    end
    valid_mappings.merge!(FILE_KEY_MAPPINGS)
  end

  invalid_options = options.reject { |k, _| valid_mappings.key?(k) }
  raise Azure::Storage::Common::InvalidOptionsError, "invalid options #{invalid_options} provided for SAS token generate" if invalid_options.length > 0

  canonicalize_time(options)

  query_hash = Hash[options.map { |k, v| [SERVICE_KEY_MAPPINGS[k], v] }]
  .reject { |k, v| SERVICE_OPTIONAL_QUERY_PARAMS.include?(k) && v.to_s == "" }
  .merge(sig: @signer.sign(signable_string_for_service(service_type, path, options)))

  URI.encode_www_form(query_hash)
end

#signable_string_for_account(options) ⇒ String

Construct the plaintext to the spec required for signatures

Returns:



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/azure/storage/common/core/auth/shared_access_signature_generator.rb', line 261

def (options)
  # Order is significant
  # The newlines from empty strings here are required
  [
    @account_name,
    options[:permissions],
    options[:service],
    options[:resource],
    options[:start],
    options[:expiry],
    options[:ip_range],
    options[:protocol],
    Azure::Storage::Common::Default::STG_VERSION,
    ""
  ].join("\n")
end

#signable_string_for_service(service_type, path, options) ⇒ String

Construct the plaintext to the spec required for signatures

Returns:



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/azure/storage/common/core/auth/shared_access_signature_generator.rb', line 192

def signable_string_for_service(service_type, path, options)
  # Order is significant
  # The newlines from empty strings here are required
  signable_fields =
  [
    options[:permissions],
    options[:start],
    options[:expiry],
    canonicalized_resource(service_type, path),
    options[:identifier],
    options[:ip_range],
    options[:protocol],
    Azure::Storage::Common::Default::STG_VERSION
  ]

  signable_fields.concat [
    options[:cache_control],
    options[:content_disposition],
    options[:content_encoding],
    options[:content_language],
    options[:content_type]
  ] if service_type == Azure::Storage::Common::ServiceType::BLOB || service_type == Azure::Storage::Common::ServiceType::FILE

  signable_fields.concat [
    options[:startpk],
    options[:startrk],
    options[:endpk],
    options[:endrk]
  ] if service_type == Azure::Storage::Common::ServiceType::TABLE

  signable_fields.join "\n"
end

#signed_uri(uri, use_account_sas, options) ⇒ Object

A customised URI reflecting options for the resource signed with Shared Access Signature

Options

  • :start - String. Optional. UTC Date/Time in ISO8601 format.

  • :expiry - String. Optional. UTC Date/Time in ISO8601 format. Default now + 30 minutes.

  • :protocol - String. Optional. Permitted protocols.

  • :ip_range - String. Optional. An IP address or a range of IP addresses from which to accept requests.

    When specifying a range, note that the range is inclusive.
    

Below options for account SAS only

  • :service - String. Required. Accessible services. Combination of ‘b’ (blob), ‘q’ (queue), ‘t’ (table), ‘f’ (file).

  • :resource - String. Required. Accessible resource types. Combination of ‘s’ (service), ‘c’ (container-level), ‘o’(object-level).

  • :permissions - String. Required. Permissions. Combination of ‘r’ (read), ‘w’ (write), ‘d’(delete), ‘l’(list), ‘a’(add),

    'c'(create), 'u'(update), 'p'(process). Permissions are only valid if they match
    the specified signed resource type; otherwise they are ignored.
    

Below options for service SAS only

  • :service - String. Required. Service type. ‘b’ (blob) or ‘q’ (queue) or ‘t’ (table) or ‘f’ (file).

  • :resource - String. Required. Resource type, ‘b’ (blob) or ‘c’ (container) or ‘f’ (file) or ‘s’ (share).

  • :identifier - String. Optional. Identifier for stored access policy.

  • :permissions - String. Optional. Combination of ‘r’, ‘a’, ‘c’, w’,‘d’,‘l’ in this order for a container.

    Combination of 'r', 'a', 'c', 'w', 'd' in this order for a blob.
    Combination of 'r', 'c', 'w', 'd', 'l' in this order for a share.
    Combination of 'r', 'c', 'w', 'd' in this order for a file.
    Combination of 'r', 'a', 'u', 'p' in this order for a queue.
    Combination of 'r', 'a', 'u', 'd' in this order for a table.
    

Below options for Blob service only

  • :cache_control - String. Optional. Response header override.

  • :content_disposition - String. Optional. Response header override.

  • :content_encoding - String. Optional. Response header override.

  • :content_language - String. Optional. Response header override.

  • :content_type - String. Optional. Response header override.

Below options for Table service only

  • :table_name - String. Required. Table name for SAS.

  • :startpk - String. Optional but must accompany startrk. The start partition key of a specified partition key range.

  • :endpk - String. Optional but must accompany endrk. The end partition key of a specified partition key range.

  • :startrk - String. Optional. The start row key of a specified row key range.

  • :endrk - String. Optional. The end row key of a specified row key range.

Parameters:

  • uri (URI)

    uri to resource including query options

  • use_account_sas (Boolean)

    Whether uses account SAS

  • options (Hash)


334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
# File 'lib/azure/storage/common/core/auth/shared_access_signature_generator.rb', line 334

def signed_uri(uri, , options)
  CGI::parse(uri.query || "").inject({}) { |memo, (k, v)| memo[k.to_sym] = v; memo }

  if options[:service] == (nil) && uri.host != (nil)
    host_splits = uri.host.split(".")
    options[:service] = host_splits[1].chr if host_splits.length > 1 && host_splits[0] == @account_name
  end

  sas_params = if 
    (options)
               else
                 generate_service_sas_token(uri.path, options)
               end

  URI.parse(uri.to_s + (uri.query.nil? ? "?" : "&") + sas_params)
end