Azure Function to Cosmos DB via Azure Active Directory

It seems very natural and expectable to authorize internal resources within one Azure Active Directory tenant or even from different tenants, but within one company – without using and transferring keys to access a resource. In this case, the resource is Cosmos DB. I consider how to set up access of Azure Function to Cosmos DB via Azure Active Directory Managed Identity.

Prepositions

  1. Azure Function
  2. Cosmos DB
  3. Azure Function and Cosmos DB in one Resource Group and tenant
  4. AAD we have access to

Add Identity Provider to Azure Function App

Go

Settings -> Authentication -> Add identity provider

Choose Microsoft Identity provider

Add Microsoft Identity provider to Function app

Add additional permissions if needed.

Configure Azure Function Managed Identity in Azure Active Directory

After the previous step done a new Enterprise Application is created. It has Application ID and Object ID we will need to use further.

Enterprise Application Properties

Then we need to add a secret or update a certificate. This is required to perform an authorization via 3rd party application, like Function App itself or something different. To do it go

Azure Active Directory -> Manage -> App registration -> the app -> Manage -> Certificated & secrets

There is already one secret generated by Function App, so add a new one.

Okay, that’s it for the Function App part. We have Enterprise App in AAD that integrated the Function App with Microsoft Identity provider. What we need from here are Object ID (Enterprise application object id), Application ID and a Secret.

Cosmos DB configuration

Unfortunately, there is no way no set up access for Azure Function to Cosmos DB via Azure Active Directory by using Managed Identity on the Azure portal. Azure portal provides three special roles in the RBAC section for the Cosmos DB:

  1. Cosmos DB Account Reader Role: Can read Azure Cosmos DB Accounts data
  2. Cosmos DB Operator: Let’s you manage Azure Cosmos DB accounts, but not access data in them. Prevents access to account keys and connection strings.
  3. CosmosBackupOperator: Can submit restore request for a Cosmos DB database or a container for an account

However, even if you give all these roles to the Managed Identity you won’t be able to establish a connection to the Cosmos DB. And the error you receive is not very informative:

Reason: (Request blocked by Auth dummydb: No AAD tenant is trusted by this database account.

Cosmos DB exception

But it is not true. No reason is in the tenant configuration or authentication. The real reason is that the roles provided by default give you access to read data from Cosmos DB collection, but don’t give you access to the Database itself. One logic access step is missed 😒

Add custom role to Cosmos DB and assign it to the Function App

Here is the PowerShell script you can execute to create a new role.

//if you don't have this module
Install-Module -Name Az.CosmosDB -AllowClobber
$resourceGroupName = "dummy_resource_group"
$accountName = "dummy_database"

New-AzCosmosDBSqlRoleDefinition -AccountName $accountName `
    -ResourceGroupName $resourceGroupName ` -Type CustomRole -RoleName AmalgamEngineCosmosDBRole ` -DataAction @( `     'Microsoft.DocumentDB/databaseAccounts/readMetadata',     'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*', `     'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*') ` -AssignableScope "/"    

Okay, this is full access to containers role for Cosmos DB. It allows read metadata, read containers and their items. The next step is to assign this role to the Enterprise application we have.

$readOnlyRoleDefinitionId = "a202cada-2cdb-4e4b-ade6-b8e139af8f9d" //this id was returned after role definition
$principalId = "bcf295a8-002f-4d14-a930-20d51fbb681e" //object id of Enterprise app
New-AzCosmosDBSqlRoleAssignment -AccountName $accountName `
    -ResourceGroupName $resourceGroupName ` -RoleDefinitionId $readOnlyRoleDefinitionId ` -Scope "/" ` -PrincipalId $principalId    

Done. We configured an access of the Azure Function to Cosmos DB via Azure Active Directory Managed Identity.

Establish connection from C# to the Cosmos DB

var servicePrincipal = new ClientSecretCredential(
                         tenantId, //AAD tenant ID
                         applicationId, //enterprise application ID
                         secret); //enterprise application secret
                     var client = new CosmosClient(endpoint, servicePrincipal, new CosmosClientOptions() { ConnectionMode = ConnectionMode.Gateway });

Conclusion

And that’s it! Everything is done and you can use your Azure Active Directory Managed Identity to connect to your Cosmos DB instead of using a key. This approach is much more securable.


Links:

  1. https://azure.microsoft.com/en-us/blog/azure-cosmos-db-and-multi-tenant-systems/
  2. https://docs.microsoft.com/en-us/azure/cosmos-db/secure-access-to-data
  3. https://zure.com/access-data-in-cosmos-db-with-managed-identities/
  4. https://docs.microsoft.com/en-us/azure/cosmos-db/how-to-setup-rbac

Read other Azure related articles by tag Azure

Leave a Reply