0

我正在尝试导出在多个组策略对象中指定的防火墙规则,并希望在导出的文件中包含 GPO 的名称。因此,每次解析一个新的 gpo 时,我都尝试将我的字符串变量$Policy放入 csv 文件中,但我得到的只是 gpo 名称,而不是来自Get-NetFirewallRule. 当然,如果我删除该$policy | Out-File $env:temp\gpos.csv -Append -Force行,那么我会从中获取所有字段Get-NetFirewallRule- 但它们都在一个大的 csv 文件中,我无法确定它们的源 GPO。


foreach ($policy in $PolicyObjects) {
$GPO = Open-NetGPO -PolicyStore "contoso.com\$policy"
$policy | Out-File $env:temp\gpos.csv  -Append -Force
Get-NetFirewallRule -GPOSession $GPO  | 
Select Name,
DisplayName,
DisplayGroup,
@{Name='Protocol';Expression={($PSItem | Get-NetFirewallPortFilter).Protocol}},
@{Name='LocalPort';Expression={($PSItem | Get-NetFirewallPortFilter).LocalPort}},
@{Name='RemotePort';Expression={($PSItem | Get-NetFirewallPortFilter).RemotePort}},
@{Name='RemoteAddress';Expression={($PSItem | Get-NetFirewallAddressFilter).RemoteAddress}},
Enabled,
Profile,
Direction,
Action | Export-CSV $env:temp\gpos.csv -Append -Force
}
Start-Process notepad $env:temp\gpos.csv 
4

3 回答 3

1

似乎您$PolicyObjects是您的组策略显示名称的列表。我会以下列方式之一收紧你的代码。

$PolicyObjects | ForEach-Object {

    $GPO = Open-NetGPO -PolicyStore "contoso.com\$_"

    foreach($rule in Get-NetFirewallRule -GPOSession $GPO)
    {
        $portfilter    = $rule | Get-NetFirewallPortFilter
        $addressfilter = $rule | Get-NetFirewallAddressFilter

        [PSCustomObject]@{
            GPOName       = $_
            RuleName      = $rule.name
            DisplayName   = $rule.displayname
            DisplayGroup  = $rule.displaygroup
            Protocol      = $portfilter.Protocol
            LocalPort     = $portfilter.LocalPort
            RemotePort    = $portfilter.RemotePort
            RemoteAddress = $addressfilter.RemoteAddress
            Enabled       = $rule.enabled
            Profile       = $rule.profile
            Direction     = $rule.direction
            Action        = $rule.action
        }
    }
} | Export-CSV $env:temp\gpos.csv -Force

Start-Process notepad $env:temp\gpos.csv 

或者

$csvdata = foreach($policy in $PolicyObjects)
{
    $GPO = Open-NetGPO -PolicyStore "contoso.com\$policy"

    foreach($rule in Get-NetFirewallRule -GPOSession $GPO)
    {
        $portfilter    = $rule | Get-NetFirewallPortFilter
        $addressfilter = $rule | Get-NetFirewallAddressFilter

        [PSCustomObject]@{
            GPOName       = $policy
            RuleName      = $rule.name
            DisplayName   = $rule.displayname
            DisplayGroup  = $rule.displaygroup
            Protocol      = $portfilter.Protocol
            LocalPort     = $portfilter.LocalPort
            RemotePort    = $portfilter.RemotePort
            RemoteAddress = $addressfilter.RemoteAddress
            Enabled       = $rule.enabled
            Profile       = $rule.profile
            Direction     = $rule.direction
            Action        = $rule.action
        }
    }
}

$csvdata | Export-CSV $env:temp\gpos.csv -Force

Start-Process notepad $env:temp\gpos.csv 

在第一个中,我们将外部循环更改为 aForeach-Object以利用管道和管道直接到Export-Csv

在第二个中,我们捕获所有输出然后导出。

在这两种方法中,我们通过将文件的打开/写入限制为一次来限制执行时间,将 portfilter 调用限制为每个规则一个而不是 3 个,并且我们使用类型加速器来构造我们的最终对象,而不是使用计算表达式[PSCustomObject]进行管道传输。Select-Object如果我理解正确,两者都应该达到你想要的结果。

于 2021-01-27T04:47:57.880 回答
0

这有什么不同吗?

$csv=foreach ($policy in $PolicyObjects) {
$GPO = Open-NetGPO -PolicyStore "contoso.com\$policy"
$policy | Out-File $env:temp\gpos.csv  -Append -Force
Get-NetFirewallRule -GPOSession $GPO  | 
Select Name,
DisplayName,
DisplayGroup,
@{Name='Protocol';Expression={($PSItem | Get-NetFirewallPortFilter).Protocol}},
@{Name='LocalPort';Expression={($PSItem | Get-NetFirewallPortFilter).LocalPort}},
@{Name='RemotePort';Expression={($PSItem | Get-NetFirewallPortFilter).RemotePort}},
@{Name='RemoteAddress';Expression={($PSItem | Get-NetFirewallAddressFilter).RemoteAddress}},
Enabled,
Profile,
Direction,
Action 
}
$csv | Export-CSV $env:temp\gpos.csv -Append -Force
Start-Process notepad $env:temp\gpos.csv 
于 2021-01-27T02:48:29.507 回答
0

当目标文件与结构不匹配时,无法使用 Export-Csv 附加数据。

在您的情况下,Export-Csv尝试从不存在的 $policy 列中附加值。因此它添加了 $null。

对于有效的 CSV 文件,您必须在使用 Export-Csv 之前将所有内容合并到一个对象中。

