Reputation: 117
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.
Upvotes: 11
Views: 13298
Reputation: 10879
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:
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
:
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.
Upvotes: 4
Reputation: 590
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
Upvotes: 0
Reputation: 117
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.
Upvotes: -4
Reputation: 1112
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.
Upvotes: 6