Skip to content

Commit 861d2f7

Browse files
authored
Merge pull request Azure#9295 from iatodoro/azure_firewall_multi_pip
Multiple public IP support for Azure Firewall
2 parents 12cef92 + 0d1bbc1 commit 861d2f7

File tree

8 files changed

+22691
-37
lines changed

8 files changed

+22691
-37
lines changed

src/Network/Network.Test/ScenarioTests/AzureFirewallTests.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ public void TestAzureFirewallCRUDWithZones()
4242
TestRunner.RunTestScript("Test-AzureFirewallCRUDWithZones");
4343
}
4444

45+
[Fact]
46+
[Trait(Category.AcceptanceType, Category.CheckIn)]
47+
[Trait(Category.Owner, NrpTeamAlias.azurefirewall)]
48+
public void TestAzureFirewallPIPAndVNETObjectTypeParams()
49+
{
50+
TestRunner.RunTestScript("Test-AzureFirewallPIPAndVNETObjectTypeParams");
51+
}
52+
4553
[Fact]
4654
[Trait(Category.AcceptanceType, Category.CheckIn)]
4755
[Trait(Category.Owner, NrpTeamAlias.azurefirewall)]

src/Network/Network.Test/ScenarioTests/AzureFirewallTests.ps1

Lines changed: 166 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ function Test-AzureFirewallCRUD
9898
# Create the Virtual Network
9999
$subnet = New-AzVirtualNetworkSubnetConfig -Name $subnetName -AddressPrefix 10.0.0.0/24
100100
$vnet = New-AzvirtualNetwork -Name $vnetName -ResourceGroupName $rgname -Location $location -AddressPrefix 10.0.0.0/16 -Subnet $subnet
101+
# Get full subnet details
102+
$subnet = Get-AzVirtualNetworkSubnetConfig -VirtualNetwork $vnet -Name $subnetName
101103

102104
# Create public ip
103105
$publicip = New-AzPublicIpAddress -ResourceGroupName $rgname -name $publicIpName -location $location -AllocationMethod Static -Sku Standard
@@ -119,6 +121,8 @@ function Test-AzureFirewallCRUD
119121
Assert-NotNull $getAzureFirewall.IpConfigurations[0].Subnet.Id
120122
Assert-NotNull $getAzureFirewall.IpConfigurations[0].PublicIpAddress.Id
121123
Assert-NotNull $getAzureFirewall.IpConfigurations[0].PrivateIpAddress
124+
Assert-AreEqual $subnet.Id $getAzureFirewall.IpConfigurations[0].Subnet.Id
125+
Assert-AreEqual $publicip.Id $getAzureFirewall.IpConfigurations[0].PublicIpAddress.Id
122126
Assert-AreEqual 0 @($getAzureFirewall.ApplicationRuleCollections).Count
123127
Assert-AreEqual 0 @($getAzureFirewall.NatRuleCollections).Count
124128
Assert-AreEqual 0 @($getAzureFirewall.NetworkRuleCollections).Count
@@ -204,8 +208,8 @@ function Test-AzureFirewallCRUD
204208
# Add NetworkRuleCollections to the Firewall using method AddNetworkRuleCollection
205209
$azureFirewall.AddNetworkRuleCollection($netRc)
206210

207-
# Update ThreatIntel mode
208-
$azureFirewall.ThreatIntelMode = "Deny"
211+
# Update ThreatIntel mode
212+
$azureFirewall.ThreatIntelMode = "Deny"
209213

210214
# Set AzureFirewall
211215
Set-AzFirewall -AzureFirewall $azureFirewall
@@ -220,7 +224,7 @@ function Test-AzureFirewallCRUD
220224
Assert-NotNull $getAzureFirewall.Location
221225
Assert-AreEqual $location $getAzureFirewall.Location
222226
Assert-NotNull $getAzureFirewall.Etag
223-
Assert-AreEqual "Deny" $getAzureFirewall.ThreatIntelMode
227+
Assert-AreEqual "Deny" $getAzureFirewall.ThreatIntelMode
224228

