I have an ARM template in which I provision a number of web apps. I want to add IP restrictions on these web apps allowing access only between theses. I can retrieve the IPs using:
reference(resourceId(resourceGroup().name, 'Microsoft.Web/sites', parameters('appName1')),'2015-08-01').PossibleOutboundIpAddresses
It's the following that I don't know how to solve in a good manner.
I have replaced the resourceId(resourceGroup().name, 'Microsoft.Web/sites', parameters('appName1'))
part with a variable instead to shorten it a bit. Can I shorten it even more somehow? It becomes even more complex as you'll see soon.
I have created a resources section for each web app in which there is a properties section. In this section the ipSecurityRestrictions resides. As the PossibleOutboundIpAddresses returns a string I use split to create a list and copy to iterate the IP addresses. But it does not work for me and returns the following error message:
The template function 'copyIndex' is not expected at this location. The function can only be used in a resource with copy specified
The section looks like this:
"resources": [
{
"type": "config",
"name": "web",
"apiVersion": "2016-08-01",
"properties": {
"copy": [
{
"name": "ipSecurityRestrictions",
"count": "[length(split(reference(variables('appName1'),'2015-08-01').PossibleOutboundIpAddresses, ','))]",
"input": {
"ipAddress": "[split(reference(variables('appName1'),'2015-08-01').PossibleOutboundIpAddresses, ',')[copyIndex('ipSecurityRestrictions')]]",
"subnetMask": "255.255.255.254"
}
}
],
},
"dependsOn": [
"[resourceId('Microsoft.Web/sites', parameters('appName1'))]"
]
}
]
I feel like I follow all examples I can find online exactly. Another problem with this is the many characters I'll have to write every time I want to reference the IP list. To make things worse, this list should be the merged one from all the provisioned web apps. So if I have 3 web apps the line is going to be incredible long and complicated.
ok, first question: can I make it shorter.
answer: it really depends, judging on what you show, not really (you can drop api-version if the resources are in the same template).
second question: The template function 'copyIndex' is not expected at this location. The function can only be used in a resource with copy specified.
answer: you cant do that, unfortunately (runtime\compile time drama). You'd have to use nested templates to achieve same outcome.
third question: Is there a better solution to this?
answer: probably. I'd create all 3 web apps as a nested deployment (NOT inline) and return an array of strings (similar to what you do)
"outputs" : {
"array": {
"type": "array",
"value": "[split(reference(variables('appName')]"
}
}
then I'd process those in a single run with concat and something like what you are doing (but this have to be in a nested template as well). something like:
"[concat(reference('deployment1').outputs.array.value, reference('deployment2').outputs.array.value, reference('deployment3').outputs.array.value)]"
and then in the nested template you can do:
"copy": [
{
"name": "ipSecurityRestrictions",
"count": "[length(parameters('myArray'))]",
"input": {
"ipAddress": "[parameters('myArray')[copyIndex('ipSecurityRestrictions')]]]",
"subnetMask": "255.255.255.254"
}
}
],