How can I create an array in my Azure ARM template, consisting of both singular objects and dynamically created objects using the copy mechanism.
In my ARM template I want to create a list that is combined of 'static' elements and ones that are dynamically created based on values in an array.
For instance I have the following resource:
{
"type": "Microsoft.KeyVault/vaults",
"apiVersion": "2019-09-01",
"name": "[parameters('keyVaultName')]",
...
"properties": {
...
// Option 1: I can do a singular accessPolicty
"accessPolicies": [
{
// here I reference a static object
"objectId": "[parameters('configuredResourceId')]",
...
}
],
// Option 2: Or iterate a list
"copy": [
{
// List of all properties per project. This will dynamically set the event processor (including secrets) and event hub.
"name": "accessPolicies",
"count": "[length(parameters('serviceNames'))]",
"input": {
"objectId": "[reference(resourceId('Microsoft.Web/sites', parameters('serviceNames')[copyIndex('accessPolicies')]), '2019-08-01', 'Full').identity.principalId]",
"tenantId": "[subscription().tenantId]",
"permissions": {
"keys": "[parameters('keysAppPermissions')]",
"secrets": "[parameters('secretsAppPermissions')]"
}
}
]
}
}
When I only include option 1 or option 2 it works. However inclduing both (not ertirely unexpected) this gives the error that I can't define the same property twice:
'Can not add property accessPolicies to Newtonsoft.Json.Linq.JObject. Property with the same name already exists on object.'.
In some cases I can probably work around this, by using the copy in the variables and then adding elements to an array. But that doesn't work when I want to use different types of functions based on the resource state (such as fethcing Ids).
I had the same problem when adding Key-Vault Policies with the 'copy' method and also adding static Key-Vault Policies.
I solved it by adding the static policies as you described in the ARM. Next I defined another/child resource which is called: Microsoft.KeyVault/vaults/accessPolicies
The last step I had to do was adding the dependsOn property and refer to the belonging Key-Vault.
The show you in JSON close to your code:
{
"type": "Microsoft.KeyVault/vaults",
"apiVersion": "2019-09-01",
"name": "[parameters('keyVaultName')]",
...
"properties": {
...
// Step 1: add static policies:
"accessPolicies": [
{
// here I reference a static object
"objectId": "[parameters('configuredResourceId')]",
...
}
],
}
},
...
{
"type": "Microsoft.KeyVault/vaults/accessPolicies",
"name": "[concat(parameters('keyVaultName'), '/add')]",
"apiVersion": "2019-09-01",
// Step 2: add depending key-vault (parent resource)
"dependsOn": [
"[resourceId('Microsoft.KeyVault/vaults', parameters('keyVaultName'))]"
],
"properties": {
// Step 3: add the copy method to iterate policies
"copy": [
{
// List of all properties per project. This will dynamically set the event processor (including secrets) and event hub.
"name": "accessPolicies",
"count": "[length(parameters('serviceNames'))]",
"input": {
"objectId": "[reference(resourceId('Microsoft.Web/sites', parameters('serviceNames')[copyIndex('accessPolicies')]), '2019-08-01', 'Full').identity.principalId]",
"tenantId": "[subscription().tenantId]",
"permissions": {
"keys": "[parameters('keysAppPermissions')]",
"secrets": "[parameters('secretsAppPermissions')]"
}
}
}
]
}
},
...
Please try the above ARM flow.