Does cosmosdb persistence support managed identity?

Hi

we are using cosmosdb as our persisence for sagas, does nservicebus cosmosdb persistence package support azure managed identity ?

thanks -Nen.

we tried the following
//in the code
persistence.CosmosClient(new CosmosClient(connection,new DefaultAzureCredential()));

and deployed to azure and are running into the following issue. We use server less cosmosdb.

however if we use the connection string with the access key, the saga gets created.

--------------------error-----------

Inner exception NServiceBus.Persistence.CosmosDB.TransactionalBatchOperationException handled at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw:
at NServiceBus.Persistence.CosmosDB.SagaSave.Conflict (NServiceBus.Persistence.CosmosDB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c: //src/NServiceBus.Persistence.CosmosDB/Saga/SagaOperations.cs:41)
at NServiceBus.Persistence.CosmosDB.TransactionalBatchExtensions+d__1.MoveNext (NServiceBus.Persistence.CosmosDB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c: /
/src/NServiceBus.Persistence.CosmosDB/SynchronizedStorage/TransactionalBatchExtensions.cs:57)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at NServiceBus.Persistence.CosmosDB.StorageSession+d__4.MoveNext (NServiceBus.Persistence.CosmosDB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c: //src/NServiceBus.Persistence.CosmosDB/SynchronizedStorage/StorageSession.cs:64)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at NServiceBus.LoadHandlersConnector+d__1.MoveNext (NServiceBus.Core, Version=7.0.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c: /
/src/NServiceBus.Core/Pipeline/Incoming/LoadHandlersConnector.cs:57)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at NServiceBus.Persistence.CosmosDB.CurrentSharedTransactionalBatchBehavior+d__1.MoveNext (NServiceBus.Persistence.CosmosDB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c: //src/NServiceBus.Persistence.CosmosDB/SynchronizedStorage/CurrentSharedTransactionalBatchBehavior.cs:18)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at NServiceBus.ScheduledTaskHandlingBehavior+d__1.MoveNext (NServiceBus.Core, Version=7.0.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c: /
/src/NServiceBus.Core/Scheduling/ScheduledTaskHandlingBehavior.cs:22)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at NServiceBus.InvokeSagaNotFoundBehavior+d__0.MoveNext (NServiceBus.Core, Version=7.0.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c: //src/NServiceBus.Core/Sagas/InvokeSagaNotFoundBehavior.cs:16)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at NServiceBus.DeserializeMessageConnector+d__1.MoveNext (NServiceBus.Core, Version=7.0.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c: /
/src/NServiceBus.Core/Pipeline/Incoming/DeserializeMessageConnector.cs:33)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at ReceivePerformanceDiagnosticsBehavior+d__0.MoveNext (NServiceBus.Metrics, Version=3.0.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at NServiceBus.InvokeAuditPipelineBehavior+d__1.MoveNext (NServiceBus.Core, Version=7.0.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c: //src/NServiceBus.Core/Audit/InvokeAuditPipelineBehavior.cs:18)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at NServiceBus.ProcessingStatisticsBehavior+d__0.MoveNext (NServiceBus.Core, Version=7.0.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c: /
/src/NServiceBus.Core/Performance/Statistics/ProcessingStatisticsBehavior.cs:25)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at NServiceBus.TransportReceiveToPhysicalMessageConnector+d__1.MoveNext (NServiceBus.Core, Version=7.0.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c: //src/NServiceBus.Core/Pipeline/Incoming/TransportReceiveToPhysicalMessageConnector.cs:37)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at NServiceBus.RetryAcknowledgementBehavior+d__2.MoveNext (NServiceBus.Core, Version=7.0.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c: /
/src/NServiceBus.Core/ServicePlatform/Retries/RetryAcknowledgementBehavior.cs:25)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at NServiceBus.MainPipelineExecutor+d__1.MoveNext (NServiceBus.Core, Version=7.0.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c: //src/NServiceBus.Core/Pipeline/MainPipelineExecutor.cs:35)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at NServiceBus.TransportReceiver+d__5.MoveNext (NServiceBus.Core, Version=7.0.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c: /
/src/NServiceBus.Core/Transports/TransportReceiver.cs:58)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at NServiceBus.TransportReceiver+d__5.MoveNext (NServiceBus.Core, Version=7.0.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c: /_/src/NServiceBus.Core/Transports/TransportReceiver.cs:64)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)

Good day Nen,

Based on the stack trace above, it looks like saving the saga failed with a concurrency conflict. Before we attempt to save the saga, we usually try to load the document first with a Get request against the container. This would mean the Get was successful, but the save not. Which would indicate a concurrency problem but not an actual connection problem.

Did you have multiple messages at the same time trying to start the saga at the time of the stack trace? Or is this something that happens as soon as you switch to managed identity?

Regards
Daniel

this happens as soon as we switch to managed identity connection string.

Thanks

Hi Nen,

I have just done the following:

  1. Created a user assigned manged identity
  2. Created a serverless cosmosdb instance
  3. Created an AKS cluster and assigned the identity to the pod
  4. Deployed a pod using the simple CosmosDB sample

Everything works as expected.

As a baseline, I used

to speed up the process.

the endpoint configuration looks like the following

            Host.CreateDefaultBuilder(args)
            .UseNServiceBus(ctx =>
            {
                var endpointConfiguration = new EndpointConfiguration("MyEndpoint");
                
                var persistence = endpointConfiguration.UsePersistence<CosmosPersistence>();
                persistence.DatabaseName(ctx.Configuration["Cosmos:Db"]);
                var credential = new DefaultAzureCredential();
                var cosmosClient = new CosmosClient(ctx.Configuration["Cosmos:Uri"], credential);
                persistence.CosmosClient(cosmosClient);
                persistence.DefaultContainer(ctx.Configuration["Cosmos:Container"], "/id");

                var transport = endpointConfiguration.UseTransport<LearningTransport>();
                transport.StorageDirectory(".learningtransport");
                endpointConfiguration.EnableInstallers();
                return endpointConfiguration;
            })

I used version 1.1 and version 1.0 of the persister and both worked.

My package references

    <ItemGroup>
        <PackageReference Include="Azure.Identity" Version="1.4.1" />
        <PackageReference Include="Microsoft.Azure.Cosmos" Version="3.21.0" />
        <PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
        <PackageReference Include="NServiceBus.Persistence.CosmosDB" Version="1.0" />
        <PackageReference Include="NServiceBus.Extensions.Hosting" Version="1.*" />
        <PackageReference Include="NServiceBus" Version="7.*" />
    </ItemGroup>

The connection string URI looks something like https://instancename.documents.azure.com:443/

Regards,
Daniel

1 Like

Thank you , the article and the code snippets helped, we are using webapp instead of kubernetes, the issue was twe were not configuring the MI properly.

1 Like