Azure / Azure/azure-functions-host
Race condition when using function host key for other resource in ARM template
- Dominant language
- C#
- Stars
- 2k
- Forks
- 482
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 38
Description
Since a few months I get a race condition when using function keys / host keys via ARM template.
I try to create a function key in the ARM template. In the same ARM template I add a KeyVault secret, with this newly generated function key as a value. When I look at this value in KeyVault I see the old function key (from the previous ARM template deployment) is stored there. This seems like a race condition.
I also see in the resource group deployment log that indeed the KeyVault secret was created earlier than the generation of this function key was finished.
I am depending on the function app and function key in both the KeyVault as in the KeyVault secret with `dependsOn`. I would expect the secret in KeyVault would than be created after the new function key is generated.
I am saying since a few months, because this used to work in the past. I can confirm it worked on 7th of January 2021, which is the last ARM deployment we did up until now. We didn't make any changes in between.
I striped down our own ARM template to the example below; When using this example and deploying it twice, you will see that in KeyVault the old function key is placed in the value.
Some additional info:
- Function app name: testhostkeyracecondition-functions
- KeyVault name: testhostkeyracecondition
- Resource group name: testhostkeyracecondition
- Region: West Europe
ARM template
```JSON
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {
"functionAppServicePlanName": "[concat(resourceGroup().name, '-functions')]",
"functionStorageAccountName": "[concat(uniqueString(resourceGroup().name), 'functions')]",
"functionAppServiceName": "[concat(resourceGroup().name, '-functions')]",
"keyVaultName": "[resourceGroup().name]"
},
"resources": [
{
"type": "Microsoft.KeyVault/vaults",
"apiVersion": "2018-02-14",
"name": "[variables('keyVaultName')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('functionAppServiceName'))]",
"[resourceId('Microsoft.Web/sites/host/functionKeys', variables('functionAppServiceName'), 'default', 'customkey')]"
],
"properties": {
"tenantId": "[subscription().tenantId]",
"sku": {
"family": "A",
"name": "standard"
},
"enableSoftDelete": true,
"accessPolicies": [
{
"tenantId": "[reference(concat('Microsoft.Web/sites/', variables('functionAppServiceName')), '2018-11-01', 'Full').identity.tenantId]",
"objectId": "[reference(concat('Microsoft.Web/sites/', variables('functionAppServiceName')), '2018-11-01', 'Full').identity.principalId]",
"permissions": {
"secrets": [
"get"
]
}
}
]
},
"resources": [
{
"name": "[concat(variables('keyVaultName'), '/', variables('functionStorageAccountName'), '-storage-connection-string')]",
"type": "Microsoft.KeyVault/vaults/secrets",
"apiVersion": "2018-02-14",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.KeyVault/vaults', variables('keyVaultName'))]",
"[resourceId('Microsoft.Storage/storageAccounts', variables('functionStorageAccountName'))]"
],
"properties": {
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('functionStorageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('functionStorageAccountName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value)]"
}
},
{
"name": "[concat(variables('keyVaultName'), '/functionkey')]",
"type": "Microsoft.KeyVault/vaults/secrets",
"apiVersion": "2018-02-14",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.KeyVault/vaults', variables('keyVaultName'))]",
"[resourceId('Microsoft.Web/sites', variables('functionAppServiceName'))]",
"[resourceId('Microsoft.Web/sites/host/functionKeys', variables('functionAppServiceName'), 'default', 'customkey')]"
],
"properties": {
"value": "[listkeys(concat(resourceId('Microsoft.Web/sites', variables('functionAppServiceName')), '/host/default/'),'2020-12-01').functionKeys.customkey]"
}
}
]
},
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-04-01",
"kind": "StorageV2",
"location": "[resourceGroup().location]",
"name": "[variables('functionStorageAccountName')]",
"properties": {
"accessTier": "Hot"
},
"sku": {
"name": "Standard_LRS"
}
},
{
"apiVersion": "2020-12-01",
"type": "Microsoft.Web/serverfarms",
"name": "[variables('functionAppServicePlanName')]",
"location": "[resourceGroup().location]",
"sku": {
"name": "Y1",
"tier": "Dynamic"
}
},
{
"apiVersion": "2020-12-01",
"type": "Microsoft.Web/sites",
"name": "[variables('functionAppServiceName')]",
"kind": "functionapp",
"location": "[resourceGroup().location]",
"properties": {
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('functionAppServicePlanName'))]",
"httpsOnly": true
},
"resources": [
{
"type": "config",
"name": "appsettings",
"apiVersion": "2018-11-01",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', variables('functionAppServiceName'))]",
"[resourceId('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]",
"[resourceId('Microsoft.Storage/storageAccounts', variables('functionStorageAccountName'))]"
],
"properties": {
"AZURE_FUNCTIONS_ENVIRONMENT": "Production",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"FUNCTIONS_EXTENSION_VERSION": "~3",
"WEBSITE_RUN_FROM_PACKAGE": "1",
"WEBSITE_CONTENTSHARE": "[toLower(variables('functionAppServiceName'))]",
"WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "[concat('@Microsoft.KeyVault(SecretUri=', reference(resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), concat(variables('functionStorageAccountName'), '-storage-connection-string'))).secretUriWithVersion, ')')]",
"AzureWebJobsStorage": "[concat('@Microsoft.KeyVault(SecretUri=', reference(resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), concat(variables('functionStorageAccountName'), '-storage-connection-string'))).secretUriWithVersion, ')')]"
}
},
{
"type": "Microsoft.Web/sites/host/functionKeys",
"apiVersion": "2020-12-01",
"name": "[concat(variables('functionAppServiceName'), '/default/customkey')]",
"properties": {
"name": "customkey"
},
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', variables('functionAppServiceName'))]"
]
}
],
"identity": {
"type": "SystemAssigned"
},
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('functionAppServicePlanName'))]"
]
}
]
}
```
Contributor guide
Assessment
This issue has not been assessed yet.