Connect Azure CosmosDB using Managed Identities from Azure Function App both locally and on Azure

PingpongSet 36 Reputation points
2022-02-17T11:09:42.01+00:00

I create a Managed Identity for a Function app and assigned it to DocumentDB Account Contributor by following the two sections below

https://learn.microsoft.com/en-us/azure/cosmos-db/managed-identity-based-authentication#assign-a-system-assigned-managed-identity-to-a-function-app

https://learn.microsoft.com/en-us/azure/cosmos-db/managed-identity-based-authentication#grant-access-to-your-azure-cosmos-account

Microsoft.Azure.Services.AppAuthentication

I got an exception when I tried to run the code from the section below:

https://learn.microsoft.com/en-us/azure/cosmos-db/managed-identity-based-authentication#programmatically-access-the-azure-cosmos-db-keys

Could not load file or assembly 'System.Text.Encodings.Web,
Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
The system cannot find the file specified.
at
System.Text.Json.Serialization.Metadata.JsonPropertyInfo.DeterminePropertyName()
at
System.Text.Json.Serialization.Metadata.JsonPropertyInfo.GetPolicies(Nullable1 ignoreCondition, Nullable1 declaringTypeNumberHandling) at
...
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at
Cosmos.Samples.AzureFunctions.AzureFunctionsCosmosClientMI.<Run>d__7.MoveNext()
in
C:.ME\MyLab.Code\AzureCode\CosmosDB\azure-cosmos-dotnet-v3-usage\AzureFunctions\AzureFunctionsCosmosClientMI.cs:line
85

Azure.Identity

Since AppAuthentication is not recommended by MS, then I switched to using Azure.Identity by following the links below:
https://learn.microsoft.com/en-us/dotnet/api/overview/azure/identity-readme?view=azure-dotnet

https://joonasaijala.com/2021/07/01/how-to-using-managed-identities-to-access-cosmos-db-data-via-rbac-and-disabling-authentication-via-keys/

and the code below

 static string cosmosUrl = "https://xxx.documents.azure.com:443/";  
    private static CosmosClient client = new CosmosClient(cosmosUrl, new DefaultAzureCredential());  
   var container = client.GetContainer("FamilyDatabase", "FamilyContainer");  
        try  
        {  
            var result = await container.CreateItemAsync<Item>(data, new PartitionKey(data.LastName));  
            return new OkObjectResult(result.Resource.Id);  
        }  
        catch (CosmosException cosmosException)  
        {  
            log.LogError("Creating item failed with error {0}", cosmosException.ToString());  
            return new BadRequestObjectResult($"Failed to create item. Cosmos Status Code {cosmosException.StatusCode}, Sub Status Code {cosmosException.SubStatusCode}: {cosmosException.Message}.");  
        }  

However, I got the exception below both locally and running it in Azure.

Failed to create item. Cosmos Status Code Forbidden, Sub Status Code
5301: Response status code does not indicate success: Forbidden (403);
Substatus: 5301; ActivityId: xxxx-bf03-4355-8642-5d316f9d3373;
Reason: (Request blocked by Auth xxxx : Request is blocked because
principal [xxx-2bff-44e9-97be-9ffeb3aae3ee] does not have
required RBAC permissions to perform action
[Microsoft.DocumentDB/databaseAccounts/readMetadata] on resource [/].
Learn more: https://aka.ms/cosmos-native-rbac. ActivityId:
xxx-bf03-4355-8642-5d316f9d3373,
Microsoft.Azure.Documents.Common/2.14.0, Windows/10.0.14393
cosmos-netstandard-sdk/3.24.1);.

Locally, I logged into VS following the link
https://learn.microsoft.com/en-us/dotnet/api/overview/azure/identity-readme?view=azure-dotnet#authenticating-via-visual-studio

Any idea for resolving issues with Azure.Identity?

Ref:

https://stackoverflow.com/questions/67512766/connect-function-app-to-cosmosdb-with-managed-identity

