I have an Azure Subscriber Function listening to a Service Bus topic. It is working perfectly under Service Bus connectionString settings. However, I want to convert this to run under Managed Identity. I have already checked few links like this and this with few other topics from Microsoft Learn but couldn't help.
What I have done: Under Service Bus IAM, assigned Azure Service Bus Data Receiver and Azure Service Bus Data Sender roles to the previously deployed Subscriber Function (that was running under connectionString). Also added a Data Owner role to myself for testing purposes (which I don't need actually):
code is like this: where \new indicates new lines that I have added to my existing code.
public class Subscriber1
{
private readonly ILogger<Subscriber1> _logger;
public Subscriber1(ILogger<Subscriber1> logger)
{
_logger = logger;
}
[Function(nameof(Subscriber1))]
public async Task Run(
[ServiceBusTrigger("topic", "Subscriber1", Connection = "SBConnectionString")]
ServiceBusReceivedMessage message,
ServiceBusMessageActions messageActions)
{
var userAssignedClientId = Environment.GetEnvironmentVariable("User_Assigned_Client_Id"); //new
var credential = new DefaultAzureCredential(
new DefaultAzureCredentialOptions
{
ManagedIdentityClientId = userAssignedClientId
}); //new
var fullyQualifiedNamespace = Environment.GetEnvironmentVariable("SBConnectionString__fullyQualifiedNamespace"); //new
var client = new ServiceBusClient(fullyQualifiedNamespace, credential); //new
var processor = client.CreateProcessor("topic", new ServiceBusProcessorOptions()); //new
_logger.LogInformation("Message ID: {id}", message.MessageId);
_logger.LogInformation("Message Body: {body}", message.Body);
_logger.LogInformation("Message Content-Type: {contentType}", message.ContentType);
// Complete the message
await messageActions.CompleteMessageAsync(message);
}
}
local.settings.json file
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
"SBConnectionString": "", /* I have left that blank, what should I enter here? */
"SBConnectionString__fullyQualifiedNamespace": "domainname.servicebus.windows.net",
"User_Assigned_Client_Id": "object id of the subcriber function"
}
}
So what should I do to make it work a) locally and b) after deployment?
Add Azure_Tenant_ID
app setting in local.settings.json
:
local.settings.json:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
"SBConnectionString__fullyQualifiedNamespace": "<Servicebus_namespace>.servicebus.windows.net",
"User_Assigned_Client_Id": "<CLient_ID>",
"AZURE_TENANT_ID": "<Tenant_ID>"
}
}
[Function(nameof(Function1))]
public async Task Run(
[ServiceBusTrigger("topic1", "subscriber1", Connection = "SBConnectionString")]
ServiceBusReceivedMessage message,
ServiceBusMessageActions messageActions)
{
var userAssignedClientId = Environment.GetEnvironmentVariable("User_Assigned_Client_Id");
var credential = new DefaultAzureCredential(
new DefaultAzureCredentialOptions
{
ManagedIdentityClientId = userAssignedClientId
});
var fullyQualifiedNamespace = Environment.GetEnvironmentVariable("SBConnectionString__fullyQualifiedNamespace");
var client = new ServiceBusClient(fullyQualifiedNamespace, credential);
var processor = client.CreateProcessor("topic", new ServiceBusProcessorOptions());
_logger.LogInformation("Message ID: {id}", message.MessageId);
_logger.LogInformation("Message Body: {body}", message.Body);
_logger.LogInformation("Message Content-Type: {contentType}", message.ContentType);
await messageActions.CompleteMessageAsync(message);
}
Local response :
Function App=>Environment Variables
: "ServiceBusConnection__fullyQualifiedNamespace": "<Servicebus_Namespace>.servicebus.windows.net",
"User_Assigned_Client_Id": "<Client_ID>",
Azure Service Bus Data Owner
role to User Assigned Managed Identity.Portal: