Troubleshoot-WindowsUpdateAgentRegistration.ps1

<#PSScriptInfo
 
.VERSION 1.1
 
.GUID fa3f8397-9d89-4f06-985c-2dfffcfd5520
 
.AUTHOR Stas Kuvshinov, Swapnil Jain
 
.COMPANYNAME Microsoft Corporation
 
.COPYRIGHT © 2020 Microsoft Corporation. All rights reserved.
 
.TAGS Automation UpdateManagement HybridRunbookWorker Troubleshoot
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
1.1 Added rules: AlwaysAutoRebootCheck, WSUSServerConfigured, AutomaticUpdateCheck
1.0 Original set of troubleshooting checks for Update Management Agent (Automation Hybrid Runbook Worker) on Windows machines
 
.PRIVATEDATA
 
#>


<#
 
.DESCRIPTION
 Troubleshooting utility for Update Management Agent (Automation Hybrid Runbook Worker) on Windows machines
 
#>
 
param(
    [string]$automationAccountLocation,
    [switch]$returnCompactFormat,
    [switch]$returnAsJson
)

$validationResults = @()
[string]$CurrentResult = ""
[string]$CurrentDetails = ""
function New-RuleCheckResult
{
    [CmdletBinding()]
    param(
        [string][Parameter(Mandatory=$true)]$ruleId,
        [string]$ruleName,
        [string]$ruleDescription,
        [string][ValidateSet("Passed","PassedWithWarning", "Failed", "Information")]$result,
        [string]$resultMessage,
        [string]$ruleGroupId = $ruleId,
        [string]$ruleGroupName,
        [string]$resultMessageId = $ruleId,
        [array]$resultMessageArguments = @()
    )

    if ($returnCompactFormat.IsPresent) {
        $compactResult = [pscustomobject] [ordered] @{
            'RuleId'= $ruleId
            'RuleGroupId'= $ruleGroupId
            'CheckResult'= $result
            'CheckResultMessageId'= $resultMessageId
            'CheckResultMessageArguments'= $resultMessageArguments
        }
        return $compactResult
    }

    $fullResult = [pscustomobject] [ordered] @{
        'RuleId'= $ruleId
        'RuleGroupId'= $ruleGroupId
        'RuleName'= $ruleName
        'RuleGroupName' = $ruleGroupName
        'RuleDescription'= $ruleDescription
        'CheckResult'= $result
        'CheckResultMessage'= $resultMessage
        'CheckResultMessageId'= $resultMessageId
        'CheckResultMessageArguments'= $resultMessageArguments
    }
    return $fullResult
}

function checkRegValue
{
    [CmdletBinding()]
    param(
        [string][Parameter(Mandatory=$true)]$path,
        [string][Parameter(Mandatory=$true)]$name,
        [int][Parameter(Mandatory=$true)]$valueToCheck
    )

    $val = Get-ItemProperty -path $path -name $name -ErrorAction SilentlyContinue
    if($val.$name -eq $null) {
        return $null
    }

    if($val.$name -eq $valueToCheck) {
        return $true
    } else {
        return $false
    }
}

function getRegValue {
    [CmdletBinding()]
    param(
        [string][Parameter(Mandatory = $true)]$path,
        [string][Parameter(Mandatory = $true)]$name
    )

    $val = Get-ItemProperty -path $path -name $name -ErrorAction SilentlyContinue
    if ($val.$name -eq $null) {
        return $null
    }
    return $val.$name
}

function Validate-OperatingSystem {
    $osRequirementsLink = "https://docs.microsoft.com/azure/automation/automation-update-management#supported-client-types"

    $ruleId = "OperatingSystemCheck"
    $ruleName = "Operating System"
    $ruleDescription = "The Windows Operating system must be version 6.1.7601 (Windows Server 2008 R2 SP1) or higher"
    $result = $null
    $resultMessage = $null
    $ruleGroupId = "prerequisites"
    $ruleGroupName = "Prerequisite Checks"
    $resultMessageArguments = @()

    if([System.Environment]::OSVersion.Version -ge [System.Version]"6.1.7601") {
        $result = "Passed"
        $resultMessage = "Operating System version is supported"
    } else {
        $result = "Failed"
        $resultMessage = "Operating System version is not supported. Supported versions listed here: $osRequirementsLink"
        $resultMessageArguments += $osRequirementsLink
    }
    $resultMessageId = "$ruleId.$result"

    return New-RuleCheckResult $ruleId $ruleName $ruleDescription $result $resultMessage $ruleGroupId $ruleGroupName $resultMessageId $resultMessageArguments
}

