16

I have created a ServiceBus namespace in Azure, along with a topic and a subscription. I also have a simple Azure version 1 function that triggers on a received topic in the ServiceBus, like this:

[FunctionName("MyServiceBusTriggerFunction")]
public static void Run([ServiceBusTrigger("myTopic", "mySubscription", Connection = "MyConnection")]string mySbMsg, TraceWriter log)
{
    log.Info($"C# ServiceBus topic trigger function processed message: {mySbMsg}");
}

The function triggers nicely for the topics in the ServiceBus when I define the connection string in functions Application Settings by using Shared Access Policy for topic, like this:

Endpoint=sb://MyNamespace.servicebus.windows.net/;SharedAccessKeyName=mypolicy;SharedAccessKey=UZ...E0=

Now, instead of Shared Access Keys, I would like to use Managed Service Identity (MSI) for accessing the ServiceBus. According to this (https://learn.microsoft.com/en-us/azure/active-directory/managed-service-identity/services-support-msi) it should be possible, unless I have misunderstood something. I haven't managed to get it working though.

What I tried, was to

  • set the Managed Service Identity "On" for my function in Azure portal
  • give Owner role for the function in ServiceBus Access Control section in Azure Portal
  • set the connection string for MyFunction like this: Endpoint=sb://MyNamespace.servicebus.windows.net/

The function is not triggering in this set-up, so what am I missing or what am I doing wrong? I'd be grateful for any advice to help me get further. Thanks.

Ilya Chernomordik
  • 27,817
  • 27
  • 121
  • 207
Yuhis
  • 502
  • 8
  • 16
  • 1
    i doubt thats how it works. i think its only used to allow the code to connect to the resource. i dont think you can use MSI for polling on the function level – 4c74356b41 Aug 20 '18 at 15:35
  • So if I wanted to use MSI for accessing ServiceBus from an Azure Function, I would need to create e.g. a timer triggered function and poll ServiceQueue from within it. – Yuhis Aug 21 '18 at 15:09
  • i'm not sure really, so dont take my word for it, but I really doubt MSI can replace connection string for this scenario – 4c74356b41 Aug 21 '18 at 15:11
  • 1
    As mentioned one trick is to use Key Vault to hold the connection strings, native MSI is not supported for triggers as yet and there's an [Azure Feedback](https://feedback.azure.com/forums/355860-azure-functions/suggestions/37907848-support-for-azure-managed-service-identities-in-ev) item to register interest – Paul Hatcher Jan 24 '21 at 17:11

3 Answers3

9

Update for Microsoft.Azure.WebJobs.Extensions.ServiceBus version 5.x

There is now an offical docs for the latest version of the package in here.

{
  "Values": {
    "<connection_name>__fullyQualifiedNamespace": "<service_bus_namespace>.servicebus.windows.net"
  }
}

Previous answer:

This actually seems to be possible now, at least worked just fine for me. You need to use this connection string:

Endpoint=sb://service-bus-namespace-name.servicebus.windows.net/;Authentication=ManagedIdentity

I have not actually found any documentation about this on Microsoft site, but in a blog here.

Microsoft does have documentation though on roles that you can use and how to limit them to scope in here. Example:

az role assignment create \
    --role $service_bus_role \
    --assignee $assignee_id \
    --scope /subscriptions/$subscription_id/resourceGroups/$resource_group/providers/Microsoft.ServiceBus/namespaces/$service_bus_namespace/topics/$service_bus_topic/subscriptions/$service_bus_subscription
Ilya Chernomordik
  • 27,817
  • 27
  • 121
  • 207
  • This should be the accepted answer. We now have documentation outlining this here: https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-service-bus-trigger?tabs=in-process%2Cextensionv5&pivots=programming-language-csharp#identity-based-connections – Will V May 17 '22 at 23:18
  • 1
    It's worth noting that 'Microsoft.Azure.WebJobs.Extensions.ServiceBus' is for in-process Azure Functions. If you using Isolated Azure Functions, you should be using 'Microsoft.Azure.Functions.Worker.Extensions.ServiceBus' and you want the version >= 5.0.0 – David Yates Sep 15 '22 at 19:59
  • @DavidYates, Does it work for 'Microsoft.Azure.Functions.Worker.Extensions.ServiceBus', because I tried to follow documentation but didn't work for Isolated? – Viorel Feb 06 '23 at 22:16
  • 1
    @Viorel. Yes. I did get it working for Azure Functions with .NET 6 and isolated functions. A couple of things to check 1) It requires that the managed identity and YOU have the following roles in the service bus: 'Azure Service Bus Data Receiver' and 'Azure Service Bus Data Sender' You need these roles because YOU are the managed identity running locally. 2) With isolated Azure Functions make sure your connection string is in the local.settings.json when running locally. Unless they've fixed in .NET 7, there some weirdness around connection strings for service bus when debugging locally. – David Yates Feb 07 '23 at 00:54
  • @DavidYates, thank you for help, I fixed yesterday. My issues was in 'Microsoft.Azure.Functions.Worker.Extensions.ServiceBus' version was under 5.0.0 and I can't figure out what was going wrong. Locally I started the project at least but on environment, it just read the value from '__fullyQualifiedNamespace' but not found as connection. And yes, on locally something strange happened but I change namespace connection with string connection which point on another service bus. – Viorel Feb 07 '23 at 16:36
  • Thanks, upgradiong my package to version 5.x allows me to use managed identity, thanks! – michasaucer Jun 12 '23 at 13:11