225229
Assert-AreEqual 1 @($getAzureFirewall.IpConfigurations).Count
226230
Assert-NotNull $azureFirewallIpConfiguration[0].Subnet.Id
@@ -456,7 +460,7 @@ function Test-AzureFirewallCRUDWithZones
456460
{
457461
# Create the resource group
458462
$resourceGroup = New-AzResourceGroup -Name $rgname -Location $location -Tags @{ testtag = "testval" }
459-
463+
460464
# Create the Virtual Network
461465
$subnet = New-AzVirtualNetworkSubnetConfig -Name $subnetName -AddressPrefix 10.0.0.0/24
462466
$vnet = New-AzvirtualNetwork -Name $vnetName -ResourceGroupName $rgname -Location $location -AddressPrefix 10.0.0.0/16 -Subnet $subnet
@@ -660,7 +664,7 @@ function Test-AzureFirewallCRUDWithZones
660664
Assert-AreEqual $appRule1ProtocolType2 $appRule.Protocols[1].ProtocolType
661665
Assert-AreEqual $appRule1Port1 $appRule.Protocols[0].Port
662666
Assert-AreEqual $appRule1Port2 $appRule.Protocols[1].Port
663-
667+
664668
Assert-AreEqual 2 $appRule.TargetFqdns.Count
665669
Assert-AreEqual $appRule1Fqdn1 $appRule.TargetFqdns[0]
666670
Assert-AreEqual $appRule1Fqdn2 $appRule.TargetFqdns[1]
@@ -739,6 +743,163 @@ function Test-AzureFirewallCRUDWithZones
739743
}
740744
}
741745