function Validate-NetFrameworkInstalled {
    $netFrameworkDownloadLink = "https://www.microsoft.com/net/download/dotnet-framework-runtime"

    $ruleId = "DotNetFrameworkInstalledCheck"
    $ruleName = ".Net Framework 4.5+"
    $ruleDescription = ".NET Framework version 4.5 or higher is required"
    $result = $null
    $resultMessage = $null
    $ruleGroupId = "prerequisites"
    $ruleGroupName = "Prerequisite Checks"
    $resultMessageArguments = @()

    # https://docs.microsoft.com/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed
    $dotNetFullRegistryPath = "HKLM:SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full"
    if((Get-ChildItem $dotNetFullRegistryPath -ErrorAction SilentlyContinue) -ne $null) {
        $versionCheck = (Get-ChildItem $dotNetFullRegistryPath) | Get-ItemPropertyValue -Name Release | ForEach-Object { $_ -ge 378389 }
        if($versionCheck -eq $true) {
            $result = "Passed"
            $resultMessage = ".NET Framework version 4.5+ is found"
        } else {
            $result = "Failed"
            $resultMessage = ".NET Framework version 4.5 or higher is required: $netFrameworkDownloadLink"
            $resultMessageArguments += $netFrameworkDownloadLink
        }
    } else{
        $result = "Failed"
        $resultMessage = ".NET Framework version 4.5 or higher is required: $netFrameworkDownloadLink"
        $resultMessageArguments += $netFrameworkDownloadLink
    }
    $resultMessageId = "$ruleId.$result"

    return New-RuleCheckResult $ruleId $ruleName $ruleDescription $result $resultMessage $ruleGroupId $ruleGroupName $resultMessageId $resultMessageArguments
}

function Validate-WmfInstalled {
    $wmfDownloadLink = "https://www.microsoft.com/download/details.aspx?id=54616"
    $ruleId = "WindowsManagementFrameworkInstalledCheck"
    $ruleName = "WMF 5.1"
    $ruleDescription = "Windows Management Framework version 4.0 or higher is required (version 5.1 or higher is preferable)"
    $result = $null
    $resultMessage = $null
    $ruleGroupId = "prerequisites"
    $ruleGroupName = "Prerequisite Checks"

    $psVersion = $PSVersionTable.PSVersion
    $resultMessageArguments = @() + $psVersion

    if($psVersion -ge 5.1) {
        $result = "Passed"
        $resultMessage = "Detected Windows Management Framework version: $psVersion"
    } elseif($psVersion.Major -ge 4) {
        $result = "PassedWithWarning"
        $resultMessage = "Detected Windows Management Framework version: $psVersion. Consider upgrading to version 5.1 or higher for increased reliability: $wmfDownloadLink"
        $resultMessageArguments += $wmfDownloadLink
    } else {
        $result = "Failed"
        $resultMessage = "Detected Windows Management Framework version: $psVersion. Version 4.0 or higher is required (version 5.1 or higher is preferable): $wmfDownloadLink"
        $resultMessageArguments += $wmfDownloadLink
    }
    $resultMessageId = "$ruleId.$result"

    return New-RuleCheckResult $ruleId $ruleName $ruleDescription $result $resultMessage $ruleGroupId $ruleGroupName $resultMessageId $resultMessageArguments
}

