EvotecIT / Testimo

Testimo is a PowerShell module for running health checks for Active Directory against a bunch of different tests
MIT License
526 stars 58 forks source link

Source Issues after Upgrade-Module #104

Closed ERAustin closed 4 years ago

ERAustin commented 4 years ago

I believe we were on version .34. Now we are on version .43. I am able to run Invoke-Testimo, however the script I created to details the specific sources and all that seems to have broken.

image

Seems like my Sources array is null. Here is the beginning of the script I have:

## Get-Date for use in report filename
$ReportDate = $null
$ReportDate = Get-Date -Format MM-dd-yyyy
$ReportFilepath = $null
$ReportFilepath = "Y:\AD Testimo\$ReportDate - AD Health Summary.html"

## Used to specify particular tests if necessary
$Sources = @(
    'ForestBackup'
    'ForestReplication'
    'ForestReplicationStatus'
    'ForestSites'
    'ForestSiteLinks'
    'ForestRoles'
    'ForestTombstoneLifetime'
    'DomainRoles'
    'DomainWellKnownFolders'
    'DomainPasswordComplexity'
    'DomainTrusts'
    'DomainEmptyOrganizationalUnits'    
    'DomainDNSScavengingForPrimaryDNSServer'
    'DomainDNSForwaders'
    'DomainDNsZonesAging'
    'DomainKerberosAccountAge'
    'DomainSecurityGroupsSchemaAdmins'
    'DomainSysVolDFSR'
    'DomainDNSZonesForest0ADEL'
    'DomainDNSZonesDomain0ADEL'
    'DCServices'
    'DCRDPSecurity'
    'DCTimeSettings'
    'DCTimeSynchronizationInternal'
    'DCTimeSynchronizationExternal'
    'DCNetworkCardSettings'
    'DCWindowsUpdates'
    'DCSMBProtocols'
    'DCSMBShares'
    'DCNTDSParameters'
    'DCDiagnostics'
)

## Compile Test Results
$ConfigFile = $null
$ConfigFile = "Y:\Testimo\testimoconfig.json"
$TestResults = Invoke-Testimo -ReturnResults -ExtendedResults -Configuration $ConfigFile -Sources $Sources