746+
<#
747+
.SYNOPSIS
748+
Tests AzureFirewall with new style params for VNET and Public IPs - objects instead of strings
749+
#>
750+
function Test-AzureFirewallPIPAndVNETObjectTypeParams
751+
{
752+
# Setup
753+
$rgname = Get-ResourceGroupName
754+
$azureFirewallName = Get-ResourceName
755+
$resourceTypeParent = "Microsoft.Network/AzureFirewalls"
756+
$location = Get-ProviderLocation $resourceTypeParent "eastus2euap"
757+
758+
$vnetName = Get-ResourceName
759+
$subnetName = "AzureFirewallSubnet"
760+
$publicIp1Name = Get-ResourceName
761+
$publicIp2Name = Get-ResourceName
762+
763+
try
764+
{
765+
# Create the resource group
766+
$resourceGroup = New-AzResourceGroup -Name $rgname -Location $location -Tags @{ testtag = "testval" }
767+
768+
# Create the Virtual Network
769+
$subnet = New-AzVirtualNetworkSubnetConfig -Name $subnetName -AddressPrefix 10.0.0.0/24
770+
$vnet = New-AzvirtualNetwork -Name $vnetName -ResourceGroupName $rgname -Location $location -AddressPrefix 10.0.0.0/16 -Subnet $subnet
771+
# Get full subnet details
772+
$subnet = Get-AzVirtualNetworkSubnetConfig -VirtualNetwork $vnet -Name $subnetName
773+
774+
# Create public ips
775+
$publicip1 = New-AzPublicIpAddress -ResourceGroupName $rgname -name $publicIp1Name -location $location -AllocationMethod Static -Sku Standard
776+
$publicip2 = New-AzPublicIpAddress -ResourceGroupName $rgname -name $publicIp2Name -location $location -AllocationMethod Static -Sku Standard
777+
778+
# Create AzureFirewall with a single public IP address
779+
$azureFirewall = New-AzFirewall –Name $azureFirewallName -ResourceGroupName $rgname -Location $location -VirtualNetwork $vnet -PublicIpAddress $publicip1
780+
781+
# Get AzureFirewall
782+
$getAzureFirewall = Get-AzFirewall -name $azureFirewallName -ResourceGroupName $rgname
783+
784+
#verification
785+
Assert-AreEqual $rgName $getAzureFirewall.ResourceGroupName
786+
Assert-AreEqual $azureFirewallName $getAzureFirewall.Name
787+
Assert-NotNull $getAzureFirewall.Location
788+
Assert-AreEqual (Normalize-Location $location) $getAzureFirewall.Location
789+
Assert-NotNull $getAzureFirewall.Etag
790+
Assert-AreEqual 1 @($getAzureFirewall.IpConfigurations).Count
791+
Assert-NotNull $getAzureFirewall.IpConfigurations[0].Subnet.Id
792+
Assert-NotNull $getAzureFirewall.IpConfigurations[0].PublicIpAddress.Id
793+
Assert-NotNull $getAzureFirewall.IpConfigurations[0].PrivateIpAddress
794+
Assert-AreEqual $subnet.Id $getAzureFirewall.IpConfigurations[0].Subnet.Id
795+
Assert-AreEqual $publicip1.Id $getAzureFirewall.IpConfigurations[0].PublicIpAddress.Id
796+
797+
# Test handling of incorrect values when adding public IP address
798+
Assert-ThrowsContains { $getAzureFirewall.AddPublicIpAddress() } "Cannot find an overload"
799+
Assert-ThrowsContains { $getAzureFirewall.AddPublicIpAddress($null) } "Public IP Address cannot be null"
800+
Assert-ThrowsContains { $getAzureFirewall.AddPublicIpAddress("ABCD") } "Cannot convert argument"
801+
Assert-ThrowsContains { $getAzureFirewall.AddPublicIpAddress($publicip1) } "already attached to firewall"
802+
803+
# Test handling of incorrect values when removing public IP Address
804+
Assert-ThrowsContains { $getAzureFirewall.RemovePublicIpAddress() } "Cannot find an overload"
805+
Assert-ThrowsContains { $getAzureFirewall.RemovePublicIpAddress($null) } "Public IP Address cannot be null"
806+
Assert-ThrowsContains { $getAzureFirewall.RemovePublicIpAddress("ABCD") } "Cannot convert argument"
807+
Assert-ThrowsContains { $getAzureFirewall.RemovePublicIpAddress($publicip2) } "not attached to firewall"
808+
809+
# Add second public IP Address
810+
$getAzureFirewall.AddPublicIpAddress($publicip2)
811+
812+
# Set AzureFirewall
813+
Set-AzFirewall -AzureFirewall $getAzureFirewall
814+
815+
# Get AzureFirewall
816+
$getAzureFirewall = Get-AzFirewall -name $azureFirewallName -ResourceGroupName $rgName
817+
$azureFirewallIpConfiguration = $getAzureFirewall.IpConfigurations
818+
819+
#verification
820+
Assert-AreEqual $rgName $getAzureFirewall.ResourceGroupName
821+
Assert-AreEqual $azureFirewallName $getAzureFirewall.Name
822+
Assert-NotNull $getAzureFirewall.Location
823+
Assert-AreEqual $location $getAzureFirewall.Location
824+
Assert-NotNull $getAzureFirewall.Etag
825+
826+
Assert-AreEqual 2 @($getAzureFirewall.IpConfigurations).Count
827+
Assert-NotNull $azureFirewallIpConfiguration[0].Subnet.Id
828+
Assert-NotNull $azureFirewallIpConfiguration[0].PublicIpAddress.Id
829+
Assert-NotNull $azureFirewallIpConfiguration[0].PrivateIpAddress
830+
Assert-AreEqual $subnet.Id $getAzureFirewall.IpConfigurations[0].Subnet.Id
831+
Assert-AreEqual $publicip1.Id $getAzureFirewall.IpConfigurations[0].PublicIpAddress.Id
832+
Assert-AreEqual $publicip2.Id $getAzureFirewall.IpConfigurations[1].PublicIpAddress.Id
833+
834+
# Remove second public IP address
835+
$getAzureFirewall.RemovePublicIpAddress($publicip2)
836+
837+
# Set AzureFirewall
838+
Set-AzFirewall -AzureFirewall $getAzureFirewall
839+
840+
# Get AzureFirewall
841+
$getAzureFirewall = Get-AzFirewall -name $azureFirewallName -ResourceGroupName $rgName
842+
$azureFirewallIpConfiguration = $getAzureFirewall.IpConfigurations
843+
844+
#verification
845+
Assert-AreEqual $rgName $getAzureFirewall.ResourceGroupName
846+
Assert-AreEqual $azureFirewallName $getAzureFirewall.Name
847+
Assert-NotNull $getAzureFirewall.Location
848+
Assert-AreEqual $location $getAzureFirewall.Location
849+
Assert-NotNull $getAzureFirewall.Etag
850+
851+
Assert-AreEqual 1 @($getAzureFirewall.IpConfigurations).Count
852+
Assert-NotNull $azureFirewallIpConfiguration[0].Subnet.Id
853+
Assert-NotNull $azureFirewallIpConfiguration[0].PublicIpAddress.Id
854+
Assert-NotNull $azureFirewallIpConfiguration[0].PrivateIpAddress
855+
Assert-AreEqual $subnet.Id $getAzureFirewall.IpConfigurations[0].Subnet.Id
856+
Assert-AreEqual $publicip1.Id $getAzureFirewall.IpConfigurations[0].PublicIpAddress.Id
857+
858+
# Delete AzureFirewall
859+
$delete = Remove-AzFirewall -ResourceGroupName $rgname -name $azureFirewallName -PassThru -Force
860+
Assert-AreEqual true $delete
861+
862+
# Create AzureFirewall with Two Public IP addresses
863+
$azureFirewall = New-AzFirewall –Name $azureFirewallName -ResourceGroupName $rgname -Location $location -VirtualNetwork $vnet -PublicIpAddress @($publicip1, $publicip2)
864+
865+
# Get AzureFirewall
866+
$getAzureFirewall = Get-AzFirewall -name $azureFirewallName -ResourceGroupName $rgname
867+
$azureFirewallIpConfiguration = $getAzureFirewall.IpConfigurations
868+
869+
#verification
870+
Assert-AreEqual $rgName $getAzureFirewall.ResourceGroupName
871+
Assert-AreEqual $azureFirewallName $getAzureFirewall.Name
872+
Assert-NotNull $getAzureFirewall.Location
873+
Assert-AreEqual $location $getAzureFirewall.Location
874+
Assert-NotNull $getAzureFirewall.Etag
875+
876+
Assert-AreEqual 2 @($getAzureFirewall.IpConfigurations).Count
877+
Assert-NotNull $azureFirewallIpConfiguration[0].Subnet.Id
878+
Assert-NotNull $azureFirewallIpConfiguration[0].PublicIpAddress.Id
879+
Assert-NotNull $azureFirewallIpConfiguration[1].PublicIpAddress.Id
880+
Assert-NotNull $azureFirewallIpConfiguration[0].PrivateIpAddress
881+
Assert-AreEqual $subnet.Id $getAzureFirewall.IpConfigurations[0].Subnet.Id
882+
Assert-AreEqual $publicip1.Id $getAzureFirewall.IpConfigurations[0].PublicIpAddress.Id
883+
Assert-AreEqual $publicip2.Id $getAzureFirewall.IpConfigurations[1].PublicIpAddress.Id
884+
885+
# Delete AzureFirewall
886+
$delete = Remove-AzFirewall -ResourceGroupName $rgname -name $azureFirewallName -PassThru -Force
887+
Assert-AreEqual true $delete
888+
889+
# Delete VirtualNetwork
890+
$delete = Remove-AzVirtualNetwork -ResourceGroupName $rgname -name $vnetName -PassThru -Force
891+
Assert-AreEqual true $delete
892+
893+
$list = Get-AzFirewall -ResourceGroupName $rgname
894+
Assert-AreEqual 0 @($list).Count
895+
}
896+
finally
897+
{
898+
# Cleanup
899+
Clean-ResourceGroup $rgname
900+
}
901+
}
902+
742903
<#
743904
.SYNOPSIS
744905
Tests AzureFirewall Set and Remove IpConfiguration

