Configure RBAC for Cosmos DB with Managed Identity instead of Service Principal

This post has been republished via RSS; it originally appeared at: New blog articles in Microsoft Tech Community.

Objectives

 

Topology and service components

  • Function App (Read Only and Read/Write)
    • Runtime: Java 11
    • HTTP binding/trigger
  • Cosmos DB Java SDK v4
    • The SDK is used in each Function App to interact with Cosmos DB.

image-3

 

Preparation

 

Function app

 

 

TokenCredential tokenCredential = new DefaultAzureCredentialBuilder().build();

 

 

Next, we pass the TokenCredential instance to CosmosClientBuilder() to initialize CosmosClient or CosmosAsyncClient. As you can see, we don’t have to use any keys to create a client instance. We can create CosmosClient with the following code. As CosmosClient and CosmosAsyncClient is auto-closable, we should create the client instance surrounded with try-with-resources clause.

CosmosClient client = new CosmosClientBuilder() .endpoint(ACCOUNT_ENDPOINT) .credential(tokenCredential) .gatewayMode() .buildClient();
  • GET : retrieve data from Cosmos DB.
  • POST: update or insert data passed in HTTP request body.
// Get data from HTTP body of request Track track = request.getBody().get(); // Update or insert data CosmosItemResponse<Track> cosmosItemResponse = cosmosContainer.upsertItem(track); // HTTP status code is used with response code from Cosmos DB HttpResponseMessage responseMessage = request.createResponseBuilder(HttpStatusType.custom(cosmosItemResponse.getStatusCode())) .header("Content-Type", "application/json") .body(track) .build();

Cosmos DB

[ { "id": "4321", "type": "Hino", "purchaseDate": "2020/10/20", "remarks": "4t" }, { "id": "1234", "type": "Isuzu", "purchaseDate": "2020/11/20", "remarks": "4t" }, { "id": "6666", "type": "Fuso", "purchaseDate": "2020/12/20", "remarks": "4t" }, { "id": "1111", "type": "Volvo", "purchaseDate": "2021/09/20", "remarks": "4t" }, { "id": "1112", "type": "Volvo", "purchaseDate": "2021/09/20", "remarks": "4t" }, { "id": "1216", "type": "Volvo", "purchaseDate": "2021/09/20", "remarks": "4t" } ]
  • JSON file for read-only role configuration : role-definition-ro.json
{ "RoleName": "MyReadOnlyRole", "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" ] }] }
  • JSON file for read-write role configuration : role-definition-rw.json
{ "RoleName": "MyReadWriteRole", "Type": "CustomRole", "AssignableScopes": ["/"], "Permissions": [{ "DataActions": [ "Microsoft.DocumentDB/databaseAccounts/readMetadata", "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*", "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*" ] }] }
resourceGroupName='<myResourceGroup>' accountName='<myCosmosAccount>' az cosmosdb sql role definition create -a $accountName -g $resourceGroupName -b @role-definition-ro.json az cosmosdb sql role definition create -a $accountName -g $resourceGroupName -b @role-definition-rw.json
az cosmosdb sql role definition list --account-name $accountName -g $resourceGroupName
[ { "assignableScopes": [ "/subscriptions/{subscription id}/resourceGroups/{resource group}/providers/Microsoft.DocumentDB/databaseAccounts/{CosmosDB account}" ], "id": "/subscriptions/{subscription id}/resourceGroups/{resource group}/providers/Microsoft.DocumentDB/databaseAccounts/{CosmosDB account}/sqlRoleDefinitions/{roleDefinitionId}", "name": "{roleDefinitionId}", "permissions": [ { "dataActions": [ "Microsoft.DocumentDB/databaseAccounts/readMetadata", "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*", "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*" ], "notDataActions": [] } ], "resourceGroup": "{resource group}", "roleName": "MyReadWriteRole", "type": "Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions", "typePropertiesType": "1" }, { "assignableScopes": [ "/subscriptions/{subscription id}/resourceGroups/{resource group}/providers/Microsoft.DocumentDB/databaseAccounts/{CosmosDB account}" ], "id": "/subscriptions/{subscription id}/resourceGroups/{resource group}/providers/Microsoft.DocumentDB/databaseAccounts/{CosmosDB account}/sqlRoleDefinitions/{roleDefinitionId}", "name": "{roleDefinitionId}", "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" ], "notDataActions": [] } ], "resourceGroup": "{resource group}", "roleName": "MyReadOnlyRole", "type": "Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions", "typePropertiesType": "1" }, {...} ]
resourceGroupName='<myResourceGroup>' accountName='<myCosmosAccount>' readOnlyRoleDefinitionId = '<roleDefinitionId of MyReadOnlyRole>' ROprincipalId = '<Managed Identity Object ID for Function App, the app will be assigned to MyReadOnlyRole.>' az cosmosdb sql role assignment create -a $accountName -g $resourceGroupName -s "/" -p $ROprincipalId -d $readOnlyRoleDefinitionId readWriteRoleDefinitionId = '<roleDefinitionId of MyReadWriteRole>' RWprincipalId = '<Managed Identity Object ID for Function App, the app will be assigned to MyReadWriteRole.>' az cosmosdb sql role assignment create -a $accountName -g $resourceGroupName -s "/" -p $RWprincipalId -d $readWriteRoleDefinitionId

Test

Conclusion

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.