When anonymous access to Azure Blob Storage is disabled, generating a Shared Access Signature (SAS) token becomes essential to access blob files securely. SAS tokens enable you to grant temporary access to your blob files with defined permissions. In this post, I’ll walk through how to generate and use SAS tokens effectively in an ASP.NET Core API and discuss the challenges and solutions for managing blob-level versus container-level tokens.
Generating SAS Tokens in ASP.NET Core
To handle operations related to Azure Blob Storage in my ASP.NET Core API, I created a dedicated service class. This class manages SAS token generation and provides URLs that include the SAS token to retrieve blob files. The front-end application can use these URLs to access files seamlessly.
Here’s how SAS token generation works at the blob level:
- The API generates a unique SAS token for each blob.
- The token is appended to the blob’s URL and returned to the client.
- The client-side application uses the URL to retrieve and display the file.
Code to generate SAS token at Blob-level
public Uri GetBlobSasUrl(string blobName)
{
var containerClient = _blobServiceClient.GetBlobContainerClient(_containerName);
var blobClient = containerClient.GetBlobClient(blobName);
if (blobClient.CanGenerateSasUri)
{
var sasBuilder = new BlobSasBuilder
{
BlobContainerName = _containerName,
BlobName = blobName,
Resource = "b", // "b" for blob-level SAS
ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(30),
};
sasBuilder.SetPermissions(BlobContainerSasPermissions.Read);
Uri sasUri = blobClient.GenerateSasUri(sasBuilder);
return sasUri;
}
else
{
throw new InvalidOperationException("BlobClient is not authorized to generate SAS tokens.");
}
}
In this code Resource = “b”, b for blob it will be “c” for container-level.
While this approach works, it presents several challenges, especially in scenarios involving multiple users or systems that need to access many blobs. Below, I’ve outlined the main drawbacks of generating SAS tokens at the blob level.
Drawbacks of Blob-Level SAS Tokens
1. Increased Token Generation Overhead
• SAS tokens need to be generated for every individual blob.
• Frequent access to multiple blobs in a short time or bulk operations can lead to performance bottlenecks.
• This process adds computational overhead, slowing down applications with high throughput demands.
2. Complexity in Managing Tokens
• Generating and maintaining multiple SAS tokens for individual blobs complicates token management.
• Revoking or rotating tokens becomes more challenging as each blob’s token must be handled independently.
3. Reduced Bulk Access Efficiency
• Blob-level SAS tokens restrict access to a single blob, making it difficult to perform bulk operations like enumerating blobs or downloading multiple files with a single token.
• Generating multiple tokens to access multiple blobs reduces efficiency.
4. Higher Risk of Expired Tokens
• Blob-level SAS tokens are prone to expiration issues if not used within their validity period.
• Frequent renewal of tokens increases the risk of errors and complicates application workflows.
5. Unsuitability for Shared or Dynamic Workflows
• For shared or dynamic workflows, blob-level tokens require generating and distributing individual tokens to each consumer.
• This approach becomes cumbersome when blobs are frequently added or removed.
Transition to Container-Level SAS Tokens
To address these challenges, I transitioned to using container-level SAS tokens. This approach provides greater flexibility and efficiency for managing access to blob storage. Here’s why container-level tokens are better:
1. Simplified Access Management
o A single token grants access to all blobs in the container.
o Revoking or rotating tokens is more straightforward as only one token needs to be managed for the container.
2. Improved Performance
o Tokens can be cached, reducing the computational overhead of generating tokens for each request.
o Bulk operations like listing or downloading multiple blobs are more efficient.
3. Flexibility for Dynamic Workflows
o Users and systems can access newly added blobs without generating additional tokens.
o Suitable for shared workflows where multiple users need access to the same container.
Code to generate SAS token at Container -level
public Uri GetContainerSasUrl()
{
var containerClient = _blobServiceClient.GetBlobContainerClient(_containerName);
if (containerClient.CanGenerateSasUri)
{
var sasBuilder = new BlobSasBuilder
{
BlobContainerName = _containerName,
Resource = "c", // "c" for container-level SAS
ExpiresOn = DateTimeOffset.UtcNow.AddHours(12), // Adjust expiration as needed
};
// Set container-level permissions
sasBuilder.SetPermissions(BlobContainerSasPermissions.Read);
Uri sasUri = containerClient.GenerateSasUri(sasBuilder);
return sasUri;
}
else
{
throw new InvalidOperationException("ContainerClient is not authorized to generate SAS tokens.");
}
}
Cache the token
public Uri GetCachedContainerSasUrl()
{
if (!_cacheService.TryGet(Constants.CacheKeys.ContainerSasUrl, out Uri _cachedSasUri))
{
_cachedSasUri = GetContainerSasUrl();
_cacheService.Set(Constants.CacheKeys.ContainerSasUrl, _cachedSasUri);
}
return _cachedSasUri;
}
From API execute the service and prepare the final URL to return
[HttpGet("getBlobUrl/{blobName}")]
public IActionResult GetBlobSasUrl(string blobName)
{
var containerSasUrl = _blobStorageService.GetCachedContainerSasUrl();
var blobUrl = $"{containerSasUrl.ToString().Split('?')[0]}/{blobName}{containerSasUrl.Query}";
return Ok(blobUrl);
}
Benefits Achieved with Container-Level SAS Tokens
By moving to container-level tokens, I achieved the following:
• Enhanced Performance: Reduced latency in accessing files and minimized the overhead of frequent token generation.
• Scalability: Simplified workflows for applications that handle large numbers of blobs.
• Ease of Management: Streamlined token management and improved security through centralized control of container-level access.
Conclusion
When working with Azure Blob Storage, choosing the right level for generating SAS tokens can significantly impact application performance and complexity. For scenarios involving frequent or bulk access, container-level SAS tokens offer a more efficient and manageable solution compared to blob-level tokens. By optimizing your approach to SAS token management, you can ensure secure, scalable, and high-performing access to your Azure Blob Storage resources.
Top comments (0)