function Validate-TlsEnabled {
    $ruleId = "TlsVersionCheck"
    $ruleName = "TLS 1.2"
    $ruleDescription = "Client and Server connections must support TLS 1.2"
    $result = $null
    $reason = ""
    $resultMessage = $null
    $ruleGroupId = "prerequisites"
    $ruleGroupName = "Prerequisite Checks"

    $tls12RegistryPath = "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.2\\"
    $serverEnabled =     checkRegValue ([System.String]::Concat($tls12RegistryPath, "Server")) "Enabled" 1
    $ServerNotDisabled = checkRegValue ([System.String]::Concat($tls12RegistryPath, "Server")) "DisabledByDefault" 0
    $clientEnabled =     checkRegValue ([System.String]::Concat($tls12RegistryPath, "Client")) "Enabled" 1
    $ClientNotDisabled = checkRegValue ([System.String]::Concat($tls12RegistryPath, "Client")) "DisabledByDefault" 0

    $ServerNotEnabled = checkRegValue ([System.String]::Concat($tls12RegistryPath, "Server")) "Enabled" 0
    $ServerDisabled =   checkRegValue ([System.String]::Concat($tls12RegistryPath, "Server")) "DisabledByDefault" 1
    $ClientNotEnabled = checkRegValue ([System.String]::Concat($tls12RegistryPath, "Client")) "Enabled" 0
    $ClientDisabled =   checkRegValue ([System.String]::Concat($tls12RegistryPath, "Client")) "DisabledByDefault" 1

    if ($validationResults[0].CheckResult -ne "Passed" -and [System.Environment]::OSVersion.Version -ge [System.Version]"6.0.6001") {
        $result = "Failed"
        $resultMessageId = "$ruleId.$result"
        $resultMessage = "TLS 1.2 is not enabled by default on the Operating System. Follow the instructions to enable it: https://support.microsoft.com/help/4019276/update-to-add-support-for-tls-1-1-and-tls-1-2-in-windows"
    } elseif([System.Environment]::OSVersion.Version -ge [System.Version]"6.1.7601" -and [System.Environment]::OSVersion.Version -le [System.Version]"6.1.8400") {
        if($ClientNotDisabled -and $ServerNotDisabled -and !($ServerNotEnabled -and $ClientNotEnabled)) {
            $result = "Passed"
            $resultMessage = "TLS 1.2 is enabled on the Operating System."
            $resultMessageId = "$ruleId.$result"
        } else {
            $result = "Failed"
            $reason = "NotExplicitlyEnabled"
            $resultMessageId = "$ruleId.$result.$reason"
            $resultMessage = "TLS 1.2 is not enabled by default on the Operating System. Follow the instructions to enable it: https://docs.microsoft.com/windows-server/security/tls/tls-registry-settings#tls-12"
        }
    } elseif([System.Environment]::OSVersion.Version -ge [System.Version]"6.2.9200") {
        if($ClientDisabled -or $ServerDisabled -or $ServerNotEnabled -or $ClientNotEnabled) {
            $result = "Failed"
            $reason = "ExplicitlyDisabled"
            $resultMessageId = "$ruleId.$result.$reason"
            $resultMessage = "TLS 1.2 is supported by the Operating System, but currently disabled. Follow the instructions to re-enable: https://docs.microsoft.com/windows-server/security/tls/tls-registry-settings#tls-12"
        } else {
            $result = "Passed"
            $reason = "EnabledByDefault"
            $resultMessageId = "$ruleId.$result.$reason"
            $resultMessage = "TLS 1.2 is enabled by default on the Operating System."
        }
    } else {
        $result = "Failed"
        $reason = "NoDefaultSupport"
        $resultMessageId = "$ruleId.$result.$reason"
        $resultMessage = "Your OS does not support TLS 1.2 by default."
    }

    return New-RuleCheckResult $ruleId $ruleName $ruleDescription $result $resultMessage $ruleGroupId $ruleGroupName $resultMessageId
}

function Validate-EndpointConnectivity {
    [CmdletBinding()]
    param(
        [string][Parameter(Mandatory=$true)]$endpoint,
        [string][Parameter(Mandatory=$true)]$ruleId,
        [string][Parameter(Mandatory=$true)]$ruleName,
        [string]$ruleDescription = "Proxy and firewall configuration must allow Automation Hybrid Worker agent to communicate with $endpoint"
    )

    $result = $null
    $resultMessage = $null
    $ruleGroupId = "connectivity"
    $ruleGroupName = "connectivity"
    $resultMessageArguments = @() + $endpoint

    if((Test-NetConnection -ComputerName $endpoint -Port 443 -WarningAction SilentlyContinue).TcpTestSucceeded) {
        $result = "Passed"
        $resultMessage = "TCP Test for $endpoint (port 443) succeeded"
    } else {
        $result = "Failed"
        $resultMessage = "TCP Test for $endpoint (port 443) failed"
    }

    $resultMessageId = "$ruleId.$result"

    return New-RuleCheckResult $ruleId $ruleName $ruleDescription $result $resultMessage $ruleGroupId $ruleGroupName $resultMessageId $resultMessageArguments
}