Azure Functions
Azure Functions
An Azure service that provides an event-driven serverless compute platform.
5,029 questions
Azure Cosmos DB
Azure Cosmos DB
An Azure NoSQL database service for app development.
1,643 questions
Microsoft Entra ID
Microsoft Entra ID
A Microsoft Entra identity service that provides identity management and access control capabilities. Replaces Azure Active Directory.
21,905 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Oleksandr Pshenychnyy 0 Reputation points
    2024-09-25T15:00:46.3233333+00:00

    Hi @MughundhanRaveendran-MSFT
    I've got exactly the same problem here, and stuck a bit already. Can provide the details I have.
    My account has the following roles assigned on Cosmos DB account instance:

    As you can see, I've already assigned almost every role I could think of, - but it didn't help.

    Using the same account in Azure Data Studio, - I can view Cosmos database, and create documents, - so I assume the issue is NOT with permissions themselves.

    On the other hand, using exactly the same Visual Studio instance (with same account logged in), - I successfully connected to Azure SQL, Storage Account (BLOB, Table, Queue), ServiceBus, and EventHub - all fine and easy. But Cosmos DB is an enigma...

    Here is how I do DI registration of the connection (sadly, there is no built-in extension for Cosmos in Microsoft.Extensions.Azure namespace):

    builder.Services.AddAzureClients(b =>

    {

    b.AddClient<CosmosClient, CosmosClientOptions>((options, credential) =>

    new CosmosClientBuilder("https://[mycosmosname].documents.azure.com:443/", credential)

    .WithApplicationName("TestApp")

    .Build())

    .WithCredential(new DefaultAzureCredential())

    .WithName("TestCosmos");

    });

    and this is how it's used:

    `[ApiController]`
    

    [Route("[controller]")]

    public class TestController : ControllerBase

    {

    readonly IAzureClientFactory<CosmosClient> _cosmosClientFactory;

    public TestController(

    IAzureClientFactory<CosmosClient> cosmosClientFactory)

    {

    _cosmosClientFactory = cosmosClientFactory;

    }

    [HttpPost]

    [Route("cosmos")]

    public async Task<string> CreateCosmosDoc()

    {

    var client = _cosmosClientFactory.CreateClient("TestCosmos");

    var database = client.GetDatabase("db1");

    var container = database.GetContainer("container1");

    await container.CreateItemAsync(new { Prop = "Hello World!", Time = DateTime.Now.ToString("s") }, new PartitionKey("test-partition"));

    return "Success";

    }

    }

    And full error text is:

    Microsoft.Azure.Cosmos.CosmosException : Response status code does not indicate success: Forbidden (403); Substatus: 5301; ActivityId: 00000000-0000-0000-0000-000000000000; Reason: ({"code":"Forbidden","message":"Request blocked by Auth cosmos-opst-test : Request is blocked because principal [......] does not have required RBAC permissions to perform action [Microsoft.DocumentDB/databaseAccounts/readMetadata] on resource [/]. Learn more: https://aka.ms/cosmos-native-rbac.This could be because the user's group memberships were not present in the AAD token.\r\nActivityId: {...guid...}, Microsoft.Azure.Documents.Common/2.14.0"}

    RequestUri: https://[mycosmosname].documents.azure.com/;

    RequestMethod: GET;

    Header: Authorization Length: 2174;

    Header: Cache-Control Length: 8;

    Header: User-Agent Length: 85;

    Header: x-ms-version Length: 10;

    Header: x-ms-cosmos-sdk-supportedcapabilities Length: 1;

    Header: Accept Length: 16;

    Header: traceparent Length: 55;

    , Request URI: /, RequestStats: , SDK: Windows/10.0.19045 cosmos-netstandard-sdk/3.36.0);

    at Microsoft.Azure.Cosmos.Routing.GlobalEndpointManager.GetAccountPropertiesHelper.GetOnlyGlobalEndpointAsync()

    at Microsoft.Azure.Cosmos.Routing.GlobalEndpointManager.GetAccountPropertiesHelper.GetAccountPropertiesAsync()

    at Microsoft.Azure.Cosmos.Routing.GlobalEndpointManager.GetDatabaseAccountFromAnyLocationsAsync(Uri defaultEndpoint, IList`1 locations, IList`1 accountInitializationCustomEndpoints, Func`2 getDatabaseAccountFn, CancellationToken cancellationToken)

    at Microsoft.Azure.Cosmos.GatewayAccountReader.InitializeReaderAsync()

    at Microsoft.Azure.Cosmos.CosmosAccountServiceConfiguration.InitializeAsync()

    at Microsoft.Azure.Cosmos.DocumentClient.InitializeGatewayConfigurationReaderAsync()

    at Microsoft.Azure.Cosmos.DocumentClient.GetInitializationTaskAsync(IStoreClientFactory storeClientFactory)

    at Microsoft.Azure.Documents.BackoffRetryUtility`1.ExecuteRetryAsync[TParam,TPolicy](Func`1 callbackMethod, Func`3 callbackMethodWithParam, Func`2 callbackMethodWithPolicy, TParam param, IRetryPolicy retryPolicy, IRetryPolicy`1 retryPolicyWithArg, Func`1 inBackoffAlternateCallbackMethod, Func`2 inBackoffAlternateCallbackMethodWithPolicy, TimeSpan minBackoffForInBackoffCallback, CancellationToken cancellationToken, Action`1 preRetryCallback)

    at Microsoft.Azure.Documents.ShouldRetryResult.ThrowIfDoneTrying(ExceptionDispatchInfo capturedException)

    at Microsoft.Azure.Documents.BackoffRetryUtility`1.ExecuteRetryAsync[TParam,TPolicy](Func`1 callbackMethod, Func`3 callbackMethodWithParam, Func`2 callbackMethodWithPolicy, TParam param, IRetryPolicy retryPolicy, IRetryPolicy`1 retryPolicyWithArg, Func`1 inBackoffAlternateCallbackMethod, Func`2 inBackoffAlternateCallbackMethodWithPolicy, TimeSpan minBackoffForInBackoffCallback, CancellationToken cancellationToken, Action`1 preRetryCallback)

    at Microsoft.Azure.Documents.BackoffRetryUtility`1.ExecuteRetryAsync[TParam,TPolicy](Func`1 callbackMethod, Func`3 callbackMethodWithParam, Func`2 callbackMethodWithPolicy, TParam param, IRetryPolicy retryPolicy, IRetryPolicy`1 retryPolicyWithArg, Func`1 inBackoffAlternateCallbackMethod, Func`2 inBackoffAlternateCallbackMethodWithPolicy, TimeSpan minBackoffForInBackoffCallback, CancellationToken cancellationToken, Action`1 preRetryCallback)

    at Microsoft.Azure.Cosmos.AsyncCacheNonBlocking`2.GetAsync(TKey key, Func`2 singleValueInitFunc, Func`2 forceRefresh)

    at Microsoft.Azure.Cosmos.AsyncCacheNonBlocking`2.GetAsync(TKey key, Func`2 singleValueInitFunc, Func`2 forceRefresh)

    at Microsoft.Azure.Cosmos.DocumentClient.EnsureValidClientAsync(ITrace trace)

    --- Cosmos Diagnostics ---{"Summary":{},"name":"CreateItemAsync","start datetime":"2024-09-25T14:58:30.055Z","duration in milliseconds":516.9528,"data":{"Client Configuration":{"Client Created Time Utc":"2024-09-25T14:58:28.5184085Z","MachineId":"hashedMachineName:c83eaf77-d872-8bb8-da4d-aad473ad757f","NumberOfClientsCreated":1,"NumberOfActiveClients":1,"ConnectionMode":"Direct","User Agent":"cosmos-netstandard-sdk/3.43.1|1|X64|Microsoft Windows 10.0.19045|.NET 8.0.8|N|TestApp","ConnectionConfig":{"gw":"(cps:50, urto:6, p:False, httpf: False)","rntbd":"(cto: 5, icto: -1, mrpc: 30, mcpe: 65535, erd: True, pr: ReuseUnicastPort)","other":"(ed:False, be:False)"},"ConsistencyConfig":"(consistency: NotSet, prgns:[], apprgn: )","ProcessorCount":16}},"children":[{"name":"ItemSerialize","duration in milliseconds":10.7522},{"name":"Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler","duration in milliseconds":492.6261,"children":[{"name":"Waiting for Initialization of client to complete","duration in milliseconds":478.6111}]}]}

    HEADERS

    =======

    Accept: text/plain

    Host: localhost:7138

    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36

    Accept-Encoding: gzip, deflate, br, zstd

    Accept-Language: en-US,en;q=0.9

    Origin: https://localhost:7138

    Referer: https://localhost:7138/swagger/index.html

    Content-Length: 0

    sec-ch-ua-platform: "Windows"

    sec-ch-ua: "Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"

    sec-ch-ua-mobile: ?0

    sec-fetch-site: same-origin

    sec-fetch-mode: cors

    sec-fetch-dest: empty

    priority: u=1, i

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.