From 37d8db92f794c0daa26d0b17d4db37e53cd1803c Mon Sep 17 00:00:00 2001 From: Przemyslaw Klys Date: Mon, 4 Jan 2021 21:15:49 +0100 Subject: [PATCH] Update to make sure it works properly for domains --- Private/Get-PrivGPOZaurrLInk.ps1 | 1 + Public/Get-GPOZaurrBrokenLink.ps1 | 34 +++++++++++++++++++++++++++- Public/Repair-GPOZaurrBrokenLink.ps1 | 34 ++++++++++++++++++++++++++-- 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/Private/Get-PrivGPOZaurrLInk.ps1 b/Private/Get-PrivGPOZaurrLInk.ps1 index 4a9dc8d..d3d2774 100644 --- a/Private/Get-PrivGPOZaurrLInk.ps1 +++ b/Private/Get-PrivGPOZaurrLInk.ps1 @@ -42,6 +42,7 @@ $DomainCN = ConvertFrom-DistinguishedName -DistinguishedName $DN -ToDomainCN $Output = [ordered] @{ DistinguishedName = $Object.DistinguishedName + #Domain = ConvertFrom-DistinguishedName -DistinguishedName $Object.DistinguishedName -ToDomainCN CanonicalName = if ($Object.CanonicalName) { $Object.CanonicalName.TrimEnd('/') } else { $Object.CanonicalName } Guid = [Regex]::Match($DN, '(?={)(.*)(?<=})').Value -replace '{' -replace '}' Enforced = $Enforced diff --git a/Public/Get-GPOZaurrBrokenLink.ps1 b/Public/Get-GPOZaurrBrokenLink.ps1 index 9bd243c..008718a 100644 --- a/Public/Get-GPOZaurrBrokenLink.ps1 +++ b/Public/Get-GPOZaurrBrokenLink.ps1 @@ -1,4 +1,32 @@ function Get-GPOZaurrBrokenLink { + <# + .SYNOPSIS + Finds any GPO link that doesn't have a matching GPO (already removed GPO). + + .DESCRIPTION + Finds any GPO link that doesn't have a matching GPO (already removed GPO). + + .PARAMETER Forest + Target different Forest, by default current forest is used + + .PARAMETER ExcludeDomains + Exclude domain from search, by default whole forest is scanned + + .PARAMETER IncludeDomains + Include only specific domains, by default whole forest is scanned + + .PARAMETER ExtendedForestInformation + Ability to provide Forest Information from another command to speed up processing + + .EXAMPLE + Get-GPOZaurrBrokenLink -Verbose | Format-Table -AutoSize * + + .EXAMPLE + Get-GPOZaurrBrokenLink -Verbose -IncludeDomains ad.evotec.pl | Format-Table -AutoSize * + + .NOTES + General notes + #> [cmdletBinding()] param( [alias('ForestName')][string] $Forest, @@ -7,7 +35,8 @@ function Get-GPOZaurrBrokenLink { [System.Collections.IDictionary] $ExtendedForestInformation ) $PoliciesAD = @{} - $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExcludeDomainControllers $ExcludeDomainControllers -IncludeDomainControllers $IncludeDomainControllers -SkipRODC:$SkipRODC -ExtendedForestInformation $ExtendedForestInformation -Extended + # We need to request all GPOS from Forest. Requesting just for any domain won't be enough + $ForestInformation = Get-WinADForestDetails -Forest $Forest -Extended # -Extended foreach ($Domain in $ForestInformation.Domains) { $QueryServer = $ForestInformation['QueryServers']["$Domain"].HostName[0] $SystemsContainer = $ForestInformation['DomainsExtended'][$Domain].SystemsContainer @@ -34,6 +63,9 @@ function Get-GPOZaurrBrokenLink { Write-Warning "Get-GPOZaurrBroken - Couldn't get GPOs from $Domain. Skipping" } } + # In case of links we can request here whatever user requested. + # This will search for broken links in domain user requested + $ForestInformation = Get-WinADForestDetails -Forest $Forest -Extended -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation $Links = Get-GPOZaurrLinkLoop -Linked 'All' -ForestInformation $ForestInformation foreach ($Link in $Links) { if (-not $PoliciesAD[$Link.GPODistinguishedName]) { diff --git a/Public/Repair-GPOZaurrBrokenLink.ps1 b/Public/Repair-GPOZaurrBrokenLink.ps1 index 73aa97f..b647bb6 100644 --- a/Public/Repair-GPOZaurrBrokenLink.ps1 +++ b/Public/Repair-GPOZaurrBrokenLink.ps1 @@ -1,4 +1,35 @@ function Repair-GPOZaurrBrokenLink { + <# + .SYNOPSIS + Removes any link to GPO that no longer exists. + + .DESCRIPTION + Removes any link to GPO that no longer exists. It scans all site, organizational unit or domain root making sure every single link that may be linking to GPO that doesn't exists anymore is gone. + + .PARAMETER Forest + Target different Forest, by default current forest is used + + .PARAMETER ExcludeDomains + Exclude domain from search, by default whole forest is scanned + + .PARAMETER IncludeDomains + Include only specific domains, by default whole forest is scanned + + .PARAMETER ExtendedForestInformation + Ability to provide Forest Information from another command to speed up processing + + .PARAMETER LimitProcessing + Allows to specify maximum number of items that will be fixed in a single run. It doesn't affect amount of GPOs processed + + .EXAMPLE + Repair-GPOZaurrBrokenLink -Verbose -LimitProcessing 1 -WhatIf + + .EXAMPLE + Repair-GPOZaurrBrokenLink -Verbose -IncludeDomains ad.evotec.pl -LimitProcessing 1 -WhatIf + + .NOTES + General notes + #> [cmdletBinding(SupportsShouldProcess)] param( [alias('ForestName')][string] $Forest, @@ -7,7 +38,7 @@ function Repair-GPOZaurrBrokenLink { [System.Collections.IDictionary] $ExtendedForestInformation, [int] $LimitProcessing ) - $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -Extended + $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -Extended $Links = Get-GPOZaurrBrokenLink -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ForestInformation $Cache = @{} foreach ($Link in $Links) { @@ -38,7 +69,6 @@ function Repair-GPOZaurrBrokenLink { Write-Verbose "Repair-GPOZaurrBrokenLink - preparing for removal link to $GPODN ($Key)" } } - # if ($Found) { $NewGpLink = $($FixedLinks -join '') try {