function Validate-RegistrationEndpointsConnectivity {
    $validationResults = @()

    $managementGroupRegistrations = Get-ChildItem 'HKLM:\\SYSTEM\\CurrentControlSet\\Services\\HealthService\\Parameters\\Management Groups' -ErrorAction SilentlyContinue | select -ExpandProperty PSChildName
    $managementGroupRegistrations | foreach {$i=1} {
        $prefix = "AOI-"
        if ($_ -match "$prefix*") {
            $workspaceId = $_.Substring($prefix.Length)
            if($automationAccountLocation -eq "usgovvirginia" -or $automationAccountLocation -eq "usgovarizona"){
                $endpoint = "$workspaceId.agentsvc.azure-automation.us"
            } elseif($automationAccountLocation -eq "chinaeast2") {
                $endpoint = "$workspaceId.agentsvc.azure-automation.cn"
            } else {
                $endpoint = "$workspaceId.agentsvc.azure-automation.net"
            }
            $ruleId = "AutomationAgentServiceConnectivityCheck$i"
            $ruleName = "Registration endpoint"

            $validationResults += Validate-EndpointConnectivity $endpoint $ruleId $ruleName

            $i++
        }
    }

    if($validationResults.Count -eq 0) {
        $ruleId = "AutomationAgentServiceConnectivityCheck1"
        $ruleName = "Registration endpoint"

        $result = "Failed"
        $reason = "NoRegistrationFound"
        $resultMessage = "Unable to find Workspace registration information in registry"

        $ruleGroupId = "connectivity"
        $ruleGroupName = "connectivity"
        $resultMessageId = "$ruleId.$result.$reason"

        $validationResults += New-RuleCheckResult $ruleId $ruleName $ruleDescription $result $resultMessage $ruleGroupId $ruleGroupName $resultMessageId
    }

    return $validationResults
}

function Validate-OperationsEndpointConnectivity {
    # https://docs.microsoft.com/azure/automation/automation-hybrid-runbook-worker#hybrid-worker-role
    if($automationAccountLocation -eq "usgovvirginia"){
        $endpoint = "usge-jobruntimedata-prod-su1.azure-automation.us"
    } elseif($automationAccountLocation -eq "usgovarizona") {
        $endpoint = "phx-jobruntimedata-prod-su1.azure-automation.us"    
    } elseif($automationAccountLocation -eq "chinaeast2") {
        $endpoint = "sha2-jobruntimedata-prod-su1.azure-automation.cn"
    } else {
        $jrdsEndpointLocationMoniker = switch ( $automationAccountLocation ) {
            "australiasoutheast"{ "ase"  }
            "canadacentral"     { "cc"   }
            "centralindia"      { "cid"  }
            "eastus2"           { "eus2" }
            "japaneast"         { "jpe"  }
            "northeurope"       { "ne"   }
            "southcentralus"    { "scus" }
            "southeastasia"     { "sea"  }
            "uksouth"           { "uks"  }
            "westcentralus"     { "wcus" }
            "westeurope"        { "we"   }
            "westus2"           { "wus2" }

            default             { "eus2" }
        }
        $endpoint = "$jrdsEndpointLocationMoniker-jobruntimedata-prod-su1.azure-automation.net"
    }
    $ruleId = "AutomationJobRuntimeDataServiceConnectivityCheck"
    $ruleName = "Operations endpoint"

    return Validate-EndpointConnectivity $endpoint $ruleId $ruleName
}

