This post is a summary of my experience dealing with user-assigned managed identity and key vaults in Azure, it explores multiple ways to achieve the same result – how to assign access policies using an ARM template. Each of the ways has its own pros and cons.
First, the simplest: to create a key vault with preassigned access policy:
{
"resources": [
{
"type": "Microsoft.KeyVault/vaults",
"apiVersion": "[variables('kvApiVersion')]",
"name": "[parameters('kvName')]",
"location": "[parameters('location')]",
"properties": {
"tenantId": "[variables('tenantId')]",
"accessPolicies": "[parameters('accessPolicies')]",
"sku": {
"name": "Standard",
"family": "A"
}
}
}
]
}
The pros of this approach are same as the cons: you have to know all access policies ahead of time. That works but only in the simplest scenarios, such as for security groups as they’re created outside of ARM and have static, well-known OID.
Second: to create a key vault, then a user-assigned managed identity, and then add an access policy:
{
"variables": {
"uaidRef": "[concat('Microsoft.ManagedIdentity/userAssignedIdentities/', parameters('uaidName'))]",
},
"resources": [
{
"type": "Microsoft.KeyVault/vaults",
"apiVersion": "[variables('kvApiVersion')]",
"name": "[parameters('kvName')]",
"location": "[parameters('location')]",
"properties": {
"tenantId": "[variables('tenantId')]",
"accessPolicies": [],
"sku": {
"name": "Standard",
"family": "A"
}
}
},
{
"type": "Microsoft.ManagedIdentity/userAssignedIdentities",
"apiVersion": "[variables('idApiVersion')]",
"name": "[parameters('uaidName')]",
"location": "[parameters('location')]"
},
{
"type": "Microsoft.KeyVault/vaults/accessPolicies",
"name": "[concat(parameters('kvName'), '/add')]",
"apiVersion": "[variables('kvApiVersion')]",
"properties": {
"accessPolicies": [
{
"tenantId": "[variables('tenantId')]",
"objectId": "[reference(variables('uaidRef'), variables('idApiVersion')).principalId]",
"permissions": "[variables('uaidPermissions')]"
}
]
},
"dependsOn": [
"[concat('Microsoft.KeyVault/vaults/', parameters('kvName'))]",
"[concat('Microsoft.ManagedIdentity/userAssignedIdentities/', parameters('uaidName'))]",
]
}
]
}
The main drawback of this one is in the effect of eviction. Since a deployment of ARM template is effectively a PUT on the respective resource, immediately after the creation, a key vault has no access policies. What means all requests to access it will fail 403 until the respective polices are not added back. The time window might be relatively short but still exist what’s may and will cause outages and incidents.
Moreover Key Vault doesn’t support adding access policies in parallel. What means that if there are multiple policies to add they must be added sequentially. Each takes several seconds what increases the window up to a minute or more. If this is a production environment then this is guaranteed to have customer impact, makes it impossible to deployment transparently and without interruption of running services, violates one of the core principles of cloud and enterprise grade infrastructure.
Finally, third: create a user-assigned managed identity, then create a key vault with preassigned access policy:
{
"variables": {
"uaidRef": "[concat('Microsoft.ManagedIdentity/userAssignedIdentities/', parameters('uaidName'))]"
},
"resources": [
{
"type": "Microsoft.ManagedIdentity/userAssignedIdentities",
"apiVersion": "[variables('idApiVersion')]",
"name": "[parameters('uaidName')]",
"location": "[parameters('location')]"
},
{
"type": "Microsoft.KeyVault/vaults",
"apiVersion": "[variables('kvApiVersion')]",
"name": "[parameters('kvName')]",
"location": "[parameters('location')]",
"properties": {
"tenantId": "[variables('tenantId')]",
"accessPolicies": [
{
"tenantId": "[variables('tenantId')]",
"objectId": "[reference(variables('uaidRef'), variables('idApiVersion')).principalId]",
"permissions": "[variables('uaidPermissions')]"
}
],
"sku": {
"name": "Standard",
"family": "A"
}
},
"dependsOn": [
"[concat('Microsoft.ManagedIdentity/userAssignedIdentities/', parameters('uaidName'))]"
]
}
]
}
This one basically combined the pros of the latter two and in my mind has no cons. It eliminates the window altogether, the key vault would never have no access polices even again.