4

what am I missing or what am I doing wrong?

You may mix up with MSI and Shared Access Policy.They are using different provider to access to Azure servicebus. You could just use connectionstring or just use MSI to authenticate.

When you use Managed Service Identity(MSI) to authenticate, you need to create a token provider for the managed service identity with the following code.

TokenProvider.CreateManagedServiceIdentityTokenProvider(ServiceAudience.ServiceBusAudience).

This TokenProvider's implementation uses the AzureServiceTokenProvider found in the Microsoft.Azure.Services.AppAuthentication library. AzureServiceTokenProvider will follow a set number of different methods, depending on the environment, to get an access token. And then initialize client to operate the servicebus. For more details, you could refer to this article.

When you use servicebus connectionstring to access which using the Shared Access Token (SAS) token provider, so you can operate directly.

Joey Cai
  • 18,968
  • 1
  • 20
  • 30
  • 4
    An Azure Function with ServiceBusTrigger requires a connection string as an argument. When it is triggered to run, it already needs to be authorized. It is too late to create a TokenProvider for MSI at that point, so looks like I can not use it. I thought MSI was supposed to handle access tokens behind the scenes, but that does not seem to be the case. Right? – Yuhis Aug 21 '18 at 15:10
  • 2
    Actually that! You could not use MSI to authenticate servicebus trigger function. – Joey Cai Aug 22 '18 at 01:22
  • There is a built-in way now with the latest package, please see my answer below – Ilya Chernomordik Jul 16 '21 at 19:55
4

Agreed that from azure function we cannot access the resource like ASB directly. However, one still does not need to put in the password in this case "SharedAccessKeyName" in the connectionstring directly. Azure function can work with Azure KeyVault. Thus one can store the connectionstring with sensitive information as a secret in the KeyVault and then grant System assigned identity from azure functions access over KeyVault and then specify the value for the settings in the portal as @Microsoft.KeyVault(SecretUri={theSecretUri}) Details on how to achieve the above is mentioned in the following blog. https://medium.com/statuscode/getting-key-vault-secrets-in-azure-functions-37620fd20a0b

This will still avoid specifying the connectionstring directly in Azure functions and provides with single point of access via Vault to be disabled in case of a security breach

  • 1
    Yes, keyvault reference is a really nice feature that I am looking forward to becoming generally available. Unfortunately it is still in preview at the moment (Aug 2019), so I am a bit hesitant to putting it to use in production yet. (https://learn.microsoft.com/en-us/azure/app-service/app-service-key-vault-references) – Yuhis Aug 05 '19 at 09:58
  • There is a built-in way now with the latest package, please see my answer below – Ilya Chernomordik Jul 16 '21 at 19:55