Quickstart: Secure your virtual hub using Azure Firewall Manager - ARM template

In this quickstart, you use an Azure Resource Manager template (ARM template) to secure your virtual hub using Azure Firewall Manager. The deployed firewall has an application rule that allows connections to www.microsoft.com . Two Windows Server 2019 virtual machines are deployed to test the firewall. One jump server is used to connect to the workload server. From the workload server, you can only connect to www.microsoft.com.

An Azure Resource Manager template is a JavaScript Object Notation (JSON) file that defines the infrastructure and configuration for your project. The template uses declarative syntax. You describe your intended deployment without writing the sequence of programming commands to create the deployment.

For more information about Azure Firewall Manager, see What is Azure Firewall Manager?.

If your environment meets the prerequisites and you're familiar with using ARM templates, select the Deploy to Azure button. The template will open in the Azure portal.

Button to deploy the Resource Manager template to Azure.

Prerequisites

Review the template

This template creates a secured virtual hub using Azure Firewall Manager, along with the necessary resources to support the scenario.

The template used in this quickstart is from Azure Quickstart Templates.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "metadata": {
    "_generator": {
      "name": "bicep",
      "version": "0.9.1.41621",
      "templateHash": "1093777410793723808"
    }
  },
  "parameters": {
    "adminUsername": {
      "type": "string",
      "metadata": {
        "description": "Admin username for the servers"
      }
    },
    "adminPassword": {
      "type": "secureString",
      "metadata": {
        "description": "Password for the admin account on the servers"
      }
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]",
      "metadata": {
        "description": "Location for all resources."
      }
    },
    "vmSize": {
      "type": "string",
      "defaultValue": "Standard_D2_v3",
      "metadata": {
        "description": "Size of the virtual machine."
      }
    }
  },
  "resources": [
    {
      "type": "Microsoft.Network/virtualWans",
      "apiVersion": "2021-08-01",
      "name": "VWan-01",
      "location": "[parameters('location')]",
      "properties": {
        "disableVpnEncryption": false,
        "allowBranchToBranchTraffic": true,
        "type": "Standard"
      }
    },
    {
      "type": "Microsoft.Network/virtualHubs",
      "apiVersion": "2021-08-01",
      "name": "Hub-01",
      "location": "[parameters('location')]",
      "properties": {
        "addressPrefix": "10.1.0.0/16",
        "virtualWan": {
          "id": "[resourceId('Microsoft.Network/virtualWans', 'VWan-01')]"
        }
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/virtualWans', 'VWan-01')]"
      ]
    },
    {
      "type": "Microsoft.Network/virtualHubs/hubVirtualNetworkConnections",
      "apiVersion": "2021-08-01",
      "name": "[format('{0}/{1}', 'Hub-01', 'hub-spoke')]",
      "properties": {
        "remoteVirtualNetwork": {
          "id": "[resourceId('Microsoft.Network/virtualNetworks', 'Spoke-01')]"
        },
        "allowHubToRemoteVnetTransit": true,
        "allowRemoteVnetToUseHubVnetGateways": false,
        "enableInternetSecurity": true,
        "routingConfiguration": {
          "associatedRouteTable": {
            "id": "[resourceId('Microsoft.Network/virtualHubs/hubRouteTables', 'Hub-01', 'RT_VNet')]"
          },
          "propagatedRouteTables": {
            "labels": [
              "VNet"
            ],
            "ids": [
              {
                "id": "[resourceId('Microsoft.Network/virtualHubs/hubRouteTables', 'Hub-01', 'RT_VNet')]"
              }
            ]
          }
        }
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/azureFirewalls', 'AzfwTest')]",
        "[resourceId('Microsoft.Network/virtualHubs/hubRouteTables', 'Hub-01', 'RT_VNet')]",
        "[resourceId('Microsoft.Network/virtualHubs', 'Hub-01')]",
        "[resourceId('Microsoft.Network/virtualNetworks', 'Spoke-01')]"
      ]
    },
    {
      "type": "Microsoft.Network/firewallPolicies",
      "apiVersion": "2021-08-01",
      "name": "Policy-01",
      "location": "[parameters('location')]",
      "properties": {
        "threatIntelMode": "Alert"
      }
    },
    {
      "type": "Microsoft.Network/firewallPolicies/ruleCollectionGroups",
      "apiVersion": "2021-08-01",
      "name": "[format('{0}/{1}', 'Policy-01', 'DefaultApplicationRuleCollectionGroup')]",
      "properties": {
        "priority": 300,
        "ruleCollections": [
          {
            "ruleCollectionType": "FirewallPolicyFilterRuleCollection",
            "name": "RC-01",
            "priority": 100,
            "action": {
              "type": "Allow"
            },
            "rules": [
              {
                "ruleType": "ApplicationRule",
                "name": "Allow-msft",
                "sourceAddresses": [
                  "*"
                ],
                "protocols": [
                  {
                    "port": 80,
                    "protocolType": "Http"
                  },
                  {
                    "port": 443,
                    "protocolType": "Https"
                  }
                ],
                "targetFqdns": [
                  "*.microsoft.com"
                ]
              }
            ]
          }
        ]
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/firewallPolicies', 'Policy-01')]"
      ]
    },
    {
      "type": "Microsoft.Network/azureFirewalls",
      "apiVersion": "2021-08-01",
      "name": "AzfwTest",
      "location": "[parameters('location')]",
      "properties": {
        "sku": {
          "name": "AZFW_Hub",
          "tier": "Standard"
        },
        "hubIPAddresses": {
          "publicIPs": {
            "count": 1
          }
        },
        "virtualHub": {
          "id": "[resourceId('Microsoft.Network/virtualHubs', 'Hub-01')]"
        },
        "firewallPolicy": {
          "id": "[resourceId('Microsoft.Network/firewallPolicies', 'Policy-01')]"
        }
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/firewallPolicies', 'Policy-01')]",
        "[resourceId('Microsoft.Network/virtualHubs', 'Hub-01')]"
      ]
    },
    {
      "type": "Microsoft.Network/virtualNetworks",
      "apiVersion": "2021-08-01",
      "name": "Spoke-01",
      "location": "[parameters('location')]",
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "10.0.0.0/16"
          ]
        },
        "enableDdosProtection": false,
        "enableVmProtection": false
      }
    },
    {
      "type": "Microsoft.Network/virtualNetworks/subnets",
      "apiVersion": "2021-08-01",
      "name": "[format('{0}/{1}', 'Spoke-01', 'Workload-SN')]",
      "properties": {
        "addressPrefix": "10.0.1.0/24",
        "privateEndpointNetworkPolicies": "Enabled",
        "privateLinkServiceNetworkPolicies": "Enabled"
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/virtualNetworks', 'Spoke-01')]"
      ]
    },
    {
      "type": "Microsoft.Network/virtualNetworks/subnets",
      "apiVersion": "2021-08-01",
      "name": "[format('{0}/{1}', 'Spoke-01', 'Jump-SN')]",
      "properties": {
        "addressPrefix": "10.0.2.0/24",
        "routeTable": {
          "id": "[resourceId('Microsoft.Network/routeTables', 'RT-01')]"
        },
        "privateEndpointNetworkPolicies": "Enabled",
        "privateLinkServiceNetworkPolicies": "Enabled"
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/routeTables', 'RT-01')]",
        "[resourceId('Microsoft.Network/virtualNetworks/subnets', 'Spoke-01', 'Workload-SN')]",
        "[resourceId('Microsoft.Network/virtualNetworks', 'Spoke-01')]"
      ]
    },
    {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2022-03-01",
      "name": "Jump-Srv",
      "location": "[parameters('location')]",
      "properties": {
        "hardwareProfile": {
          "vmSize": "[parameters('vmSize')]"
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "MicrosoftWindowsServer",
            "offer": "WindowsServer",
            "sku": "2019-Datacenter",
            "version": "latest"
          },
          "osDisk": {
            "osType": "Windows",
            "createOption": "FromImage",
            "caching": "ReadWrite",
            "managedDisk": {
              "storageAccountType": "StandardSSD_LRS"
            },
            "diskSizeGB": 127
          }
        },
        "osProfile": {
          "computerName": "Jump-Srv",
          "adminUsername": "[parameters('adminUsername')]",
          "adminPassword": "[parameters('adminPassword')]",
          "windowsConfiguration": {
            "provisionVMAgent": true,
            "enableAutomaticUpdates": true
          },
          "allowExtensionOperations": true
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces', 'netInterface-jump-srv')]"
            }
          ]
        }
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/networkInterfaces', 'netInterface-jump-srv')]"
      ]
    },
    {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2022-03-01",
      "name": "Workload-Srv",
      "location": "[parameters('location')]",
      "properties": {
        "hardwareProfile": {
          "vmSize": "[parameters('vmSize')]"
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "MicrosoftWindowsServer",
            "offer": "WindowsServer",
            "sku": "2019-Datacenter",
            "version": "latest"
          },
          "osDisk": {
            "osType": "Windows",
            "createOption": "FromImage",
            "caching": "ReadWrite",
            "managedDisk": {
              "storageAccountType": "StandardSSD_LRS"
            },
            "diskSizeGB": 127
          }
        },
        "osProfile": {
          "computerName": "Workload-Srv",
          "adminUsername": "[parameters('adminUsername')]",
          "adminPassword": "[parameters('adminPassword')]",
          "windowsConfiguration": {
            "provisionVMAgent": true,
            "enableAutomaticUpdates": true
          },
          "allowExtensionOperations": true
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces', 'netInterface-workload-srv')]"
            }
          ]
        }
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/networkInterfaces', 'netInterface-workload-srv')]"
      ]
    },
    {
      "type": "Microsoft.Network/networkInterfaces",
      "apiVersion": "2021-08-01",
      "name": "netInterface-workload-srv",
      "location": "[parameters('location')]",
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "subnet": {
                "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', 'Spoke-01', 'Workload-SN')]"
              },
              "primary": true,
              "privateIPAddressVersion": "IPv4"
            }
          }
        ],
        "enableAcceleratedNetworking": false,
        "enableIPForwarding": false,
        "networkSecurityGroup": {
          "id": "[resourceId('Microsoft.Network/networkSecurityGroups', 'nsg-workload-srv')]"
        }
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/networkSecurityGroups', 'nsg-workload-srv')]",
        "[resourceId('Microsoft.Network/virtualNetworks/subnets', 'Spoke-01', 'Workload-SN')]"
      ]
    },
    {
      "type": "Microsoft.Network/networkInterfaces",
      "apiVersion": "2021-08-01",
      "name": "netInterface-jump-srv",
      "location": "[parameters('location')]",
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "publicIPAddress": {
                "id": "[resourceId('Microsoft.Network/publicIPAddresses', 'publicIP-jump-srv')]"
              },
              "subnet": {
                "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', 'Spoke-01', 'Jump-SN')]"
              },
              "primary": true,
              "privateIPAddressVersion": "IPv4"
            }
          }
        ],
        "enableAcceleratedNetworking": false,
        "enableIPForwarding": false,
        "networkSecurityGroup": {
          "id": "[resourceId('Microsoft.Network/networkSecurityGroups', 'nsg-jump-srv')]"
        }
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/networkSecurityGroups', 'nsg-jump-srv')]",
        "[resourceId('Microsoft.Network/publicIPAddresses', 'publicIP-jump-srv')]",
        "[resourceId('Microsoft.Network/virtualNetworks/subnets', 'Spoke-01', 'Jump-SN')]"
      ]
    },
    {
      "type": "Microsoft.Network/networkSecurityGroups",
      "apiVersion": "2021-08-01",
      "name": "nsg-jump-srv",
      "location": "[parameters('location')]",
      "properties": {
        "securityRules": [
          {
            "name": "RDP",
            "properties": {
              "protocol": "Tcp",
              "sourcePortRange": "*",
              "destinationPortRange": "3389",
              "sourceAddressPrefix": "*",
              "destinationAddressPrefix": "*",
              "access": "Allow",
              "priority": 300,
              "direction": "Inbound"
            }
          }
        ]
      }
    },
    {
      "type": "Microsoft.Network/networkSecurityGroups",
      "apiVersion": "2021-08-01",
      "name": "nsg-workload-srv",
      "location": "[parameters('location')]",
      "properties": {}
    },
    {
      "type": "Microsoft.Network/publicIPAddresses",
      "apiVersion": "2021-08-01",
      "name": "publicIP-jump-srv",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard"
      },
      "properties": {
        "publicIPAddressVersion": "IPv4",
        "publicIPAllocationMethod": "Static",
        "idleTimeoutInMinutes": 4
      }
    },
    {
      "type": "Microsoft.Network/routeTables",
      "apiVersion": "2021-08-01",
      "name": "RT-01",
      "location": "[parameters('location')]",
      "properties": {
        "disableBgpRoutePropagation": false,
        "routes": [
          {
            "name": "jump-to-inet",
            "properties": {
              "addressPrefix": "0.0.0.0/0",
              "nextHopType": "Internet"
            }
          }
        ]
      }
    },
    {
      "type": "Microsoft.Network/virtualHubs/hubRouteTables",
      "apiVersion": "2021-08-01",
      "name": "[format('{0}/{1}', 'Hub-01', 'RT_VNet')]",
      "properties": {
        "routes": [
          {
            "name": "Workload-SNToFirewall",
            "destinationType": "CIDR",
            "destinations": [
              "10.0.1.0/24"
            ],
            "nextHopType": "ResourceId",
            "nextHop": "[resourceId('Microsoft.Network/azureFirewalls', 'AzfwTest')]"
          },
          {
            "name": "InternetToFirewall",
            "destinationType": "CIDR",
            "destinations": [
              "0.0.0.0/0"
            ],
            "nextHopType": "ResourceId",
            "nextHop": "[resourceId('Microsoft.Network/azureFirewalls', 'AzfwTest')]"
          }
        ],
        "labels": [
          "VNet"
        ]
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/azureFirewalls', 'AzfwTest')]",
        "[resourceId('Microsoft.Network/virtualHubs', 'Hub-01')]"
      ]
    }
  ]
}

