locked
ARM Template - Add Rule to multiple Network Security Groups RRS feed

  • Question

  • Hello,

    I'm looking for a way to add one security rule to multiple Network Security Groups using an ARM Template. I tried to use the Take function, but the deployment fails. I would appreciate if someone could take a look and advise on that. I'm only working with ARM templates for about a week and I still have a lot to learn.

    {
        "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
        "contentVersion": "1.0.0.0",
        "parameters": {
            "NSG-AppDMZ": {
                "defaultValue": "nsg-app-AppDmz-001",
                "type": "string"
            },
            "NSG-AppDMZLotus": {
                "defaultValue": "nsg-app-AppDmzLotus-001",
                "type": "string"
            },
            "numberOfProps": {
                "type": "int",
                "maxValue": 13,
                "defaultValue": 13,
                "metadata": {
                "description": "Number of properties to deploy"
                }
            }
        },
        "variables": {
            "name": "allow-cmk-icmp-in-999",
            "Properties":[
                {
                        "description": "Test",
                        "protocol": "ICMP",
                        "sourcePortRange": "*",
                        "destinationPortRange": "*",
                        "sourceAddressPrefix": "192.168.11.50",
                        "destinationAddressPrefix": "*",
                        "access": "Allow",
                        "priority": 999,
                        "direction": "Inbound",
                        "sourcePortRanges": [],
                        "destinationPortRanges": [],
                        "sourceAddressPrefixes": [],
                        "destinationAddressPrefixes": []
                }
            ]
        },
        "resources": [
            {
                "type": "Microsoft.Network/networkSecurityGroups/securityRules",
                "apiVersion": "2019-11-01",
                "name": "[parameters('NSG-AppDMZ')]/[variables('name')]",
                "location": "germanywestcentral",
                "properties": "[take(variables('Properties'),parameters('numberOfProps'))]"
            },
            {
                "type": "Microsoft.Network/networkSecurityGroups/securityRules",
                "apiVersion": "2019-11-01",
                "name": "[parameters('NSG-AppDMZLotus')]/[variables('name')]",
                "location": "germanywestcentral",
                "properties": "[take(variables('Properties'),parameters('numberOfProps'))]"
            }
        ]
    }


    One problem I have is with the name when I'm trying to combine a name from the parameter and a name from the variable:

    "name": "[parameters('NSG-NSG-AppDMZ')]/[variables('name']]",

    At this point it fails at the validation

    Deployment template language expression evaluation failed: 'Unable to parse language expression 'parameters('NSG-AppDMZ')]/[variables('name')': expected token 'EndOfData' and actual 'RightSquareBracket'.'. Please see https://aka.ms/arm-template-expressions for usage details. (Code: InvalidTemplate)

    So I would appreciate if someone could point me to the proper way of doign this.

    but even when I write the name explicitly:

    "name": "nsg-app-AppDmz-001/allow-cmk-icmp-in-999",

    I get a failed deployment.

    {"code":"DeploymentFailed","message":"At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage details.","details":[{"code":"BadRequest","message":"{\r\n \"error\": {\r\n \"code\": \"InvalidRequestFormat\",\r\n \"message\": \"Cannot parse the request.\",\r\n \"details\": [\r\n {\r\n \"code\": \"InvalidJson\",\r\n \"message\": \"Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Microsoft.WindowsAzure.Networking.Nrp.Frontend.Contract.Csm.Public.SecurityRuleProperties' because the type requires a JSON object (e.g. {\\\"name\\\":\\\"value\\\"}) to deserialize correctly.\\r\\nTo fix this error either change the JSON to a JSON object (e.g. {\\\"name\\\":\\\"value\\\"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.\\r\\nPath 'properties', line 1, position 47.\"\r\n }\r\n ]\r\n }\r\n}"},{"code":"BadRequest","message":"{\r\n \"error\": {\r\n \"code\": \"InvalidRequestFormat\",\r\n \"message\": \"Cannot parse the request.\",\r\n \"details\": [\r\n {\r\n \"code\": \"InvalidJson\",\r\n \"message\": \"Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Microsoft.WindowsAzure.Networking.Nrp.Frontend.Contract.Csm.Public.SecurityRuleProperties' because the type requires a JSON object (e.g. {\\\"name\\\":\\\"value\\\"}) to deserialize correctly.\\r\\nTo fix this error either change the JSON to a JSON object (e.g. {\\\"name\\\":\\\"value\\\"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.\\r\\nPath 'properties', line 1, position 47.\"\r\n }\r\n ]\r\n }\r\n}"}]}

    Kind regards,

    Wojciech



    Thursday, April 2, 2020 11:12 AM

All replies

  • Have you tried referencing the parameter when defining the variable - rather then using both in the resources section?

    hth
    Marcin

    Thursday, April 2, 2020 12:14 PM
  • Hi,

    Sorry for the late reply.

    I'm not sure how this would work out. I would need to update all instances of the NSGs in the template with the new variable name. Which is easy to do when you have 2 or 3 but if you have 10 or 20 it becomes problematic.

    That being said, since I'm under a bit of pressure I did something like that, except I dropped the name from the variables and added it to the default value for each NSG. It's not perfect because I need to copy the template to an editor, and replace the name with a new one each time I am trying to deploy a rule. 

    I was hoping that there is a way that I only change the variable name with the new rule name. Because the number of NSGs is, more or less, fixed.

    But putting the name aside, the more pressing matter is to find a way to dynamically input the rule properties into the parameter. Again, the workaround is to define all of them times the amount of NSGs and just adjust the variables. But there is a problem with that, because from what I've noticed you can't have both destinationPortRange and destinationPortRanges in the same resource, or the deployment will fail. Which wuold mean that, based on whether I want to add a rule for only one port or several, I would need to modify the properties in the resources section each time I would be making a deployment.

    Kind regards,

    Wojciech

    Monday, April 6, 2020 7:57 AM