ActiveDirectory.tests.ps1
[CmdletBinding()] Param( [string]$ADFile, [string]$ADGoldFile = $(Get-ChildItem ("ADGoldConfig-*.xml") | Select name -last 1).name ) #Try to load the Active Directory configuration files for comparison Try{ If ($ADFile) { Write-Verbose "Loading the AD Snapshot from: $ADFile" $ADSnapshot = Import-Clixml $ADFile } Else{ Write-Verbose "No AD Snapshot file specified. Attempting to get config via Audit-ADConfig.ps1." $ADSnapshot = Invoke-Expression ".\Audit-ADConfig.ps1 -ExportToXML:$False" } Write-Verbose "Loading the AD Gold Config from: $ADGoldFile" $ADGoldConfig = Import-Clixml $ADGoldFile }Catch{ Write-Error "Could not load the Active Directory 'Gold' configuration or load/generate a current snapshot." Exit } #Begin testing Describe 'Active Directory configuration checks' { Context 'Verifying Forest Configuration'{ it "Forest FQDN $($ADGoldConfig.ForestInformation.RootDomain)" { $ADGoldConfig.ForestInformation.RootDomain | Should be $ADSnapshot.ForestInformation.RootDomain } it "ForestMode $($ADGoldConfig.ForestInformation.ForestMode.ToString())"{ $ADGoldConfig.ForestInformation.ForestMode.ToString() | Should be $ADSnapshot.ForestInformation.ForestMode.ToString() } } Context 'Verifying GlobalCatalogs'{ $ADGoldConfig.ForestInformation.GlobalCatalogs | ForEach-Object{ it "Server $($_) is a GlobalCatalog"{ $ADSnapshot.ForestInformation.GlobalCatalogs.Contains($_) | Should be $true } } } Context 'Verifying Domain Configuration'{ it "Total Domain Controllers $($ADGoldConfig.DomainControllers.Count)" { $ADGoldConfig.DomainControllers.Count | Should be $ADSnapshot.DomainControllers.Count } $ADGoldConfig.DomainControllers.Name | ForEach-Object{ it "DomainController $($_) exists"{ $ADSnapshot.DomainControllers.Name.Contains($_) | Should be $true } } it "DNSRoot $($ADGoldConfig.DomainInformation.DNSRoot)"{ $ADGoldConfig.DomainInformation.DNSRoot | Should be $ADSnapshot.DomainInformation.DNSRoot } it "NetBIOSName $($ADGoldConfig.DomainInformation.NetBIOSName)"{ $ADGoldConfig.DomainInformation.NetBIOSName | Should be $ADSnapshot.DomainInformation.NetBIOSName } it "DomainMode $($ADGoldConfig.DomainInformation.DomainMode.ToString())"{ $ADGoldConfig.DomainInformation.DomainMode.ToString() | Should be $ADSnapshot.DomainInformation.DomainMode.ToString() } it "DistinguishedName $($ADGoldConfig.DomainInformation.DistinguishedName)"{ $ADGoldConfig.DomainInformation.DistinguishedName | Should be $ADSnapshot.DomainInformation.DistinguishedName } it "Server $($ADGoldConfig.DomainInformation.RIDMaster) is RIDMaster"{ $ADGoldConfig.DomainInformation.RIDMaster | Should be $ADSnapshot.DomainInformation.RIDMaster } it "Server $($ADGoldConfig.DomainInformation.PDCEmulator) is PDCEmulator"{ $ADGoldConfig.DomainInformation.PDCEmulator | Should be $ADSnapshot.DomainInformation.PDCEmulator } it "Server $($ADGoldConfig.DomainInformation.InfrastructureMaster) is InfrastructureMaster"{ $ADGoldConfig.DomainInformation.InfrastructureMaster | Should be $ADSnapshot.DomainInformation.InfrastructureMaster } } Context 'Verifying Default Password Policy'{ it 'ComplexityEnabled'{ $ADGoldConfig.DefaultPassWordPoLicy.ComplexityEnabled | Should be $ADSnapshot.DefaultPassWordPoLicy.ComplexityEnabled } it 'Password History count'{ $ADGoldConfig.DefaultPassWordPoLicy.PasswordHistoryCount | Should be $ADSnapshot.DefaultPassWordPoLicy.PasswordHistoryCount } it "Lockout Threshold equals $($ADGoldConfig.DefaultPassWordPoLicy.LockoutThreshold)"{ $ADGoldConfig.DefaultPassWordPoLicy.LockoutThreshold | Should be $ADSnapshot.DefaultPassWordPoLicy.LockoutThreshold } it "Lockout duration equals $($ADGoldConfig.DefaultPassWordPoLicy.LockoutDuration)"{ $ADGoldConfig.DefaultPassWordPoLicy.LockoutDuration | Should be $ADSnapshot.DefaultPassWordPoLicy.LockoutDuration.ToString() } it "Lockout observation window equals $($ADGoldConfig.DefaultPassWordPoLicy.LockoutObservationWindow)"{ $ADGoldConfig.DefaultPassWordPoLicy.LockoutObservationWindow | Should be $ADSnapshot.DefaultPassWordPoLicy.LockoutObservationWindow.ToString() } it "Min password age equals $($ADGoldConfig.DefaultPassWordPoLicy.MinPasswordAge)"{ $ADGoldConfig.DefaultPassWordPoLicy.MinPasswordAge | Should be $ADSnapshot.DefaultPassWordPoLicy.MinPasswordAge.ToString() } it "Max password age equals $($ADGoldConfig.DefaultPassWordPoLicy.MaxPasswordAge)"{ $ADGoldConfig.DefaultPassWordPoLicy.MaxPasswordAge | Should be $ADSnapshot.DefaultPassWordPoLicy.MaxPasswordAge.ToString() } } Context 'Verifying Active Directory Sites'{ $ADGoldConfig.Sites.Name | ForEach-Object{ it "Site $($_)" { $ADSnapshot.Sites.Name.Contains($_) | Should be $true } } } Context 'Verifying Active Directory Sitelinks'{ $lookupSiteLinks = $ADSnapshot.Sitelinks | Group-Object -AsHashTable -Property Name $ADGoldConfig.Sitelinks | ForEach-Object{ it "Sitelink $($_.Name)" { $_.Name | Should be $($lookupSiteLinks.$($_.Name).Name) } it "Sitelink $($_.Name) costs $($_.Cost)" { $_.Cost | Should be $lookupSiteLinks.$($_.Name).Cost } it "Sitelink $($_.Name) replication interval $($_.ReplicationFrequencyInMinutes)" { $_.ReplicationFrequencyInMinutes | Should be $lookupSiteLinks.$($_.Name).ReplicationFrequencyInMinutes } } } Context 'Verifying Active Directory Subnets'{ $lookupSubnets = $ADSnapshot.SubNets | Group-Object -AsHashTable -Property Name $ADGoldConfig.Subnets | ForEach-Object{ it "Subnet $($_.Name)" { $_.Name | Should be $lookupSubnets.$($_.Name).Name } it "Site $($_.Site)" { $_.Site | Should be $lookupSubnets.$($_.Name).Site } } } } Describe 'Active Directory health checks' { Context 'Checking the output of NLTest /Query'{ $NLTest = NLTest.exe /Query it "NLTest.exe /Query Result" { ($NLTest | out-string).contains("Success") | Should be $true } } Context 'Checking the output of DCDiag for issues on all DCs'{ $DCDiag = dcdiag.exe -a it "DCDiag.exe -a Result" { ($DCDiag | out-string).contains("failed") | Should be $false } } Context 'Checking the output of RepAdmin /showrepl for replication issues'{ (Repadmin.exe /showrepl * /csv | convertfrom-csv) | Sort "Source DSA" | ?{$_."Number of Failures" -ge 0} | ForEach-Object{ it "Replication from $($_."Source DSA") to $($_."Destination DSA") has $($_."Number of Failures") failures" { $_."Number of Failures" | Should Not BeGreaterThan 0 } } } Context 'Pinging each Domain Controller'{ $ADGoldConfig.DomainControllers.Name | Sort | ForEach-Object{ it "Ping result for Domain Controller $($_)"{ Test-Connection $_ -Quiet | Should be $true } } } Context 'Testing local Active Directory TCP ports respond'{ # AD Ports: https://technet.microsoft.com/en-us/library/dd772723(v=ws.10).aspx $Ports = @(53,88,135,139,389,445,464,636,3268,3269,9389) $Ports | foreach-object{ it "Port test for TCP $_" { (Test-netconnection -ComputerName $env:COMPUTERNAME -Port $_).TcpTestSucceeded | Should be $true } } } Context 'Checking local Active Directory Windows services are running'{ $Services = @("ADWS","BITS","CertPropSvc","CryptSvc","Dfs","DFSR","DNS","Dnscache","eventlog","gpsvc","kdc",` "LanmanServer","LanmanWorkstation","Netlogon","NTDS","NtFrs","RpcEptMapper","RpcSs","SamSs",` "W32Time") $Services | foreach-object{ $Svc = get-service $_ it "Service: $($Svc.DisplayName)" { $Svc.status | Should be "Running" } } } } |