Reputation: 2001
I'm trying to do the following:
Originally I was creating the Access Policy within the Keyvault, but I had to declare the AZ function as depending on the Key Vault (such that I could fetch its URI). Obviously, I was then unable to set Key Vault to depend on the AZ Function (since this would create a cyclic dependency). I then tried creating the AccessPolicy as another step, and marking it as depends on the KeyVault, and the AZ Function (thinking it would be provisioned last).
But for some reason, when looking at the deployment logs, it always seems like he's trying to deploy it first! Any help would be appreciated.
ARM Template truncated for brevity:
"resources": [
{
"type": "Microsoft.KeyVault/vaults",
"apiVersion": "2016-10-01",
"name": "[variables('keyVaultName')]",
"location": "[ResourceGroup().location]",
"properties": {
"sku": {
"family": "A",
"name": "Standard"
},
"tenantId": "[subscription().tenantId]",
"accessPolicies": [
{
"tenantId": "[subscription().tenantId]",
"objectId": "[parameters('userId')]",
"permissions": {
"keys": [
"Get",
"List",
"Update",
"Create",
"Import",
"Delete",
"Recover",
"Backup",
"Restore"
],
"secrets": [
"Get",
"List",
"Set",
"Delete",
"Recover",
"Backup",
"Restore"
],
"certificates": [
"Get",
"List",
"Update",
"Create",
"Import",
"Delete",
"Recover",
"Backup",
"Restore",
"ManageContacts",
"ManageIssuers",
"GetIssuers",
"ListIssuers",
"SetIssuers",
"DeleteIssuers"
]
}
}
],
"enabledForDeployment": false,
"enabledForDiskEncryption": false,
"enabledForTemplateDeployment": false
}
},
{
"type": "Microsoft.KeyVault/vaults/accessPolicies",
"name": "[concat(variables('keyVaultName'),'/add')]",
"apiVersion": "2018-02-14",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('functionName'))]",
"[resourceId('Microsoft.KeyVault/vaults', variables('keyVaultName'))]"
],
//tried both the above and the below
"dependsOn": [
"[variables('keyVaultName')]",
"[variables('functionName')]"
],
"properties": {
"accessPolicies": [
{
"tenantId": "[subscription().tenantId]",
"objectId": "[reference(concat(resourceId('Microsoft.Web/sites', variables('functionName')), '/providers/Microsoft.ManagedIdentity/Identities/default'), '2015-08-31-PREVIEW').principalId]",
"permissions": {
"keys": [
],
"secrets": [
"Get",
"Set",
"Delete"
],
"certificates": [
]
}
}
]
}
},
.
.
.
.
.
.
.
.
{
"type": "Microsoft.Web/sites",
"apiVersion": "2016-08-01",
"name": "[variables('functionName')]",
"location": "[ResourceGroup().location]",
"dependsOn": [
"[variables('planName')]",
"[variables('appInsightsName')]",
"[variables('storageAccName')]",
"[variables('keyVaultName')]",
"[variables('databaseName')]"
],
"kind": "functionapp",
"identity": {
"type": "SystemAssigned"
},
"properties": {
"serverFarmId": "[variables('planName')]",
"enabled": true,
"reserved": false
},
"resources": [
{
"apiVersion": "2015-08-01",
"name": "connectionstrings",
"type": "config",
"dependsOn": [
"[variables('functionName')]",
"[variables('databaseName')]"
],
"properties": {
}
},
{
"apiVersion": "2015-08-01",
"name": "appsettings",
"type": "config",
"dependsOn": [
"[variables('functionName')]",
"[variables('appInsightsName')]",
"[variables('storageAccName')]",
"[variables('keyVaultName')]"
],
"properties": "[union(variables('completeAppSettings'),json(concat('{ AzureWebJobsStorage:\"', concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccName')), '2019-04-01').keys[0].value), '\", WEBSITE_CONTENTAZUREFILECONNECTIONSTRING:\"',\tconcat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccName')), '2019-04-01').keys[0].value), '\", WEBSITE_CONTENTSHARE:\"', variables('functionName'), '\", APPINSIGHTS_INSTRUMENTATIONKEY:\"', reference(concat('microsoft.insights/components/', variables('appInsightsName'))).InstrumentationKey, '\", KeyVaultUri:\"', reference(concat('Microsoft.KeyVault/vaults/', variables('keyVaultName'))).vaultUri, '\"}')))]"
},
{
"type": "slots",
"apiVersion": "2016-08-01",
"name": "[variables('functionStagingName')]",
"location": "[ResourceGroup().location]",
"dependsOn": [
"[variables('functionName')]",
"[variables('keyVaultName')]"
],
"kind": "functionapp",
"properties": {
"enabled": false,
"serverFarmId": "[variables('planName')]"
}
}
]
}
]
P.s. I know the way I'm creating my app settings is a work of art (sarcasm). Please don't judge me, just know that it works.
P.p.s Complete ARM Template: https://pastebin.com/mma4PyRu
Upvotes: 3
Views: 981
Reputation: 8717
Try removing the apiVersion from the reference() function, that should delay the call until after the resource is provisioned. e.g.
[reference(concat(resourceId('Microsoft.Web/sites', variables('functionName')), '/providers/Microsoft.ManagedIdentity/Identities/default')).principalId]"
Upvotes: 1
Reputation: 72171
your template is absolutely fine, so if this doesnt work it looks like a bug. having said that, you can always work around this by moving your accessPolicy
assignment into a nested template:
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2018-05-01",
"name": "linkedTemplate",
"dependsOn": [
"[variables('keyVaultName')]",
"[variables('functionName')]"
],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri":"https://mystorageaccount.blob.core.windows.net/AzureTemplates/newStorageAccount.json",
"contentVersion":"1.0.0.0"
},
"parameters": {
"managedIdentityId":{"value": "[reference(concat(resourceId('Microsoft.Web/sites', variables('functionName')), '/providers/Microsoft.ManagedIdentity/Identities/default'), '2015-08-31-PREVIEW').principalId]"}
}
}
You'd need to upload the template somewhere (which should consist of just your accessPolicy
assignment
Upvotes: 2