试试下面的方法,它应该工作得更快,因为它不会Get-NetFirewallAddressFilter对同一个项目使用多次,但每个 GPO-Session 只使用一次

不幸的是,我无法使用 GPO-Session 对其进行测试,但由于 Parameter也-GPOSession存在Get-NetFirewallPortFilterGet-NetFirewallAddressFilter因此它可能会起作用。如果你只想在本地测试它,你只需要移除外部的 foreach-loop 和所有 GPOSession 相关的命令和参数。Open-NetGPO-GPOSession

在为本地防火墙规则构建报告时,我的方法与分别为每个规则检索端口和地址过滤器(即使每个规则只有一次)之间的比较:

我的方法:< 2 秒
其他:> 3 分钟 (对每个规则使用一次 Get-NetFirwall*Filter)

该代码需要一个提升的控制台!

#requires -RunAsAdministrator
$ruleReport = [System.Collections.Generic.List[psobject]]::new()
foreach ($policy in $PolicyObjects) {
    <#
        if you want to append to file after each policy, place the list here instead of above
        $ruleReport = [System.Collections.Generic.List[psobject]]::new()
    #>

    $GPO   = Open-NetGPO -PolicyStore "contoso.com\$policy"
    $rules = Get-NetFirewallRule -GPOSession $GPO

    # retrieving filters once in advance speeds up the execution extremely! (Requires elevated session to get all filters)
    # local execution time with that approach reduces the execution time from   >3 minutes  TO   <2 seconds
    $portFilters    = Get-NetFirewallPortFilter -All -GPOSession $GPO
    $addressFilters = Get-NetFirewallAddressFilter -All -GPOSession $GPO

    # build dictionary for port filters for rule lookups
    $portFilterDict    = [System.Collections.Generic.Dictionary[[string], [ciminstance]]]::new()
    foreach ($portFilter in $portFilters) {
        $portFilterDict.Add($portFilter.InstanceID, $portFilter)
    }

    # build dictionary for addresss filters for rule lookups
    $addressFilterDict = [System.Collections.Generic.Dictionary[[string], [ciminstance]]]::new()
    foreach ($addressFilter in $addressFilters) {
        $addressFilterDict.Add($addressFilter.InstanceID, $addressFilter)
    }


    foreach ($rule in $rules) {
        $ruleInstanceId    = $rule.InstanceID
        $rulePortFilter    = $portFilterDict[$ruleInstanceId]
        $ruleAddressFilter = $addressFilterDict[$ruleInstanceId]

        # build combined object
        $ruleReportItem = [pscustomobject][ordered]@{
            Policy        = $policy
            Name          = $rule.Name
            DisplayName   = $rule.DisplayName
            DisplayGroup  = $rule.DisplayGroup
            Protocol      = $rulePortFilter.Protocol
            LocalPort     = $rulePortFilter.LocalPort
            RemotePort    = $rulePortFilter.RemotePort
            RemoteAddress = $ruleAddressFilter.RemoteAddress
            Enabled       = $rule.Enabled
            Profile       = $rule.Profiles
            Direction     = $rule.Direction
            Action        = $rule.Action
        }

        # append to list
        $ruleReport.Add($ruleReportItem)
    }

    <#
        if you want to append to file after each policy, place the export here instead of below
        $ruleReport | Export-Csv $env:temp\gpos.csv -Append
    #>
}

$ruleReport | Export-Csv $env:temp\gpos.csv

更新

要仅针对本地防火墙规则测试该方法,请使用此脚本。
该代码需要一个提升的控制台!

#requires -RunAsAdministrator
$ruleReport = [System.Collections.Generic.List[psobject]]::new()
$rules      = Get-NetFirewallRule

# retrieving filters once in advance speeds up the execution extremely! (Requires elevated session to get all filters)
# local execution time with that approach reduces the execution time from   >3 minutes  TO   <2 seconds
$portFilters    = Get-NetFirewallPortFilter -All
$addressFilters = Get-NetFirewallAddressFilter -All

# build dictionary for port filters for rule lookups
$portFilterDict = [System.Collections.Generic.Dictionary[[string], [ciminstance]]]::new()
foreach ($portFilter in $portFilters) {
    $portFilterDict.Add($portFilter.InstanceID, $portFilter)
}

# build dictionary for addresss filters for rule lookups
$addressFilterDict = [System.Collections.Generic.Dictionary[[string], [ciminstance]]]::new()
foreach ($addressFilter in $addressFilters) {
    $addressFilterDict.Add($addressFilter.InstanceID, $addressFilter)
}


foreach ($rule in $rules) {
    $ruleInstanceId    = $rule.InstanceID
    $rulePortFilter    = $portFilterDict[$ruleInstanceId ]
    $ruleAddressFilter = $addressFilterDict[$ruleInstanceId ]

    # build combined object
    $ruleReportItem = [pscustomobject][ordered]@{
        Name          = $rule.Name
        DisplayName   = $rule.DisplayName
        DisplayGroup  = $rule.DisplayGroup
        Protocol      = $rulePortFilter.Protocol
        LocalPort     = $rulePortFilter.LocalPort
        RemotePort    = $rulePortFilter.RemotePort
        RemoteAddress = $ruleAddressFilter.RemoteAddress
        Enabled       = $rule.Enabled
        Profile       = $rule.Profiles
        Direction     = $rule.Direction
        Action        = $rule.Action
    }

    # append to list
    $ruleReport.Add($ruleReportItem)
}


$ruleReport | Export-Csv $env:temp\gpos.csv -NoTypeInformation
write-host "Exported to $($env:temp)"
于 2021-01-27T05:45:46.840 回答