Recently, I’ve been working on an Azure Function that’ll automate the creation of a resource group and a Cosmos DB account within that resource group. The function app was configured to use MSI(Managed Service Identity). The function app will run under this identity and the MSI needs to have access to perform the required operations – creation of a resource group and creation of a Cosmos DB account.
You can turn on MSI when deploying Azure Functions through ARM templates by setting the identity type as SystemAssigned.
"identity": {
"type": "SystemAssigned"
}
Behind the scenes, Azure creates an identity for the Azure Function with the same name as the function. You can get the details of the managed identity using the below PowerShell command:
Get-AzureRmADServicePrincipal -DisplayName "deployapiapp"
Now that a managed identity has been created for you, you need to assign the appropriate access rights. You can assign one of the Azure built-in roles. Or, you may want to tailor it to the specific operations that the function will perform. I found that it is tedious to start from scratch. When you try to deploy an Azure resource using an ARM template from an Azure Function and the function doesn’t have the necessary access rights, the error message gives you exactly what access right was missing. That’s great, but you have to re-run the function multiple times to figure out all the access rights required.
Alternatively, you can explore the pre-defined roles and build your custom role based on one of those roles. The following PowerShell command gets the role definition of the built-in role “DocumentDB Account Contributor”. You can use a subset of the access rights from the built-in role or use it as a base and add more later.
Get-AzureRmRoleDefinition "DocumentDB Account Contributor" | ConvertTo-Json
Here, I’m creating a custom role based on an existing role – DocumentDB Account Contributor.
$role = [Microsoft.Azure.Commands.Resources.Models.Authorization.PSRoleDefinition]::new() $role.Name = 'Custom Role Cosmos' $role.Description = 'Custom role To deploy Cosmos DB.' $role.IsCustom = $true $perms = (Get-AzureRmRoleDefinition -Name 'DocumentDB Account Contributor').Actions $role.Actions = $perms $subs = '/subscriptions/' $role.AssignableScopes = $subs New-AzureRmRoleDefinition -Role $role
Now, the custom role has the same access rights as the built-in role. You can update the role by adding more actions to the role, like below.
$role = Get-AzureRmRoleDefinition "Custom Role Cosmos"
$role.Actions.Add("Microsoft.Resources/subscriptions/resourcegroups/write")
Set-AzureRmRoleDefinition -Role $role
Now, the custom role can create resource groups and also create Cosmos DB accounts.
The custom role has to be assigned to the MSI. You can get the ObjectId of the MSI using the Get-AzureRmADServicePrincipal command mentioned at the beginning of this post.
New-AzureRmRoleAssignment -ObjectId -RoleDefinitionName 'Custom Role Cosmos' -Scope '/subscriptions/'
For the sake of completeness, here are the commands to delete the role assignment and the custom role itself.
Remove role assignment:
Remove-AzureRmRoleAssignment -ObjectId -RoleDefinitionName 'Custom Role Cosmos' -Scope '/subscriptions/'
Remove custom role:
Get-AzureRmRoleDefinition "Custom Role Cosmos" | Remove-AzureRmRoleDefinition
References: