I resorted to parsing the strings which are written to HKLM\SOFTWARE\Policies\Microsoft\WindowsFirewall\FirewallRules
by the group policy firewall extension. This is what the raw registry value data might look like for a specific rule:
v2.10|Action=Allow|Active=TRUE|Dir=In|Protocol=6|LPort=5666|RA4=192.168.21.55|RA4=192.168240.10|RA4=192.168.240.11|RA4=192.168.240.12|App=%ProgramFiles%\NSClient++\nscp.exe|Name=NSClient++ Monitoring Agent|Desc=Allow NSClient/NRPE connections from Nagios servers|
As those are Name=Value
pairs of data where "Name" is not unique, there is some more work than just a series of Split()
calls, but it still sufficiently clean to work with in PowerShell v2 and onwards:
Function Get-GPOFirewallRules()
{
$regPath="HKLM:\SOFTWARE\Policies\Microsoft\WindowsFirewall\FirewallRules"
# fetch rule value strings from registry into an array of strings,
# map version info and GPO rule ID into fields in string
$rulesRaw = (Get-ItemProperty -Path $regPath).PSObject.Properties | `
Where-Object { $_.Name -like "{[0-9A-F\-]*}" } | `
Select-Object "Name", "Value" | `
ForEach-Object { $_.Value -replace "^(v[0-9\.]*)\|", `
"GPOID=$($_.Name)|GPOVERSION=`$1|" }
# construct a result set of hashtables
$rulesRaw | ForEach-Object {
$rule=@{} # initialize as hashtable
$_.Split("|") | ForEach-Object {
$name = $_.Split("=")[0]
$value = $_.Split("=")[1]
# for multi-valued names, cast to array and add value element
If ($rule.ContainsKey($name)) {
$rule.$name = [array]($rule.$name) + $value
} Else {
$rule.Add($name, $value)
}
} # $_.Split("|") | ForEach-Object
$rule
} #$rulesRaw | ForEach-Object
}
The output is a list of hashtables where key names have been derived from the respective registry field names and the values are either strings or arrays of strings:
Get-GPOFirewallRules
Action Allow
GPOVERSION v2.10
Dir In
Desc Allow NSClient/NRPE connections from Nagios servers
Name NSClient++ Monitoring Agent
Active TRUE
RA4 {192.168.21.55, 192.168.240.10, 192.168.240.11, 192.168.240.12}
App %ProgramFiles%\NSClient++\nscp.exe
Protocol 6
LPort 5666
GPOID {1FEFA84F-0779-4279-9C02-F5678C949304}
Action Allow
GPOVERSION v2.10
Dir In
Name Allow ICMP for Monitoring und Management
Active TRUE
RA4 {192.168.21.55, 192.168.3.60, 192.168.3.61, 192.168.8.0/255.255.255.0...}
ICMP4 {3:*, 8:*, 11:*}
Protocol 1
GPOID {6CA2C52C-6AD6-4513-B197-3702637BD9DF}
The naming scheme is different from what (New-object –comObject HNetCfg.FwPolicy2).rules
is returning and the structure seems to be slightly different (and likely subject to change in future Windows versions) too, but it seems to serve its purpose for now.