Files
GPOZaurr/Public/Get-GPOZaurrLink.ps1
T
Przemyslaw Klys 28d941ec26 Update
2020-06-18 16:36:35 +02:00

218 lines
12 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
$ADObjectGPO = Get-ADObject @Splat
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
$ADObjectGPO = Get-ADObject @Splat
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
$ADObjectGPO = Get-ADObject @Splat
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
$ADObjectGPO = Get-ADObject @Splat
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']
if ($SearchBase -notlike "*$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
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
}
}
}
}
} catch {
Write-Warning "Get-GPOZaurrLink - Processing error $($_.Exception.Message)"
}
}
}
} else {
foreach ($Object in $ADObject) {
Get-PrivGPOZaurrLink -Object $Object -Limited:$Limited.IsPresent -GPOCache $GPOCache
}
}
}
End {
}
}