Files
GPOZaurr/Public/Get-GPOZaurrOrganizationalUnit.ps1
T
Przemyslaw Klys cab639239f Fixes #30
2021-12-05 11:01:19 +01:00

163 lines
8.5 KiB
PowerShell

function Get-GPOZaurrOrganizationalUnit {
[CmdletBinding()]
param(
[alias('ForestName')][string] $Forest,
[string[]] $ExcludeDomains,
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
[System.Collections.IDictionary] $ExtendedForestInformation,
[ValidateSet('OK', 'Unlink', 'Delete')][string[]] $Option,
[alias('ExcludeOU', 'Exclusions')][string[]] $ExcludeOrganizationalUnit
)
$CachedOu = [ordered] @{}
$CachedGPO = [ordered] @{}
$ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
$DefaultFolders = Get-WellKnownFolders -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
$GroupPolicies = Get-GPOZaurrAD -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
foreach ($GPO in $GroupPolicies) {
$CachedGPO[$GPO.GPODistinguishedName] = $GPO
}
foreach ($Domain in $ForestInformation.Domains) {
Write-Verbose "Get-GPOZaurrOrganizationalUnit - Processing $($Domain)"
$CountTop = 0
$TopOrganizationalUnits = Get-ADOrganizationalUnit -Filter * -Properties LinkedGroupPolicyObjects, DistinguishedName, ntSecurityDescriptor -Server $ForestInformation['QueryServers'][$Domain]['hostname'][0] -SearchScope OneLevel
foreach ($TopOU in $TopOrganizationalUnits) {
$CountTop++
Write-Verbose "Get-GPOZaurrOrganizationalUnit - Processing $($Domain) / $($TOPOU.DistinguishedName) [$CountTop/$($TopOrganizationalUnits.Count)]"
# cache top ou
if ($TopOU.LinkedGroupPolicyObjects) {
$LinkedGPOs = $CachedGPO[$TopOU.LinkedGroupPolicyObjects]
} else {
$LinkedGPOs = $null
}
$CachedOu[$TopOU.DistinguishedName] = [ordered]@{
'LinkedGroupPolicyObjects' = $TopOU.LinkedGroupPolicyObjects
'LinkedGroupPolicy' = $LinkedGPOs
'Objects' = [ordered] @{}
'ObjectsClasses' = [ordered] @{}
'ObjectsCountDirect' = 0
'ObjectsCountIndirect' = 0
'ObjectsCountTotal' = 0
'Level' = 'Top'
'RootLevel' = $TopOU.Name
'Domain' = $Domain
}
# cache children OUs
$OUs = Get-ADOrganizationalUnit -SearchScope Subtree -SearchBase $TopOU.DistinguishedName -Server $ForestInformation['QueryServers'][$Domain]['hostname'][0] -Properties LinkedGroupPolicyObjects, DistinguishedName -Filter *
Write-Verbose "Get-GPOZaurrOrganizationalUnit - Processing $($Domain) / $($TOPOU.DistinguishedName) [$CountTop/$($TopOrganizationalUnits.Count)], found $($OUs.Count) OU's to process."
foreach ($OU in $OUs) {
if (-not $CachedOu[$OU.DistinguishedName]) {
if ($OU.LinkedGroupPolicyObjects) {
$LinkedGPOs = $CachedGPO[$OU.LinkedGroupPolicyObjects]
} else {
$LinkedGPOs = $null
}
$CachedOu[$OU.DistinguishedName] = [ordered]@{
'LinkedGroupPolicyObjects' = $OU.LinkedGroupPolicyObjects
'LinkedGroupPolicy' = $LinkedGPOs
'Objects' = [ordered] @{}
'ObjectsClasses' = [ordered] @{}
'ObjectsCountDirect' = 0
'ObjectsCountIndirect' = 0
'ObjectsCountTotal' = 0
'Level' = 'Child'
'RootLevel' = $TopOU.Name
'Domain' = $Domain
}
}
}
# Find all objects in those OUs
$ObjectsInOu = Get-ADObject -LDAPFilter "(|(ObjectClass=user)(ObjectClass=contact)(ObjectClass=computer)(ObjectClass=group)(objectClass=inetOrgPerson))" -SearchBase $TopOU.distinguishedName -Server $ForestInformation['QueryServers'][$Domain]['hostname'][0]
Write-Verbose "Get-GPOZaurrOrganizationalUnit - Processing $($Domain) / $($TOPOU.DistinguishedName) [$CountTop/$($TopOrganizationalUnits.Count)], found $($ObjectsInOu.Count) objects to process."
foreach ($Object in $ObjectsInOu) {
$Place = ConvertFrom-DistinguishedName -ToOrganizationalUnit -DistinguishedName $Object.DistinguishedName
$AllOUs = ConvertFrom-DistinguishedName -ToMultipleOrganizationalUnit -IncludeParent -DistinguishedName $Place
foreach ($OU in $AllOUs) {
if ($OU -eq $Place) {
$CachedOu[$OU]['Objects'][$Object.DistinguishedName] = $Object
$CachedOu[$OU]['ObjectsClasses'][$Object.ObjectClass] = ''
$CachedOu[$OU]['ObjectsCountDirect']++
} else {
$CachedOu[$OU]['ObjectsClasses'][$Object.ObjectClass] = ''
$CachedOu[$OU]['ObjectsCountIndirect']++
}
$CachedOu[$OU]['ObjectsCountTotal']++
}
}
}
}
foreach ($OU in $CachedOu.Keys) {
$ObjectClasses = [string[]] $CachedOu[$OU]['ObjectsClasses'].Keys
if ($CachedOu[$OU]['ObjectsCountTotal'] -eq 0 -and $CachedOu[$OU]['LinkedGroupPolicyObjects'].Count -gt 0) {
$Status = "Unlink GPO", 'Delete OU'
} elseif ($CachedOu[$OU]['ObjectsCountTotal'] -eq 0 -and $CachedOu[$OU]['LinkedGroupPolicyObjects'].Count -eq 0) {
$Status = 'Delete OU'
} elseif ($CachedOU[$Ou]['ObjectsCountTotal'] -gt 0 -and $CachedOu[$OU]['LinkedGroupPolicyObjects'].Count -gt 0 -and $ObjectClasses -notcontains 'User' -and $ObjectClasses -notcontains 'Computer' ) {
$Status = "Unlink GPO"
} else {
$Status = 'OK'
}
if ($Option) {
$Found = $false
if ($Option -contains 'Ok' -and $Status -contains 'OK') {
$Found = $true
} elseif ($Option -contains 'Unlink' -and $Status -contains 'Unlink GPO') {
$Found = $true
} elseif ($Option -contains 'Delete' -and $Status -contains 'Delete OU') {
$Found = $true
}
if ($ExcludeOrganizationalUnit) {
foreach ($ExcludedOU in $ExcludeOrganizationalUnit) {
if ($OU -like $ExcludedOU) {
$Found = $false
break
}
}
}
foreach ($Exclude in $DefaultFolders) {
if ($OU -eq "$Exclude") {
$Found = $false
break
}
}
if (-not $Found) {
continue
}
} else {
if ($ExcludeOrganizationalUnit) {
foreach ($ExcludedOU in $ExcludeOrganizationalUnit) {
if ($OU -like $ExcludedOU) {
$Status = 'Excluded'
break
}
}
}
foreach ($Exclude in $DefaultFolders) {
if ($OU -eq "$Exclude") {
$Status = 'Excluded, Default OU'
break
}
}
}
[PSCustomObject] @{
Organizationalunit = $OU
Level = $CachedOu[$OU]['Level']
RootLevel = $CachedOu[$OU]['RootLevel']
DomainName = $CachedOu[$OU]['Domain']
Status = $Status
GPOCount = $CachedOu[$OU]['LinkedGroupPolicyObjects'].Count
ObjectCountDirect = $CachedOu[$OU]['ObjectsCountDirect']
ObjectCountIndirect = $CachedOu[$OU]['ObjectsCountIndirect']
ObjectCountTotal = $CachedOu[$OU]['ObjectsCountTotal']
ObjectClasses = $ObjectClasses
GPONames = $CachedOu[$OU]['LinkedGroupPolicy'].DisplayName
Objects = $CachedOu[$OU]['Objects'].Values.Name
GPO = $CachedOu[$OU]['LinkedGroupPolicy']
}
}
}