mirror of
https://github.com/EvotecIT/GPOZaurr.git
synced 2026-08-21 07:26:57 +00:00
163 lines
8.5 KiB
PowerShell
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']
|
|
}
|
|
}
|
|
} |