diff --git a/Diagnostics/HealthChecker/Analyzer/Invoke-AnalyzerFrequentConfigurationIssues.ps1 b/Diagnostics/HealthChecker/Analyzer/Invoke-AnalyzerFrequentConfigurationIssues.ps1 index c0045e99c1..eb3af3147d 100644 --- a/Diagnostics/HealthChecker/Analyzer/Invoke-AnalyzerFrequentConfigurationIssues.ps1 +++ b/Diagnostics/HealthChecker/Analyzer/Invoke-AnalyzerFrequentConfigurationIssues.ps1 @@ -348,4 +348,48 @@ function Invoke-AnalyzerFrequentConfigurationIssues { } Add-AnalyzedResultInformation @params } + + $edgeKey = $exchangeInformation.ApplicationConfigFileStatus.Keys | Where-Object { $_ -like "*\EdgeTransport.exe.config" } + $antiMalwareKey = $exchangeInformation.FileContentInformation.Keys | Where-Object { $_ -like "*\Monitoring\Config\AntiMalware.xml" } + + if ($null -ne $edgeKey -and + $null -ne $antiMalwareKey -and + $exchangeInformation.ApplicationConfigFileStatus[$edgeKey].Present -and + $exchangeInformation.FileContentInformation[$antiMalwareKey].Present) { + $params = $baseParams + @{ + Name = "UnifiedContent Auto Cleanup Configured" + Details = "Unknown" + DisplayWriteType = "Red" + } + try { + $temporaryStoragePath = (([xml]$exchangeInformation.ApplicationConfigFileStatus[$edgeKey].Content).configuration.appSettings.add | + Where-Object { $_.key -eq "TemporaryStoragePath" }).value + $edgeKeySuccessful = $true + $cleanupFolderResponderFolderPaths = (([xml]$exchangeInformation.FileContentInformation[$antiMalwareKey].Content).Definition.MaintenanceDefinition.ExtensionAttributes.CleanupFolderResponderFolderPaths) + $cleanupPathsExists = $cleanupFolderResponderFolderPaths -like "*$temporaryStoragePath\UnifiedContent*" + + if ($cleanupPathsExists) { + $params.DisplayWriteType = "Green" + } + + $params.Details = $cleanupPathsExists + Add-AnalyzedResultInformation @params + + if ($cleanupPathsExists -eq $false) { + $params = $baseParams + @{ + Details = "More Information: https://aka.ms/HC-UnifiedContentCleanup" + DisplayWriteType = "Yellow" + DisplayCustomTabNumber = 2 + } + Add-AnalyzedResultInformation @params + } + } catch { + if ($edgeKeySuccessful) { + $params.Details = "AntiMalware.xml Invalid Config Format" + } else { + $params.Details = "Error - EdgeTransport.exe.config Invalid Config Format" + } + Add-AnalyzedResultInformation @params + } + } } diff --git a/Diagnostics/HealthChecker/DataCollection/ExchangeInformation/Get-ExchangeInformation.ps1 b/Diagnostics/HealthChecker/DataCollection/ExchangeInformation/Get-ExchangeInformation.ps1 index 802f254bda..b510737207 100644 --- a/Diagnostics/HealthChecker/DataCollection/ExchangeInformation/Get-ExchangeInformation.ps1 +++ b/Diagnostics/HealthChecker/DataCollection/ExchangeInformation/Get-ExchangeInformation.ps1 @@ -115,7 +115,8 @@ function Get-ExchangeInformation { $configParams = @{ ComputerName = $Server FileLocation = @("$([System.IO.Path]::Combine($serverExchangeBinDirectory, "EdgeTransport.exe.config"))", - "$([System.IO.Path]::Combine($serverExchangeBinDirectory, "Search\Ceres\Runtime\1.0\noderunner.exe.config"))") + "$([System.IO.Path]::Combine($serverExchangeBinDirectory, "Search\Ceres\Runtime\1.0\noderunner.exe.config"))", + "$([System.IO.Path]::Combine($serverExchangeBinDirectory, "Monitoring\Config\AntiMalware.xml"))") } if ($getExchangeServer.IsEdgeServer -eq $false -and @@ -203,7 +204,7 @@ function Get-ExchangeInformation { CatchActionFunction = ${Function:Invoke-CatchActions} ScriptBlock = { [PSCustomObject]@{ - LocalGroupMember = (Get-LocalGroupMember -SID "S-1-5-32-544" -ErrorAction Stop) + LocalGroupMember = (Get-LocalGroupMember -SID "S-1-5-32-544" -ErrorAction Stop) ADGroupMembership = (Get-ADPrincipalGroupMembership (Get-ADComputer $env:COMPUTERNAME).DistinguishedName) } } diff --git a/Diagnostics/HealthChecker/Tests/DataCollection/E15/Exchange/Antimalware.xml b/Diagnostics/HealthChecker/Tests/DataCollection/E15/Exchange/Antimalware.xml new file mode 100644 index 0000000000..30e5a30bfb --- /dev/null +++ b/Diagnostics/HealthChecker/Tests/DataCollection/E15/Exchange/Antimalware.xml @@ -0,0 +1,938 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Diagnostics/HealthChecker/Tests/DataCollection/E16/Exchange/Antimalware.xml b/Diagnostics/HealthChecker/Tests/DataCollection/E16/Exchange/Antimalware.xml new file mode 100644 index 0000000000..1d317cdca8 --- /dev/null +++ b/Diagnostics/HealthChecker/Tests/DataCollection/E16/Exchange/Antimalware.xml @@ -0,0 +1,839 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Diagnostics/HealthChecker/Tests/DataCollection/E19/Exchange/Antimalware.xml b/Diagnostics/HealthChecker/Tests/DataCollection/E19/Exchange/Antimalware.xml new file mode 100644 index 0000000000..1d317cdca8 --- /dev/null +++ b/Diagnostics/HealthChecker/Tests/DataCollection/E19/Exchange/Antimalware.xml @@ -0,0 +1,839 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Diagnostics/HealthChecker/Tests/DataCollection/E19/Exchange/Antimalware1.xml b/Diagnostics/HealthChecker/Tests/DataCollection/E19/Exchange/Antimalware1.xml new file mode 100644 index 0000000000..9f1c192029 --- /dev/null +++ b/Diagnostics/HealthChecker/Tests/DataCollection/E19/Exchange/Antimalware1.xml @@ -0,0 +1,839 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Diagnostics/HealthChecker/Tests/HealthChecker.E15.Main.Tests.ps1 b/Diagnostics/HealthChecker/Tests/HealthChecker.E15.Main.Tests.ps1 index 65cea5fe84..773c257bb4 100644 --- a/Diagnostics/HealthChecker/Tests/HealthChecker.E15.Main.Tests.ps1 +++ b/Diagnostics/HealthChecker/Tests/HealthChecker.E15.Main.Tests.ps1 @@ -118,8 +118,10 @@ Describe "Testing Health Checker by Mock Data Imports - Exchange 2013" { TestObjectMatch "EdgeTransport.exe.config Present" "True" -WriteType "Green" TestObjectMatch "Open Relay Wild Card Domain" "Not Set" TestObjectMatch "EXO Connector Present" "False" + # For some reason by default Exchange 2013 doesn't have this setting. not going to look into it just going to make a not of it and move on. + TestObjectMatch "UnifiedContent Auto Cleanup Configured" $false -WriteType "Red" - $Script:ActiveGrouping.Count | Should -Be 11 + $Script:ActiveGrouping.Count | Should -Be 13 } It "Display Results - Security Settings" { diff --git a/Diagnostics/HealthChecker/Tests/HealthChecker.E16.Main.Tests.ps1 b/Diagnostics/HealthChecker/Tests/HealthChecker.E16.Main.Tests.ps1 index af9567a0f5..7671d4231f 100644 --- a/Diagnostics/HealthChecker/Tests/HealthChecker.E16.Main.Tests.ps1 +++ b/Diagnostics/HealthChecker/Tests/HealthChecker.E16.Main.Tests.ps1 @@ -120,7 +120,7 @@ Describe "Testing Health Checker by Mock Data Imports - Exchange 2016" { TestObjectMatch "Open Relay Wild Card Domain" "Not Set" TestObjectMatch "EXO Connector Present" "False" - $Script:ActiveGrouping.Count | Should -Be 11 + $Script:ActiveGrouping.Count | Should -Be 12 } It "Display Results - Security Settings" { diff --git a/Diagnostics/HealthChecker/Tests/HealthChecker.E19.Main.Tests.ps1 b/Diagnostics/HealthChecker/Tests/HealthChecker.E19.Main.Tests.ps1 index 286a394c8d..6d0f18c372 100644 --- a/Diagnostics/HealthChecker/Tests/HealthChecker.E19.Main.Tests.ps1 +++ b/Diagnostics/HealthChecker/Tests/HealthChecker.E19.Main.Tests.ps1 @@ -121,8 +121,9 @@ Describe "Testing Health Checker by Mock Data Imports" { TestObjectMatch "NodeRunner.exe memory limit" "0 MB" -WriteType "Green" TestObjectMatch "Open Relay Wild Card Domain" "Not Set" TestObjectMatch "EXO Connector Present" "True" # Custom EXO Connector with no TlsDomain TlsAuthLevel + TestObjectMatch "UnifiedContent Auto Cleanup Configured" $true -WriteType "Green" - $Script:ActiveGrouping.Count | Should -Be 13 + $Script:ActiveGrouping.Count | Should -Be 14 } It "Display Results - Security Settings" { diff --git a/Diagnostics/HealthChecker/Tests/HealthChecker.E19.Scenarios.Tests.ps1 b/Diagnostics/HealthChecker/Tests/HealthChecker.E19.Scenarios.Tests.ps1 index d59130c0e1..68a194c346 100644 --- a/Diagnostics/HealthChecker/Tests/HealthChecker.E19.Scenarios.Tests.ps1 +++ b/Diagnostics/HealthChecker/Tests/HealthChecker.E19.Scenarios.Tests.ps1 @@ -318,6 +318,10 @@ Describe "Testing Health Checker by Mock Data Imports" { TestObjectMatch "EdgeTransport.exe.config Invalid Config Format" $true -WriteType "Red" } + It "EdgeTransport.exe.config invalid config for UnifiedContent" { + TestObjectMatch "UnifiedContent Auto Cleanup Configured" "Error - EdgeTransport.exe.config Invalid Config Format" -WriteType "Red" + } + It "TLS Settings" { SetActiveDisplayGrouping "Security Settings" TestObjectMatch "TLS 1.0" "Misconfigured" -WriteType "Red" @@ -369,6 +373,7 @@ Describe "Testing Health Checker by Mock Data Imports" { -MockWith { return Import-Clixml "$Script:MockDataCollectionRoot\Hardware\Physical_Win32_Processor1.xml" } Mock Get-ExSetupFileVersionInfo { return Import-Clixml "$Script:MockDataCollectionRoot\Exchange\ExSetup1.xml" } Mock Invoke-ScriptBlockHandler -ParameterFilter { $ScriptBlockDescription -eq "Getting applicationHost.config" } -MockWith { return Get-Content "$Script:MockDataCollectionRoot\Exchange\IIS\applicationHost2.config" -Raw -Encoding UTF8 } + Mock Get-Content -ParameterFilter { $Path -eq "C:\Program Files\Microsoft\Exchange Server\V15\Bin\Monitoring\Config\AntiMalware.xml" } -MockWith { Get-Content "$Script:MockDataCollectionRoot\Exchange\AntiMalware1.xml" -Raw -Encoding UTF8 } SetDefaultRunOfHealthChecker "Debug_Scenario3_Physical_Results.xml" } @@ -408,6 +413,11 @@ Describe "Testing Health Checker by Mock Data Imports" { TestObjectMatch "HighPerformanceSet" $false -WriteType "Red" } + It "UnifiedContent Auto Update" { + SetActiveDisplayGrouping "Frequent Configuration Issues" + TestObjectMatch "UnifiedContent Auto Cleanup Configured" $false -WriteType "Red" + } + It "Extended Protection" { SetActiveDisplayGrouping "Security Vulnerability" TestObjectMatch "Extended Protection Vulnerable" "True" -WriteType "Red" diff --git a/Diagnostics/HealthChecker/Tests/HealthCheckerTest.CommonMocks.NotPublished.ps1 b/Diagnostics/HealthChecker/Tests/HealthCheckerTest.CommonMocks.NotPublished.ps1 index 2c61effa31..2b7bf49d4f 100644 --- a/Diagnostics/HealthChecker/Tests/HealthCheckerTest.CommonMocks.NotPublished.ps1 +++ b/Diagnostics/HealthChecker/Tests/HealthCheckerTest.CommonMocks.NotPublished.ps1 @@ -59,11 +59,13 @@ Mock Test-Path -ParameterFilter { $Path -eq "C:\Program Files\Microsoft\Exchange Mock Test-Path -ParameterFilter { $Path -eq "C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\SharedWebConfig.config" } -MockWith { return $true } Mock Test-Path -ParameterFilter { $Path -eq "C:\Program Files\Microsoft\Exchange Server\V15\Bin\EdgeTransport.exe.config" } -MockWith { return $true } Mock Test-Path -ParameterFilter { $Path -eq "C:\Program Files\Microsoft\Exchange Server\V15\Bin\Search\Ceres\Runtime\1.0\noderunner.exe.config" } -MockWith { return $true } +Mock Test-Path -ParameterFilter { $Path -eq "C:\Program Files\Microsoft\Exchange Server\V15\Bin\Monitoring\Config\AntiMalware.xml" } -MockWith { return $true } Mock Get-Content -ParameterFilter { $Path -eq "C:\Program Files\Microsoft\Exchange Server\V15\FrontEnd\HttpProxy\SharedWebConfig.config" } -MockWith { Get-Content "$Script:MockDataCollectionRoot\Exchange\IIS\DefaultWebSite_SharedWebConfig.config" -Raw -Encoding UTF8 } Mock Get-Content -ParameterFilter { $Path -eq "C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\SharedWebConfig.config" } -MockWith { Get-Content "$Script:MockDataCollectionRoot\Exchange\IIS\ExchangeBackEnd_SharedWebConfig.config" -Raw -Encoding UTF8 } Mock Get-Content -ParameterFilter { $Path -eq "C:\Program Files\Microsoft\Exchange Server\V15\Bin\EdgeTransport.exe.config" } -MockWith { Get-Content "$Script:MockDataCollectionRoot\Exchange\EdgeTransport.exe.config" -Raw -Encoding UTF8 } Mock Get-Content -ParameterFilter { $Path -eq "C:\Program Files\Microsoft\Exchange Server\V15\Bin\Search\Ceres\Runtime\1.0\noderunner.exe.config" } -MockWith { Get-Content "$Script:MockDataCollectionRoot\Exchange\noderunner.exe.config" -Raw -Encoding UTF8 } +Mock Get-Content -ParameterFilter { $Path -eq "C:\Program Files\Microsoft\Exchange Server\V15\Bin\Monitoring\Config\AntiMalware.xml" } -MockWith { Get-Content "$Script:MockDataCollectionRoot\Exchange\AntiMalware.xml" -Raw -Encoding UTF8 } function Get-WebApplication { return Import-Clixml "$Script:MockDataCollectionRoot\Exchange\IIS\GetWebApplication.xml" } diff --git a/docs/Diagnostics/HealthChecker/UnifiedContentCleanup.md b/docs/Diagnostics/HealthChecker/UnifiedContentCleanup.md new file mode 100644 index 0000000000..d6a2b5e8cc --- /dev/null +++ b/docs/Diagnostics/HealthChecker/UnifiedContentCleanup.md @@ -0,0 +1,13 @@ +# UnifiedContent Automatic Cleanup + +Within Exchange Monitoring, we have a probe that will attempt to clear out the old temp data that is generated from EdgeTransport.exe process. However, this probe definition is defined in the `%ExchangeInstallPath%\Bin\Monitoring\Config\AntiMalware.xml` with a hardcoded path options to look. By default, we are only looking at `"D:\ExchangeTemp\TransportCts\UnifiedContent;C:\Windows\Temp\UnifiedContent;C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\data\Temp\UnifiedContent"`. Therefore, if Exchange is not installed in at `C:\Program Files\Microsoft\Exchange Server\V15\` or if the `TemporaryStoragePath` of the `EdgeTransport.exe.config` value is anything other than `C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\data\Temp` the probe will not work as intended to clean up the data files. + +The only way to get the probe to automatically clean up the temp files is to add the correct location to the `%ExchangeInstallPath%\Bin\Monitoring\Config\AntiMalware.xml` file. + +**Included in HTML Report?** + +Yes + +**Additional resources:** + +[Exchange UnifiedContent folder fills up the drive](https://learn.microsoft.com/en-us/exchange/troubleshoot/administration/unifiedcontent-folder-fills-up-drive) diff --git a/mkdocs.yml b/mkdocs.yml index dce6bec2f2..955fc0e0e0 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -70,6 +70,7 @@ nav: - HCScheduledTask: Diagnostics/HealthChecker/RunHCViaSchedTask.md - ADSiteCount: Diagnostics/HealthChecker/ADSiteCount.md - ExchangeComputerMembership: Diagnostics/HealthChecker/ExchangeComputerMembership.md + - UnifiedContentCleanup: Diagnostics/HealthChecker/UnifiedContentCleanup.md - ManagedAvailabilityTroubleshooter: Diagnostics/ManagedAvailabilityTroubleshooter.md - Test-ExchAVExclusions: Diagnostics/Test-ExchAVExclusions.md - Hybrid: