Quickstart: Deploy Azure Firewall with Availability Zones - Bicep
Article 03/08/2023
2 contributors
Feedback
In this article
Prerequisites
Review the Bicep file
Deploy the Bicep file
Review deployed resources
Clean up resources
Next steps
Show 2 more
In this quickstart, you use Bicep to deploy an Azure Firewall in three Availability Zones.
Bicep is a domain-specific language (DSL) that uses declarative syntax to deploy Azure resources. It provides concise syntax, reliable type safety, and support for code reuse. Bicep offers the best authoring experience for your infrastructure-as-code solutions in Azure.
The Bicep file creates a test network environment with a firewall. The network has one virtual network (VNet) with three subnets: AzureFirewallSubnet , ServersSubnet , and JumpboxSubnet . The ServersSubnet and JumpboxSubnet subnet each have a single, two-core Windows Server virtual machine.
The firewall is in the AzureFirewallSubnet subnet, and has an application rule collection with a single rule that allows access to www.microsoft.com
.
A user-defined route points network traffic from the ServersSubnet subnet through the firewall, where the firewall rules are applied.
For more information about Azure Firewall, see Deploy and configure Azure Firewall using the Azure portal .
This Bicep file creates an Azure Firewall with Availability Zones, along with the necessary resources to support the Azure Firewall.
The Bicep file used in this quickstart is from Azure Quickstart Templates .
@description('virtual network name' )
param virtualNetworkName string = 'test-vnet'
@description('Location for all resources.' )
param location string = resourceGroup() .location
@description('Username for the Virtual Machine.' )
param adminUsername string
@description('Password for the Virtual Machine.' )
@secure()
param adminPassword string
@description('Availability zone numbers e.g. 1,2,3.' )
param availabilityZones array = [
'1'
'2'
'3'
]
@description('Number of public IP addresses for the Azure Firewall' )
@minValue(1 )
@maxValue(100 )
param numberOfFirewallPublicIPAddresses int = 1
@description('Size of the virtual machine.' )
param jumpBoxSize string = 'Standard_D2s_v3'
@description('Size of the virtual machine.' )
param serverSize string = 'Standard_D2s_v3'
var vnetAddressPrefix = '10.0.0.0/16'
var serversSubnetPrefix = '10.0.2.0/24'
var azureFirewallSubnetPrefix = '10.0.1.0/24'
var jumpboxSubnetPrefix = '10.0.0.0/24'
var nextHopIP = '10.0.1.4'
var azureFirewallSubnetName = 'AzureFirewallSubnet'
var jumpBoxSubnetName = 'JumpboxSubnet'
var serversSubnetName = 'ServersSubnet'
var jumpBoxPublicIPAddressName = 'JumpHostPublicIP'
var jumpBoxNsgName = 'JumpHostNSG'
var jumpBoxNicName = 'JumpHostNic'
var jumpBoxSubnetId = resourceId('Microsoft.Network/virtualNetworks/subnets' , virtualNetworkName , jumpBoxSubnetName )
var serverNicName = 'ServerNic'
var serverSubnetId = resourceId('Microsoft.Network/virtualNetworks/subnets' , virtualNetworkName , serversSubnetName )
var storageAccountName = '${uniqueString(resourceGroup() .id ) } sajumpbox'
var azfwRouteTableName = 'AzfwRouteTable'
var firewallName = 'firewall1'
var publicIPNamePrefix = 'publicIP'
var azureFirewallSubnetId = resourceId('Microsoft.Network/virtualNetworks/subnets' , virtualNetworkName , azureFirewallSubnetName )
var azureFirewallSubnetJSON = json('{"id": "${azureFirewallSubnetId } "}' )
var networkSecurityGroupName = '${serversSubnetName } -nsg'
var azureFirewallIpConfigurations = [for i in range(0 , numberOfFirewallPublicIPAddresses ) : {
name : 'IpConf${i } '
properties : {
subnet : ((i == 0 ) ? azureFirewallSubnetJSON : json('null ' ) )
publicIPAddress : {
id : publicIPAddress [i ].id
}
}
}]
resource storageAccount 'Microsoft.Storage/storageAccounts@2021-08-01' = {
name : storageAccountName
location : location
sku : {
name : 'Standard_LRS'
}
kind : 'Storage'
properties : {}
}
resource azfwRouteTable 'Microsoft.Network/routeTables@2021-03-01' = {
name : azfwRouteTableName
location : location
properties : {
disableBgpRoutePropagation : false
routes : [
{
name : 'AzfwDefaultRoute'
properties : {
addressPrefix : '0.0.0.0/0'
nextHopType : 'VirtualAppliance'
nextHopIpAddress : nextHopIP
}
}
]
}
}
resource nsg 'Microsoft.Network/networkSecurityGroups@2021-03-01' = {
name : networkSecurityGroupName
location : location
properties : {}
}
resource virtualNetwork 'Microsoft.Network/virtualNetworks@2021-05-01' = {
name : virtualNetworkName
location : location
tags : {
displayName : virtualNetworkName
}
properties : {
addressSpace : {
addressPrefixes : [
vnetAddressPrefix
]
}
subnets : [
{
name : jumpBoxSubnetName
properties : {
addressPrefix : jumpboxSubnetPrefix
}
}
{
name : azureFirewallSubnetName
properties : {
addressPrefix : azureFirewallSubnetPrefix
}
}
{
name : serversSubnetName
properties : {
addressPrefix : serversSubnetPrefix
routeTable : {
id : azfwRouteTable .id
}
networkSecurityGroup : {
id : nsg .id
}
}
}
]
}
}
resource publicIPAddress 'Microsoft.Network/publicIPAddresses@2021-03-01' = [for i in range(0 , numberOfFirewallPublicIPAddresses ) : {
name : '${publicIPNamePrefix } ${i +1 } '
location : location
sku : {
name : 'Standard'
}
properties : {
publicIPAllocationMethod : 'Static'
publicIPAddressVersion : 'IPv4'
}
zones : availabilityZones
}]
resource jumpBoxPublicIPAddress 'Microsoft.Network/publicIPAddresses@2021-03-01' = {
name : jumpBoxPublicIPAddressName
location : location
properties : {
publicIPAllocationMethod : 'Dynamic'
}
}
resource jumpBoxNsg 'Microsoft.Network/networkSecurityGroups@2021-05-01' = {
name : jumpBoxNsgName
location : location
properties : {
securityRules : [
{
name : 'myNetworkSecurityGroupRuleRDP'
properties : {
protocol : 'Tcp'
sourcePortRange : '*'
destinationPortRange : '3389'
sourceAddressPrefix : '*'
destinationAddressPrefix : '*'
access : 'Allow'
priority : 1000
direction : 'Inbound'
}
}
]
}
}
resource JumpBoxNic 'Microsoft.Network/networkInterfaces@2021-05-01' = {
name : jumpBoxNicName
location : location
properties : {
ipConfigurations : [
{
name : 'ipconfig1'
properties : {
privateIPAllocationMethod : 'Dynamic'
publicIPAddress : {
id : jumpBoxPublicIPAddress .id
}
subnet : {
id : jumpBoxSubnetId
}
}
}
]
networkSecurityGroup : {
id : jumpBoxNsg .id
}
}
dependsOn : [
virtualNetwork
]
}
resource ServerNic 'Microsoft.Network/networkInterfaces@2021-05-01' = {
name : serverNicName
location : location
properties : {
ipConfigurations : [
{
name : 'ipconfig1'
properties : {
privateIPAllocationMethod : 'Dynamic'
subnet : {
id : serverSubnetId
}
}
}
]
}
dependsOn : [
virtualNetwork
]
}
resource JumpBoxVM 'Microsoft.Compute/virtualMachines@2021-11-01' = {
name : 'JumpBox'
location : location
tags : {
AzSecPackAutoConfigReady : true
}
properties : {
hardwareProfile : {
vmSize : jumpBoxSize
}
storageProfile : {
imageReference : {
publisher : 'MicrosoftCBLMariner'
offer : 'cbl-mariner'
sku : 'cbl-mariner-2-gen2'
version : 'latest'
}
osDisk : {
osType : 'Linux'
createOption : 'FromImage'
diskSizeGB : 127
}
}
osProfile : {
computerName : 'JumpBox'
adminUsername : adminUsername
adminPassword : adminPassword
linuxConfiguration :{
patchSettings : {
patchMode : 'AutomaticByPlatform'
}
}
}
networkProfile : {
networkInterfaces : [
{
id : JumpBoxNic .id
}
]
}
diagnosticsProfile : {
bootDiagnostics : {
enabled : true
storageUri : storageAccount .properties .primaryEndpoints .blob
}
}
}
}
resource ServerVM 'Microsoft.Compute/virtualMachines@2021-11-01' = {
name : 'Server'
location : location
tags : {
AzSecPackAutoConfigReady : true
}
properties : {
hardwareProfile : {
vmSize : serverSize
}
storageProfile : {
imageReference : {
publisher : 'MicrosoftCBLMariner'
offer : 'cbl-mariner'
sku : 'cbl-mariner-2-gen2'
version : 'latest'
}
osDisk : {
osType : 'Linux'
createOption : 'FromImage'
diskSizeGB : 127
}
}
osProfile : {
computerName : 'Server'
adminUsername : adminUsername
adminPassword : adminPassword
linuxConfiguration :{
patchSettings : {
patchMode : 'AutomaticByPlatform'
}
}
}
networkProfile : {
networkInterfaces : [
{
id : ServerNic .id
}
]
}
diagnosticsProfile : {
bootDiagnostics : {
enabled : true
storageUri : storageAccount .properties .primaryEndpoints .blob
}
}
}
}
resource firewall 'Microsoft.Network/azureFirewalls@2021-05-01' = {
name : firewallName
location : location
zones : ((length(availabilityZones ) == 0 ) ? json('null ' ) : availabilityZones )
properties : {
ipConfigurations : azureFirewallIpConfigurations
applicationRuleCollections : [
{
name : 'appRc1'
properties : {
priority : 101
action : {
type : 'Allow'
}
rules : [
{
name : 'appRule1'
protocols : [
{
port : 80
protocolType : 'Http'
}
{
port : 443
protocolType : 'Https'
}
]
targetFqdns : [
'www.microsoft.com'
]
sourceAddresses : [
'10.0.2.0/24'
]
}
]
}
}
]
networkRuleCollections : [
{
name : 'netRc1'
properties : {
priority : 200
action : {
type : 'Allow'
}
rules : [
{
name : 'netRule1'
protocols : [
'TCP'
]
sourceAddresses : [
'10.0.2.0/24'
]
destinationAddresses : [
'*'
]
destinationPorts : [
'8000-8999'
]
}
]
}
}
]
}
dependsOn : [
virtualNetwork
publicIPAddress
]
}
Multiple Azure resources are defined in the Bicep file:
Save the Bicep file as main.bicep
to your local computer.
Deploy the Bicep file using either Azure CLI or Azure PowerShell.
az group create --name exampleRG --location eastus
az deployment group create --resource-group exampleRG --template-file main.bicep --parameters adminUsername= <admin-user>
New-AzResourceGroup -Name exampleRG -Location eastus
New-AzResourceGroupDeployment -ResourceGroupName exampleRG -TemplateFile ./main.bicep -adminUsername "<admin-user>"
Note
Replace <admin-user> with the administrator login username for the virtual machine. You'll be prompted to enter adminPassword .
When the deployment finishes, you should see a message indicating the deployment succeeded.
Review deployed resources
Use the Azure portal, Azure CLI, or Azure PowerShell to validate the deployment and review the deployed resources.
az resource list --resource-group exampleRG
Get-AzResource -ResourceGroupName exampleRG
To learn about the syntax and properties for a firewall in a Bicep file, see Microsoft.Network/azureFirewalls .
When you no longer need them, use the Azure portal, Azure CLI, or Azure PowerShell to remove the resource group, firewall, and all related resources.
az group delete --name exampleRG
Remove-AzResourceGroup -Name exampleRG
Next, you can monitor the Azure Firewall logs.