Skip to content

Commit 6c0a163

Browse files
authored
Merge pull request #10653 from b564518128/cnfw-privaterange
Adding PrivateRange to AzFirewall
2 parents 0ded3e0 + 8520219 commit 6c0a163

15 files changed

+13515
-13835
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,5 +74,12 @@ public void TestAzureFirewallThreatIntelWhitelistCRUD()
7474
TestRunner.RunTestScript("Test-AzureFirewallThreatIntelWhitelistCRUD");
7575
}
7676

77+
[Fact]
78+
[Trait(Category.AcceptanceType, Category.CheckIn)]
79+
[Trait(Category.Owner, NrpTeamAlias.azurefirewall)]
80+
public void TestAzureFirewallPrivateRangeCRUD()
81+
{
82+
TestRunner.RunTestScript("Test-AzureFirewallPrivateRangeCRUD");
83+
}
7784
}
7885
}

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

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ function Test-AzureFirewallCRUD {
8080
$networkRule1Protocol3 = "ICMP"
8181
$networkRule1DestinationPort1 = "90"
8282

83-
# AzureFirewallNetworkRule 2
83+
# AzureFirewallNetworkRule 2
8484
$networkRule2Name = "networkRule2"
8585
$networkRule2Desc = "desc2"
8686
$networkRule2SourceAddress1 = "10.0.0.0"
@@ -107,7 +107,7 @@ function Test-AzureFirewallCRUD {
107107
$natRule1TranslatedAddress = "10.1.2.3"
108108
$natRule1TranslatedPort = "91"
109109

110-
# AzureFirewallNatRule 2
110+
# AzureFirewallNatRule 2
111111
$natRule2Name = "natRule2"
112112
$natRule2Desc = "desc2"
113113
$natRule2SourceAddress1 = "10.0.0.0"
@@ -1172,7 +1172,7 @@ function Test-AzureFirewallThreatIntelWhitelistCRUD {
11721172
$publicIpName = Get-ResourceName
11731173

11741174
$threatIntelWhitelist1 = New-AzFirewallThreatIntelWhitelist -FQDN @("*.microsoft.com", "microsoft.com") -IpAddress @("8.8.8.8", "1.1.1.1")
1175-
$threatIntelWhitelist2 = New-AzFirewallThreatIntelWhitelist -IpAddress @(" 2.2.2.2 "," 3.3.3.3 ") -FQDN @(" bing.com ", "yammer.com ")
1175+
$threatIntelWhitelist2 = New-AzFirewallThreatIntelWhitelist -IpAddress @(" 2.2.2.2 ", " 3.3.3.3 ") -FQDN @(" bing.com ", "yammer.com ")
11761176

11771177
try {
11781178
# Create the resource group
@@ -1205,3 +1205,50 @@ function Test-AzureFirewallThreatIntelWhitelistCRUD {
12051205
Clean-ResourceGroup $rgname
12061206
}
12071207
}
1208+
1209+
<#
1210+
.SYNOPSIS
1211+
Tests AzureFirewall PrivateRange
1212+
#>
1213+
function Test-AzureFirewallPrivateRangeCRUD {
1214+
$rgname = Get-ResourceGroupName
1215+
$azureFirewallName = Get-ResourceName
1216+
$resourceTypeParent = "Microsoft.Network/AzureFirewalls"
1217+
$location = Get-ProviderLocation $resourceTypeParent "eastus"
1218+
1219+
$vnetName = Get-ResourceName
1220+
$subnetName = "AzureFirewallSubnet"
1221+
$publicIpName = Get-ResourceName
1222+
1223+
$privateRange1 = @("IANAPrivateRanges", "0.0.0.0/0", "66.92.0.0/16")
1224+
$privateRange2 = @("3.3.0.0/24", "98.0.0.0/8")
1225+
1226+
try {
1227+
# Create the resource group
1228+
$resourceGroup = New-AzResourceGroup -Name $rgname -Location $location
1229+
1230+
# Create the Virtual Network
1231+
$subnet = New-AzVirtualNetworkSubnetConfig -Name $subnetName -AddressPrefix 10.0.0.0/24
1232+
$vnet = New-AzVirtualNetwork -Name $vnetName -ResourceGroupName $rgname -Location $location -AddressPrefix 10.0.0.0/16 -Subnet $subnet
1233+
1234+
# Create public ip
1235+
$publicip = New-AzPublicIpAddress -ResourceGroupName $rgname -name $publicIpName -location $location -AllocationMethod Static -Sku Standard
1236+
1237+
# Create AzureFirewall
1238+
$azureFirewall = New-AzFirewall -Name $azureFirewallName -ResourceGroupName $rgname -Location $location -PrivateRange $privateRange1
1239+
1240+
# Verify
1241+
$getAzureFirewall = Get-AzFirewall -Name $azureFirewallName -ResourceGroupName $rgname
1242+
Assert-AreEqualArray $privateRange1 $getAzureFirewall.PrivateRange
1243+
1244+
# Modify
1245+
$azureFirewall.PrivateRange = $privateRange2
1246+
Set-AzFirewall -AzureFirewall $azureFirewall
1247+
$getAzureFirewall = Get-AzFirewall -Name $azureFirewallName -ResourceGroupName $rgname
1248+
Assert-AreEqualArray $privateRange2 $getAzureFirewall.PrivateRange
1249+
}
1250+
finally {
1251+
# Cleanup
1252+
Clean-ResourceGroup $rgname
1253+
}
1254+
}

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

Lines changed: 1711 additions & 2984 deletions
Large diffs are not rendered by default.

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

Lines changed: 2111 additions & 1472 deletions
Large diffs are not rendered by default.

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

Lines changed: 1955 additions & 2521 deletions
Large diffs are not rendered by default.

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

Lines changed: 3568 additions & 5737 deletions
Large diffs are not rendered by default.

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

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

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

Lines changed: 383 additions & 611 deletions
Large diffs are not rendered by default.

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

Lines changed: 1184 additions & 500 deletions
Large diffs are not rendered by default.

src/Network/Network/AzureFirewall/NewAzureFirewallCommand.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,12 @@ public class NewAzureFirewallCommand : AzureFirewallBaseCmdlet
140140
HelpMessage = "The whitelist for Threat Intelligence")]
141141
public PSAzureFirewallThreatIntelWhitelist ThreatIntelWhitelist { get; set; }
142142

143+
[Parameter(
144+
Mandatory = false,
145+
HelpMessage = "The private IP ranges to which traffic won't be SNAT'ed"
146+
)]
147+
public string[] PrivateRange { get; set; }
148+
143149
[Parameter(
144150
Mandatory = false,
145151
ValueFromPipelineByPropertyName = true,
@@ -262,6 +268,7 @@ private PSAzureFirewall CreateAzureFirewall()
262268
NetworkRuleCollections = this.NetworkRuleCollection?.ToList(),
263269
ThreatIntelMode = this.ThreatIntelMode ?? MNM.AzureFirewallThreatIntelMode.Alert,
264270
ThreatIntelWhitelist = this.ThreatIntelWhitelist,
271+
PrivateRange = this.PrivateRange,
265272
Sku = sku
266273
};
267274

src/Network/Network/ChangeLog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323

2424
## Version 2.1.0
2525
* Change `Start-AzVirtualNetworkGatewayConnectionPacketCapture.md` and `Start-AzVirtualnetworkGatewayPacketCapture.md` FilterData option examples.
26+
* Add `PrivateRange` parameter to `AzureFirewall`
27+
- Updated cmdlet:
28+
- New-AzFirewall
2629

2730
## Version 2.0.0
2831
* Change all cmdlets for PrivateEndpointConnection to support generic service provider.

src/Network/Network/Common/NetworkResourceManagerProfile.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,7 @@ private static void Initialize()
11601160
{
11611161
{ "ThreatIntel.Whitelist.FQDNs", src.ThreatIntelWhitelist?.FQDNs?.Aggregate((result, item) => result + "," + item) },
11621162
{ "ThreatIntel.Whitelist.IpAddresses", src.ThreatIntelWhitelist?.IpAddresses?.Aggregate((result, item) => result + "," + item) },
1163+
{ "Network.SNAT.PrivateRanges", src.PrivateRange?.Aggregate((result, item) => result + "," + item) }
11631164
}.Where(kvp => kvp.Value != null).ToDictionary(key => key.Key, val => val.Value); // TODO: remove after backend code is refactored
11641165
});
11651166
cfg.CreateMap<CNM.PSAzureFirewallSku, MNM.AzureFirewallSku>();
@@ -1195,6 +1196,14 @@ private static void Initialize()
11951196
{
11961197
dest.ThreatIntelWhitelist.IpAddresses = null;
11971198
}
1199+
try
1200+
{
1201+
dest.PrivateRange = src.AdditionalProperties?.SingleOrDefault(kvp => kvp.Key.Equals("Network.SNAT.PrivateRanges", StringComparison.OrdinalIgnoreCase)).Value?.Split(',').Select(str => str.Trim()).ToArray();
1202+
}
1203+
catch (PSArgumentException)
1204+
{
1205+
dest.ThreatIntelWhitelist.IpAddresses = null;
1206+
}
11981207
});
11991208
cfg.CreateMap<MNM.AzureFirewallSku, CNM.PSAzureFirewallSku>();
12001209
cfg.CreateMap<MNM.AzureFirewallIPConfiguration, CNM.PSAzureFirewallIpConfiguration>();