src/Network/Network.Test/SessionRecords/Commands.Network.Test.ScenarioTests.AzureFirewallTests/TestAzureFirewallPIPAndVNETObjectTypeParams.json

Lines changed: 22295 additions & 0 deletions
Large diffs are not rendered by default.

src/Network/Network/AzureFirewall/NewAzureFirewallCommand.cs

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
using Microsoft.Azure.Commands.Network.Models;
2121
using Microsoft.Azure.Commands.ResourceManager.Common.Tags;
2222
using Microsoft.Azure.Management.Network;
23+
using Microsoft.WindowsAzure.Commands.Common.CustomAttributes;
2324
using MNM = Microsoft.Azure.Management.Network.Models;
2425

2526
namespace Microsoft.Azure.Commands.Network
@@ -30,7 +31,7 @@ public class NewAzureFirewallCommand : AzureFirewallBaseCmdlet
3031
private const string DefaultParameterSet = "Default";
3132

3233
private PSVirtualNetwork virtualNetwork;
33-
private PSPublicIpAddress publicIpAddress;
34+
private PSPublicIpAddress[] publicIpAddresses;
3435

3536
[Alias("ResourceName")]
3637
[Parameter(
@@ -54,22 +55,56 @@ public class NewAzureFirewallCommand : AzureFirewallBaseCmdlet
5455
[ValidateNotNullOrEmpty]
5556
public virtual string Location { get; set; }
5657

58+
[CmdletParameterBreakingChange(
59+
"VirtualNetworkName",
60+
deprecateByVersion: "2.0.0",
61+
ChangeDescription = "This parameter will be removed in an upcoming breaking change release. After this point the Virtual Network will be provided as an object instead of a string.",
62+
OldWay = "New-AzFirewall -VirtualNetworkName \"vnet-name\"",
63+
NewWay = "New-AzFirewall -VirtualNetwork $vnet",
64+
OldParamaterType = typeof(string),
65+
NewParameterTypeName = nameof(PSVirtualNetwork),
66+
ReplaceMentCmdletParameterName = "VirtualNetwork")]
5767
[Parameter(
5868
Mandatory = true,
5969
ValueFromPipelineByPropertyName = true,
60-
ParameterSetName = "IpConfigurationParameterValues",
70+
ParameterSetName = "OldIpConfigurationParameterValues",
6171
HelpMessage = "Virtual Network Name")]
6272
[ValidateNotNullOrEmpty]
6373
public string VirtualNetworkName { get; set; }
6474

75+
[CmdletParameterBreakingChange(
76+
"PublicIpName",
77+
deprecateByVersion: "2.0.0",
78+
ChangeDescription = "This parameter will be removed in an upcoming breaking change release. After this point the Public IP Address will be provided as a list of one or more objects instead of a string.",
79+
OldWay = "New-AzFirewall -PublicIpName \"public-ip-name\"",
80+
NewWay = "New-AzFirewall -PublicIpAddress @($publicip1, $publicip2)",
81+
OldParamaterType = typeof(string),
82+
NewParameterTypeName = "List<PSPublicIpAddress>",
83+
ReplaceMentCmdletParameterName = "PublicIpAddress")]
6584
[Parameter(
6685
Mandatory = true,
6786
ValueFromPipelineByPropertyName = true,
68-
ParameterSetName = "IpConfigurationParameterValues",
69-
HelpMessage = "Public Ip Name")]
87+
ParameterSetName = "OldIpConfigurationParameterValues",
88+
HelpMessage = "Public IP address name. The Public IP must use Standard SKU and must belong to the same resource group as the Firewall.")]
7089
[ValidateNotNullOrEmpty]
7190
public string PublicIpName { get; set; }
7291

