Azure Blob and Queue Storage is a low-cost solution to store and access unstructured data at scale. Queues integrate easily with managed identities, which are appealing because secrets such as connection strings are not required to be copied onto developers’ machines or checked into source control. In this guide, you will learn how to use managed identities to connect a .NET app service to Azure Blob Storage and Azure Queue Storage.
In Azure, a managed identity allows an Azure resource to have an identity created for it automatically in Azure Active Directory (AD). This allows these resources to identify themselves to other protected Azure resources, such as storage accounts, using Azure AD authentication. This guide will look at using managed identities with Azure App Services.
Azure App Services supports both user-assigned and system-assigned managed identities. There are a few differences:
To start using an Azure App Service managed identities, create a new project and install a few packages.
Microsoft's newest packages make it easy to do this with minimal code. Run the following commands in the command prompt:
1mkdir PLStorageManagedIdentity
2cd PLStorageManagedIdentity
3dotnet new mvc
4dotnet add package Azure.Storage.Blobs
5dotnet add package Azure.Identity
6dotnet add package Microsoft.Extensions.Azure
The code above creates a new MVC project and installs Azure.Storage.Blobs
, Azure.Identity
, and Microsoft.Extensions.Azure
.
Azure.Identity
is a generic package that allows you to fetch tokens to authorize with differences protected Azure resources.
Then update your Startup.cs
file to register Blob Services for dependency injection.
1// Startup.cs
2public void ConfigureServices(IServiceCollection services)
3{
4 services.AddControllersWithViews();
5 services.AddAzureClients(cfg =>
6 {
7 cfg.AddBlobServiceClient(Configuration.GetSection("Blobs")).WithCredential(new Azure.Identity.DefaultAzureCredential());
8 });
9}
The code above will look at your configuration, such as AppSettings.json
, to determine which Azure Storage Blob account to connect.
If it is run on your development machine, it will use Visual Studio or Azure CLI to attempt to authenticate.
When run in the Azure App Service, it will use the user-assigned identity discussed above.
To configure the Azure Storage Blob account, you can update AppSettings.json
to the following:
1{
2 "Logging": {
3 "LogLevel": {
4 "Default": "Information",
5 "Microsoft": "Warning",
6 "Microsoft.Hosting.Lifetime": "Information"
7 }
8 },
9 "AllowedHosts": "*",
10 "Blobs": {
11 "ServiceUri": "https://xxxxxxxx.blob.core.windows.net/"
12 }
13}
Note that no secrets like connection strings or passwords are required.
You will also need to make sure your identities have the correct roles for the Azure Storage Blob account.
If you need read and write access, assign the Storage Blob Data Contributor
built-in role.
Finally, to use the newly registered blob services, update HomeController.cs
with the following:
1public HomeController(ILogger<HomeController> logger, BlobServiceClient blobServiceClient)
2{
3 _logger = logger;
4 _blobContainerClient = blobServiceClient.GetBlobContainerClient("artifacts");
5}
6private readonly BlobContainerClient _blobContainerClient;
7
8public IActionResult Blob()
9{
10 var result = new { exists = _blobContainerClient.Exists() };
11 return Json(result);
12}
With your roles set up correctly, you can now read and write to the blob container. Queue storage and file storage services can be also be authenticated in a similar way.
So far, the code above only connects to one storage account. The Azure SDK also makes it easy to connect to multiple storage accounts.
1services.AddAzureClients(cfg =>
2{
3 cfg.AddBlobServiceClient(Configuration.GetSection("Blobs")).WithCredential(new Azure.Identity.DefaultAzureCredential());
4 cfg.AddBlobServiceClient(Configuration.GetSection("Inputs")).WithName("Inputs").WithCredential(new Azure.Identity.DefaultAzureCredential());
5});
You have created a named registration and a default registration.
They are configured separately in the AppSettings.json
file.
1{
2 "Blobs": {
3 "ServiceUri": "https://xxxxxxxx.blob.core.windows.net/"
4 },
5 "Inputs": {
6 "ServiceUri": "https://yyyyyyyy.blob.core.windows.net/"
7 }
8}
There are two separate ServiceUri
s set. There are two configuration sections, one called Blobs
and one called Inputs
.
To access them in the rest of your code, you need to use the IAzureClientFactory
.
1public HomeController(
2 ILogger<HomeController> logger,
3 IAzureClientFactory<BlobServiceClient> clientFactory,
4 BlobServiceClient blobServiceClient)
5{
6 _logger = logger;
7 var client2 = clientFactory.CreateClient("Inputs");
8 _blobContainerClient = blobServiceClient.GetBlobContainerClient("artifacts");
9}
If you want to access the default Azure Storage Blob Account, you can directly inject BlobServiceClient
to the constructor.
If you want to access a named registration, you need to inject the IAzureClientFactory<T>
and call its CreateClient("Inputs")
method.
This is similar to using the HttpClientFactory
.
Microsoft Azure has a growing list of services that support managed identities for Azure resources. Using this feature can enhance the security of your application since you don't need to manage secrets yourself. To build on these skills, read about How to Define Azure Role-based Access Control (RBAC).