I have been trying to create a policy definition to deploy a security rule to NSGs should it not already exist. I have managed to get this working using the modify effect but ideally would like to have it working using deployifnotexists.
I am able to create and assign the policy however the remediation step always fails with the error "Policy evaluation exceeded the maximum allowed time." Any help greatly appreciated.
{
"type": "Microsoft.Authorization/policyDefinitions",
"properties": {
"displayName": "Append NSG Rule",
"description": "This Policy will append a rule to newly deployed NSGs.",
"mode": "All",
"parameters": {
"name": {
"type": "String",
"metadata": {
"displayName": "Rule Name",
"description": "This is the name of the security rule itself."
}
},
"protocol": {
"type": "String",
"metadata": {
"displayName": "protocol",
"description": "Network protocol this rule applies to. - Tcp, Udp, Icmp, Esp, *, Ah"
}
},
"sourcePortRange": {
"type": "Array",
"metadata": {
"displayName": "sourcePortRange",
"description": "The source port or range. Integer or range between 0 and 65535. Asterisk '*' can also be used to match all ports."
}
},
"destinationPortRange": {
"type": "Array",
"metadata": {
"displayName": "destinationPortRange",
"description": "The destination port or range. Integer or range between 0 and 65535. Asterisk '*' can also be used to match all ports."
}
},
"sourceAddressPrefix": {
"type": "Array",
"metadata": {
"displayName": "sourceAddressPrefix",
"description": "The CIDR or source IP range. Asterisk '*' can also be used to match all source IPs. Default tags such as 'VirtualNetwork', 'AzureLoadBalancer' and 'Internet' can also be used. If this is an ingress rule, specifies where network traffic originates from."
}
},
"destinationAddressPrefix": {
"type": "Array",
"metadata": {
"displayName": "destinationAddressPrefix",
"description": "The destination address prefix. CIDR or destination IP range. Asterisk '*' can also be used to match all source IPs. Default tags such as 'VirtualNetwork', 'AzureLoadBalancer' and 'Internet' can also be used."
}
},
"access": {
"type": "String",
"metadata": {
"displayName": "access",
"description": "The network traffic is allowed or denied. - Allow or Deny"
}
},
"priority": {
"type": "Integer",
"metadata": {
"displayName": "priority",
"description": "The priority of the rule. The value can be between 100 and 4096. The priority number must be unique for each rule in the collection. The lower the priority number, the higher the priority of the rule."
}
},
"direction": {
"type": "String",
"metadata": {
"displayName": "direction",
"description": "The direction of the rule. The direction specifies if rule will be evaluated on incoming or outgoing traffic. - Inbound or Outbound"
}
}
},
"policyRule": {
"if": {
"field": "type",
"equals": "Microsoft.Network/networkSecurityGroups"
},
"then": {
"effect": "DeployIfNotExists",
"details": {
"type": "Microsoft.Network/networkSecurityGroups",
"roleDefinitionIds": [
"/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635"
],
"existencecondition": {
"allOf": [{
"field": "type",
"equals": "Microsoft.Network/networkSecurityGroups"
},
{
"count": {
"field": "Microsoft.Network/networkSecurityGroups/securityRules[*]",
"where": {
"allOf": [{
"field": "Microsoft.Network/networkSecurityGroups/securityRules[*].name",
"equals": "[parameters('name')]"
},
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules[*].protocol",
"equals": "[parameters('protocol')]"
},
{
"anyOf": [{
"value": "[equals(field('Microsoft.Network/networkSecurityGroups/securityRules[*].sourcePortRange'), parameters('sourcePortRange'))]",
"equals": true
},
{
"value": "[equals(field('Microsoft.Network/networkSecurityGroups/securityRules[*].sourcePortRanges'), parameters('sourcePortRange'))]",
"equals": true
}
]
},
{
"anyOf": [{
"value": "[equals(field('Microsoft.Network/networkSecurityGroups/securityRules[*].destinationPortRange'), parameters('destinationPortRange'))]",
"equals": true
},
{
"value": "[equals(field('Microsoft.Network/networkSecurityGroups/securityRules[*].destinationPortRanges'), parameters('destinationPortRange'))]",
"equals": true
}
]
},
{
"anyOf": [{
"value": "[equals(field('Microsoft.Network/networkSecurityGroups/securityRules[*].sourceAddressPrefix'), parameters('sourceAddressPrefix'))]",
"equals": true
},
{
"value": "[equals(field('Microsoft.Network/networkSecurityGroups/securityRules[*].sourceAddressPrefixes'), parameters('sourceAddressPrefix'))]",
"equals": true
}
]
},
{
"anyOf": [{
"value": "[equals(field('Microsoft.Network/networkSecurityGroups/securityRules[*].destinationAddressPrefix'), parameters('destinationAddressPrefix'))]",
"equals": true
},
{
"value": "[equals(field('Microsoft.Network/networkSecurityGroups/securityRules[*].destinationAddressPrefixes'), parameters('destinationAddressPrefix'))]",
"equals": true
}
]
},
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules[*].access",
"equals": "[parameters('access')]"
},
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules[*].priority",
"equals": "[parameters('priority')]"
},
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules[*].direction",
"equals": "[parameters('direction')]"
}
]
}
},
"equals": 0
}
]
},
"deployment": {
"properties": {
"mode": "incremental",
"parameters": {
"name": {
"value": "[parameters('name')]"
},
"protocol": {
"value": "[parameters('protocol')]"
},
"sourcePortRange": {
"value": "[parameters('sourcePortRange')]"
},
"destinationPortRange": {
"value": "[parameters('destinationPortRange')]"
},
"sourceAddressPrefix": {
"value": "[parameters('sourceAddressPrefix')]"
},
"destinationAddressPrefix": {
"value": "[parameters('destinationAddressPrefix')]"
},
"access": {
"value": "[parameters('access')]"
},
"priority": {
"value": "[parameters('priority')]"
},
"direction": {
"value": "[parameters('direction')]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"name": {
"type": "String"
},
"protocol": {
"type": "String"
},
"sourcePortRange": {
"type": "Array"
},
"destinationPortRange": {
"type": "Array"
},
"sourceAddressPrefix": {
"type": "Array"
},
"destinationAddressPrefix": {
"type": "Array"
},
"access": {
"type": "String"
},
"priority": {
"type": "Integer"
},
"direction": {
"type": "String"
}
},
"resources": [{
"name": "[parameters('name')]",
"type": "Microsoft.Network/networkSecurityGroups/securityRules",
"apiVersion": "2020-07-01",
"properties": {
"protocol": "[parameters('protocol')]",
"sourcePortRange": "[if(equals(length(parameters('sourcePortRange')), 1), parameters('sourcePortRange')[0], json('null'))]",
"sourcePortRanges": "[if(greater(length(parameters('sourcePortRange')), 1), parameters('sourcePortRange'), json('null'))]",
"destinationPortRange": "[if(equals(length(parameters('destinationPortRange')), 1), parameters('destinationPortRange')[0], json('null'))]",
"destinationPortRanges": "[if(greater(length(parameters('destinationPortRange')), 1), parameters('destinationPortRange'), json('null'))]",
"sourceAddressPrefix": "[if(equals(length(parameters('sourceAddressPrefix')), 1), parameters('sourceAddressPrefix')[0], json('null'))]",
"sourceAddressPrefixes": "[if(greater(length(parameters('sourceAddressPrefix')), 1), parameters('sourceAddressPrefix'), json('null'))]",
"destinationAddressPrefix": "[if(equals(length(parameters('destinationAddressPrefix')), 1), parameters('destinationAddressPrefix')[0], json('null'))]",
"destinationAddressPrefixes": "[if(greater(length(parameters('destinationAddressPrefix')), 1), parameters('destinationAddressPrefix'), json('null'))]",
"access": "[parameters('access')]",
"priority": "[parameters('priority')]",
"direction": "[parameters('direction')]"
}
}]
}
}
}
}
}
}
}
}