Skip to content

Commit

Permalink
Merge pull request #2165 from microsoft/dpaul-HcInstalledDate
Browse files Browse the repository at this point in the history
Include SU/CU Installed Date
  • Loading branch information
dpaulson45 authored Aug 8, 2024
2 parents cb21ece + cfdb3ac commit 0569068
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ function Invoke-AnalyzerExchangeInformation {
}
Add-AnalyzedResultInformation @params

if ($null -ne $exchangeInformation.BuildInformation.ExchangeSetup.InstallTime) {
$params = $baseParams + @{
Name = "Latest Install Time (SU/CU)"
Details = $exchangeInformation.BuildInformation.ExchangeSetup.InstallTime
}
Add-AnalyzedResultInformation @params
}

if ($exchangeInformation.BuildInformation.VersionInformation.Supported -eq $false) {
$daysOld = ($date - $exchangeInformation.BuildInformation.VersionInformation.ReleaseDate).Days

Expand Down Expand Up @@ -129,19 +137,21 @@ function Invoke-AnalyzerExchangeInformation {
Add-AnalyzedResultInformation @params
}

if ($null -ne $exchangeInformation.BuildInformation.KBsInstalled) {
if ($null -ne $exchangeInformation.BuildInformation.KBsInstalledInfo.PackageName) {
Add-AnalyzedResultInformation -Name "Exchange IU or Security Hotfix Detected" @baseParams
$problemKbFound = $false
$problemKbName = "KB5029388"

foreach ($kb in $exchangeInformation.BuildInformation.KBsInstalled) {
foreach ($kbInfo in $exchangeInformation.BuildInformation.KBsInstalledInfo) {
$kbName = $kbInfo.PackageName
$params = $baseParams + @{
Details = $kb
Details = "$kbName - Installed on $($kbInfo.InstalledDate)"
DisplayCustomTabNumber = 2
TestingName = "Exchange IU"
}
Add-AnalyzedResultInformation @params

if ($kb.Contains($problemKbName)) {
if ($kbName.Contains($problemKbName)) {
$problemKbFound = $true
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ function Invoke-AnalyzerSecurityCve-MarchSuSpecial {
#Description: March 2021 Exchange vulnerabilities Security Update (SU) check for outdated version (CUs)
#Affected Exchange versions: Exchange 2013, Exchange 2016, Exchange 2016 (we only provide this special SU for these versions)
#Fix: Update to a supported CU and apply KB5000871
$march2021SUInstalled = $null -ne $SecurityObject.ExchangeInformation.BuildInformation.KBsInstalled -and
$SecurityObject.ExchangeInformation.BuildInformation.KBsInstalled -like "*KB5000871*"
$march2021SUInstalled = $null -ne $SecurityObject.ExchangeInformation.BuildInformation.KBsInstalledInfo.PackageName -and
$SecurityObject.ExchangeInformation.BuildInformation.KBsInstalledInfo.PackageName -like "*KB5000871*"
$ex2019 = "Exchange2019"
$ex2016 = "Exchange2016"
$ex2013 = "Exchange2013"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function Get-ExchangeInformation {
CU = $versionInformation.CU
ExchangeSetup = $exSetupDetails
VersionInformation = $versionInformation
KBsInstalled = [array](Get-ExchangeUpdates -Server $Server -ExchangeMajorVersion $versionInformation.MajorVersion)
KBsInstalledInfo = [array](Get-ExchangeUpdates -Server $Server -ExchangeMajorVersion $versionInformation.MajorVersion)
}

$dependentServices = (Get-ExchangeDependentServices -MachineName $Server)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,18 @@ function Get-ExchangeUpdates {
$IU = $RegKey.GetSubKeyNames()
if ($null -ne $IU) {
Write-Verbose "Detected fixes installed on the server"
$fixes = @()
$installedUpdates = New-Object System.Collections.Generic.List[object]
foreach ($key in $IU) {
$IUKey = $RegKey.OpenSubKey($key)
$IUName = $IUKey.GetValue("PackageName")
Write-Verbose "Found: $IUName"
$fixes += $IUName
$IUInstalledDate = $IUKey.GetValue("InstalledDate")
$installedUpdates.Add(([PSCustomObject]@{
PackageName = $IUName
InstalledDate = $IUInstalledDate
}))
}
return $fixes
return $installedUpdates
} else {
Write-Verbose "No IUs found in the registry"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,33 @@ Describe "Testing Health Checker by Mock Data Imports" {
if ($Name -eq "MSExchangeMitigation") { return Import-Clixml "$Script:MockDataCollectionRoot\Exchange\GetServiceMitigation.xml" }
return Import-Clixml "$Script:MockDataCollectionRoot\OS\GetService1.xml"
}
Mock Get-RemoteRegistrySubKey -ParameterFilter { $SubKey -eq "SOFTWARE\Microsoft\Updates\Exchange 2019" } -MockWith {
$obj = New-Object System.Collections.Generic.List[object]
$suObject = [PSCustomObject]@{
Name = "Empty"
}
$suObject | Add-Member -MemberType ScriptMethod -Name GetSubKeyNames -Value { return @("KB5029388", "KB5030877") }
$suObject | Add-Member -MemberType ScriptMethod -Name OpenSubKey -Value { param($id) if ($id -eq "KB5029388") {
$o = [PSCustomObject]@{
Name = "Empty"
}
$o | Add-Member -MemberType ScriptMethod -Name GetValue -Value { param ($name) if ($name -eq "PackageName") {
return "Security Update for Exchange Server 2019 Cumulative Update 12 (KB5029388)"
} elseif ( $name -eq "InstalledDate") { return "9/20/2023" } }
return $o
} elseif ($id -eq "KB5030877") {
$o = [PSCustomObject]@{
Name = "Empty"
}
$o | Add-Member -MemberType ScriptMethod -Name GetValue -Value { param ($name) if ($name -eq "PackageName") {
return "Security Update for Exchange Server 2019 Cumulative Update 12 (KB5030877)"
} elseif ( $name -eq "InstalledDate") { return "10/20/2023" } }
return $o
}
}
$obj.Add($suObject)
return $obj
}

SetDefaultRunOfHealthChecker "Debug_Scenario1_Results.xml"
}
Expand All @@ -82,6 +109,8 @@ Describe "Testing Health Checker by Mock Data Imports" {
TestObjectMatch "Exchange Server Membership" "Failed" -WriteType "Red"
TestObjectMatch "Exchange Trusted Subsystem - Local System Membership" "Exchange Trusted Subsystem - Local System Membership" -WriteType "Red"
TestObjectMatch "Exchange Trusted Subsystem - AD Group Membership" "Exchange Trusted Subsystem - AD Group Membership" -WriteType "Red"
$hotfixInstalled = GetObject "Exchange IU"
$hotfixInstalled.Count | Should -Be 2
}

It "Dependent Services" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Describe "Testing Health Checker by Mock Data Imports" {
Assert-MockCalled Get-WmiObjectHandler -Exactly 6
Assert-MockCalled Invoke-ScriptBlockHandler -Exactly 5
Assert-MockCalled Get-RemoteRegistryValue -Exactly 25
Assert-MockCalled Get-RemoteRegistrySubKey -Exactly 1
Assert-MockCalled Get-NETFrameworkVersion -Exactly 1
Assert-MockCalled Get-DotNetDllFileVersions -Exactly 1
Assert-MockCalled Get-NicPnpCapabilitiesSetting -Exactly 1
Expand All @@ -75,7 +76,6 @@ Describe "Testing Health Checker by Mock Data Imports" {
Assert-MockCalled Get-AllTlsSettings -Exactly 1
Assert-MockCalled Get-SmbServerConfiguration -Exactly 1
Assert-MockCalled Get-ExchangeAppPoolsInformation -Exactly 1
Assert-MockCalled Get-ExchangeUpdates -Exactly 1
Assert-MockCalled Get-ExchangeDomainsAclPermissions -Exactly 1
Assert-MockCalled Get-ExchangeAdSchemaClass -Exactly 2
Assert-MockCalled Get-ExchangeServer -Exactly 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,20 @@ Mock Get-RemoteRegistryValue {
}
}

Mock Get-RemoteRegistrySubKey {
param(
[string]$MachineName,
[string]$SubKey
)

switch ($SubKey) {
"SOFTWARE\Microsoft\Updates\Exchange 2013" { return $null }
"SOFTWARE\Microsoft\Updates\Exchange 2016" { return $null }
"SOFTWARE\Microsoft\Updates\Exchange 2019" { return $null }
default { throw "Failed to find SubKey: $SubKey" }
}
}

Mock Get-NETFrameworkVersion {
return [PSCustomObject]@{
FriendlyName = "4.8"
Expand Down Expand Up @@ -199,10 +213,6 @@ Mock Get-ExchangeAppPoolsInformation {
return Import-Clixml "$Script:MockDataCollectionRoot\Exchange\GetExchangeAppPoolsInformation.xml"
}

Mock Get-ExchangeUpdates {
return $null
}

Mock Get-ExchangeAdSchemaClass -ParameterFilter { $SchemaClassName -eq "ms-Exch-Storage-Group" } {
return Import-Clixml "$Script:MockDataCollectionRoot\Exchange\GetExchangeAdSchemaClass_ms-Exch-Storage-Group.xml"
}
Expand Down
10 changes: 8 additions & 2 deletions Shared/Get-ExSetupFileVersionInfo.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,20 @@ function Get-ExSetupFileVersionInfo {
$exSetupDetails = [string]::Empty
function Get-ExSetupDetailsScriptBlock {
try {
Get-Command ExSetup -ErrorAction Stop | ForEach-Object { $_.FileVersionInfo }
$getCommand = Get-Command ExSetup -ErrorAction Stop | ForEach-Object { $_.FileVersionInfo }
$getItem = Get-Item -ErrorAction SilentlyContinue $getCommand[0].FileName
$getCommand | Add-Member -MemberType NoteProperty -Name InstallTime -Value ($getItem.LastAccessTime)
$getCommand
} catch {
try {
Write-Verbose "Failed to find ExSetup by environment path locations. Attempting manual lookup."
$installDirectory = (Get-ItemProperty HKLM:\SOFTWARE\Microsoft\ExchangeServer\v15\Setup -ErrorAction Stop).MsiInstallPath

if ($null -ne $installDirectory) {
Get-Command ([System.IO.Path]::Combine($installDirectory, "bin\ExSetup.exe")) -ErrorAction Stop | ForEach-Object { $_.FileVersionInfo }
$getCommand = Get-Command ([System.IO.Path]::Combine($installDirectory, "bin\ExSetup.exe")) -ErrorAction Stop | ForEach-Object { $_.FileVersionInfo }
$getItem = Get-Item -ErrorAction SilentlyContinue $getCommand[0].FileName
$getCommand | Add-Member -MemberType NoteProperty -Name InstallTime -Value ($getItem.LastAccessTime)
$getCommand
}
} catch {
Write-Verbose "Failed to find ExSetup, need to fallback."
Expand Down

0 comments on commit 0569068

Please sign in to comment.