function Validate-MmaIsRunning {
    $mmaServiceName = "HealthService"
    $mmaServiceDisplayName = "Microsoft Monitoring Agent"

    $ruleId = "MonitoringAgentServiceRunningCheck"
    $ruleName = "Monitoring Agent service status"
    $ruleDescription = "$mmaServiceName must be running on the machine"
    $result = $null
    $resultMessage = $null
    $ruleGroupId = "servicehealth"
    $ruleGroupName = "VM Service Health Checks"
    $resultMessageArguments = @() + $mmaServiceDisplayName + $mmaServiceName

    if(Get-Service -Name $mmaServiceName -ErrorAction SilentlyContinue| Where-Object {$_.Status -eq "Running"} | Select-Object) {
        $result = "Passed"
        $resultMessage = "$mmaServiceDisplayName service ($mmaServiceName) is running"
    } else {
        $result = "Failed"
        $resultMessage = "$mmaServiceDisplayName service ($mmaServiceName) is not running"
    }
    $resultMessageId = "$ruleId.$result"

    return New-RuleCheckResult $ruleId $ruleName $ruleDescription $result $resultMessage $ruleGroupId $ruleGroupName $resultMessageId $resultMessageArguments
}

function Validate-MmaEventLogHasNoErrors {
    $mmaServiceName = "Microsoft Monitoring Agent"
    $logName = "Operations Manager"
    $eventId = 4502

    $ruleId = "MonitoringAgentServiceEventsCheck"
    $ruleName = "Monitoring Agent service events"
    $ruleDescription = "Event Log must not have event 4502 logged in the past 24 hours"
    $result = $null
    $reason = ""
    $resultMessage = $null
    $ruleGroupId = "servicehealth"
    $ruleGroupName = "VM Service Health Checks"
    $resultMessageArguments = @() + $mmaServiceName + $logName + $eventId

    $OpsMgrLogExists = [System.Diagnostics.EventLog]::Exists($logName);
    if($OpsMgrLogExists) {
        $event = Get-EventLog -LogName "Operations Manager" -Source "Health Service Modules" -After (Get-Date).AddHours(-24) | where {$_.eventID -eq $eventId}
        if($event -eq $null) {
            $result = "Passed"
            $resultMessageId = "$ruleId.$result"
            $resultMessage = "$mmaServiceName service Event Log ($logName) does not have event $eventId logged in the last 24 hours."
        } else {
            $result = "Failed"
            $reason = "EventFound"
            $resultMessageId = "$ruleId.$result.$reason"
            $resultMessage = "$mmaServiceName service Event Log ($logName) has event $eventId logged in the last 24 hours. Look at the results of other checks to troubleshoot the reasons."
        }
    } else {
        $result = "Failed"
        $reason = "NoLog"
        $resultMessageId = "$ruleId.$result.$reason"
        $resultMessage = "$mmaServiceName service Event Log ($logName) does not exist on the machine"
    }

    return New-RuleCheckResult $ruleId $ruleName $ruleDescription $result $resultMessage $ruleGroupId $ruleGroupName $resultMessageId $resultMessageArguments
}

function Validate-MachineKeysFolderAccess {
    $folder = "C:\\ProgramData\\Microsoft\\Crypto\\RSA\\MachineKeys"

    $ruleId = "CryptoRsaMachineKeysFolderAccessCheck"
    $ruleName = "Crypto RSA MachineKeys Folder Access"
    $ruleDescription = "SYSTEM account must have WRITE and MODIFY access to '$folder'"
    $result = $null
    $resultMessage = $null
    $ruleGroupId = "permissions"
    $ruleGroupName = "Access Permission Checks"
    $resultMessageArguments = @() + $folder

    $User = $env:UserName
    $permission = (Get-Acl $folder).Access | ? {($_.IdentityReference -match $User) -or ($_.IdentityReference -match "Everyone")} | Select IdentityReference, FileSystemRights
    if ($permission) {
        $result = "Passed"
        $resultMessage = "Have permissions to access $folder"
    } else {
        $result = "Failed"
        $resultMessage = "Missing permissions to access $folder"
    }
    $resultMessageId = "$ruleId.$result"

    return New-RuleCheckResult $ruleId $ruleName $ruleDescription $result $resultMessage $ruleGroupId $ruleGroupName $resultMessageId $resultMessageArguments
}