src/Network/Network/Models/AzureFirewall/PSAzureFirewall.cs

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
using System;
1717
using System.Collections.Generic;
1818
using System.Linq;
19+
using System.Management.Automation;
20+
using System.Net;
21+
using Microsoft.Rest;
1922
using Newtonsoft.Json;
2023

2124
namespace Microsoft.Azure.Commands.Network.Models
@@ -24,7 +27,9 @@ public class PSAzureFirewall : PSTopLevelResource
2427
{
2528
private const string AzureFirewallSubnetName = "AzureFirewallSubnet";
2629
private const string AzureFirewallIpConfigurationName = "AzureFirewallIpConfiguration";
30+
private const string IANAPrivateRanges = "IANAPrivateRanges";
2731

32+
private string[] privateRange;
2833

2934
public List<PSAzureFirewallIpConfiguration> IpConfigurations { get; set; }
3035

@@ -44,6 +49,19 @@ public class PSAzureFirewall : PSTopLevelResource
4449

4550
public PSAzureFirewallThreatIntelWhitelist ThreatIntelWhitelist { get; set; }
4651

52+
public string[] PrivateRange {
53+
get
54+
{
55+
return this.privateRange;
56+
}
57+
set
58+
{
59+
if (value != null)
60+
ValidatePrivateRange(value);
61+
privateRange = value;
62+
}
63+
}
64+
4765
public string ProvisioningState { get; set; }
4866

4967
public List<string> Zones { get; set; }
@@ -78,6 +96,12 @@ public string ThreatIntelWhitelistText
7896
get { return JsonConvert.SerializeObject(ThreatIntelWhitelist, Formatting.Indented); }
7997
}
8098