## Parse $TestResults to HTML. Removed charts as they are too resource intensive  
New-HTML -FilePath $ReportFilepath -UseCssLinks -UseJavaScriptLinks {
    [Array] $PassedTests = $TestResults['Results'] | Where-Object { $_.Status -eq $true }
    [Array] $FailedTests = $TestResults['Results'] | Where-Object { $_.Status -ne $true }
    New-HTMLTab -Name 'Summary' -IconBrands galactic-senate {
        New-HTMLSection -HeaderText "Tests results" -HeaderBackGroundColor DarkGray {
            New-HTMLPanel {
                New-HTMLChart {
                    New-ChartPie -Name 'Passed' -Value ($TestResults['Summary'].Passed) -Color ForestGreen
                    New-ChartPie -Name 'Failed' -Value ($TestResults['Summary'].Failed) -Color OrangeRed
                    New-ChartPie -Name 'Failed' -Value ($TestResults['Summary'].Skipped) -Color LightBlue
                }
                New-HTMLTable -DataTable $TestResults['Summary'] -HideFooter -DisableSearch {
                    New-HTMLTableContent -ColumnName 'Passed' -BackGroundColor ForestGreen -Color White
                    New-HTMLTableContent -ColumnName 'Failed' -BackGroundColor OrangeRed -Color White
                    New-HTMLTableContent -ColumnName 'Skipped' -BackGroundColor LightBlue -Color White
                }
            }
            New-HTMLPanel {
                New-HTMLTable -DataTable $TestResults['Results'] {
                    New-HTMLTableCondition -Name 'Status' -Value $true -Color Green -Row
                    New-HTMLTableCondition -Name 'Status' -Value $false -Color Red -Row
                }
            }
        }
    }
    New-HTMLTab -Name 'Forest' -IconBrands first-order {
        foreach ($Source in $TestResults['Forest']['Tests'].Keys) {
            $Name = $TestResults['Forest']['Tests'][$Source]['Name']
            $Data = $TestResults['Forest']['Tests'][$Source]['Data']
            $SourceCode = $TestResults['Forest']['Tests'][$Source]['SourceCode']
            $Results = $TestResults['Forest']['Tests'][$Source]['Results']
            #$Details = $TestResults['Forest']['Tests'][$Source]['Details']
            [Array] $PassedTestsSingular = $TestResults['Forest']['Tests'][$Source]['Results'] | Where-Object { $_.Status -eq $true }
            [Array] $FailedTestsSingular = $TestResults['Forest']['Tests'][$Source]['Results'] | Where-Object { $_.Status -ne $true }
            New-HTMLSection -HeaderText $Name -HeaderBackGroundColor DarkGray -CanCollapse {
                New-HTMLContainer {
                    New-HTMLPanel {
                        #New-HTMLChart {
                        #    New-ChartPie -Name 'Passed' -Value ($PassedTestsSingular.Count) -Color ForestGreen
                        #    New-ChartPie -Name 'Failed' -Value ($FailedTestsSingular.Count) -Color OrangeRed
                        #}
                        New-HTMLCodeBlock -Code $SourceCode -Style 'PowerShell' -Theme enlighter
                    }
                }
                New-HTMLContainer {
                    New-HTMLPanel {
                        New-HTMLTable -DataTable $Data
                        New-HTMLTable -DataTable $Results {
                            New-HTMLTableCondition -Name 'Status' -Value $true -Color Green -Row
                            New-HTMLTableCondition -Name 'Status' -Value $false -Color Red -Row
                        }
                    }
                }
            }
        }
    }
    foreach ($Domain in $TestResults['Domains'].Keys) {
        New-HTMLTab -Name "Domain $Domain" -IconBrands deskpro {
            foreach ($Source in $TestResults['Domains'][$Domain]['Tests'].Keys) {
                $Name = $TestResults['Domains'][$Domain]['Tests'][$Source]['Name']
                $Data = $TestResults['Domains'][$Domain]['Tests'][$Source]['Data']
                $SourceCode = $TestResults['Domains'][$Domain]['Tests'][$Source]['SourceCode']
                $Results = $TestResults['Domains'][$Domain]['Tests'][$Source]['Results']
                # $Details = $TestResults['Domains'][$Domain]['Tests'][$Source]['Details']
                [Array] $PassedTestsSingular = $TestResults['Domains'][$Domain]['Tests'][$Source]['Results'] | Where-Object { $_.Status -eq $true }
                [Array] $FailedTestsSingular = $TestResults['Domains'][$Domain]['Tests'][$Source]['Results'] | Where-Object { $_.Status -ne $true }
                New-HTMLSection -HeaderText $Name -HeaderBackGroundColor DarkGray -CanCollapse {
                    New-HTMLContainer {
                        New-HTMLPanel {
                            #New-HTMLChart {
                            #    New-ChartPie -Name 'Passed' -Value ($PassedTestsSingular.Count) -Color ForestGreen
                            #    New-ChartPie -Name 'Failed' -Value ($FailedTestsSingular.Count) -Color OrangeRed
                            #}
                            New-HTMLCodeBlock -Code $SourceCode -Style 'PowerShell' -Theme enlighter
                        }
                    }
                    New-HTMLContainer {
                        New-HTMLPanel {
                            New-HTMLTable -DataTable $Data
                            New-HTMLTable -DataTable $Results {
                                New-HTMLTableCondition -Name 'Status' -Value $true -Color Green -Row
                                New-HTMLTableCondition -Name 'Status' -Value $false -Color Red -Row
                            }
                        }
                    }
                }
            }
            foreach ($DC in $TestResults['Domains'][$Domain]['DomainControllers'].Keys) {
                New-HTMLSection -HeaderText "Domain Controller - $DC" -HeaderBackGroundColor DarkSlateGray -CanCollapse -Collapsed {
                    New-HTMLContainer {
                        foreach ($Source in  $TestResults['Domains'][$Domain]['DomainControllers'][$DC]['Tests'].Keys) {
                            $Name = $TestResults['Domains'][$Domain]['DomainControllers'][$DC]['Tests'][$Source]['Name']
                            $Data = $TestResults['Domains'][$Domain]['DomainControllers'][$DC]['Tests'][$Source]['Data']
                            $SourceCode = $TestResults['Domains'][$Domain]['DomainControllers'][$DC]['Tests'][$Source]['SourceCode']
                            $Results = $TestResults['Domains'][$Domain]['DomainControllers'][$DC]['Tests'][$Source]['Results']
                            #$Details = $TestResults['Domains'][$Domain]['DomainControllers'][$DC]['Tests'][$Source]['Details']
                            [Array] $PassedTestsSingular = $TestResults['Domains'][$Domain]['DomainControllers'][$DC]['Tests'][$Source]['Results'] | Where-Object { $_.Status -eq $true }
                            [Array] $FailedTestsSingular = $TestResults['Domains'][$Domain]['DomainControllers'][$DC]['Tests'][$Source]['Results'] | Where-Object { $_.Status -ne $true }
                            New-HTMLSection -HeaderText $Name -HeaderBackGroundColor DarkGray {
                                New-HTMLContainer {
                                    New-HTMLPanel {
                                        #New-HTMLChart {
                                        #    New-ChartPie -Name 'Passed' -Value ($PassedTestsSingular.Count) -Color ForestGreen
                                        #    New-ChartPie -Name 'Failed' -Value ($FailedTestsSingular.Count) -Color OrangeRed
                                       # }
                                        New-HTMLCodeBlock -Code $SourceCode -Style 'PowerShell' -Theme enlighter
                                    }
                                }
                                New-HTMLContainer {
                                    New-HTMLPanel {
                                        New-HTMLTable -DataTable $Data
                                        New-HTMLTable -DataTable $Results {
                                            New-HTMLTableCondition -Name 'Status' -Value $true -Color Green -Row
                                            New-HTMLTableCondition -Name 'Status' -Value $false -Color Red -Row
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
} -ShowHTML
PrzemyslawKlys commented 4 years ago

The first error means the source is incorrect. Most likely it was renamed. Between 34 and 43 there were few changes and additions. If I rename Source test it's gonna have an impact on you. And since I add, change a lot of things to accommodate new changes... well:

You can compare it with:

Get-TestimoSources -SourcesOnly

or for more advanced:

Get-TestimoSources | Format-Table *

Sorry for that.

The warnings are from:

New-HTML -FilePath $ReportFilepath -UseCssLinks -UseJavaScriptLinks {

Which you can change to:

New-HTML -FilePath $ReportFilepath -Online {

The rest of errors is related to your HTML building, but probably because Invoke-Testimo fails.

PrzemyslawKlys commented 4 years ago
$Sources = @(
    'ForestBackup'
    'ForestReplication'
    'ForestReplicationStatus'
    'ForestSites'
    'ForestSiteLinks'
    'ForestRoles'
    'ForestTombstoneLifetime'
    'DomainRoles'
    'DomainWellKnownFolders'
    'DomainPasswordComplexity'
    'DomainTrusts'
    'DomainEmptyOrganizationalUnits'
    'DomainDNSScavengingForPrimaryDNSServer'
    'DomainDNSForwaders'
    'DomainDNsZonesAging'
    'DomainKerberosAccountAge'
    'DomainSecurityGroupsSchemaAdmins'
    'DomainSysVolDFSR'
    'DomainDNSZonesForest0ADEL'
    'DomainDNSZonesDomain0ADEL'
    'DCServices'
    'DCRDPSecurity'
    'DCTimeSettings'
    'DCTimeSynchronizationInternal'
    'DCTimeSynchronizationExternal'
    'DCNetworkCardSettings'
    'DCWindowsUpdates'
    'DCSMBProtocols'
    'DCSMBShares'
    'DCNTDSParameters'
    'DCDiagnostics'
)

$NewSources = Get-TestimoSources -SourcesOnly
$Sources | ForEach-Object { if ($_ -notin $NewSources) { $_ } }

The test that is wrong: DomainEmptyOrganizationalUnits which was renamed to DomainOrganizationalUnitsEmpty

ERAustin commented 4 years ago

The first error is on me and not reading the error carefully. I read in the patch notes before install that it was changed, but should have correlated the error to the source name change. I also made the name change in the JSON file.

I also made the update about the depreciated CSS and Java links.

It's still appearing like something is not being passed, as it continues to complain about a null array. This is not the source array this time though:

PS C:\Windows\system32> Y:\Testimo\Full_AD_Health_Report.ps1
[i][Testimo] Version [Informative] [Current/Latest: 0.0.43 at 06/17/2020 00:38:13]
[i][Testimo] Using configuration provided by userImport-TestimoConfiguration : Cannot index into a null array.
At C:\Program Files\WindowsPowerShell\Modules\Testimo\0.0.43\Testimo.psm1:4667 char:5
+     Import-TestimoConfiguration -Configuration $Configuration
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Import-TestimoConfiguration], RuntimeException
    + FullyQualifiedErrorId : NullArray,Import-TestimoConfiguration

PS C:\Windows\system32> 
PrzemyslawKlys commented 4 years ago

There may be more changes in the JSON file. I guess once you remove it it works? I did a few changes which may have impacted it.

PrzemyslawKlys commented 4 years ago

One of the JSON changes could be related to:

I'm sure there are few other things that will impact JSON

ERAustin commented 4 years ago

Ok, I will test and make necessary changes to the JSON file. If/when I get it working I will document it here and then close the case. Appreciate your insight.

PrzemyslawKlys commented 4 years ago

isn't it easier to generate new one and just apply changes you made?

ERAustin commented 4 years ago

I guess you're right. I was trying to not have to go back through 2100 lines and recreate my 'true' and 'false' parameters, but I guess that's a 1 time thing rather than pouring over the file trying to find the 1 or 2 lines that aren't right. I suppose both ways there's some work involved, and the 'generate a new one' way means the JSON is actually right. :)

PrzemyslawKlys commented 4 years ago

I'm sorry for trouble, just Testimo isn't yet in a state where breaking changes are less common. I've not yet reached stable phase and you can expect more changes this year. I'mn heading into changing Pass/Fail into multistate, export to Excel, Word and more tests. It will impact you ;)

PrzemyslawKlys commented 4 years ago

I can also see that JSON most likely will miss some settings as I've not changed everything in code. Will update it I guess in next version.

ERAustin commented 4 years ago

I'm happy to hear of the improvements you're planning :)

I generated and ran a new JSON without issue so I'll apply my changes to it through something like Beyond Compare and it won't be too bad - work is what I'm here for right?

Once again, thanks for your assistance!