function Validate-AlwaysAutoRebootEnabled {
    $ruleId = "AlwaysAutoRebootCheck"
    $ruleName = "AutoReboot"
    $ruleDescription = "Automatic reboot should not be enable as it forces a reboot irrespective of update configuration"
    $result = $null
    $reason = ""
    $resultMessage = $null
    $ruleGroupId = "machineSettings"
    $ruleGroupName = "Machine Override Checks"

    $automaticUpdatePath = "HKLM:\\Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU"
    $rebootEnabledBySchedule = checkRegValue ($automaticUpdatePath) "AlwaysAutoRebootAtScheduledTime" 1
    $rebootEnabledByDuration = getRegValue ($automaticUpdatePath) "AlwaysAutoRebootAtScheduledTimeMinutes"


    if (  $rebootEnabledBySchedule -or $rebootEnabledByDuration ) {
        $result = "PassedWithWarning"
        $reason = "Auto Reboot is enabled on the system and will interfere with Update Management Configuration passed during runs"
        $resultMessage = "Windows Update reboot registry keys are set. This can cause unexpected reboots when installing updates"
    }
    else {
        $result = "Passed"
        $resultMessage = "Windows Update reboot registry keys are not set to automatically reboot"

    }
    $resultMessageId = "$ruleId.$result"
    return New-RuleCheckResult $ruleId $ruleName $ruleDescription $result $resultMessage $ruleGroupId $ruleGroupName $resultMessageId $resultMessageArguments
}

function Validate-AutomaticUpdateEnabled {
    $ruleId = "AutomaticUpdateCheck"
    $ruleName = "AutoUpdate"
    $ruleDescription = "AutoUpdate should not be enabled on the machine"
    $result = $null
    $reason = ""
    $resultMessage = $null
    $ruleGroupId = "machineSettings"
    $ruleGroupName = "Machine Override Checks"

    $automaticUpdatePath = "HKLM:\\Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU"
    $autoUpdateEnabled = checkRegValue ($automaticUpdatePath) "AUOptions" 4


    if ( $autoUpdateEnabled ) {
        $result = "PassedWithWarning"
        $reason = "Auto Update is enabled on the machine and will interfere with Update management Solution"
        $resultMessage = "Windows Update will automatically download and install new updates as they become available"
    }
    else {
        $result = "Passed"
        $resultMessage = "Windows Update is not set to automatically install updates as they become available"

    }
    $resultMessageId = "$ruleId.$result"
    return New-RuleCheckResult $ruleId $ruleName $ruleDescription $result $resultMessage $ruleGroupId $ruleGroupName $resultMessageId $resultMessageArguments
}

function Validate-WSUSServerConfigured {
    $ruleId = "WSUSServerConfigured"
    $ruleName = "isWSUSServerConfigured"
    $ruleDescription = "Increase awareness on WSUS configured on the server"
    $result = $null
    $reason = ""
    $resultMessage = $null
    $ruleGroupId = "machineSettings"
    $ruleGroupName = "Machine Override Checks"

    $automaticUpdatePath = "HKLM:\\Software\\Policies\\Microsoft\\Windows\\WindowsUpdate"
    $wsusServerConfigured = getRegValue ($automaticUpdatePath) "WUServer"

    if ( $null -ne $wsusServerConfigured ) {
        $result = "PassedWithWarning"
        $reason = "WSUS Server is configured on the server"
        $resultMessage = "Windows Updates are downloading from a configured WSUS Server $wsusServerConfigured. Ensure the WSUS server is accessible and updates are being approved for installation"
        $resultMessageArguments = @() + $wsusServerConfigured
    }
    else {
        $result = "Passed"
        $resultMessage = "Windows Updates are downloading from the default Windows Update location. Ensure the server has access to the Windows Update service"
    }
    $resultMessageId = "$ruleId.$result"
    return New-RuleCheckResult $ruleId $ruleName $ruleDescription $result $resultMessage $ruleGroupId $ruleGroupName $resultMessageId $resultMessageArguments
}

$validationResults += Validate-OperatingSystem
$validationResults += Validate-NetFrameworkInstalled
$validationResults += Validate-WmfInstalled
Validate-RegistrationEndpointsConnectivity | % { $validationResults += $_ }
$validationResults += Validate-OperationsEndpointConnectivity
$validationResults += Validate-MmaIsRunning
$validationResults += Validate-MmaEventLogHasNoErrors
$validationResults += Validate-MachineKeysFolderAccess
$validationResults += Validate-TlsEnabled
$validationResults += Validate-AlwaysAutoRebootEnabled
$validationResults += Validate-WSUSServerConfigured
$validationResults += Validate-AutomaticUpdateEnabled

if($returnAsJson.IsPresent) {
    return ConvertTo-Json $validationResults -Compress
} else {
    return $validationResults
}