{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "virtualNetworkName": {
      "type": "string",
      "defaultValue": "[concat('vnet', uniqueString(resourceGroup().id))]",
      "metadata": {
        "description": "virtual network name"
      }
    },
    "ipgroups_name1": {
      "defaultValue": "[concat('ipgroup1', uniqueString(resourceGroup().id))]",
      "type": "String"
    },
    "ipgroups_name2": {
      "defaultValue": "[concat('ipgroup2', uniqueString(resourceGroup().id))]",
      "type": "String"
    },
    "firewallPolicyName": {
      "defaultValue": "[concat('firewallPolicy', uniqueString(resourceGroup().id))]",
      "type": "String"
    },
    "adminUsername": {
      "type": "string",
      "metadata": {
        "description": "Username for the Virtual Machine."
      }
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]",
      "metadata": {
        "description": "Location for all resources."
      }
    },
    "vmSize": {
      "type": "string",
      "defaultValue": "Standard_DS2_v2",
      "metadata": {
        "description": "Size of VM"
      }
    },
    "availabilityZones": {
      "type": "array",
      "defaultValue": [
      ],
      "metadata": {
        "description": "Zone numbers e.g. 1,2,3."
      }
    },
    "numberOfFirewallPublicIPAddresses": {
      "type": "int",
      "defaultValue": 1,
      "minValue": 1,
      "maxValue": 100,
      "metadata": {
        "description": "Number of public IP addresses for the Azure Firewall"
      }
    },
    "authenticationType": {
      "type": "string",
      "defaultValue": "sshPublicKey",
      "allowedValues": [
        "sshPublicKey",
        "password"
      ],
      "metadata": {
        "description": "Type of authentication to use on the Virtual Machine. SSH key is recommended."
      }
    },
    "adminPasswordOrKey": {
      "type": "securestring",
      "metadata": {
        "description": "SSH Key or password for the Virtual Machine. SSH key is recommended."
      }
    }
  },
  "variables": {
    "vnetAddressPrefix": "10.0.0.0/16",
    "serversSubnetPrefix": "10.0.2.0/24",
    "azureFirewallSubnetPrefix": "10.0.1.0/24",
    "jumpboxSubnetPrefix": "10.0.0.0/24",
    "nextHopIP": "10.0.1.4",
    "azureFirewallSubnetName": "AzureFirewallSubnet",
    "jumpBoxSubnetName": "JumpboxSubnet",
    "serversSubnetName": "ServersSubnet",
    "jumpBoxPublicIPAddressName": "JumpHostPublicIP",
    "jumpBoxNsgName": "JumpHostNSG",
    "jumpBoxNicName": "JumpHostNic",
    "jumpBoxSubnetId": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), variables('jumpBoxSubnetName'))]",
    "serverNicName": "ServerNic",
    "serverSubnetId": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), variables('serversSubnetName'))]",
    "storageAccountName": "[concat(uniquestring(resourceGroup().id), 'sajumpbox')]",
    "azfwRouteTableName": "AzfwRouteTable",
    "firewallName": "firewall1",
    "publicIPNamePrefix": "publicIP",
    "azureFirewallSubnetId": "[resourceId('Microsoft.Network/virtualNetworks/subnets',parameters('virtualNetworkName'), variables('azureFirewallSubnetName'))]",
    "azureFirewallSubnetJSON": "[json(format('{{\"id\": \"{0}\"}}', variables('azureFirewallSubnetId')))]",
    "copy": [
      {
        "name": "azureFirewallIpConfigurations",
        "count": "[parameters('numberOfFirewallPublicIPAddresses')]",
        "input": {
          "name": "[concat('IpConf', copyIndex('azureFirewallIpConfigurations'))]",
          "properties": {
            "subnet": "[if(equals(copyIndex('azureFirewallIpConfigurations'), 0), variables('azureFirewallSubnetJSON'), json('null'))]",
            "publicIPAddress": {
              "id": "[resourceId('Microsoft.Network/publicIPAddresses', concat(variables('publicIPNamePrefix'), add(copyIndex('azureFirewallIpConfigurations'), 1)))]"
            }
          }
        }
      }
    ],
    "linuxConfiguration": {
      "disablePasswordAuthentication": true,
      "ssh": {
        "publicKeys": [
          {
            "path": "[concat('/home/', parameters('adminUsername'), '/.ssh/authorized_keys')]",
            "keyData": "[parameters('adminPasswordOrKey')]"
          }
        ]
      }
    },
    "networkSecurityGroupName": "[concat(variables('serversSubnetName'), '-nsg')]"
  },
  "resources": [
    {
      "type": "Microsoft.Network/ipGroups",
      "apiVersion": "2019-12-01",
      "name": "[parameters('ipgroups_name1')]",
      "location": "[parameters('location')]",
      "properties": {
        "ipAddresses": [
          "13.73.64.64/26",
          "13.73.208.128/25",
          "52.126.194.0/23"
        ]
      }
    },
    {
      "type": "Microsoft.Network/ipGroups",
      "apiVersion": "2019-12-01",
      "name": "[parameters('ipgroups_name2')]",
      "location": "[parameters('location')]",
      "properties": {
        "ipAddresses": [
          "12.0.0.0/24",
          "13.9.0.0/24"
        ]
      }
    },
    {
      "type": "Microsoft.Storage/storageAccounts",
      "name": "[variables('storageAccountName')]",
      "apiVersion": "2019-06-01",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "Storage",
      "properties": {}
    },
    {
      "type": "Microsoft.Network/routeTables",
      "name": "[variables('azfwRouteTableName')]",
      "apiVersion": "2019-12-01",
      "location": "[parameters('location')]",
      "properties": {
        "disableBgpRoutePropagation": false,
        "routes": [
          {
            "name": "AzfwDefaultRoute",
            "properties": {
              "addressPrefix": "0.0.0.0/0",
              "nextHopType": "VirtualAppliance",
              "nextHopIpAddress": "[variables('nextHopIP')]"
            }
          }
        ]
      }
    },
    {
      "comments": "Simple Network Security Group for subnet [variables('serversSubnetName')]",
      "type": "Microsoft.Network/networkSecurityGroups",
      "apiVersion": "2019-08-01",
      "name": "[variables('networkSecurityGroupName')]",
      "location": "[parameters('location')]",
      "properties": {}
    },
    {
      "name": "[parameters('virtualNetworkName')]",
      "apiVersion": "2019-12-01",
      "type": "Microsoft.Network/virtualNetworks",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Network/routeTables', variables('azfwRouteTableName'))]",
        "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
      ],
      "tags": {
        "displayName": "[parameters('virtualNetworkName')]"
      },
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "[variables('vnetAddressPrefix')]"
          ]
        },
        "subnets": [
          {
            "name": "[variables('jumpBoxSubnetName')]",
            "properties": {
              "addressPrefix": "[variables('jumpboxSubnetPrefix')]"
            }
          },
          {
            "name": "[variables('azureFirewallSubnetName')]",
            "properties": {
              "addressPrefix": "[variables('azureFirewallSubnetPrefix')]"
            }
          },
          {
            "name": "[variables('serversSubnetName')]",
            "properties": {
              "addressPrefix": "[variables('serversSubnetPrefix')]",
              "routeTable": {
                "id": "[resourceId('Microsoft.Network/routeTables', variables('azfwRouteTableName'))]"
              },
              "networkSecurityGroup": {
                "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
              }
            }
          }
        ]
      }
    },
    {
      "name": "[concat(variables('publicIPNamePrefix'), add(copyIndex(), 1))]",
      "type": "Microsoft.Network/publicIPAddresses",
      "apiVersion": "2019-12-01",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard"
      },
      "copy": {
        "name": "publicIpCopy",
        "count": "[parameters('numberOfFirewallPublicIPAddresses')]"
      },
      "properties": {
        "publicIPAllocationMethod": "Static",
        "publicIPAddressVersion": "IPv4"
      }
    },
    {
      "name": "[variables('jumpBoxPublicIPAddressName')]",
      "type": "Microsoft.Network/publicIPAddresses",
      "apiVersion": "2019-12-01",
      "location": "[parameters('location')]",
      "properties": {
        "publicIPAllocationMethod": "Dynamic"
      }
    },
    {
      "name": "[variables('jumpBoxNsgName')]",
      "type": "Microsoft.Network/networkSecurityGroups",
      "apiVersion": "2019-12-01",
      "location": "[parameters('location')]",
      "properties": {
        "securityRules": [
          {
            "name": "myNetworkSecurityGroupRuleSSH",
            "properties": {
              "protocol": "Tcp",
              "sourcePortRange": "*",
              "destinationPortRange": "22",
              "sourceAddressPrefix": "*",
              "destinationAddressPrefix": "*",
              "access": "Allow",
              "priority": 1000,
              "direction": "Inbound"
            }
          }
        ]
      }
    },
    {
      "apiVersion": "2019-12-01",
      "type": "Microsoft.Network/networkInterfaces",
      "name": "[variables('JumpBoxNicName')]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Network/publicIPAddresses', variables('jumpBoxPublicIPAddressName'))]",
        "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]",
        "[resourceId('Microsoft.Network/networkSecurityGroups', variables('jumpBoxNsgName'))]"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "publicIPAddress": {
                "id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('jumpBoxPublicIPAddressName'))]"
              },
              "subnet": {
                "id": "[variables('jumpBoxSubnetId')]"
              }
            }
          }
        ],
        "networkSecurityGroup": {
          "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('jumpBoxNsgName'))]"
        }
      }
    },
    {
      "apiVersion": "2019-12-01",
      "type": "Microsoft.Network/networkInterfaces",
      "name": "[variables('ServerNicName')]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "subnet": {
                "id": "[variables('serverSubnetId')]"
              }
            }
          }
        ]
      }
    },
    {
      "name": "JumpBox",
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2019-03-01",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]",
        "[resourceId('Microsoft.Network/networkInterfaces', variables('JumpBoxNicName'))]"
      ],
      "properties": {
        "hardwareProfile": {
          "vmSize": "[parameters('vmSize')]"
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "Canonical",
            "offer": "UbuntuServer",
            "sku": "18.04-LTS",
            "version": "latest"
          },
          "osDisk": {
            "createOption": "FromImage"
          }
        },
        "osProfile": {
          "computerName": "JumpBox",
          "adminUsername": "[parameters('adminUsername')]",
          "adminPassword": "[parameters('adminPasswordOrKey')]",
          "linuxConfiguration": "[if(equals(parameters('authenticationType'), 'password'), json('null'), variables('linuxConfiguration'))]"
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('JumpBoxNicName'))]"
            }
          ]
        },
        "diagnosticsProfile": {
          "bootDiagnostics": {
            "enabled": true,
            "storageUri": "[reference(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))).primaryEndpoints.blob]"
          }
        }
      }
    },
    {
      "name": "Server",
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2019-03-01",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]",
        "[resourceId('Microsoft.Network/networkInterfaces', variables('ServerNicName'))]"
      ],
      "properties": {
        "hardwareProfile": {
          "vmSize": "[parameters('vmSize')]"
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "Canonical",
            "offer": "UbuntuServer",
            "sku": "18.04-LTS",
            "version": "latest"
          },
          "osDisk": {
            "createOption": "FromImage"
          }
        },
        "osProfile": {
          "computerName": "Server",
          "adminUsername": "[parameters('adminUsername')]",
          "adminPassword": "[parameters('adminPasswordOrKey')]",
          "linuxConfiguration": "[if(equals(parameters('authenticationType'), 'password'), json('null'), variables('linuxConfiguration'))]"
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('ServerNicName'))]"
            }
          ]
        },
        "diagnosticsProfile": {
          "bootDiagnostics": {
            "enabled": true,
            "storageUri": "[reference(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))).primaryEndpoints.blob]"
          }
        }
      }
    },
    {
      "apiVersion": "2020-05-01",
      "type": "Microsoft.Network/firewallPolicies",
      "name": "[parameters('firewallPolicyName')]",
      "location": "[parameters('location')]",
      "properties": {
        "threatIntelMode": "Alert"
      },
      "resources":[
      {
         "apiVersion": "2020-05-01",
         "type": "ruleCollectionGroups",
         "name": "RuleCollectionGroup1",
         "location": "[parameters('location')]",
         "dependsOn": [
            "[resourceId('Microsoft.Network/ipGroups', parameters('ipgroups_name1'))]",
            "[resourceId('Microsoft.Network/ipGroups', parameters('ipgroups_name2'))]",
            "[resourceId('Microsoft.Network/firewallPolicies',parameters('firewallPolicyName'))]"
         ],
         "properties" : {
            "priority": 100,
            "ruleCollections": [
            {
               "ruleCollectionType": "FirewallPolicyFilterRuleCollection",
               "name": "Example-Filter-Rule",
               "action": {
                  "type": "Deny"
               },
               "priority": 1000,
               "rules": [
                  {
                     "ruleType": "NetworkRule",
                     "name": "network-rule1",
                     "ipProtocols": [
                     "TCP"
                     ],
                     "destinationPorts": [
                     "*"
                     ],
                     "sourceIpGroups": [
                        "[resourceId('Microsoft.Network/ipGroups', parameters('ipgroups_name1'))]"
                     ],
                     "destinationIpGroups": [
                        "[resourceId('Microsoft.Network/ipGroups', parameters('ipgroups_name2'))]"
                     ]
                  }
               ]
            }
         ]
         }
      }
      ]
    },
    {
      "apiVersion": "2019-09-01",
      "type": "Microsoft.Network/azureFirewalls",
      "name": "[variables('firewallName')]",
      "location": "[parameters('location')]",
      "zones": "[if(equals(length(parameters('availabilityZones')), 0), json('null'), parameters('availabilityZones'))]",
      "dependsOn": [
        "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]",
        "[resourceId('Microsoft.Network/firewallPolicies', parameters('firewallPolicyName'))]",
        "publicIpCopy"
      ],
      "properties": {
        "ipConfigurations": "[variables('azureFirewallIpConfigurations')]",
        "firewallPolicy":{
              "id": "[resourceId('Microsoft.Network/firewallPolicies', parameters('firewallPolicyName'))]"
        }
      }
    }
  ]
}
