Skip to content

Bump default Azure Blob and SAS API versions to 2025-07-05

There are notably two version bumps in this merge request from 2018-11-09 to 2025-07-05:

  1. Blob storage API
  2. SAS token signatures

Blob Storage API

According to https://learn.microsoft.com/en-us/rest/api/storageservices/previous-azure-storage-service-versions, 2025-07-05 is fully GA now, and this is the version that should be used. There appear to be no breaking changes, just additional features that can be used.

Previously the Azure client defaulted to using API version 2018-11-09, but Azure Stack Hub requires a newer version of the API. Add a api_version that can be configured to override the default.

SAS token signatures

The signature version bump needs to be adjusted:

Service SAS

Before (2018-11-09)

StringToSign = signedPermissions + "\n" +  
               signedStart + "\n" +  
               signedExpiry + "\n" +  
               canonicalizedResource + "\n" +  
               signedIdentifier + "\n" +  
               signedIP + "\n" +  
               signedProtocol + "\n" +  
               signedVersion + "\n" +  
               signedResource + "\n"
               signedSnapshotTime + "\n" +
               rscc + "\n" +  
               rscd + "\n" +  
               rsce + "\n" +  
               rscl + "\n" +  
               rsct

After (2020-12-06 and later)

StringToSign = signedPermissions + "\n" +  
               signedStart + "\n" +  
               signedExpiry + "\n" +  
               canonicalizedResource + "\n" +  
               signedIdentifier + "\n" +  
               signedIP + "\n" +  
               signedProtocol + "\n" +  
               signedVersion + "\n" +  
               signedResource + "\n" +
               signedSnapshotTime + "\n" +
               signedEncryptionScope + "\n" +
               rscc + "\n" +  
               rscd + "\n" +  
               rsce + "\n" +  
               rscl + "\n" +
               rsct

User Delegation SAS

Before (2018-11-09)

StringToSign =  signedPermissions + "\n" +  
                signedStart + "\n" +  
                signedExpiry + "\n" +  
                canonicalizedResource + "\n" +  
                signedKeyObjectId + "\n" +
                signedKeyTenantId + "\n" +
                signedKeyStart + "\n" +
                signedKeyExpiry  + "\n" +
                signedKeyService + "\n" +
                signedKeyVersion + "\n" +
                signedAuthorizedUserObjectId + "\n" +
                signedUnauthorizedUserObjectId + "\n" +
                signedCorrelationId + "\n" +
                signedIP + "\n" +  
                signedProtocol + "\n" +  
                signedVersion + "\n" +  
                signedResource + "\n" +
                rscc + "\n" +
                rscd + "\n" +  
                rsce + "\n" +  
                rscl + "\n" +  
                rsct

After (2025-07-05 and later)

StringToSign =  signedPermissions + "\n" +
                signedStart + "\n" +
                signedExpiry + "\n" +
                canonicalizedResource + "\n" +
                signedKeyObjectId + "\n" +
                signedKeyTenantId + "\n" +
                signedKeyStart + "\n" +
                signedKeyExpiry  + "\n" +
                signedKeyService + "\n" +
                signedKeyVersion + "\n" +
                signedAuthorizedUserObjectId + "\n" +
                signedUnauthorizedUserObjectId + "\n" +
                signedCorrelationId + "\n" +
                "\n" +
                "\n" +
                signedIP + "\n" +
                signedProtocol + "\n" +
                signedVersion + "\n" +
                signedResource + "\n" +
                signedSnapshotTime + "\n" +
                signedEncryptionScope + "\n" +
                rscc + "\n" +
                rscd + "\n" +
                rsce + "\n" +
                rscl + "\n" +
                rsct

How to validate locally

Fortunately the integration test with Azurite caught issues with our token generation.

I tested this with both a managed identity and an shared access key:

require 'fog/azurerm'

ENV['DEBUG'] = "1"

connection = Fog::Storage.new(
  {
    provider: 'AzureRM',
    azure_storage_account_name: 'YOUR-ACCOUNT-NAME'
  })

dir = connection.directories.new(key: 'test1')
f = dir.files
f = dir.files.create(key: 'test.txt', body: 'test')
pp dir.files.head('test.txt')
pp f.url(Time.now + 60)

If the SAS signature is not right, the URL printed is not accessible.

Relates to #8 (closed)

Edited by Stan Hu

Merge request reports

Loading