Skip to content

Commit

Permalink
Merge branch 'RBA_Script_Add_RBA_Log_Summary' of https://github.com/S…
Browse files Browse the repository at this point in the history
…hanefe/CSS-Exchange into RBA_Script_Add_RBA_Log_Summary
  • Loading branch information
Shanefe committed Sep 6, 2023
2 parents f6488bb + 7868adf commit 8c54fec
Show file tree
Hide file tree
Showing 53 changed files with 33,198 additions and 200 deletions.
2 changes: 2 additions & 0 deletions .build/cspell-words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ hsts
httperr
ietf
imap
inetsrv
Infoworker
Inproc
INSUFF
Expand Down Expand Up @@ -90,6 +91,7 @@ msdcs
MSDTC
MSERT
msert
msipc
msrc
Multiplexor
nato
Expand Down
7 changes: 7 additions & 0 deletions .build/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
".vscode",
"/cspell-words.txt"
],
"patterns": [
{
"name": "return-newline-tab-tab",
"pattern": "\\`r\\`n\\`t\\`t"
}
],
"ignoreRegExpList": ["return-newline-tab-tab"],
"caseSensitive": true,
"overrides": [
{
Expand Down
78 changes: 64 additions & 14 deletions Diagnostics/AVTester/Test-ExchAVExclusions.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ AV Modules loaded into Exchange Processes may indicate that AV Process Exclusion
Will test not just the root folders but all SubFolders.
Generally should not be needed unless all folders pass without -Recuse but AV is still suspected.
.PARAMETER SkipVersionCheck
Skip script version verification.
.PARAMETER ScriptUpdateOnly
Just update script version to latest one.
.OUTPUTS
Log file:
$env:LOCALAPPDATA\ExchAvExclusions.log
Expand All @@ -55,24 +61,48 @@ Puts and removes an EICAR file in all test paths.
Puts and Remove an EICAR file in all test paths + all SubFolders.
#>
[CmdletBinding()]
[CmdletBinding(DefaultParameterSetName = 'Test')]
param (

[Parameter()]
[switch]
$Recurse,
[Parameter(ParameterSetName = "Test")]
[switch]$Recurse,

[Parameter(ParameterSetName = "Test")]
[switch]$OpenLog,

[Parameter()]
[switch]
$OpenLog
[Parameter(ParameterSetName = "Test")]
[switch]$SkipVersionCheck,

[Parameter(Mandatory = $true, ParameterSetName = "ScriptUpdateOnly")]
[switch]$ScriptUpdateOnly
)

. $PSScriptRoot\..\..\Shared\Confirm-Administrator.ps1
. $PSScriptRoot\..\..\Shared\Confirm-ExchangeShell.ps1
. $PSScriptRoot\..\..\Shared\Get-ExchAVExclusions.ps1
. $PSScriptRoot\..\..\Shared\ScriptUpdateFunctions\Test-ScriptVersion.ps1
. $PSScriptRoot\Write-SimpleLogFile.ps1
. $PSScriptRoot\Start-SleepWithProgress.ps1

$BuildVersion = ""

Write-Host ("Test-ExchAVExclusions.ps1 script version $($BuildVersion)") -ForegroundColor Green

if ($ScriptUpdateOnly) {
switch (Test-ScriptVersion -AutoUpdate -VersionsUrl "https://aka.ms/Test-ExchAVExclusions-VersionsURL" -Confirm:$false) {
($true) { Write-Host ("Script was successfully updated") -ForegroundColor Green }
($false) { Write-Host ("No update of the script performed") -ForegroundColor Yellow }
default { Write-Host ("Unable to perform ScriptUpdateOnly operation") -ForegroundColor Red }
}
return
}

if ((-not($SkipVersionCheck)) -and
(Test-ScriptVersion -AutoUpdate -VersionsUrl "https://aka.ms/Test-ExchAVExclusions-VersionsURL" -Confirm:$false)) {
Write-Host ("Script was updated. Please re-run the command") -ForegroundColor Yellow
return
}

# Log file name
$LogFile = "ExchAvExclusions.log"

Expand Down Expand Up @@ -115,6 +145,11 @@ if (-not($exchangeShell.ShellLoaded)) {
exit
}

Write-SimpleLogFile -String ("###########################################################################################") -name $LogFile
Write-SimpleLogFile -String ("Starting AV Exclusions analysis at $((Get-Date).ToString())") -name $LogFile
Write-SimpleLogFile -String ("###########################################################################################") -name $LogFile
Write-SimpleLogFile -String ("You can find a detailed log on: $($Env:LocalAppData)\$LogFile") -name $LogFile -OutHost

# Create the Array List
$BaseFolders = Get-ExchAVExclusionsPaths -ExchangePath $ExchangePath -MsiProductMinor ([byte]$serverExchangeInstallDirectory.MsiProductMinor)

Expand All @@ -126,13 +161,25 @@ if ( $BaseFolders.count -eq 0 ) {
# Create list object to hold all Folders we are going to test
$FolderList = New-Object Collections.Generic.List[string]

# Make sure each folders in our list resolve
$randomCharForWildCard = (Get-Random -Maximum 16).ToString('x')
$nonExistentFolder = New-Object Collections.Generic.List[string]

foreach ($path in $BaseFolders) {
try {
if ($path -match '\?') {
$path = $path -replace '\?', $randomCharForWildCard
$FolderList.Add($path.ToLower())
$nonExistentFolder.Add($path.ToLower())
New-Item -Path (Split-Path $path) -Name $path.split('\')[-1] -ItemType Directory -Force | Out-Null
Write-SimpleLogFile -string ("Created folder: " + $path) -Name $LogFile
}
# Resolve path only returns a bool so we have to manually throw to catch
if (!(Resolve-Path -Path $path -ErrorAction SilentlyContinue)) {
throw "Failed to resolve"
$nonExistentFolder.Add($path.ToLower())
New-Item -Path (Split-Path $path) -Name $path.split('\')[-1] -ItemType Directory -Force | Out-Null
Write-SimpleLogFile -string ("Created folder: " + $path) -Name $LogFile
}

# If -recurse then we need to find all SubFolders and Add them to the list to be tested
if ($Recurse) {

Expand All @@ -143,7 +190,7 @@ foreach ($path in $BaseFolders) {
Get-ChildItem $path -Recurse -Directory -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName | ForEach-Object { $FolderList.Add($_.ToLower()) }
}
# Just Add the root folder
else { $FolderList.Add($path.ToLower()) }
$FolderList.Add($path.ToLower())
} catch { Write-SimpleLogFile -string ("[ERROR] - Failed to resolve folder " + $path) -Name $LogFile }
}

Expand Down Expand Up @@ -177,9 +224,7 @@ foreach ($Folder in $FolderList) {
catch {
Write-Warning "$Folder $eicarFullFileName file couldn't be created. Either permissions or AV prevented file creation."
}
}

else {
} else {
Write-SimpleLogFile -string ("[WARNING] - $eicarFullFileName already exists!: " + $FilePath) -name $LogFile -OutHost
}
}
Expand All @@ -188,7 +233,7 @@ foreach ($Folder in $FolderList) {
$randomString = -join ((65..90) + (97..122) | Get-Random -Count 10 | ForEach-Object { [char]$_ })
$randomFolder = New-Item -Path (Join-Path (Join-Path $env:SystemDrive '\') "TestExchAVExclusions-$randomString") -ItemType Directory
$extensionsList = New-Object Collections.Generic.List[string]
$extensionsList = Get-ExchAVExclusionsExtensions -ExchangePath $ExchangePath -MsiProductMinor ([byte]$serverExchangeInstallDirectory.MsiProductMinor)
$extensionsList = Get-ExchAVExclusionsExtensions -MsiProductMinor ([byte]$serverExchangeInstallDirectory.MsiProductMinor)

if ($randomFolder) {
foreach ($extension in $extensionsList) {
Expand Down Expand Up @@ -270,6 +315,11 @@ foreach ($Folder in $FolderList) {
Write-SimpleLogFile -String ("[FAIL] - Possible AV Scanning on Path: " + $Folder) -name $LogFile -OutHost
$BadFolderList.Add($Folder)
}

if ($nonExistentFolder -contains $Folder) {
Remove-Item $Folder -Confirm:$false -Force -Recurse
Write-SimpleLogFile -string ("Removed folder: " + $Folder) -Name $LogFile
}
}

$BadExtensionList = New-Object Collections.Generic.List[string]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,41 @@ function Invoke-AnalyzerExchangeInformation {

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

foreach ($kb in $exchangeInformation.BuildInformation.KBsInstalled) {
$params = $baseParams + @{
Details = $kb
DisplayCustomTabNumber = 2
}
Add-AnalyzedResultInformation @params

if ($kb.Contains($problemKbName)) {
$problemKbFound = $true
}
}

if ($problemKbFound) {
Write-Verbose "Found problem $problemKbName"
if ($null -ne $HealthServerObject.OSInformation.BuildInformation.OperatingSystem.OSLanguage) {
[int]$OSLanguageID = [int]($HealthServerObject.OSInformation.BuildInformation.OperatingSystem.OSLanguage)
# https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-operatingsystem
$englishLanguageIDs = @(9, 1033, 2057, 3081, 4105, 5129, 6153, 7177, 8201, 10249, 11273)
if ($englishLanguageIDs.Contains($OSLanguageID)) {
Write-Verbose "OS is english language. No action required"
} else {
Write-Verbose "Non english language code: $OSLanguageID"
$params = $baseParams + @{
Details = "Error: August 2023 SU 1 Problem Detected. More Information: https://aka.ms/HC-Aug23SUIssue"
DisplayWriteType = "Red"
DisplayCustomTabNumber = 2
}
Add-AnalyzedResultInformation @params
}
} else {
Write-Verbose "Language Code is null"
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ function Invoke-AnalyzerFrequentConfigurationIssues {
}
}
}
$iisWebSitesWithHstsSettings = $iisWebSettings | Where-Object { $null -ne $_.hsts }

if ($null -ne $missingWebApplicationConfigFile) {
$params = $baseParams + @{
Expand Down Expand Up @@ -372,6 +373,124 @@ function Invoke-AnalyzerFrequentConfigurationIssues {
}
Add-AnalyzedResultInformation @params
}

# TODO: Move this check to the new IIS section that we'll add to HC in near future - See issue: 1363
if (($iisWebSitesWithHstsSettings.Hsts.NativeHstsSettings.enabled -notcontains $true) -and
($iisWebSitesWithHstsSettings.Hsts.HstsViaCustomHeader.enabled -notcontains $true)) {
$params = $baseParams + @{
Name = "HSTS Enabled"
Details = $false
}
Add-AnalyzedResultInformation @params
} else {
$showAdditionalHstsInformation = $false
foreach ($webSite in $iisWebSitesWithHstsSettings) {
$hstsConfiguration = $null
$isExchangeBackEnd = $webSite.Name -eq "Exchange Back End"
$hstsMaxAgeWriteType = "Green"

if (($webSite.Hsts.NativeHstsSettings.enabled) -or
($webSite.Hsts.HstsViaCustomHeader.enabled)) {
$params = $baseParams + @{
Name = "HSTS Enabled"
Details = "$($webSite.Name)"
TestingName = "hsts-Enabled-$($webSite.Name)"
DisplayTestingValue = $true
DisplayWriteType = if ($isExchangeBackEnd) { "Red" } else { "Green" }
}
Add-AnalyzedResultInformation @params

if ($isExchangeBackEnd) {
$showAdditionalHstsInformation = $true
$params = $baseParams + @{
Details = "HSTS on 'Exchange Back End' is not supported and can cause issues"
DisplayWriteType = "Red"
TestingName = "hsts-BackendNotSupported"
DisplayTestingValue = $true
DisplayCustomTabNumber = 2
}
Add-AnalyzedResultInformation @params
}

if (($webSite.Hsts.NativeHstsSettings.enabled) -and
($webSite.Hsts.HstsViaCustomHeader.enabled)) {
$showAdditionalHstsInformation = $true
Write-Verbose "HSTS conflict detected"
$params = $baseParams + @{
Details = ("HSTS configured via customHeader and native IIS control - please remove one configuration" +
"`r`n`t`tHSTS native IIS control has a higher weight than the customHeader and will be used")
DisplayWriteType = "Yellow"
TestingName = "hsts-conflict"
DisplayTestingValue = $true
DisplayCustomTabNumber = 2
}
Add-AnalyzedResultInformation @params
}

if ($webSite.Hsts.NativeHstsSettings.enabled) {
Write-Verbose "HSTS configured via native IIS control"
$hstsConfiguration = $webSite.Hsts.NativeHstsSettings
} else {
Write-Verbose "HSTS configured via customHeader"
$hstsConfiguration = $webSite.Hsts.HstsViaCustomHeader
}

$maxAgeValue = $hstsConfiguration.'max-age'
if ($maxAgeValue -lt 31536000) {
$showAdditionalHstsInformation = $true
$hstsMaxAgeWriteType = "Yellow"
}
$params = $baseParams + @{
Details = "max-age: $maxAgeValue"
DisplayWriteType = $hstsMaxAgeWriteType
TestingName = "hsts-max-age-$($webSite.Name)"
DisplayTestingValue = $maxAgeValue
DisplayCustomTabNumber = 2
}
Add-AnalyzedResultInformation @params

$params = $baseParams + @{
Details = "includeSubDomains: $($hstsConfiguration.includeSubDomains)"
TestingName = "hsts-includeSubDomains-$($webSite.Name)"
DisplayTestingValue = $hstsConfiguration.includeSubDomains
DisplayCustomTabNumber = 2
}
Add-AnalyzedResultInformation @params

$params = $baseParams + @{
Details = "preload: $($hstsConfiguration.preload)"
TestingName = "hsts-preload-$($webSite.Name)"
DisplayTestingValue = $hstsConfiguration.preload
DisplayCustomTabNumber = 2
}
Add-AnalyzedResultInformation @params

$redirectHttpToHttpsConfigured = $hstsConfiguration.redirectHttpToHttps
$params = $baseParams + @{
Details = "redirectHttpToHttps: $redirectHttpToHttpsConfigured"
TestingName = "hsts-redirectHttpToHttps-$($webSite.Name)"
DisplayTestingValue = $redirectHttpToHttpsConfigured
DisplayCustomTabNumber = 2
}
if ($redirectHttpToHttpsConfigured) {
$showAdditionalHstsInformation = $true
$params.Add("DisplayWriteType", "Red")
}
Add-AnalyzedResultInformation @params
}
}

if ($showAdditionalHstsInformation) {
$params = $baseParams + @{
Details = "`r`n`t`tMore Information about HSTS: https://aka.ms/HC-HSTS"
DisplayWriteType = "Yellow"
TestingName = 'hsts-MoreInfo'
DisplayTestingValue = $true
DisplayCustomTabNumber = 2
}
Add-AnalyzedResultInformation @params
}
}
} elseif ($null -ne $exchangeInformation.IISSettings.ApplicationHostConfig) {
Write-Verbose "Wasn't able find any other IIS settings, likely due to application host config file being messed up."
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ function Invoke-AnalyzerNicSettings {
Add-AnalyzedResultInformation -Name "IPv4 Address" @baseParams

foreach ($address in $adapter.IPv4Addresses) {
$displayValue = "{0}\{1}" -f $address.Address, $address.Subnet
$displayValue = "{0}/{1}" -f $address.Address, $address.Subnet

if ($address.DefaultGateway -ne [string]::Empty) {
$displayValue += " Gateway: {0}" -f $address.DefaultGateway
Expand Down
Loading

0 comments on commit 8c54fec

Please sign in to comment.