Public/Test-GSAClientProfileConnectivity.ps1
|
# # Function: Test-GSAClientProfileConnectivity # Public function for the GSA client diagnostics toolkit. # function Test-GSAClientProfileConnectivity { <# .SYNOPSIS Tests local forwarding profile retrieval and edge/diagnostic connectivity for one or more GSA channels. .DESCRIPTION Confirms the locally cached ForwardingProfile registry value contains a channel for the requested profile type(s) (m365/private/internet), tests TCP connectivity to each channel's primary edge (falling back to the secondary edge), and confirms each channel's diagnostic endpoint responds with HTTP 200 and body 'pong'. This is a fully local/offline check; it does not call Microsoft Graph. .PARAMETER ProfileType The forwarding profile channel(s) to test: m365, private, and/or internet. Defaults to all three when not specified. .PARAMETER RegistryValueName Registry value name containing the GSA JSON policy (default: ForwardingProfile). .PARAMETER PassThru Return the $true/$false test result (across all tested profiles). By default nothing is returned - only logged. .EXAMPLE Test-GSAClientProfileConnectivity -ProfileType private .EXAMPLE Test-GSAClientProfileConnectivity #> [CmdletBinding()] param ( [ValidateSet("m365", "private", "internet")] [string[]]$ProfileType, [string]$RegistryValueName = "ForwardingProfile", [switch]$PassThru, [ValidateSet("ERROR", "WARNING", "INFO", "DEBUG", "SUCCESS")] [string]$LogLevel ) if ($PSBoundParameters.ContainsKey('LogLevel')) { $script:LogLevel = $LogLevel } # No profile specified - test every channel if (-not $ProfileType -or @($ProfileType).Count -eq 0) { $ProfileType = @('m365', 'private', 'internet') } $profileNames = @{ m365 = "Microsoft Traffic"; private = "Private Access"; internet = "Internet Access" } $allPassed = $true # Iterate through each specified profile type and test its connectivity. foreach ($type in @($ProfileType)) { $profileName = $profileNames[$type] Write-Log "Checking $profileName profile..." "INFO" # Load the GSA client configuration from the registry. $jsonContent = Get-JsonFromRegistry -ValueName $RegistryValueName if (-not $jsonContent) { Write-Log "Failed to load GSA client configuration from the registry." "ERROR" $allPassed = $false continue } # Retrieve the channel configuration for the current profile type. $channel = @($jsonContent.policy.channels) | Where-Object { $_.name -eq $type } | Select-Object -First 1 if (-not $channel) { Write-Log "$profileName forwarding profile channel was not retrieved." "ERROR" Write-Log "Recommended action: Ensure the $profileName forwarding profile is enabled and the user is assigned in Entra portal under Global Secure Access > Connect > Traffic forwarding." "WARNING" $allPassed = $false continue } Write-Log "$profileName forwarding profile configuration has been retrieved." "SUCCESS" $primaryEdge = $channel.edgesSettings.primaryEdges | Select-Object -First 1 $secondaryEdge = $channel.edgesSettings.secondaryEdges | Select-Object -First 1 $diagnosticUri = $channel.diagnosticUri # Check connectivity to the primary and secondary edges of the current profile. Write-Log "Checking connectivity to $profileName edge..." "INFO" $primaryReachable = $primaryEdge -and (Test-NetConnection -ComputerName $primaryEdge.edgeAddress -Port $primaryEdge.edgePort -InformationLevel Quiet -WarningAction SilentlyContinue) if ($primaryReachable) { Write-Log "Connection to the $profileName primary edge ($($primaryEdge.edgeAddress):$($primaryEdge.edgePort)) succeeded." "SUCCESS" } else { Write-Log "Failed to connect to the $profileName primary edge, checking the secondary edge..." "WARNING" $secondaryReachable = $secondaryEdge -and (Test-NetConnection -ComputerName $secondaryEdge.edgeAddress -Port $secondaryEdge.edgePort -InformationLevel Quiet -WarningAction SilentlyContinue) if (-not $secondaryReachable) { Write-Log "Unable to connect to any $profileName edge." "ERROR" Write-Log "Recommended action: Ensure outbound connectivity to the following $profileName edges is allowed: $($primaryEdge.edgeAddress), $($secondaryEdge.edgeAddress)." "WARNING" $allPassed = $false continue } Write-Log "Connection to the $profileName secondary edge ($($secondaryEdge.edgeAddress):$($secondaryEdge.edgePort)) succeeded." "SUCCESS" } Write-Log "Checking connectivity to the $profileName diagnostic endpoint..." "INFO" try { $healthCheck = Invoke-WebRequest -Uri $diagnosticUri -UseBasicParsing } catch { Write-Log "Failed to connect to the $profileName diagnostic endpoint ($diagnosticUri): $($_.Exception.Message)" "ERROR" Write-Log "Recommended action: Ensure outbound traffic to $diagnosticUri is allowed." "WARNING" $allPassed = $false continue } if ($healthCheck.StatusCode -ne 200 -or $healthCheck.Content -ne 'pong') { Write-Log "The $profileName diagnostic endpoint did not respond as expected." "ERROR" Write-Log "Recommended action: Ensure outbound traffic to $diagnosticUri is allowed." "WARNING" $allPassed = $false continue } Write-Log "Connection to the $profileName diagnostic endpoint succeeded." "SUCCESS" } if ($PassThru) { return $allPassed } } |