azureazure-functionsazure-managed-identity

Azure Subscriber Function not running with Managed Identity


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):

enter image description here

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?


Solution

  • 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 :

    enter image description here

     "ServiceBusConnection__fullyQualifiedNamespace": "<Servicebus_Namespace>.servicebus.windows.net",
     "User_Assigned_Client_Id": "<Client_ID>",
    

    enter image description here

    Portal:

    enter image description here

    enter image description here