Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Azure Managed Identity in Azure Function to access Service Bus with a trigger?

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://docs.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.

like image 377
Yuhis Avatar asked Aug 20 '18 14:08

Yuhis


3 Answers

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
like image 195
Ilya Chernomordik Avatar answered Sep 28 '22 04:09

Ilya Chernomordik


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.

like image 36
Joey Cai Avatar answered Sep 28 '22 02:09

Joey Cai


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

like image 21
Rishabh Ajmera Avatar answered Sep 28 '22 03:09

Rishabh Ajmera