Src/Private/Report/Get-AbrADForest.ps1
|
function Get-AbrADForest { <# .SYNOPSIS Used by As Built Report to retrieve Microsoft AD information from Domain Controller .DESCRIPTION .NOTES Version: 0.9.12 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux .EXAMPLE .LINK #> [CmdletBinding()] param ( ) begin { Write-PScriboMessage -Message $reportTranslate.GetAbrADForest.Collecting Show-AbrDebugExecutionTime -Start -TitleMessage 'AD Forest' } process { try { $Data = Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock { Get-ADForest } $ForestInfo = $Data.RootDomain.toUpper() $DomainDN = Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock { (Get-ADDomain -Identity (Get-ADForest | Select-Object -ExpandProperty RootDomain )).DistinguishedName } $TombstoneLifetime = Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock { Get-ADObject "CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,$using:DomainDN" -Properties tombstoneLifetime | Select-Object -ExpandProperty tombstoneLifetime } $ADVersion = Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock { Get-ADObject (Get-ADRootDSE).schemaNamingContext -property objectVersion | Select-Object -ExpandProperty objectVersion } $ValuedsHeuristics = Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock { Get-ADObject -Identity "CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,$(($using:DomainDN))" -Properties dsHeuristics -ErrorAction SilentlyContinue } if ($ADVersion -eq '88') { $server = 'Windows Server 2019' } elseif ($ADVersion -eq '91') { $server = 'Windows Server 2025' } elseif ($ADVersion -eq '87') { $server = 'Windows Server 2016' } elseif ($ADVersion -eq '69') { $server = 'Windows Server 2012 R2' } elseif ($ADVersion -eq '56') { $server = 'Windows Server 2012' } elseif ($ADVersion -eq '47') { $server = 'Windows Server 2008 R2' } elseif ($ADVersion -eq '44') { $server = 'Windows Server 2008' } elseif ($ADVersion -eq '31') { $server = 'Windows Server 2003 R2' } elseif ($ADVersion -eq '30') { $server = 'Windows Server 2003' } $OutObj = [System.Collections.Generic.List[object]]::new() if ($Data) { foreach ($Item in $Data) { try { $inObj = [ordered] @{ $reportTranslate.GetAbrADForest.ForestName = $Item.RootDomain $reportTranslate.GetAbrADForest.ForestFunctionalLevel = $Item.ForestMode $reportTranslate.GetAbrADForest.SchemaVersion = $reportTranslate.GetAbrADForest.SchemaVersionValue -f $ADVersion, $server $reportTranslate.GetAbrADForest.TombstoneLifetime = $TombstoneLifetime $reportTranslate.GetAbrADForest.Domains = $Item.Domains -join '; ' $reportTranslate.GetAbrADForest.GlobalCatalogs = $Item.GlobalCatalogs -join '; ' $reportTranslate.GetAbrADForest.DomainsCount = $Item.Domains.Count $reportTranslate.GetAbrADForest.GlobalCatalogsCount = $Item.GlobalCatalogs.Count $reportTranslate.GetAbrADForest.SitesCount = $Item.Sites.Count $reportTranslate.GetAbrADForest.ApplicationPartitions = $Item.ApplicationPartitions $reportTranslate.GetAbrADForest.PartitionsContainer = [string]$Item.PartitionsContainer $reportTranslate.GetAbrADForest.SPNSuffixes = $Item.SPNSuffixes $reportTranslate.GetAbrADForest.UPNSuffixes = ($Item.UPNSuffixes -join ', ') $reportTranslate.GetAbrADForest.AnonymousAccess = & { if (($ValuedsHeuristics.dsHeuristics -eq '') -or ($ValuedsHeuristics.dsHeuristics.Length -lt 7)) { $reportTranslate.GetAbrADForest.AnonymousAccessDisabled } elseif (($ValuedsHeuristics.dsHeuristics.Length -ge 7) -and ($ValuedsHeuristics.dsHeuristics[6] -eq '2')) { $reportTranslate.GetAbrADForest.AnonymousAccessEnabled } } } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { Write-PScriboMessage -IsWarning $_.Exception.Message } } if ($HealthCheck.Domain.Security) { $OutObj | Where-Object { $_.$($reportTranslate.GetAbrADForest.AnonymousAccess) -eq $reportTranslate.GetAbrADForest.AnonymousAccessEnabled } | Set-Style -Style Critical -Property $reportTranslate.GetAbrADForest.AnonymousAccess $OutObj | Where-Object { $_.$($reportTranslate.GetAbrADForest.TombstoneLifetime) -lt 180 } | Set-Style -Style Warning -Property $reportTranslate.GetAbrADForest.TombstoneLifetime } $TableParams = @{ Name = "Forest Summary - $($ForestInfo)" List = $true ColumnWidths = 40, 60 } if ($Report.ShowTableCaptions) { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Table @TableParams if ($HealthCheck.Domain.Security -and ($OutObj | Where-Object { $_.$($reportTranslate.GetAbrADForest.AnonymousAccess) -eq $reportTranslate.GetAbrADForest.AnonymousAccessEnabled }) ) { Paragraph $reportTranslate.GetAbrADForest.HealthCheck -Bold -Underline BlankLine if ($OutObj | Where-Object { $_.$($reportTranslate.GetAbrADForest.AnonymousAccess) -eq $reportTranslate.GetAbrADForest.AnonymousAccessEnabled }) { Paragraph { Text $reportTranslate.GetAbrADForest.BestPractice -Bold Text $reportTranslate.GetAbrADForest.AnonAccessBP } BlankLine Paragraph $reportTranslate.GetAbrADForest.Reference -Bold BlankLine Paragraph $reportTranslate.GetAbrADForest.AnonAccessRef -Color blue } if ($OutObj | Where-Object { $_.$($reportTranslate.GetAbrADForest.TombstoneLifetime) -lt 180 }) { Paragraph { Text $reportTranslate.GetAbrADForest.BestPractice -Bold Text $reportTranslate.GetAbrADForest.TombstoneBP } } } if ($Options.EnableDiagrams) { try { try { $Graph = Get-AbrDiagrammer -DiagramType 'Forest' -DiagramOutput base64 -PSSessionObject $TempPssSession } catch { Write-PScriboMessage -IsWarning -Message "Forest Diagram Graph: $($_.Exception.Message)" } if ($Graph) { $BestAspectRatio = Get-BestImageAspectRatio -GraphObj $Graph -MaxWidth 600 -MaxHeight 600 PageBreak Section -Style Heading3 $reportTranslate.GetAbrADForest.ForestDiagram { Image -Base64 $Graph -Text $reportTranslate.GetAbrADForest.ForestDiagram -Width $BestAspectRatio.Width -Height $BestAspectRatio.Height -Align Center PageBreak } } } catch { Write-PScriboMessage -IsWarning -Message "Forest Diagram Section: $($_.Exception.Message)" } } } } catch { Write-PScriboMessage -IsWarning $_.Exception.Message } try { $ConfigNCDN = $Data.PartitionsContainer.Split(',') | Select-Object -Skip 1 $rootCA = Get-ADObjectSearch -DN "CN=Certification Authorities,CN=Public Key Services,CN=Services,$($ConfigNCDN -join ',')" -Filter { objectClass -eq 'certificationAuthority' } -Properties 'Name' -SelectPrty 'DistinguishedName', 'Name' -Session $TempPssSession $subordinateCA = Get-ADObjectSearch -DN "CN=Enrollment Services,CN=Public Key Services,CN=Services,$($ConfigNCDN -join ',')" -Filter { objectClass -eq 'pKIEnrollmentService' } -Properties '*' -SelectPrty 'dNSHostName', 'Name' -Session $TempPssSession if ($rootCA -or $subordinateCA) { Section -Style Heading3 $reportTranslate.GetAbrADForest.CASection { if ($Options.ShowDefinitionInfo) { Paragraph $reportTranslate.GetAbrADForest.CADefinition BlankLine } if (-not $Options.ShowDefinitionInfo) { Paragraph $reportTranslate.GetAbrADForest.CAParagraph BlankLine } if ($rootCA) { Section -ExcludeFromTOC -Style NOTOCHeading4 $reportTranslate.GetAbrADForest.CARootSection { $OutObj = [System.Collections.Generic.List[object]]::new() foreach ($Item in $rootCA) { try { $inObj = [ordered] @{ $reportTranslate.GetAbrADForest.CAName = $Item.Name $reportTranslate.GetAbrADForest.CADistinguishedName = $Item.DistinguishedName } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { Write-PScriboMessage -IsWarning $_.Exception.Message } } if ($HealthCheck.Forest.BestPractice) { ($OutObj | Measure-Object).Count -gt 1 | Set-Style -Style Warning } $TableParams = @{ Name = "$($reportTranslate.GetAbrADForest.CARootSection) - $($ForestInfo)" List = $false ColumnWidths = 40, 60 } if ($Report.ShowTableCaptions) { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Sort-Object -Property $reportTranslate.GetAbrADForest.CAName | Table @TableParams if ($HealthCheck.Forest.BestPractice -and (($OutObj | Measure-Object).Count -gt 1 ) ) { Paragraph $reportTranslate.GetAbrADForest.HealthCheck -Bold -Underline BlankLine Paragraph { Text $reportTranslate.GetAbrADForest.BestPractice -Bold Text $reportTranslate.GetAbrADForest.MultipleRootCABP } } } } else { Write-PScriboMessage -Message "No Certificate Authority Root information found in $ForestInfo, Disabling this section." } if ($subordinateCA) { Section -ExcludeFromTOC -Style NOTOCHeading4 $reportTranslate.GetAbrADForest.CAIssuerSection { $OutObj = [System.Collections.Generic.List[object]]::new() foreach ($Item in $subordinateCA) { try { $inObj = [ordered] @{ $reportTranslate.GetAbrADForest.CAName = $Item.Name $reportTranslate.GetAbrADForest.CADnsName = $Item.dNSHostName } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { Write-PScriboMessage -IsWarning $_.Exception.Message } } $TableParams = @{ Name = "$($reportTranslate.GetAbrADForest.CAIssuerSection) - $($ForestInfo)" List = $false ColumnWidths = 40, 60 } if ($Report.ShowTableCaptions) { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Sort-Object -Property $reportTranslate.GetAbrADForest.CAName | Table @TableParams } } else { Write-PScriboMessage -Message 'No Certificate Authority Issuer information found, Disabling this section.' } } if ($Options.EnableDiagrams) { try { try { $Graph = Get-AbrDiagrammer -DiagramType 'CertificateAuthority' -DiagramOutput base64 -PSSessionObject $TempPssSession } catch { Write-PScriboMessage -IsWarning -Message "Certificate Authority Diagram Graph: $($_.Exception.Message)" } if ($Graph) { $BestAspectRatio = Get-BestImageAspectRatio -GraphObj $Graph -MaxWidth 600 -MaxHeight 600 PageBreak Section -Style Heading4 $reportTranslate.GetAbrADForest.CADiagram { Image -Base64 $Graph -Text $reportTranslate.GetAbrADForest.CADiagram -Width $BestAspectRatio.Width -Height $BestAspectRatio.Height -Align Center PageBreak } } } catch { Write-PScriboMessage -IsWarning -Message "Certificate Authority Diagram Section: $($_.Exception.Message)" } } } } catch { Write-PScriboMessage -IsWarning $_.Exception.Message } try { Section -Style Heading3 $reportTranslate.GetAbrADForest.OptionalFeatures { $Data = Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock { Get-ADOptionalFeature -Filter * } $OutObj = [System.Collections.Generic.List[object]]::new() if ($Data) { foreach ($Item in $Data) { try { $inObj = [ordered] @{ $reportTranslate.GetAbrADForest.OFName = $Item.Name $reportTranslate.GetAbrADForest.OFRequiredForestMode = $Item.RequiredForestMode $reportTranslate.GetAbrADForest.OFEnabled = switch (($Item.EnabledScopes).count) { 0 { $reportTranslate.GetAbrADForest.OFEnabledNo } default { $reportTranslate.GetAbrADForest.OFEnabledYes } } } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { Write-PScriboMessage -IsWarning $_.Exception.Message } } if ($HealthCheck.Forest.BestPractice) { $OutObj | Where-Object { $_.$($reportTranslate.GetAbrADForest.OFName) -eq 'Recycle Bin Feature' -and $_.$($reportTranslate.GetAbrADForest.OFEnabled) -eq $reportTranslate.GetAbrADForest.OFEnabledNo } | Set-Style -Style Warning -Property $reportTranslate.GetAbrADForest.OFEnabled } $TableParams = @{ Name = "$($reportTranslate.GetAbrADForest.OptionalFeatures) - $($ForestInfo)" List = $false ColumnWidths = 40, 30, 30 } if ($Report.ShowTableCaptions) { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Sort-Object -Property $reportTranslate.GetAbrADForest.OFName | Table @TableParams if ($HealthCheck.Forest.BestPractice -and ($OutObj | Where-Object { $_.$($reportTranslate.GetAbrADForest.OFName) -eq 'Recycle Bin Feature' -and $_.$($reportTranslate.GetAbrADForest.OFEnabled) -eq $reportTranslate.GetAbrADForest.OFEnabledNo }) ) { Paragraph $reportTranslate.GetAbrADForest.HealthCheck -Bold -Underline BlankLine Paragraph { Text $reportTranslate.GetAbrADForest.BestPractice -Bold Text $reportTranslate.GetAbrADForest.RecycleBinBP } BlankLine Paragraph { Text $reportTranslate.GetAbrADForest.Reference -Bold BlankLine Text $reportTranslate.GetAbrADForest.RecycleBinRef -Color blue } } } else { Write-PScriboMessage -Message "No Optional Feature information found in $ForestInfo, Disabling this section." } } } catch { Write-PScriboMessage -IsWarning $_.Exception.Message } } end { Show-AbrDebugExecutionTime -End -TitleMessage 'AD Forest' } } |