mirror of
https://github.com/EvotecIT/GPOZaurr.git
synced 2026-07-26 11:49:17 +00:00
193 lines
10 KiB
PowerShell
193 lines
10 KiB
PowerShell
function Get-GPOZaurrOrganizationalUnit {
|
|
<#
|
|
.SYNOPSIS
|
|
Retrieves information about Group Policy Objects (GPOs) linked to Organizational Units (OUs) within a specified forest.
|
|
|
|
.DESCRIPTION
|
|
This function retrieves detailed information about the GPOs linked to OUs within a specified forest. It provides information on linked GPOs, objects within OUs, and counts of objects at different levels.
|
|
|
|
.PARAMETER Forest
|
|
Specifies the name of the forest to retrieve information from.
|
|
|
|
.PARAMETER ExcludeDomains
|
|
Specifies an array of domains to exclude from processing.
|
|
|
|
.PARAMETER IncludeDomains
|
|
Specifies an array of domains to include for processing.
|
|
|
|
.PARAMETER ExtendedForestInformation
|
|
Specifies additional information about the forest.
|
|
|
|
.PARAMETER Option
|
|
Specifies the action to perform on the retrieved data. Valid values are 'OK', 'Unlink', or 'Delete'.
|
|
|
|
.PARAMETER ExcludeOrganizationalUnit
|
|
Specifies an array of OUs to exclude from processing.
|
|
|
|
.EXAMPLE
|
|
Get-GPOZaurrOrganizationalUnit -Forest "contoso.com" -IncludeDomains "child.contoso.com" -ExcludeDomains "test.contoso.com" -ExtendedForestInformation $ExtendedInfo -Option "OK" -ExcludeOrganizationalUnit "OU=Test,DC=contoso,DC=com"
|
|
Retrieves information about GPOs linked to OUs in the "contoso.com" forest, including the "child.contoso.com" domain, excluding the "test.contoso.com" domain, with additional forest information, performing the 'OK' action, and excluding the "OU=Test,DC=contoso,DC=com" OU.
|
|
|
|
#>
|
|
[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)(ObjectClass=PrintQueue))" -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']
|
|
}
|
|
}
|
|
} |