我正在研究用于停用服务器的脚本。该脚本删除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
}