Multiple Azure resources are defined in the template:

Deploy the template

Deploy the ARM template to Azure:

  1. Select Deploy to Azure to sign in to Azure and open the template. The template creates an Azure Firewall, a virtual WAN and virtual hub, the network infrastructure, and two virtual machines.

    Button to deploy the Resource Manager template to Azure.

  2. In the portal, on the Secured virtual hubs page, type or select the following values:

    • Subscription: Select from existing subscriptions
    • Resource group: Select from existing resource groups or select Create new, and select OK.
    • Location: Select a location
    • Admin Username: Type username for the administrator user account
    • Admin Password: Type an administrator password or key
  3. Select Review + create and then select Create. The deployment can take 10 minutes or longer to complete.

Validate the deployment

Now, test the firewall rules to confirm that it works as expected.

  1. From the Azure portal, review the network settings for the Workload-Srv virtual machine and note the private IP address.

  2. Connect a remote desktop to Jump-Srv virtual machine, and sign in. From there, open a remote desktop connection to the Workload-Srv private IP address.

  3. Open Internet Explorer and browse to www.microsoft.com.

  4. Select OK > Close on the Internet Explorer security alerts.

    You should see the Microsoft home page.

  5. Browse to www.google.com.

    You should be blocked by the firewall.

So now you've verified that the firewall rules are working:

  • You can browse to the one allowed FQDN, but not to any others.

Clean up resources

When you no longer need the resources that you created with the firewall, delete the resource group. This removes the firewall and all the related resources.

To delete the resource group, call the Remove-AzResourceGroup cmdlet:

Remove-AzResourceGroup -Name "<your resource group name>"

Next steps