99+
[JsonIgnore]
100+
public string PrivateRangeText
101+
{
102+
get { return JsonConvert.SerializeObject(PrivateRange, Formatting.Indented); }
103+
}
104+
81105
#region Ip Configuration Operations
82106

83107
public void Allocate(PSVirtualNetwork virtualNetwork, PSPublicIpAddress[] publicIpAddresses)
@@ -272,6 +296,54 @@ public void RemoveNetworkRuleCollectionByPriority(uint priority)
272296

273297
#endregion // Application Rule Collections Operations
274298

299+
#region Private Range Validation
300+
private void ValidatePrivateRange(string[] privateRange)
301+
{
302+
foreach (var ip in privateRange)
303+
{
304+
if (ip.Equals(IANAPrivateRanges, StringComparison.OrdinalIgnoreCase))
305+
continue;
306+
307+
if (ip.Contains("/"))
308+
ValidateMaskedIpAddress(ip);
309+
else
310+
ValidateSingleIpAddress(ip);
311+
}
312+
}
313+
314+
private void ValidateSingleIpAddress(string ipAddress)
315+
{
316+
IPAddress ipVal;
317+
if (!IPAddress.TryParse(ipAddress, out ipVal) || ipVal.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork)
318+
{
319+
throw new PSArgumentException(String.Format("\'{0}\' is not a valid private range ip address", ipAddress));
320+
}
321+
}
322+
323+
private void ValidateMaskedIpAddress(string ipAddress)
324+
{
325+
var split = ipAddress.Split('/');
326+
if (split.Length != 2)
327+
throw new PSArgumentException(String.Format("\'{0}\' is not a valid private range ip address", ipAddress));
328+
329+
// validate the ip
330+
ValidateSingleIpAddress(split[0]);
331+
332+
// validate mask
333+
var bit = 0;
334+
if (!Int32.TryParse(split[1], out bit) || bit < 0 || bit > 32)
335+
throw new PSArgumentException(String.Format("\'{0}\' is not a valid private range ip address, subnet mask should between 0 and 32", ipAddress));
336+
337+
// validated that unmasked bits are 0
338+
var splittedIp = split[0].Split('.');
339+
var ip = Int32.Parse(splittedIp[0]) << 24;
340+
ip = ip + Int32.Parse(splittedIp[1]) << 16 + Int32.Parse(splittedIp[2]) << 8 + Int32.Parse(splittedIp[3]);
341+
if (ip << bit != 0)
342+
throw new PSArgumentException(String.Format("\'{0}\' is not a valid private range ip address, bits not covered by subnet mask should be all 0", ipAddress));
343+
}
344+
345+
#endregion
346+
275347
#region Private Methods
276348

