Author avatar

Benney Au

How to Use Managed Identities with Azure Service Bus

Benney Au

  • Oct 16, 2020
  • 7 Min read
  • 64 Views
  • Oct 16, 2020
  • 7 Min read
  • 64 Views
Cloud
Cloud Application Development
Microsoft Azure
Cloud Application Development

Introduction

Many cloud applications rely on asynchronous messaging to improve reliability and decouple different parts of a solution. You can use Azure Service Bus as a cloud messaging service to achieve these goals. One big advantage of Azure Service Bus is that it supports managed identities, a Microsoft Azure feature that allows your applications to authenticate or authorize themselves with Azure Service Bus. The appeal is that secrets such as connection strings are not required to be copied onto developers’ machines or checked into source control.

Microsoft has recently updated their Azure Service Bus .NET SDKs to make working with managed identities easier. In this guide, you will learn how to use managed identities to connect a .NET App Service to Azure Service Bus.

Set up Managed Identities with Roles

To get started working with App Service managed identities and Service Bus, you need to create a few resources.

You can do this easily using the Azure CLI:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
rg=my-resource-group
webapp=my-app-name
erviceplan=my-sp
servicebus=demo-pl-service-bus

# create app service plan and app service
az appservice plan create --is-linux --sku f1 -g $rg -n $serviceplan
az webapp create -g $rg -p $serviceplan -n $webapp -r "dotnetcore|3.1"
az webapp identity assign -g $rg -n $webapp
APP_IDENTITY=$(az webapp identity show -n $webapp -g $rg --query "{principalId:principalId}" -o tsv)

# create service bus and queue
az servicebus namespace create --sku standard -g $rg -n $servicebus
queue_id=$(az servicebus queue create -n test --namespace-name $servicebus -g $rg -o tsv --query "{id:id}")

# assign roles to listen and send messages to the queue
az role assignment create --role "Azure Service Bus Data Receiver" --assignee $APP_IDENTITY --scope $queue_id
az role assignment create --role "Azure Service Bus Data Sender" --assignee $APP_IDENTITY --scope $queue_id
sh

These commands do three things: 1. Create an app service plan and Azure App Service with a system-assigned identity 2. Create a Service Bus namespace and a queue 3. Use Role-based Access Control (RBAC) to grant the newly created app service's managed identity to receive and send messages to the test queue

Install the .NET SDK for Azure Service Bus

Microsoft has several .NET SDKs for interacting with Azure Service Bus. The latest at the time of writing is called the Service Bus Track 2 Library and it has a NuGet package named Azure.Messaging.ServiceBus.

This package is currently in pre-release, and it is the easiest to integrate with managed identities.

To start using this package in an ASP.NET Core application, run the following commands from your project:

1
2
3
dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.Azure
dotnet add package Azure.Messaging.ServiceBus --version 7.0.0-preview.8
sh

Update Your Code

With all the resources created and roles assigned, you need to update your code to get everything working.

Start by updating your Startup.cs method and register a new HostedService to listen to messages and register the ServiceBusClient.

1
2
3
4
5
services.AddHostedService<ServiceBusHostedService>();
services.AddAzureClients(cfg =>
{
  cfg.AddServiceBusClient(Configuration.GetSection("ServiceBus")).WithCredential(new Azure.Identity.DefaultAzureCredential());
});
csharp

This code reads the Service Bus location from a configuration such as AppSettings.json. This is ideal especially if you have multiple environments and use different Service Bus namespaces staging and production.

Add the following configuration to your AppSettings.json.

1
2
3
4
5
{
  "ServiceBus": {
    "FullyQualifiedNamespace": "xxxxxxxx.servicebus.windows.net"
  }
}
json

To actually listen to messages, create the class ServiceBusHostedService and add the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class ServiceBusHostedService : IHostedService
{
    private readonly ServiceBusClient _serviceBusClient;
    private ServiceBusProcessor _processor;

    public ServiceBusHostedService(ServiceBusClient serviceBusClient)
    {
        _serviceBusClient = serviceBusClient;
    }

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        _processor = _serviceBusClient.CreateProcessor("test");

        _processor.ProcessMessageAsync += ProcessMessageAsync;
        _processor.ProcessErrorAsync += ProcessErrorAsync;

        await _processor.StartProcessingAsync(cancellationToken);
    }

    private Task ProcessErrorAsync(ProcessErrorEventArgs arg)
    {
        return Task.CompletedTask;
    }

    private Task ProcessMessageAsync(ProcessMessageEventArgs arg)
    {
        // perform your business logic to process messages

        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        return _processor.CloseAsync(cancellationToken: cancellationToken);
    }
}
csharp

Your code is now listening for new Service Bus messages in the background using IHostedService in ASP.NET Core.

To send messages, inject the ServiceBusClient class and call the CreateSender() method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public ServiceBusSender _serviceBusSender { get; private set; }

public HomeController(
    ILogger<HomeController> logger,
    ServiceBusClient serviceBusClient)
{
    _logger = logger;
    _serviceBusSender = serviceBusClient.CreateSender("test");
}

[HttpPost("post-message")]
public async Task<IActionResult> Message(MyModel model)
{
    var message = new ServiceBusMessage(Azure.BinaryData.FromObjectAsync(model)));
    await _serviceBusSender.SendMessageAsync(message);
    return Accepted();
}
csharp

Notice that in all the code samples, no connection string or client secret was required. This authorization is handled for you. When you are working on your local development machine, you use your Azure CLI credentials or Visual Studio credentials to authorize against these protected resources. When the app is running the Azure App Service, it uses managed identities for authentication.

Conclusion

Azure Service Bus provides reliable cloud messaging as a service. If you learn to use the newer SDKs, you can make your application more secure and develop features faster. To learn more about the latest developments in Azure Service Bus' .NET SDK, read Microsoft's GitHub Repository's Service Bus issues.

1