Search code examples
rubyazureazure-blob-storageazure-storageshared-access-signatures

Generate Azure Storage SAS Signature In Ruby


I am trying to use the following code to generate a valid URL for accessing a blob in my Azure storage account. The Azure account name and key are stored in .env files. For some reason, the URL doesn't work; I get a Signature did not match error.

# version 2018-11-09 and later, https://learn.microsoft.com/en-us/rest/api/storageservices/create-service-sas#version-2018-11-09-and-later

signed_permissions = "r"
signed_start = "#{(start_time - 5.minutes).iso8601}"
signed_expiry = "#{(start_time + 10.minutes).iso8601}"
canonicalized_resource = "/blob/#{Config.azure_storage_account_name}/media/#{medium.tinyurl}"
signed_identifier = ""
signed_ip = ""
signed_protocol = "https"
signed_version = "2018-11-09"
signed_resource = "b"
signed_snapshottime = ""
rscc = ""
rscd = ""
rsce = ""
rscl = ""
rsct = ""

string_to_sign = signed_permissions + "\n" +
          signed_start + "\n" +
          signed_expiry + "\n" +
          canonicalized_resource + "\n" +
          signed_identifier + "\n" +
          signed_ip + "\n" +
          signed_protocol + "\n" +
          signed_version + "\n" +
          signed_resource + "\n" +
          signed_snapshottime + "\n" +
          rscc + "\n" +
          rscd + "\n" +
          rsce + "\n" +
          rscl + "\n" +
          rsct

sig = OpenSSL::HMAC.digest('sha256', Base64.strict_decode64(Config.azure_storage_account_key), string_to_sign.encode(Encoding::UTF_8))

sig = Base64.strict_encode64(sig)

@result = "#{medium.storageurl}?sp=#{signed_permissions}&st=#{signed_start}&se=#{signed_expiry}&spr=#{signed_protocol}&sv=#{signed_version}&sr=#{signed_resource}&sig=#{sig}"

PS: This is in Rails and medium is a record pulled from the DB that contains information about the blob in Azure.


Solution

  • Turns out the issue was clock skew. The signed_start and signed_expiry amounts I was using were too tight. WHen I relaxed then to -30/+20, I could reliably create SAS tokens using the snipper I posted.