Generate SAS Token For Azure Blob Storage Using Managed Identity

Shared Access Signature (SAS) token is used to grant limited access to blob for anonymous users.  This access can be timebound to a specific time range and actions like read, write, or more to a specific file held within blob storage.

This article demonstrates how to generate user delegation shared access signature (SAS) tokens for an Azure Blob. As we know, managed identities for Azure resources are highly recommended wherever possible as this is a security best practice. Here, We will enable managed identity for an Azure storage account from Access Control (IAM). Then we will generate a user delegation SAS token using Default Azure Credential. This SAS token will ensure secure and delegated access to the blob present in the storage container.

For demonstration purpose, we will create a web application where some images are accessed from azure blob storage. To access the image from the storage container, we will generate a user delegation SAS token. Using this SAS token, we will access image or media files into our website.

Let’s understand step by step approach to achieving this. Here I am assuming that we have an existing application where we are trying to access blobs using SAS. In my case, I have a simple website build in .NET and storage account created with container name “media” and uploaded an image there in the container.

Step 1 - Install Guget packages

Below packages need to install in your application. This is required for MSI and Blob operation.

<PackageReference Include="Azure.Identity" Version="1.5.0" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.10.0" />

Step 2 - Generating a User Delegation SAS

We can easily connect to Azure storage account using Azure AD Credentials using DefaultAzureCredential helper class. Let’s create blob service client with Azure AD credentials and then create a user delegation key for the Blob service that's valid for 2 hours. Here, I am reading StorageAccountName and ContainerName from appsettings configuration.

public IActionResult Index() 
{
    var storageAccountName = _configuration.GetValue<string>("StorageAccountName");
    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(_configuration.GetValue<string>("ContainerName"));
    var blobClient = blobContainerClient.GetBlobClient("azure.jpg"); // 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 = blobClient.BlobContainerName,
        BlobName = blobClient.Name, 
        Resource = "b", // b for blob, c for container
        StartsOn = DateTimeOffset.UtcNow,
        ExpiresOn = DateTimeOffset.UtcNow.AddHours(2),
    };

    sasBuilder.SetPermissions(BlobSasPermissions.Read); // read permissions
    // Add the SAS token to the container URI.
    var blobUriBuilder = new BlobUriBuilder(blobClient.Uri)
    {
        Sas = sasBuilder.ToSasQueryParameters(userDelegationKey,blobServiceClient.AccountName)
    };

    ViewData["imgSrc"] = blobUriBuilder.ToUri().ToString();
    return View();
}

Step 3 - Add role assignment in Storage Account

Now go to storage account -> Access Control (IAM) -> + Add -> Add Role Assignment -> Sreach for Role like “Storage Blob Data Reader” -> Select members then assign role that user.

In my case, I granted RBAC for a user called “msi user”.

Step 4 - Set up Azure Service Authentication account in VS

Go to Tools -> Options -> Azure Service Authentication. Choose an account that has given permission to manged identity in earlier step.

Set up Azure Service Authentication account in VS

Sometimes it’s causing issue as we are not selecting the right account. That’s may stop you to test it locally due to below error. If we select correct account which is having proper permission granted in earlier step, we can avoid this issue.

Set up Azure Service Authentication account in VS

Step 5 - Test in localhost

Once everything is setup locally and we choose correct Azure Service Authentication, we can test our logic locally. In my case, I am accessing an image of my application from storage.

If we try to hit directly to the URL without SAS, it’s will show an error – which is expected as Blob public access is disabled, and we don’t want to anonymous to access it.

Awesome! We can see that how easily we can access blob using SAS token. An interesting part of it, we didn’t use any connection string or access key to get it done. This is the beauty of MSI.

Now after deployment of application in azure app service, enable system assigned Identity for app service. And add that Object Id of Identity to storage account role assignment. All set! Now deployed app will work as it was working locally.

Happy Learning!