277349
private List<BaseRuleCollection> AddRuleCollection<BaseRuleCollection>(BaseRuleCollection ruleCollection, List<BaseRuleCollection> existingRuleCollections) where BaseRuleCollection : PSAzureFirewallBaseRuleCollection
@@ -301,7 +373,6 @@ private BaseRuleCollection GetRuleCollectionByName<BaseRuleCollection>(string ru
301373

302374
return ruleCollection;
303375
}
304-
305376
#endregion // Private Methods
306377
}
307378
}

src/Network/Network/Network.format.ps1xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3298,6 +3298,10 @@
32983298
<Label>ThreatIntelWhitelist</Label>
32993299
<PropertyName>ThreatIntelWhitelistText</PropertyName>
33003300
</ListItem>
3301+
<ListItem>
3302+
<Label>PrivateRange</Label>
3303+
<PropertyName>PrivateRangeText</PropertyName>
3304+
</ListItem>
33013305
<ListItem>
33023306
<Label>Sku</Label>
33033307
<PropertyName>Sku</PropertyName>

src/Network/Network/help/New-AzFirewall.md

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ New-AzFirewall -Name <String> -ResourceGroupName <String> -Location <String>
1919
[-ApplicationRuleCollection <PSAzureFirewallApplicationRuleCollection[]>]
2020
[-NatRuleCollection <PSAzureFirewallNatRuleCollection[]>]
2121
[-NetworkRuleCollection <PSAzureFirewallNetworkRuleCollection[]>] [-ThreatIntelMode <String>]
22-
[-ThreatIntelWhitelist <PSAzureFirewallThreatIntelWhitelist>] [-Tag <Hashtable>] [-Force] [-AsJob]
23-
[-Zone <String[]>] [-Sku <String>] [-VirtualHubId <String>] [-FirewallPolicyId <String>]
22+
[-ThreatIntelWhitelist <PSAzureFirewallThreatIntelWhitelist>] [-PrivateRange <String[]>] [-Tag <Hashtable>]
23+
[-Force] [-AsJob] [-Zone <String[]>] [-Sku <String>] [-VirtualHubId <String>] [-FirewallPolicyId <String>]
2424
[-DefaultProfile <IAzureContextContainer>] [-WhatIf] [-Confirm] [<CommonParameters>]
2525
```
2626

@@ -30,8 +30,8 @@ New-AzFirewall -Name <String> -ResourceGroupName <String> -Location <String> -Vi
3030
-PublicIpName <String> [-ApplicationRuleCollection <PSAzureFirewallApplicationRuleCollection[]>]
3131
[-NatRuleCollection <PSAzureFirewallNatRuleCollection[]>]
3232
[-NetworkRuleCollection <PSAzureFirewallNetworkRuleCollection[]>] [-ThreatIntelMode <String>]
33-
[-ThreatIntelWhitelist <PSAzureFirewallThreatIntelWhitelist>] [-Tag <Hashtable>] [-Force] [-AsJob]
34-
[-Zone <String[]>] [-Sku <String>] [-VirtualHubId <String>] [-FirewallPolicyId <String>]
33+
[-ThreatIntelWhitelist <PSAzureFirewallThreatIntelWhitelist>] [-PrivateRange <String[]>] [-Tag <Hashtable>]
34+
[-Force] [-AsJob] [-Zone <String[]>] [-Sku <String>] [-VirtualHubId <String>] [-FirewallPolicyId <String>]
3535
[-DefaultProfile <IAzureContextContainer>] [-WhatIf] [-Confirm] [<CommonParameters>]
3636
```
3737

