How to run Azure Function locally using User Assigned Managed Identity configuration
Asked Answered
O

4

10

I'm trying to run an Azure Function on my local dev machine. The function is configured to use User Assigned Managed Identity to access a Service Bus resource.

When I publish this function to Azure it works perfectly fine, however when I try to run it locally I get the following exception.

Azure.Identity: ManagedIdentityCredential authentication unavailable. Multiple attempts failed to obtain a token from the managed identity endpoint. Azure.Core: Retry failed after 4 tries. Retry settings can be adjusted in ClientOptions.Retry. (A socket operation was attempted to an unreachable network. (169.254.169.254:80))

I am using ServiceBusTrigger bindings like so.

Function1.cs

[FunctionName("Function1")]
public void Run([ServiceBusTrigger("myqueue", Connection = "ServiceBusConnection")] string myQueueItem, ILogger log)
{
    log.LogInformation($"C# ServiceBus queue trigger function processed message: {myQueueItem}");
}

local.settings.json

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet",
    "ServiceBusConnection__clientId": "<my_uami_client_id",
    "ServiceBusConnection__credential": "managedIdentity",
    "ServiceBusConnection__fullyQualifiedNamespace": "my-service-bus.servicebus.windows.net"
  }
}

csproj package references

  <ItemGroup>
    <PackageReference Include="Azure.Identity" Version="1.8.0" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.ServiceBus" Version="5.9.0" />
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.3" />
  </ItemGroup>

My Visual Studio IDE is configured to use my user account for Azure Service Authentication. From what I understand, VS should try to authenticate with DefaultAzureCredential and iterate through the following credential types: EnvironmentCredential, ManagedIdentityCredential, SharedTokenCacheCredential, InteractiveBrowserCredential

I was expecting VS to successfully authenticate with my selected user account, but the exception message would suggest that it is failing at the ManagedIdentityCredential option.

Does anyone know what I might be missing here? Thanks in advance.

Obeisance answered 4/4, 2023 at 13:37 Comment(0)
O
-4

I managed to get access to another Azure subscription and I was able to successfully run my Azure Function locally - as described above.

Subsequently, I think the issue is somehow linked to the first subscription I was using. Anyway, I'm unblocked and the issue seemed to be at my end, so I'm closing this question now.

Obeisance answered 6/4, 2023 at 12:54 Comment(1)
Your question was specifically about using a managed identity locally!Gunman
G
5

Managed Identities do not work locally. Under the hood, it uses a certificate, which is installed in the Azure resource, which, obviously, your local machine does not have.

Gunman answered 4/4, 2023 at 16:30 Comment(2)
Is that still true today? When I read the Microsoft documentation it states: Local machines don't support managed identities for Azure resources. As a result, the Azure.Identity library uses your developer credentials to run in your local development environment. For local development, AzureServiceTokenProvider fetches tokens using Visual Studio, Azure command-line interface (CLI), or Azure AD Integrated Authentication. Each option is tried sequentially and the library uses the first option that succeedsObeisance
Authenticate via Visual Studio Developers using Visual Studio 2017 or later can authenticate an Azure AD account through the IDE. Applications using the DefaultAzureCredential or the VisualStudioCredential can then use this account to authenticate calls in their application when running locally.Obeisance
L
3

This is not an authoritative answer but it may help others find a workaround and was too long for comments.

Research:

These two official docs seem to talk around the topic:

https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=portal%2Cjavascript

https://learn.microsoft.com/en-us/javascript/api/overview/azure/identity-readme?view=azure-node-latest#authenticate-the-client-in-development-environment

The latter starts with:

While we recommend using managed identity or service principal authentication in your production application, it is typical for a developer to use their own account for authenticating calls to Azure services when debugging and executing code locally. There are several developer tools which can be used to perform this authentication in your development environment.

Solution

The only way I got it working for my scenario was:

  • Create an 'App registration' with Sites.Selected permissions

  • Create a secret, and note its secret value and the client id of the app registration

  • Grant it 'Write' permissions to a specific site using the /permissions endpoint in Graph API

  • (the above action requires another App registration with the required permissions to grant that permission)

  • Add these values to your Function App's local.settings.json:

    • AZURE_CLIENT_ID
    • AZURE_TENANT_ID
    • AZURE_CLIENT_SECRET

In a local environment, it will use these values, in a live environment it will use the Managed Identity.

The code I am using to get a token is:

const { DefaultAzureCredential } = require("@azure/identity");
const credential = new DefaultAzureCredential();
const token = await credential.getToken("https://graph.microsoft.com/.default");

So this works, but it seems illogical that I need an App registration in order to test Function Apps with Managed Identities in a local environment. I would prefer to just have a Managed Identity, that somehow works in a local development environment as well.

What Didn't Work

Without creating an app registration, I tried login via local terminal Azure CLI az login with my ADMIN account (which can do anything).

I started an Azure function locally with func start and made a call to the local function endpoint via Postman.

I got a 403 error when my function is trying to retrieve items from a SharePoint library.

When I look at the token that is returned from:

const credential = new DefaultAzureCredential(); 
const token = await credential.getToken("https://graph.microsoft.com/.default");

at https://jwt.ms, the scp value is:

AuditLog.Read.All Directory.AccessAsUser.All email Group.ReadWrite.All openid profile User.ReadWrite.All

So those permissions did not allow me to get items from a SharePoint library.

Lundy answered 7/11, 2023 at 9:59 Comment(0)
P
0

You do not have a Managed Service Identity on your local machine.

But you do! Visual Studio uses the credentials of the logged in user of Visual Studio. So If you make use of the MSI while debugging locally make sure the user that is logged in into Visual Studio has the proper rights within Azure

Putter answered 21/6, 2023 at 19:8 Comment(0)
O
-4

I managed to get access to another Azure subscription and I was able to successfully run my Azure Function locally - as described above.

Subsequently, I think the issue is somehow linked to the first subscription I was using. Anyway, I'm unblocked and the issue seemed to be at my end, so I'm closing this question now.

Obeisance answered 6/4, 2023 at 12:54 Comment(1)
Your question was specifically about using a managed identity locally!Gunman

© 2022 - 2024 — McMap. All rights reserved.