Reputation: 8009
I create a Managed Identity for a Function app and assigned it to DocumentDB Account Contributor
by following the two sections below
Microsoft.Azure.Services.AppAuthentication
I got an exception when I tried to run the code from the section below:
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(Nullable
1 ignoreCondition, Nullable
1 declaringTypeNumberHandling) at ... System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at Cosmos.Samples.AzureFunctions.AzureFunctionsCosmosClientMI.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
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:
Connect Function App to CosmosDB with Managed Identity
Upvotes: 8
Views: 14535
Reputation: 21
In case you are facing the issue below when authenticating using Default Azure Credentials:
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."
There is an action missing in any of the roles currently provided in the Azure Portal. You need to run the command below. It will assign a readMetadata role, enabling you to authenticate successfully:
az cosmosdb sql role assignment create -a <cosmosdbName> -g <resourceGroupName> -s "/" -p <principalId> -d 00000000-0000-0000-0000-000000000002
This works for Cosmos DocumentDB as well as for SQL DB.
Upvotes: 2
Reputation: 71
Azure Cosmos DB actually has built-in roles for that.
For read only, roleDefinitionId is 00000000-0000-0000-0000-000000000001
. For read and write, roleDefinitionId is 00000000-0000-0000-0000-000000000002
. More details at Configure role-based access control with Azure AD - Azure Cosmos Db | Microsoft Learn
So all you need to do is give your principal the adequate permission.
az cosmosdb sql role assignment create -a <cosmosdbName> -g <resourceGroupName> -s "/" -p <principalId> -d 00000000-0000-0000-0000-000000000002
Upvotes: 7
Reputation: 141
I ran into this same error this morning while setting up CosmosDB to use the Managed Identity of my Azure VM. The error message states that your principal does not have the RBAC permission Microsoft.DocumentDB/databaseAccounts/readMetadata. Once you give the principal you are using that permission authentication using Azure.Identity should work.
The DocumentDB Account Contributor doesn't have the role Microsoft.DocumentDB/databaseAccounts/readMetadata, and I couldn't find a built in Azure role that contained that permission so I created my own custom CosmosDBReadWrite role by following the example in this article.
To create the custom role definitions and assignments, you will need to have the Azure CLI installed.
First you will need to create a json file with the role definition. Here are 2 different custom role configuration json files, one for read-only access to the CosmosDB and the other has read-write role access.
{
"RoleName": "CosmosDBReadOnlyRole",
"Type": "CustomRole",
"AssignableScopes": ["/"],
"Permissions": [{
"DataActions": [
"Microsoft.DocumentDB/databaseAccounts/readMetadata",
"Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/read",
"Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/executeQuery",
"Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/readChangeFeed"
]
}]
}
{
"RoleName": "CosmosDBReadWriteRole",
"Type": "CustomRole",
"AssignableScopes": ["/"],
"Permissions": [{
"DataActions": [
"Microsoft.DocumentDB/databaseAccounts/readMetadata",
"Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*",
"Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*"
]
}]
}
After you have your json file saved with your custom role definition, we can create the custom role with the Azure CLI and then assign it to the correct principal.
Create your custom role using the JSON file you created above
resourceGroupName='<myResourceGroup>'
accountName='<myCosmosAccount>'
az cosmosdb sql role definition create -a $accountName -g $resourceGroupName -b @role-definition.json
After you create the role, the definition of the created role should be returned. If not, use the following command to find the roleDefinitionId which can be found in the name property.
az cosmosdb sql role definition list --account-name $accountName -g $resourceGroupName
Finally, apply the custom role to your principal that needs permission to access CosmosDB.
resourceGroupName='<myResourceGroup>'
accountName='<myCosmosAccount>'
roleDefinitionId = '<roleDefinitionId>'
principalId = '<ID for the Object that needs access to the CosmosDB>'
az cosmosdb sql role assignment create -a $accountName -g $resourceGroupName -s "/" -p $principalId -d $roleDefinitionId
Hope this solves the error you are running into as well!
Upvotes: 14