92+
[Parameter(
93+
Mandatory = true,
94+
ValueFromPipeline = true,
95+
ParameterSetName = "IpConfigurationParameterValues",
96+
HelpMessage = "Virtual Network")]
97+
[ValidateNotNullOrEmpty]
98+
public PSVirtualNetwork VirtualNetwork { get; set; }
99+
100+
[Parameter(
101+
Mandatory = true,
102+
ValueFromPipelineByPropertyName = true,
103+
ParameterSetName = "IpConfigurationParameterValues",
104+
HelpMessage = "One or more Public IP Addresses. The Public IP addresses must use Standard SKU and must belong to the same resource group as the Firewall.")]
105+
[ValidateNotNullOrEmpty]
106+
public PSPublicIpAddress[] PublicIpAddress { get; set; }
107+
73108
[Parameter(
74109
Mandatory = false,
75110
ValueFromPipelineByPropertyName = true,
@@ -122,16 +157,23 @@ public class NewAzureFirewallCommand : AzureFirewallBaseCmdlet
122157

123158
public override void Execute()
124159
{
125-
var isVnetPresent = VirtualNetworkName!=null;
126-
127-
// Get the virtual network, get the public IP address
128-
if (isVnetPresent)
160+
// Old params provided - Get the virtual network, get the public IP address
161+
if (!string.IsNullOrEmpty(VirtualNetworkName))
129162
{
130163
var vnet = this.VirtualNetworkClient.Get(this.ResourceGroupName, VirtualNetworkName);
131164
this.virtualNetwork = NetworkResourceManagerProfile.Mapper.Map<PSVirtualNetwork>(vnet);
132165

133166
var publicIp = this.PublicIPAddressesClient.Get(this.ResourceGroupName, PublicIpName);
134-
this.publicIpAddress = NetworkResourceManagerProfile.Mapper.Map<PSPublicIpAddress>(publicIp);
167+
this.publicIpAddresses = new PSPublicIpAddress[]
168+
{
169+
NetworkResourceManagerProfile.Mapper.Map<PSPublicIpAddress>(publicIp)
170+
};
171+
}
172+
// New params
173+
else if (VirtualNetwork != null)
174+
{
175+
this.virtualNetwork = VirtualNetwork;
176+
this.publicIpAddresses = PublicIpAddress;
135177
}
136178

137179
base.Execute();
@@ -166,7 +208,7 @@ private PSAzureFirewall CreateAzureFirewall()
166208

167209
if (this.virtualNetwork != null)
168210
{
169-
firewall.Allocate(this.virtualNetwork, this.publicIpAddress);
211+
firewall.Allocate(this.virtualNetwork, this.publicIpAddresses);
170212
}
171213

172214
// Map to the sdk object

src/Network/Network/ChangeLog.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@
5353
* Add Availability Zones support for Azure Firewall
5454
* Added cmdlet Get-AzNetworkServiceTag
5555

56+
* Add support for multiple public IP addresses for Azure Firewall
57+
- Updated New-AzFirewall cmdlet:
58+
- Added parameter -PublicIpAddress which accepts one or more Public IP Address objects
59+
- Added parameter -VirtualNetwork which accepts a Virtual Network object
60+
- Added methods AddPublicIpAddress and RemovePublicIpAddress on firewall object - these accept a Public IP Address object as input
61+
- Deprecated parameters -PublicIpName and -VirtualNetworkName
62+
5663
## Version 1.8.1
5764
* Add DisableBgpRoutePropagation flag to Effective Route Table output
5865
- Updated cmdlet:

0 commit comments

Comments
 (0)