Search code examples
azureasp.net-web-apiazure-blob-storageazure-managed-identitysas-token

Generate Sas token for storage account with managed identity


I use the following to get a sas token, it works perfectly targeting the specific container and blob:

[HttpGet]
        public IActionResult GetBlobSasToken()
        {
            var storageAccountName = "storage-Name";
            var saUri = $"https://{storageAccountName}.blob.core.windows.net";

            // Create a new Blob service client with Azure AD credentials.
            var blobServiceClient = new BlobServiceClient(new Uri(saUri), new DefaultAzureCredential());

            var blobContainerClient = blobServiceClient.GetBlobContainerClient("container-Name");
            var blobClient = blobContainerClient.GetBlobClient("Blob-Name"); // Blob name

            // Get a user delegation key for the Blob service that's valid for 2 hours.
            var userDelegationKey = blobServiceClient.GetUserDelegationKey(DateTimeOffset.UtcNow,
                                                                 DateTimeOffset.UtcNow.AddHours(2));


            var sasBuilder = new BlobSasBuilder()
            {
                BlobContainerName = blobContainerClient.Name,
                BlobName = blobClient.Name,
                Resource = "b", 
                StartsOn = DateTimeOffset.UtcNow,
                ExpiresOn = DateTimeOffset.UtcNow.AddHours(2),
            };

            sasBuilder.SetPermissions(BlobSasPermissions.Read); // Read permissions


            // Build the blob URL with the SAS token
            var blobUriBuilder = new BlobUriBuilder(blobClient.Uri)
            {
                Sas = sasBuilder.ToSasQueryParameters(userDelegationKey, blobServiceClient.AccountName)
            };

            var blobUrlWithSas = blobUriBuilder.ToUri().ToString();

            return Ok(new { BlobUrlWithSas = blobUrlWithSas });
        }

and verify the sas token by adding the path https://{StorageAccountName}.blob.core.windows.net/{containerName}/{BlobName}?{SasToken}

and verify the sas token by adding the path https://{StorageAccountName}.blob.core.windows.net/{containerName}/{BlobName}?{SasToken}. It runs smoothly.

What I want to figure out is to generate the sas token but at the storage account level.

I tried to modify:


               // Create the blob URL with the SAS token
               var blobUriBuilder = new BlobUriBuilder(blobServiceClient.Uri)

And while generating the sas token I get the 403 error:

<?xmlversion="1.0" encoding="utf-8"?>
<Error>
       <Code>Authentication failed</Code>
       <Message> The server could not authenticate the request. Make sure the authorization header value is correctly formed, including the signature.
Request ID: f100b2a0-501e-0038-06dd-cb612f000000
Time:2023-08-10T22:53:59.3204012Z</Message>

Solution

  • Generate Sas token for storage account with managed identity

    You cannot create an account-level SAS with a user delegation key.

    A user delegation SAS only applies to Blob storage and is secured with Azure AD credentials, while an account-level SAS is connected with the storage account key and may assign access to resources in multiple storage services.

    For account-level SAS creation, you need to use your storage account key.

    Code:

     var storageAccountName = "venkat123";
     var storageaccountKey = "xx";
     var storageAccountUri = $"https://{storageAccountName}.blob.core.windows.net";
    
     var blobServiceClient = new BlobServiceClient(new Uri(storageAccountUri), new StorageSharedKeyCredential(storageAccountName, storageaccountKey));
                
     var sasBuilder = new AccountSasBuilder()
     {
       Services = AccountSasServices.Blobs,
       ResourceTypes = AccountSasResourceTypes.Container | AccountSasResourceTypes.Object,
       StartsOn = DateTimeOffset.UtcNow,
       ExpiresOn = DateTimeOffset.UtcNow.AddHours(2),
      };
     sasBuilder.SetPermissions(AccountSasPermissions.Read | AccountSasPermissions.Write); // read  write permissions
     string sasToken = sasBuilder.ToSasQueryParameters(new StorageSharedKeyCredential(storageAccountName, storageaccountKey)).ToString();
    
     // Append the SAS token to the URL
     string accountlevelurl = $"{storageAccountUri}?{sasToken}";
     Console.WriteLine(accountlevelurl);  
    

    Output:

      https://xxxxx.blob.core.windows.net?sv=2023-08-03&ss=b&srt=co&st=2023-08-11T06%3A26%3A16Z&se=2023-08-11T08%3A26%3A16Z&sp=rw&sig=xxxxxxx
    

    Now, you can use the above URL with your container and blob to fetch the files from the blob service.

    Portal:

    enter image description here

    Reference:

    Grant limited access to data with shared access signatures (SAS) - Azure Storage | Microsoft Learn