在PowerShell中提取具有孤立SID的所有GPO

时间:2018-07-11 14:18:41

标签: powershell gpo

我正在研究用于停用服务器的脚本。该脚本删除VM,删除A.D.对象,所有DNS记录,并最终从任何GPO中删除对象。一切正常,但最后一部分。我开始做这样的事情:

$aServers = Import-Csv -Path 
$domain = "myCompany.com"
$GPOs = Get-GPO -Domain $domain -All | Select DisplayName

$aReport = @()
    foreach ($server in $aServers) {
        foreach($gpo in $GPOs) {
            $myObject = New-Object PSObject
            try {
                If (!((Get-GPPermissions -DomainName $domain -Name $gpo.DisplayName -TargetName $server.ComputerName -TargetType Computer -ErrorAction Stop) -eq "")) {                   
                    $myObject | Add-Member -MemberType NoteProperty -Name "Server" -Value $($server.ComputerName)
                    $myObject | Add-Member -MemberType NoteProperty -Name "GPO" -Value $($gpo.DisplayName)
                }
                $aReport += $myObject
            } catch {
                Write-Host "$($server.ComputerName) not found in $($gpo.DisplayName)"
            }
        }

...虽然有效,但丑陋且缓慢。我认为有一种方法可以更简单地做到这一点:

Get-GPO -All | 
   foreach{
      Get-GPPermissions -Guid $_.Id -All | 
         Where-Object {$_.Trustee -like "S-1-5-*"}
   }

...但是我似乎无法正确理解语法。我确信我缺少一些愚蠢的简单东西,但是任何建议都会不胜感激。

编辑:我想我越来越近了。这似乎可行:

    $aReport = @()
    $domain = "mycompany.com"
    $aGPOs = Get-GPO -Domain $domain -All | Select DisplayName, Id

    foreach ($gpo in $aGPOs) {
        $myObj = New-Object -TypeName PSObject
        if ($perms = Get-GPPermissions -DomainName $domain -Guid $gpo.Id -All | 
            Where-Object {$_.Trustee.Name -like ""}) {
                $myObj | Add-Member -MemberType NoteProperty -Name "GPO" -Value $gpo.DisplayName
                $myObj | Add-Member -MemberType NoteProperty -Name "Member Name" -Value $perms.Trustee.Name
                $myObj | Add-Member -MemberType NoteProperty -Name "Member SID" -Value $perms.Trustee.Sid

                $aReport += $myObj
        }
    }

尽管速度很慢。它还执行一次遍历,将特定GPO的所有孤立SID集中到一行中。由于最终的目标是能够循环通过并删除这些孤儿,所以我要么不得不在另一个阶段处理数据,要么添加另一个for循环以获取每行的每个SID,如下所示:

    $aReport = @()
    $domain = "mycompany.com"
    $aGPOs = Get-GPO -Domain $domain -All | Select DisplayName, Id

    foreach ($gpo in $aGPOs) {
        if ($perms = Get-GPPermissions -DomainName $domain -Guid $gpo.Id -All | 
            Where-Object {$_.Trustee.Name -like ""}) {
                foreach ($perm in $perms) {
                    $myObj = New-Object -TypeName PSObject
                    $myObj | Add-Member -MemberType NoteProperty -Name "GPO" -Value $gpo.DisplayName
                    $myObj | Add-Member -MemberType NoteProperty -Name "Member Name" -Value $perm.Trustee.Name
                    $myObj | Add-Member -MemberType NoteProperty -Name "Member SID" -Value $perm.Trustee.Sid
                    $aReport += $myObj
                }
        }
    }

感谢到目前为止的建议;仍然对改善它持开放态度。

Edit2:

在从另一篇文章中无耻地借用后,我终于把这件事凑在一起了。似乎运作良好;在不到一分钟的时间内清除100多个测试策略中的所有孤立SID:

Function Remove-GPOUnknownSIDs {
   param ([parameter(mandatory = $true)][Microsoft.GroupPolicy.Gpo]$GPO)
   $name = $GPO.DisplayName
   $gpoSecurity = $GPO.GetSecurityInfo()
   $UnknownSIDs = $gpoSecurity.Trustee | Where SidType -Like "Unknown"
      foreach($UnknownSID in $UnknownSIDs) {
         $SIDToRemove = $UnknownSID.Sid.Value
         $gpoSecurity.RemoveTrustee($SIDToRemove)
         $GPO.SetSecurityInfo($gpoSecurity)
      }
}

$domain = "mycompany.com"
$aGPOs = Get-GPO -Domain $domain -All
   foreach($GPO in $aGPOs) {
      Remove-GPOUnknownSIDs $GPO
   }

0 个答案:

没有答案