Src/Private/Get-AbrADDomainController.ps1
function Get-AbrADDomainController { <# .SYNOPSIS Used by As Built Report to retrieve Microsoft AD Domain Controller information. .DESCRIPTION .NOTES Version: 0.7.5 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux .EXAMPLE .LINK #> [CmdletBinding()] param ( [Parameter ( Position = 0, Mandatory)] [string] $Domain ) begin { Write-PscriboMessage "Collecting AD Domain Controller information." } process { try { $OutObj = @() Write-PscriboMessage "Discovering Active Directory Domain Controller information from $Domain." $DCs = Invoke-Command -Session $TempPssSession {Get-ADDomain -Identity $using:Domain | Select-Object -ExpandProperty ReplicaDirectoryServers | Where-Object { $_ -notin ($using:Options).Exclude.DCs}} if ($DCs) { foreach ($DC in $DCs) { if (Test-Connection -ComputerName $DC -Quiet -Count 1) { Write-PscriboMessage "Discovered '$(($DCs | Measure-Object).Count)' Active Directory Domain Controller in domain $Domain." try { Write-PscriboMessage "Collecting AD Domain Controller Summary information of $DC." $DCInfo = Invoke-Command -Session $TempPssSession {Get-ADDomainController -Identity $using:DC -Server $using:DC} $inObj = [ordered] @{ 'DC Name' = ($DCInfo.Name).ToString().ToUpper() 'Domain Name' = $DCInfo.Domain 'Site' = $DCInfo.Site 'Global Catalog' = ConvertTo-TextYN $DCInfo.IsGlobalCatalog 'Read Only' = ConvertTo-TextYN $DCInfo.IsReadOnly 'IP Address' = $DCInfo.IPv4Address } $OutObj += [pscustomobject]$inobj } catch { Write-PscriboMessage -IsWarning "$($_.Exception.Message) (Domain Controller Item)" } } } $TableParams = @{ Name = "Domain Controller Summary - $($Domain.ToString().ToUpper())" List = $false ColumnWidths = 25, 25, 15, 10, 10, 15 } if ($Report.ShowTableCaptions) { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Sort-Object -Property 'DC Name' | Table @TableParams } } catch { Write-PscriboMessage -IsWarning "$($_.Exception.Message) (Domain Controller Table)" } if ($InfoLevel.Domain -ge 2) { try { Write-PscriboMessage "Collecting AD Domain Controller Hardware information for domain $Domain" Section -Style Heading5 'Hardware Inventory' { Paragraph "The following section provides a summary of the Domain Controller Hardware for $($Domain.ToString().ToUpper())." BlankLine $OutObj = @() Write-PscriboMessage "Discovering Active Directory Domain Controller information in $Domain." if ($DCs) { foreach ($DC in $DCs) { if (Test-Connection -ComputerName $DC -Quiet -Count 1) { try { Write-PscriboMessage "Collecting AD Domain Controller Hardware information for $DC." $CimSession = New-CimSession $DC -Credential $Credential -Authentication $Options.PSDefaultAuthentication $DCPssSession = New-PSSession $DC -Credential $Credential -Authentication $Options.PSDefaultAuthentication $HW = Invoke-Command -Session $DCPssSession -ScriptBlock { Get-ComputerInfo } $License = Get-CimInstance -Query 'Select * from SoftwareLicensingProduct' -CimSession $CimSession | Where-Object { $_.LicenseStatus -eq 1 } $HWCPU = Get-CimInstance -Class Win32_Processor -CimSession $CimSession $HWBIOS = Get-CimInstance -Class Win32_Bios -CimSession $CimSession Remove-PSSession -Session $DCPssSession Remove-CimSession $CimSession if ($HW) { $inObj = [ordered] @{ 'Name' = $HW.CsDNSHostName 'Windows Product Name' = $HW.WindowsProductName 'Windows Current Version' = $HW.WindowsCurrentVersion 'Windows Build Number' = $HW.OsVersion 'Windows Install Type' = $HW.WindowsInstallationType 'AD Domain' = $HW.CsDomain 'Windows Installation Date' = $HW.OsInstallDate 'Time Zone' = $HW.TimeZone 'License Type' = $License.ProductKeyChannel 'Partial Product Key' = $License.PartialProductKey 'Manufacturer' = $HW.CsManufacturer 'Model' = $HW.CsModel 'Serial Number' = $HostBIOS.SerialNumber 'Bios Type' = $HW.BiosFirmwareType 'BIOS Version' = $HostBIOS.Version 'Processor Manufacturer' = $HWCPU[0].Manufacturer 'Processor Model' = $HWCPU[0].Name 'Number of Processors' = $HWCPU.Length 'Number of CPU Cores' = $HWCPU[0].NumberOfCores 'Number of Logical Cores' = $HWCPU[0].NumberOfLogicalProcessors 'Physical Memory (GB)' = ConvertTo-FileSizeString $HW.CsTotalPhysicalMemory } $OutObj = [pscustomobject]$inobj $TableParams = @{ Name = "Domain Controller Hardware - $($HW.CsDNSHostName.ToString().ToUpper())" List = $true ColumnWidths = 40, 60 } if ($Report.ShowTableCaptions) { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Table @TableParams } } catch { Write-PscriboMessage -IsWarning "$($_.Exception.Message) (Domain Controller Hardware Item)" } } } } } } catch { Write-PscriboMessage -IsWarning "$($_.Exception.Message) (Domain Controller Hardware Table)" } } try { Write-PscriboMessage "Collecting AD Domain Controller NTDS information." Section -Style Heading5 'NTDS Information' { Paragraph "The following section provides a summary of the Domain Controller NTDS file size on $($Domain.ToString().ToUpper())." BlankLine $OutObj = @() Write-PscriboMessage "Discovering Active Directory Domain Controller information in $Domain." if ($DCs) { foreach ($DC in $DCs) { if (Test-Connection -ComputerName $DC -Quiet -Count 1) { try { Write-PscriboMessage "Collecting AD Domain Controller NTDS information for $DC." $DCPssSession = New-PSSession $DC -Credential $Credential -Authentication $Options.PSDefaultAuthentication $NTDS = Invoke-Command -Session $DCPssSession -ScriptBlock {Get-ItemProperty -Path HKLM:\System\CurrentControlSet\Services\NTDS\Parameters | Select-Object -ExpandProperty 'DSA Database File'} $size = Invoke-Command -Session $DCPssSession -ScriptBlock {(Get-ItemProperty -Path $using:NTDS).Length} $LogFiles = Invoke-Command -Session $DCPssSession -ScriptBlock {Get-ItemProperty -Path HKLM:\System\CurrentControlSet\Services\NTDS\Parameters | Select-Object -ExpandProperty 'Database log files path'} $SYSVOL = Invoke-Command -Session $DCPssSession -ScriptBlock {Get-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters | Select-Object -ExpandProperty 'SysVol'} Remove-PSSession -Session $DCPssSession if ( $NTDS -and $size ) { $inObj = [ordered] @{ 'DC Name' = $DC.ToString().ToUpper().Split(".")[0] 'Database File' = $NTDS 'Database Size' = ConvertTo-FileSizeString $size 'Log Path' = $LogFiles 'SysVol Path' = $SYSVOL } $OutObj += [pscustomobject]$inobj } } catch { Write-PscriboMessage -IsWarning "$($_.Exception.Message) (NTDS Item)" } } } $TableParams = @{ Name = "NTDS Database File Usage - $($Domain.ToString().ToUpper())" List = $false ColumnWidths = 20, 22, 14, 22, 22 } if ($Report.ShowTableCaptions) { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Sort-Object -Property 'DC Name' | Table @TableParams } } } catch { Write-PscriboMessage -IsWarning "$($_.Exception.Message) (NTDS Table)" } try { Write-PscriboMessage "Collecting AD Domain Controller Time Source information." Section -Style Heading5 'Time Source Information' { Paragraph "The following section provides a summary of the Domain Controller Time Source configuration on $($Domain.ToString().ToUpper())." BlankLine $OutObj = @() Write-PscriboMessage "Discovering Active Directory Domain Controller information in $Domain." if ($DCs) { Write-PscriboMessage "Discovered '$(($DCs | Measure-Object).Count)' Active Directory Domain Controller in domain $Domain." foreach ($DC in $DCs) { if (Test-Connection -ComputerName $DC -Quiet -Count 1) { try { Write-PscriboMessage "Collecting AD Domain Controller Time Source information for $DC." $DCPssSession = New-PSSession $DC -Credential $Credential -Authentication $Options.PSDefaultAuthentication $NtpServer = Invoke-Command -Session $DCPssSession -ScriptBlock {Get-ItemProperty -Path HKLM:\System\CurrentControlSet\Services\W32Time\Parameters | Select-Object -ExpandProperty 'NtpServer'} $SourceType = Invoke-Command -Session $DCPssSession -ScriptBlock {Get-ItemProperty -Path HKLM:\System\CurrentControlSet\Services\W32Time\Parameters | Select-Object -ExpandProperty 'Type'} Remove-PSSession -Session $DCPssSession if ( $NtpServer -and $SourceType ) { try { $inObj = [ordered] @{ 'Name' = $DC.ToString().ToUpper().Split(".")[0] 'Time Server' = Switch ($NtpServer) { 'time.windows.com,0x8' {"Domain Hierarchy"} 'time.windows.com' {"Domain Hierarchy"} '0x8' {"Domain Hierarchy"} default {$NtpServer} } 'Type' = Switch ($SourceType) { 'NTP' {"MANUAL (NTP)"} 'NT5DS' {"DOMHIER"} default {$SourceType} } } $OutObj += [pscustomobject]$inobj } catch { Write-PscriboMessage -IsWarning "$($_.Exception.Message) (Time Source Item)" } } } catch { Write-PscriboMessage -IsWarning "$($_.Exception.Message) (Time Source Table)" } } } $TableParams = @{ Name = "Time Source Configuration - $($Domain.ToString().ToUpper())" List = $false ColumnWidths = 30, 50, 20 } if ($Report.ShowTableCaptions) { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Sort-Object -Property 'DC Name' | Table @TableParams } } } catch { Write-PscriboMessage -IsWarning "$($_.Exception.Message) (Time Source)" } if ($HealthCheck.DomainController.Diagnostic) { try { Write-PscriboMessage "Collecting AD Domain Controller SRV Records Status." Section -Style Heading5 'Health Check - SRV Records Status' { Paragraph "The following section provides a status of the Domain Controller dns srv records status on $($Domain.ToString().ToUpper())." BlankLine $OutObj = @() Write-PscriboMessage "Discovering Active Directory Domain Controller SRV Records Status in $Domain." if ($DCs) { Write-PscriboMessage "Discovered '$(($DCs | Measure-Object).Count)' Active Directory Domain Controller in domain $Domain." foreach ($DC in $DCs) { if (Test-Connection -ComputerName $DC -Quiet -Count 1) { try { Write-PscriboMessage "Collecting AD Domain Controller SRV Records Status for $DC." $CimSession = New-CimSession $DC -Credential $Credential -Authentication $Options.PSDefaultAuthentication $PDCEmulator = Invoke-Command -Session $TempPssSession {(Get-ADDomain $using:Domain -ErrorAction Stop).PDCEmulator} if ($Domain -eq $ADSystem.RootDomain) { $SRVRR = Get-DnsServerResourceRecord -CimSession $CimSession -ZoneName _msdcs.$Domain -RRType Srv $DCARR = Get-DnsServerResourceRecord -CimSession $CimSession -ZoneName $Domain -RRType A | Where-Object {$_.Hostname -eq $DC.ToString().ToUpper().Split(".")[0]} if ($DC -in $PDCEmulator) { $PDC = $SRVRR | Where-Object {$_.Hostname -eq "_ldap._tcp.pdc" -and $_.RecordData.DomainName -eq "$($DC)."} } else {$PDC = 'NonPDC'} if ($DC -in $ADSystem.GlobalCatalogs) { $GC = $SRVRR | Where-Object {$_.Hostname -eq "_ldap._tcp.gc" -and $_.RecordData.DomainName -eq "$($DC)."} } else {$GC = 'NonGC'} $KDC = $SRVRR | Where-Object {$_.Hostname -eq "_kerberos._tcp.dc" -and $_.RecordData.DomainName -eq "$($DC)."} $DCRR = $SRVRR | Where-Object {$_.Hostname -eq "_ldap._tcp.dc" -and $_.RecordData.DomainName -eq "$($DC)."} } else { $SRVRR = Get-DnsServerResourceRecord -CimSession $CimSession -ZoneName $Domain -RRType Srv $DCARR = Get-DnsServerResourceRecord -CimSession $CimSession -ZoneName $Domain -RRType A | Where-Object {$_.Hostname -eq $DC.ToString().ToUpper().Split(".")[0]} if ($DC -in $PDCEmulator) { $PDC = $SRVRR | Where-Object {$_.Hostname -eq "_ldap._tcp.pdc._msdcs" -and $_.RecordData.DomainName -eq "$($DC)."} } else {$PDC = 'NonPDC'} if ($DC -in $ADSystem.GlobalCatalogs) { $GC = Get-DnsServerResourceRecord -CimSession $CimSession -ZoneName "_msdcs.$($ADSystem.RootDomain)" -RRType Srv | Where-Object {$_.Hostname -eq "_ldap._tcp.gc" -and $_.RecordData.DomainName -eq "$($DC)."} } else {$GC = 'NonGC'} $KDC = $SRVRR | Where-Object {$_.Hostname -eq "_kerberos._tcp.dc._msdcs" -and $_.RecordData.DomainName -eq "$($DC)."} $DCRR = $SRVRR | Where-Object {$_.Hostname -eq "_ldap._tcp.dc._msdcs" -and $_.RecordData.DomainName -eq "$($DC)."} } Remove-CimSession $CimSession if ( $SRVRR ) { try { $inObj = [ordered] @{ 'Name' = $DC.ToString().ToUpper().Split(".")[0] 'A Record' = Switch ([string]::IsNullOrEmpty($DCARR)) { $True {'Fail'} default {'OK'} } 'KDC SRV' = Switch ([string]::IsNullOrEmpty($KDC)) { $True {'Fail'} default {'OK'} } 'PDC SRV' = Switch ([string]::IsNullOrEmpty($PDC)) { $True {'Fail'} $False { Switch ($PDC) { 'NonPDC' {'Non PDC'} default {'OK'} } } } 'GC SRV' = Switch ([string]::IsNullOrEmpty($GC)) { $True {'Fail'} $False { Switch ($GC) { 'NonGC' {'Non GC'} default {'OK'} } } } 'DC SRV' = Switch ([string]::IsNullOrEmpty($DCRR)) { $True {'Fail'} default {'OK'} } } $OutObj += [pscustomobject]$inobj } catch { Write-PscriboMessage -IsWarning "$($_.Exception.Message) (SRV Records Status Item)" } if ($HealthCheck.DomainController.Diagnostic) { $OutObj | Where-Object { $_.'A Record' -eq 'Fail' } | Set-Style -Style Critical -Property 'A Record' $OutObj | Where-Object { $_.'KDC SRV' -eq 'Fail' } | Set-Style -Style Critical -Property 'KDC SRV' $OutObj | Where-Object { $_.'PDC SRV' -eq 'Fail' } | Set-Style -Style Critical -Property 'PDC SRV' $OutObj | Where-Object { $_.'GC SRV' -eq 'Fail' } | Set-Style -Style Critical -Property 'GC SRV' $OutObj | Where-Object { $_.'GC SRV' -eq 'Non GC' } | Set-Style -Style Warning -Property 'GC SRV' $OutObj | Where-Object { $_.'DC SRV' -eq 'Fail' } | Set-Style -Style Critical -Property 'DC SRV' } } } catch { Write-PscriboMessage -IsWarning "$($_.Exception.Message) (SRV Records Status Table)" } } } $TableParams = @{ Name = "SRV Records Status - $($Domain.ToString().ToUpper())" List = $false ColumnWidths = 20, 16, 16, 16, 16, 16 } if ($Report.ShowTableCaptions) { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Sort-Object -Property 'Name' | Table @TableParams if ( $OutObj | Where-Object { { $_.'KDC SRV' -eq 'Fail' } -or { $_.'PDC SRV' -eq 'Fail' } -or { $_.'GC SRV' -eq 'Fail' } -or { $_.'DC SRV' -eq 'Fail' }}) { Paragraph "Health Check:" -Italic -Bold -Underline Paragraph "Best Practice: The SRV record is a Domain Name System (DNS) resource record. It's used to identify computers hosting specific services. SRV resource records are used to locate domain controllers for Active Directory." -Italic -Bold Paragraph "Corrective Actions: Attempted to fix the situation by doing the following: 1. on the DC, run ipconfig /flushDNS 2. ipconfig /registerDNS 3. net stop NETLOGON, net start NETLOGON (should register the SRV records)" -Italic -Bold } } } } catch { Write-PscriboMessage -IsWarning "$($_.Exception.Message) (SRV Records Status)" } } if ($HealthCheck.DomainController.Software) { try { Write-PscriboMessage "Collecting additional software running on the Domain Controller." Section -Style Heading5 'Health Check - Installed Software on DC' { Paragraph "The following section provides a summary of additional software running on $($Domain.ToString().ToUpper())." BlankLine Write-PscriboMessage "Discovering Active Directory Domain Controller information in $Domain." if ($DCs) { foreach ($DC in $DCs) { if (Test-Connection -ComputerName $DC -Quiet -Count 1) { try { $OutObj = @() Write-PscriboMessage "Collecting AD Domain Controller installed software information for $DC." $DCPssSession = New-PSSession $DC -Credential $Credential -Authentication $Options.PSDefaultAuthentication $Software = Invoke-Command -Session $DCPssSession -ScriptBlock {Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object {($_.Publisher -notlike "Microsoft*" -and $_.DisplayName -notlike "VMware*") -and ($Null -ne $_.Publisher -or $Null -ne $_.DisplayName)} | Select-Object -Property DisplayName,Publisher,InstallDate | Sort-Object -Property DisplayName} Remove-PSSession -Session $DCPssSession if ( $Software ) { Section -Style Heading6 "$($DC.ToString().ToUpper().Split(".")[0]) additional software" { foreach ($APP in $Software) { try { $inObj = [ordered] @{ 'Name' = $APP.DisplayName 'Publisher' = $APP.Publisher 'Install Date' = $APP.InstallDate } $OutObj = [pscustomobject]$inobj if ($HealthCheck.DomainController.Software) { $OutObj | Set-Style -Style Warning } } catch { Write-PscriboMessage -IsWarning $_.Exception.Message } } $TableParams = @{ Name = "Installed Software - $($DC.ToString().ToUpper().Split(".")[0])" List = $false ColumnWidths = 34, 33, 33 } if ($Report.ShowTableCaptions) { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Sort-Object -Property 'Name' | Table @TableParams if ($HealthCheck.DomainController.Software) { Paragraph "Health Check:" -Italic -Bold -Underline Paragraph "Best Practices: Do not run other software or services on a Domain Controller." -Italic -Bold } } } } catch { Write-PscriboMessage -IsWarning "$($_.Exception.Message) (Installed Software Table)" } } } } } } catch { Write-PscriboMessage -IsWarning "$($_.Exception.Message) (Domain Controller Section)" } } } end {} } |