Azure / azure-webjobs-sdk-extensions

Azure WebJobs SDK Extensions
MIT License
342 stars 206 forks source link

CosmosDB 4.0.0-preview1 always throws an exception when AAD authentication is configured #741

Closed shibayan closed 3 years ago

shibayan commented 3 years ago

Whenever I set up and run CosmosDBTrigger or CosmosDB to use AAD authentication, it throws a NullReferenceException and fails to start.

I checked and found that AzureComponentFactory is always passed null for DefaultCosmosDBServiceFactory. The root cause seems to be that AddAzureClientsCore is not registered in the DI.

Example (Service Bus Extension) : https://github.com/Azure/azure-sdk-for-net/blob/4162f6fa2445b2127468b9cfd080f01c9da88eba/sdk/servicebus/Microsoft.Azure.WebJobs.Extensions.ServiceBus/src/Config/ServiceBusHostBuilderExtensions.cs#L91-L93

Repro steps

  1. Create new function (v3) project
  2. Add CosmosDBTrigger function
  3. Update Microsoft.Azure.WebJobs.Extensions.CosmosDB version 4.0.0-preview1
  4. Setup RBAC and connection string
  5. Run function app

Expected behavior

An error always occurs when starting Function.

[2021-09-01T15:07:18.499Z] Microsoft.Azure.WebJobs.Host: Error indexing method 'Function2'. 
Microsoft.Azure.WebJobs.Extensions.CosmosDB: Cannot create container information for TodoItem in database SampleDB with lease leases in database SampleDB : Object reference not set to an instance of an object. 
Microsoft.Azure.WebJobs.Extensions.CosmosDB: Object reference not set to an instance of an object.
[2021-09-01T15:07:18.536Z] Error indexing method 'Function2'

Actual behavior

CosmosDBTrigger and Managed Identity can be used without any errors.

Known workarounds

Related information

ealsur commented 3 years ago

@shibayan Yes, I think the issue is that AddAzureClientsCore(); is not being called, I was under the impression that this needed to be done by the client application.

If you add it to your Function initialization, does it work correctly?

shibayan commented 3 years ago

@ealsur Yes, it works. It did work by installing Microsoft.Azure.Functions.Extensions and adding the following startup code. It seems to be caused by the lack of AddAzureClientsCore.

For other Azure AD supported Function Extensions (Storage / Event Hubs / Service Bus), I think it is better to match the behavior since the extension will automatically register them.

Workaround code

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.Azure;

[assembly: FunctionsStartup(typeof(FunctionApp24.Startup))]

namespace FunctionApp24
{
    class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddAzureClientsCore();
        }
    }
}
ealsur commented 3 years ago

@shibayan sent a PR with the fix, thanks for reporting

shibayan commented 3 years ago

@ealsur Wow! Thanks for the quick response!

ealsur commented 3 years ago

Should be fixed in preview2 release

shahabganji commented 1 year ago

@ealsur, I have the same issue with preview2, and even calling services.AddAzureClientsCore(); did not help.

Here is the local.settings.json file:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
    "CosmosConnectionInfo__accountEndpoint": "https://<my-cosmosdb-account-name>.documents.azure.com:443/",
    "CosmosConnectionInfo__credential": "managedidentity",
    "CosmosDatabase": "Crm"
  },
  "ConnectionStrings": {
      // omitted for brevity
  }
}

and my function looks like:

public class CosmosDBSampleFunction
{
    [Function(nameof(CosmosDBSampleFunction))]
    public async Task Run([CosmosDBTrigger(
            databaseName: "%CosmosDatabase%",
            containerName: "MyContainer",
            Connection = "CosmosConnectionInfo",
            LeaseContainerName = "leases",
            CreateLeaseContainerIfNotExists = true
        )]
        IReadOnlyList<JsonObject> inputs, FunctionContext context)
    {
        foreach (var input in inputs)
        {
           // do the operation
        }
    }
}

and the NuGet packages:

        <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.8.0-preview2" />
        <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.CosmosDB" Version="4.0.0-preview2" />
        <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="5.0.1" />
Microsoft.Azure.WebJobs.Extensions.CosmosDB: Cosmos DB connection configuration 'CosmosConnectionInfo' does not exist. Make sure that it is a defined App Setting.

PS: As you may have noted the function app is using dotnet-isolated, Isolated Worker rather than Default Worker

ealsur commented 1 year ago

@shahabganji You are not using Microsoft.Azure.Functions.Extensions.CosmosDB but Microsoft.Azure.Functions.Worker.Extensions.CosmosDB, these are different packages. I am not sure how Microsoft.Azure.Functions.Worker.Extensions.CosmosDB is generated so I cannot comment on what is expected for that package.

https://github.com/Azure/azure-webjobs-sdk-extensions/pull/742 changed the source code of Microsoft.Azure.Functions.Extensions.CosmosDB and added the tests required for this scenario.

shahabganji commented 1 year ago

Thanks, @ealsur! Yes, we are using the isolated process for the azure functions. Maybe it is not yet supported :(