@@ -42,8 +42,8 @@ New-AzFirewall -Name <String> -ResourceGroupName <String> -Location <String> -Vi
4242
[-ApplicationRuleCollection <PSAzureFirewallApplicationRuleCollection[]>]
4343
[-NatRuleCollection <PSAzureFirewallNatRuleCollection[]>]
4444
[-NetworkRuleCollection <PSAzureFirewallNetworkRuleCollection[]>] [-ThreatIntelMode <String>]
45-
[-ThreatIntelWhitelist <PSAzureFirewallThreatIntelWhitelist>] [-Tag <Hashtable>] [-Force] [-AsJob]
46-
[-Zone <String[]>] [-Sku <String>] [-VirtualHubId <String>] [-FirewallPolicyId <String>]
45+
[-ThreatIntelWhitelist <PSAzureFirewallThreatIntelWhitelist>] [-PrivateRange <String[]>] [-Tag <Hashtable>]
46+
[-Force] [-AsJob] [-Zone <String[]>] [-Sku <String>] [-VirtualHubId <String>] [-FirewallPolicyId <String>]
4747
[-DefaultProfile <IAzureContextContainer>] [-WhatIf] [-Confirm] [<CommonParameters>]
4848
```
4949

@@ -172,6 +172,17 @@ New-AzFirewall -Name "azFw" -ResourceGroupName $rgName -Location centralus -Virt
172172

173173
This example creates a Firewall that whitelist "www.microsoft.com" and "8.8.8.8" from threat intelligence
174174

175+
### 11: Create a Firewall with customized private range setup
176+
```
177+
$rgName = "resourceGroupName"
178+
$vnet = Get-AzVirtualNetwork -ResourceGroupName $rgName -Name "vnet"
179+
$pip = Get-AzPublicIpAddress -ResourceGroupName $rgName -Name "publicIpName"
180+
181+
New-AzFirewall -Name "azFw" -ResourceGroupName $rgName -Location centralus -VirtualNetwork $vnet -PublicIpAddress $pip -PrivateRange @("99.99.99.0/24", "66.66.0.0/16")
182+
```
183+
184+
This example creates a Firewall that treats "99.99.99.0/24" and "66.66.0.0/16" as private ip ranges and won't snat traffic to those addresses
185+
175186
## PARAMETERS
176187

177188
### -ApplicationRuleCollection
@@ -309,6 +320,21 @@ Accept pipeline input: True (ByPropertyName)
309320
Accept wildcard characters: False
310321
```
311322
323+
### -PrivateRange
324+
The private IP ranges to which traffic won't be SNAT'ed
325+
326+
```yaml
327+
Type: System.String[]
328+
Parameter Sets: (All)
329+
Aliases:
330+
331+
Required: False
332+
Position: Named
333+
Default value: None
334+
Accept pipeline input: False
335+
Accept wildcard characters: False
336+
```
337+
312338
### -PublicIpAddress
313339
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.
314340

0 commit comments

Comments
 (0)