mirror of
https://github.com/EvotecIT/GPOZaurr.git
synced 2026-08-19 06:36:18 +00:00
3557ecefc2
Added some error logging
235 lines
13 KiB
PowerShell
235 lines
13 KiB
PowerShell
function Get-GPOZaurrLink {
|
|
[cmdletbinding()]
|
|
param(
|
|
[parameter(ParameterSetName = 'ADObject', ValueFromPipeline, ValueFromPipelineByPropertyName, Mandatory)][Microsoft.ActiveDirectory.Management.ADObject[]] $ADObject,
|
|
# weirdly enough site doesn't really work this way unless you give it 'CN=Configuration,DC=ad,DC=evotec,DC=xyz' as SearchBase
|
|
[parameter(ParameterSetName = 'Filter')][string] $Filter = "(objectClass -eq 'organizationalUnit' -or objectClass -eq 'domainDNS' -or objectClass -eq 'site')",
|
|
[parameter(ParameterSetName = 'Filter')][string] $SearchBase,
|
|
[parameter(ParameterSetName = 'Filter')][Microsoft.ActiveDirectory.Management.ADSearchScope] $SearchScope,
|
|
|
|
[parameter(ParameterSetName = 'Linked', Mandatory)][validateset('Root', 'DomainControllers', 'Site', 'Other')][string] $Linked,
|
|
|
|
[parameter(ParameterSetName = 'Filter')]
|
|
[parameter(ParameterSetName = 'ADObject')]
|
|
[parameter(ParameterSetName = 'Linked')]
|
|
[switch] $Limited,
|
|
|
|
[parameter(ParameterSetName = 'Filter')]
|
|
[parameter(ParameterSetName = 'ADObject')]
|
|
[parameter(ParameterSetName = 'Linked')]
|
|
[switch] $SkipDuplicates,
|
|
|
|
[parameter(ParameterSetName = 'Filter')]
|
|
[parameter(ParameterSetName = 'ADObject')]
|
|
[parameter(ParameterSetName = 'Linked')]
|
|
[System.Collections.IDictionary] $GPOCache,
|
|
|
|
[parameter(ParameterSetName = 'Filter')]
|
|
[parameter(ParameterSetName = 'ADObject')]
|
|
[parameter(ParameterSetName = 'Linked')]
|
|
[alias('ForestName')][string] $Forest,
|
|
|
|
[parameter(ParameterSetName = 'Filter')]
|
|
[parameter(ParameterSetName = 'ADObject')]
|
|
[parameter(ParameterSetName = 'Linked')]
|
|
[string[]] $ExcludeDomains,
|
|
|
|
[parameter(ParameterSetName = 'Filter')]
|
|
[parameter(ParameterSetName = 'ADObject')]
|
|
[parameter(ParameterSetName = 'Linked')]
|
|
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
|
|
|
[parameter(ParameterSetName = 'Filter')]
|
|
[parameter(ParameterSetName = 'ADObject')]
|
|
[parameter(ParameterSetName = 'Linked')]
|
|
[System.Collections.IDictionary] $ExtendedForestInformation
|
|
)
|
|
Begin {
|
|
$CacheReturnedGPOs = [ordered] @{}
|
|
$ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
|
|
if (-not $GPOCache -and -not $Limited) {
|
|
$GPOCache = @{ }
|
|
# While initially we used $ForestInformation.Domains but the thing is GPOs can be linked to other domains so we need to get them all so we can use cache of it later on even if we're processing just one domain
|
|
# That's why we use $ForestInformation.Forest.Domains instead
|
|
foreach ($Domain in $ForestInformation.Forest.Domains) {
|
|
$QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
|
|
Get-GPO -All -DomainName $Domain -Server $QueryServer | ForEach-Object {
|
|
$GPOCache["$Domain$($_.ID.Guid)"] = $_
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Process {
|
|
if (-not $ADObject) {
|
|
if ($Linked) {
|
|
foreach ($Domain in $ForestInformation.Domains) {
|
|
$Splat = @{
|
|
#Filter = $Filter
|
|
Properties = 'distinguishedName', 'gplink', 'CanonicalName'
|
|
# Filter = "(objectClass -eq 'organizationalUnit' -or objectClass -eq 'domainDNS' -or objectClass -eq 'site')"
|
|
Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
|
|
}
|
|
if ($Linked -contains 'DomainControllers') {
|
|
$SearchBase = $ForestInformation['DomainsExtended'][$Domain]['DomainControllersContainer']
|
|
#if ($SearchBase -notlike "*$DomainDistinguishedName") {
|
|
# we check if SearchBase is part of domain distinugishname. If it isn't we skip
|
|
# continue
|
|
#}
|
|
$Splat['Filter'] = "(objectClass -eq 'organizationalUnit')"
|
|
$Splat['SearchBase'] = $SearchBase
|
|
try {
|
|
$ADObjectGPO = Get-ADObject @Splat
|
|
} catch {
|
|
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
|
}
|
|
foreach ($_ in $ADObjectGPO) {
|
|
$OutputGPOs = Get-PrivGPOZaurrLink -Object $_ -Limited:$Limited.IsPresent -GPOCache $GPOCache
|
|
foreach ($OutputGPO in $OutputGPOs) {
|
|
if (-not $SkipDuplicates) {
|
|
$OutputGPO
|
|
} else {
|
|
$UniqueGuid = -join ($OutputGPO.DomainName, $OutputGPO.Guid)
|
|
if (-not $CacheReturnedGPOs[$UniqueGuid]) {
|
|
$CacheReturnedGPOs[$UniqueGuid] = $OutputGPO
|
|
$OutputGPO
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ($Linked -contains 'Root') {
|
|
$SearchBase = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']
|
|
#if ($SearchBase -notlike "*$DomainDistinguishedName") {
|
|
# we check if SearchBase is part of domain distinugishname. If it isn't we skip
|
|
# continue
|
|
# }
|
|
$Splat['Filter'] = "objectClass -eq 'domainDNS'"
|
|
$Splat['SearchBase'] = $SearchBase
|
|
try {
|
|
$ADObjectGPO = Get-ADObject @Splat
|
|
} catch {
|
|
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
|
}
|
|
foreach ($_ in $ADObjectGPO) {
|
|
$OutputGPOs = Get-PrivGPOZaurrLink -Object $_ -Limited:$Limited.IsPresent -GPOCache $GPOCache
|
|
foreach ($OutputGPO in $OutputGPOs) {
|
|
if (-not $SkipDuplicates) {
|
|
$OutputGPO
|
|
} else {
|
|
$UniqueGuid = -join ($OutputGPO.DomainName, $OutputGPO.Guid)
|
|
if (-not $CacheReturnedGPOs[$UniqueGuid]) {
|
|
$CacheReturnedGPOs[$UniqueGuid] = $OutputGPO
|
|
$OutputGPO
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ($Linked -contains 'Site') {
|
|
# Sites are defined only in primary domain
|
|
if ($ForestInformation['DomainsExtended'][$Domain]['DNSRoot'] -eq $ForestInformation['DomainsExtended'][$Domain]['Forest']) {
|
|
$SearchBase = -join ("CN=Configuration,", $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName'])
|
|
# if ($SearchBase -notlike "*$DomainDistinguishedName") {
|
|
# we check if SearchBase is part of domain distinugishname. If it isn't we skip
|
|
#continue
|
|
#}
|
|
$Splat['Filter'] = "(objectClass -eq 'site')"
|
|
$Splat['SearchBase'] = $SearchBase
|
|
try {
|
|
$ADObjectGPO = Get-ADObject @Splat
|
|
} catch {
|
|
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
|
}
|
|
foreach ($_ in $ADObjectGPO) {
|
|
Get-PrivGPOZaurrLink -Object $_ -Limited:$Limited.IsPresent -GPOCache $GPOCache
|
|
}
|
|
}
|
|
}
|
|
if ($Linked -contains 'Other') {
|
|
$SearchBase = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']
|
|
#if ($SearchBase -notlike "*$DomainDistinguishedName") {
|
|
# we check if SearchBase is part of domain distinugishname. If it isn't we skip
|
|
# continue
|
|
#}
|
|
$Splat['Filter'] = "(objectClass -eq 'organizationalUnit')"
|
|
$Splat['SearchBase'] = $SearchBase
|
|
try {
|
|
$ADObjectGPO = Get-ADObject @Splat
|
|
} catch {
|
|
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
|
}
|
|
foreach ($_ in $ADObjectGPO) {
|
|
if ($_.DistinguishedName -eq $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']) {
|
|
# other skips Domain Root
|
|
} elseif ($_.DistinguishedName -eq $ForestInformation['DomainsExtended'][$Domain]['DomainControllersContainer']) {
|
|
# other skips Domain Controllers
|
|
} else {
|
|
$OutputGPOs = Get-PrivGPOZaurrLink -Object $_ -Limited:$Limited.IsPresent -GPOCache $GPOCache
|
|
foreach ($OutputGPO in $OutputGPOs) {
|
|
if (-not $SkipDuplicates) {
|
|
$OutputGPO
|
|
} else {
|
|
$UniqueGuid = -join ($OutputGPO.DomainName, $OutputGPO.Guid)
|
|
if (-not $CacheReturnedGPOs[$UniqueGuid]) {
|
|
$CacheReturnedGPOs[$UniqueGuid] = $OutputGPO
|
|
$OutputGPO
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
foreach ($Domain in $ForestInformation.Domains) {
|
|
$Splat = @{
|
|
Filter = $Filter
|
|
Properties = 'distinguishedName', 'gplink', 'CanonicalName'
|
|
Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
|
|
|
|
}
|
|
if ($PSBoundParameters.ContainsKey('SearchBase')) {
|
|
$DomainDistinguishedName = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']
|
|
$SearchBaseDC = ConvertFrom-DistinguishedName -DistinguishedName $SearchBase -ToDC
|
|
if ($SearchBaseDC -ne $DomainDistinguishedName) {
|
|
# we check if SearchBase is part of domain distinugishname. If it isn't we skip
|
|
continue
|
|
}
|
|
$Splat['SearchBase'] = $SearchBase
|
|
|
|
}
|
|
if ($PSBoundParameters.ContainsKey('SearchScope')) {
|
|
$Splat['SearchScope'] = $SearchScope
|
|
}
|
|
|
|
try {
|
|
$ADObjectGPO = Get-ADObject @Splat
|
|
} catch {
|
|
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
|
}
|
|
foreach ($_ in $ADObjectGPO) {
|
|
$OutputGPOs = Get-PrivGPOZaurrLink -Object $_ -Limited:$Limited.IsPresent -GPOCache $GPOCache
|
|
foreach ($OutputGPO in $OutputGPOs) {
|
|
if (-not $SkipDuplicates) {
|
|
$OutputGPO
|
|
} else {
|
|
$UniqueGuid = -join ($OutputGPO.DomainName, $OutputGPO.Guid)
|
|
if (-not $CacheReturnedGPOs[$UniqueGuid]) {
|
|
$CacheReturnedGPOs[$UniqueGuid] = $OutputGPO
|
|
$OutputGPO
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
foreach ($Object in $ADObject) {
|
|
Get-PrivGPOZaurrLink -Object $Object -Limited:$Limited.IsPresent -GPOCache $GPOCache
|
|
}
|
|
}
|
|
}
|
|
End {
|
|
|
|
}
|
|
} |