Skip to content

Commit 8baad32

Browse files
authored
Merge pull request #2282 from microsoft/FebCU15
Exchange 2019 CU15 Release
2 parents 89f30e3 + 217b864 commit 8baad32

11 files changed

+326
-91
lines changed

Diagnostics/HealthChecker/Analyzer/Invoke-AnalyzerExchangeInformation.ps1

+84
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
. $PSScriptRoot\Add-AnalyzedResultInformation.ps1
55
. $PSScriptRoot\Get-DisplayResultsGroupingKey.ps1
66
. $PSScriptRoot\Invoke-AnalyzerKnownBuildIssues.ps1
7+
. $PSScriptRoot\..\..\..\Shared\CompareExchangeBuildLevel.ps1
78
function Invoke-AnalyzerExchangeInformation {
89
[CmdletBinding()]
910
param(
@@ -581,6 +582,89 @@ function Invoke-AnalyzerExchangeInformation {
581582
}
582583
}
583584

585+
if ((Test-ExchangeBuildGreaterOrEqualThanBuild -CurrentExchangeBuild $exchangeInformation.BuildInformation.VersionInformation -Version "Exchange2019" -CU "CU15") -and
586+
$exchangeInformation.GetExchangeServer.IsEdgeServer -eq $false) {
587+
# This feature only needs to be displayed if we are on Exchange 2019 CU15+
588+
if ($null -eq $exchangeInformation.GetExchangeServer.RingLevel) {
589+
$params = $baseParams + @{
590+
Name = "Feature Flighting"
591+
Details = "Unknown - No data on Get-ExchangeServer related to this feature. Likely due to connecting to an Exchange Server for shell not on supported build."
592+
DisplayWriteType = "Yellow"
593+
}
594+
Add-AnalyzedResultInformation @params
595+
} else {
596+
Add-AnalyzedResultInformation @baseParams -Name "Feature Flighting"
597+
598+
$getExchangeServer = $exchangeInformation.GetExchangeServer
599+
$flightingBaseParams = $baseParams + @{ DisplayCustomTabNumber = 2 }
600+
$params = $flightingBaseParams + @{
601+
Name = "Ring Level"
602+
Details = $getExchangeServer.RingLevel
603+
}
604+
Add-AnalyzedResultInformation @params
605+
606+
$endpointDisplayWriteType = "Grey"
607+
$endpointDetails = "200 - Reachable"
608+
if ($exchangeInformation.ExchangeFeatureFlightingServiceResult.StatusCode -ne 200) {
609+
$endpointDisplayWriteType = "Yellow"
610+
$endpointDetails = "Unreachable - More Information: https://aka.ms/HC-ExchangeServerFeatureFlighting"
611+
}
612+
$params = $flightingBaseParams + @{
613+
Name = "Endpoint Service Status"
614+
Details = $endpointDetails
615+
DisplayWriteType = $endpointDisplayWriteType
616+
}
617+
Add-AnalyzedResultInformation @params
618+
619+
$params = $flightingBaseParams + @{
620+
Name = "Last Service Run Time"
621+
Details = $getExchangeServer.LastFlightingServiceRunTime
622+
}
623+
Add-AnalyzedResultInformation @params
624+
625+
if ($getExchangeServer.FeaturesEnabled.Count -gt 0) {
626+
$details = ([string]::Join(", ", $getExchangeServer.FeaturesEnabled))
627+
} else {
628+
$details = "None Enabled"
629+
}
630+
$params = $flightingBaseParams + @{
631+
Name = "Features Enabled"
632+
Details = $details
633+
}
634+
Add-AnalyzedResultInformation @params
635+
636+
# The rest of the settings, only display if we have something there.
637+
if ($getExchangeServer.FeaturesApproved.Count -gt 0) {
638+
$params = $flightingBaseParams + @{
639+
Name = "Features Approved"
640+
Details = ([string]::Join(", ", $getExchangeServer.FeaturesApproved))
641+
}
642+
Add-AnalyzedResultInformation @params
643+
}
644+
if ($getExchangeServer.FeaturesAwaitingAdminApproval.Count -gt 0) {
645+
$params = $flightingBaseParams + @{
646+
Name = "Features Awaiting Admin Approval"
647+
Details = ([string]::Join(", ", $getExchangeServer.FeaturesAwaitingAdminApproval))
648+
}
649+
Add-AnalyzedResultInformation @params
650+
}
651+
if ($getExchangeServer.FeaturesBlocked.Count -gt 0) {
652+
$params = $flightingBaseParams + @{
653+
Name = "Features Blocked"
654+
Details = ([string]::Join(", ", $getExchangeServer.FeaturesBlocked))
655+
}
656+
Add-AnalyzedResultInformation @params
657+
}
658+
if ($getExchangeServer.FeaturesDisabled.Count -gt 0) {
659+
$params = $flightingBaseParams + @{
660+
Name = "Features Disabled"
661+
Details = ([string]::Join(", ", $getExchangeServer.FeaturesDisabled))
662+
}
663+
Add-AnalyzedResultInformation @params
664+
}
665+
}
666+
}
667+
584668
if ($null -ne $exchangeInformation.SettingOverrides) {
585669

586670
$overridesDetected = $null -ne $exchangeInformation.SettingOverrides.SettingOverrides

Diagnostics/HealthChecker/Analyzer/Security/Invoke-AnalyzerSecurityCve-2023-36434.ps1

+6-1
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,15 @@ function Invoke-AnalyzerSecurityCve-2023-36434 {
2424

2525
begin {
2626
Write-Verbose "Calling: $($MyInvocation.MyCommand)"
27+
# Because we don't have the revision number here, we don't want to provide the 4th value otherwise it will not work correctly
28+
$notWindows2025OrGreater = $SecurityObject.OsInformation.BuildInformation.BuildVersion -lt [System.Version]"10.0.26100"
2729
$tokenCacheModuleVersionInformation = $SecurityObject.ExchangeInformation.IISSettings.IISTokenCacheModuleInformation
2830
$tokenCacheFixedVersionNumber = $null
2931
$tokenCacheVersionGreaterOrEqual = $false
3032
}
3133
process {
32-
if ($SecurityObject.IsEdgeServer -eq $false) {
34+
if ($SecurityObject.IsEdgeServer -eq $false -and
35+
$notWindows2025OrGreater) {
3336
Write-Verbose "Testing CVE: CVE-2023-21709 / CVE-2023-36434"
3437

3538
if ($SecurityObject.ExchangeInformation.IISSettings.IISModulesInformation.ModuleList.Name -contains "TokenCacheModule") {
@@ -68,6 +71,8 @@ function Invoke-AnalyzerSecurityCve-2023-36434 {
6871
Add-AnalyzedResultInformation @params
6972
}
7073
}
74+
} elseif ( -not $notWindows2025OrGreater) {
75+
Write-Verbose "Windows Server 2025 or greater is not affected by this vulnerability"
7176
} else {
7277
Write-Verbose "Edge Server Role is not affected by this vulnerability as it has no IIS installed"
7378
}

Diagnostics/HealthChecker/Analyzer/Security/Invoke-AnalyzerSecuritySettings.ps1

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Copyright (c) Microsoft Corporation.
22
# Licensed under the MIT License.
33

4+
. $PSScriptRoot\..\..\..\..\Shared\CompareExchangeBuildLevel.ps1
45
. $PSScriptRoot\..\Add-AnalyzedResultInformation.ps1
56
. $PSScriptRoot\..\Get-DisplayResultsGroupingKey.ps1
67
. $PSScriptRoot\Invoke-AnalyzerSecurityExchangeCertificates.ps1
@@ -50,6 +51,7 @@ function Invoke-AnalyzerSecuritySettings {
5051

5152
$tlsVersions = @("1.0", "1.1", "1.2", "1.3")
5253
$tls13SupportedOS = @("Windows2012", "Windows2012R2", "Windows2016", "Windows2019") -notcontains $osInformation.BuildInformation.MajorVersion
54+
$tls13SupportedExchange = Test-ExchangeBuildGreaterOrEqualThanBuild -CurrentExchangeBuild $HealthServerObject.ExchangeInformation.BuildInformation.VersionInformation -Version "Exchange2019" -CU "CU15"
5355
$currentNetVersion = $osInformation.TLSSettings.Registry.NET["NETv4"]
5456

5557
$tlsSettings = $osInformation.TLSSettings.Registry.TLS
@@ -79,12 +81,13 @@ function Invoke-AnalyzerSecuritySettings {
7981

8082
# Any TLS version is Misconfigured or Half Disabled is Red
8183
# Only TLS 1.2 being Disabled is Red
82-
# Currently TLS 1.3 being Enabled is Red
84+
# TLS 1.3 being Enabled is Red on unsupported OS and Exchange version.
85+
# TLS 1.3 started support with Exchange 2019 CU15 with Windows Server 2022 or newer versions
8386
# TLS 1.0 or 1.1 being Enabled is Yellow as we recommend to disable this weak protocol versions
8487
if (($currentTlsVersion.TLSConfiguration -eq "Misconfigured" -or
8588
$currentTlsVersion.TLSConfiguration -eq "Half Disabled") -or
8689
($tlsKey -eq "1.2" -and $currentTlsVersion.TLSConfiguration -eq "Disabled") -or
87-
($tlsKey -eq "1.3" -and $currentTlsVersion.TLSConfiguration -eq "Enabled")) {
90+
($tlsKey -eq "1.3" -and $currentTlsVersion.TLSConfiguration -eq "Enabled" -and (-not $tls13SupportedOS -or -not $tls13SupportedExchange))) {
8891
$displayWriteType = "Red"
8992
} elseif ($currentTlsVersion.TLSConfiguration -eq "Enabled" -and
9093
($tlsKey -eq "1.1" -or $tlsKey -eq "1.0")) {

Diagnostics/HealthChecker/DataCollection/ExchangeInformation/Get-ExchangeInformation.ps1

+29-13
Original file line numberDiff line numberDiff line change
@@ -180,23 +180,38 @@ function Get-ExchangeInformation {
180180

181181
$FIPFSUpdateIssue = Get-FIPFSScanEngineVersionState @fipFsParams
182182

183-
$eemsEndpointParams = @{
183+
$endpointScriptBlock = {
184+
param($url, $proxy)
185+
186+
if ($null -eq $url) {
187+
throw "NULL URL provided for endpoint script block"
188+
}
189+
Write-Verbose "Going to try to get the endpoint information for: $url"
190+
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
191+
if ($null -ne $proxy) {
192+
Write-Verbose "Proxy Server detected. Going to use: $proxy"
193+
[System.Net.WebRequest]::DefaultWebProxy = New-Object System.Net.WebProxy($proxy)
194+
[System.Net.WebRequest]::DefaultWebProxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
195+
[System.Net.WebRequest]::DefaultWebProxy.BypassProxyOnLocal = $true
196+
} elseif ($null -ne [System.Net.WebRequest]::DefaultWebProxy.Address) {
197+
Write-Verbose "No Exchange proxy provided, but one is set on the PowerShell session. Going to remove it."
198+
[System.Net.WebRequest]::DefaultWebProxy = $null
199+
}
200+
Invoke-WebRequest -Method Get -Uri $url -UseBasicParsing
201+
}
202+
203+
$scriptBlockEndpointParams = @{
184204
ComputerName = $Server
185205
ScriptBlockDescription = "Test EEMS pattern service connectivity"
186206
CatchActionFunction = ${Function:Invoke-CatchActions}
187-
ArgumentList = $getExchangeServer.InternetWebProxy
188-
ScriptBlock = {
189-
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
190-
if ($null -ne $args[0]) {
191-
Write-Verbose "Proxy Server detected. Going to use: $($args[0])"
192-
[System.Net.WebRequest]::DefaultWebProxy = New-Object System.Net.WebProxy($args[0])
193-
[System.Net.WebRequest]::DefaultWebProxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
194-
[System.Net.WebRequest]::DefaultWebProxy.BypassProxyOnLocal = $true
195-
}
196-
Invoke-WebRequest -Method Get -Uri "https://officeclient.microsoft.com/GetExchangeMitigations" -UseBasicParsing
197-
}
207+
ArgumentList = @("https://officeclient.microsoft.com/GetExchangeMitigations", $getExchangeServer.InternetWebProxy)
208+
ScriptBlock = $endpointScriptBlock
198209
}
199-
$eemsEndpointResults = Invoke-ScriptBlockHandler @eemsEndpointParams
210+
$eemsEndpointResults = Invoke-ScriptBlockHandler @scriptBlockEndpointParams
211+
212+
$scriptBlockEndpointParams.ScriptBlockDescription = "Test Feature Flighting service connectivity"
213+
$scriptBlockEndpointParams.ArgumentList[0] = "https://officeclient.microsoft.com/GetExchangeConfig"
214+
$featureFlightingEndpointResults = Invoke-ScriptBlockHandler @scriptBlockEndpointParams
200215

201216
Write-Verbose "Checking AES256-CBC information protection readiness and configuration"
202217
$aes256CbcParams = @{
@@ -321,6 +336,7 @@ function Get-ExchangeInformation {
321336
ServerMaintenance = $serverMaintenance
322337
ExchangeCertificates = [array]$exchangeCertificates
323338
ExchangeEmergencyMitigationServiceResult = $eemsEndpointResults
339+
ExchangeFeatureFlightingServiceResult = $featureFlightingEndpointResults
324340
EdgeTransportResourceThrottling = $edgeTransportResourceThrottling # If we want to checkout other diagnosticInfo, we should create a new object here.
325341
ApplicationConfigFileStatus = $applicationConfigFileStatus
326342
DependentServices = $dependentServices

Diagnostics/HealthChecker/DataCollection/ExchangeInformation/Get-ExchangeServerMaintenanceState.ps1

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@ function Get-ExchangeServerMaintenanceState {
2020
$getServerComponentState = Get-ServerComponentState -Identity $Server -ErrorAction SilentlyContinue
2121

2222
try {
23+
$errorCount = $Error.Count
2324
$getClusterNode = Get-ClusterNode -Name $Server -ErrorAction Stop
2425
} catch {
2526
Write-Verbose "Failed to run Get-ClusterNode"
26-
Invoke-CatchActions
27+
Invoke-ErrorCatchActionLoopFromIndex $errorCount
2728
}
2829

2930
Write-Verbose "Running ServerComponentStates checks"

Diagnostics/HealthChecker/DataCollection/ServerInformation/Get-ServerOperatingSystemVersion.ps1

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ function Get-ServerOperatingSystemVersion {
4444
"*Server 2016*" { $osReturnValue = "Windows2016" }
4545
"*Server 2019*" { $osReturnValue = "Windows2019" }
4646
"*Server 2022*" { $osReturnValue = "Windows2022" }
47+
"*Server 2025*" { $osReturnValue = "Windows2025" }
4748
default { $osReturnValue = "Unknown" }
4849
}
4950
}

0 commit comments

Comments
 (0)