GSAClientDiagnosticsToolkit.psd1

#
# Module manifest for module 'GSAClientDiagnosticsToolkit'
#
# Generated by: Michael Morten Sonne
#
# Generated on: 11/11/2026
#

@{

# Script module or binary module file associated with this manifest.
RootModule = 'GSAClientDiagnosticsToolkit.psm1'

# Version number of this module.
ModuleVersion = '1.0.0'

# Supported PSEditions
CompatiblePSEditions = 'Desktop'

# ID used to uniquely identify this module
GUID = 'a3f7c2b1-4d89-4e6a-b012-5f8c9d3e7a21'

# Author of this module
Author = 'Michael Morten Sonne'

# Company or vendor of this module
CompanyName = 'blog.sonnes.cloud'

# Copyright statement for this module
Copyright = '(c) Michael Morten Sonne. All rights reserved.'

# Description of the functionality provided by this module
Description = 'Troubleshooting and diagnostics toolkit for the Microsoft Entra Global Secure Access (GSA) Windows client (Entra Internet Access, Entra Private Access, Microsoft 365 traffic). Checks client services, forwarding profile, DNS, TLS/mTLS connectivity, proxy, IPv6, Entra device/PRT status, authentication certificate, Intelligent Local Access and Private Access applications (via Microsoft Graph).'

# Minimum version of the PowerShell engine required by this module
PowerShellVersion = '5.1'

# Name of the PowerShell host required by this module
# PowerShellHostName = ''

# Minimum version of the PowerShell host required by this module
# PowerShellHostVersion = ''

# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# DotNetFrameworkVersion = ''

# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# ClrVersion = ''

# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''

# Modules that must be imported into the global environment prior to importing this module
# RequiredModules = @()

# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = @()

# Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = @()

# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = @()

# Format files (.ps1xml) to be loaded when importing this module
FormatsToProcess = 'GSAClientDiagnosticsToolkit.format.ps1xml'

# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
# NestedModules = @()

# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = 'Invoke-GSAClientConnectivityCheck', 'Get-GSAEndpoints', 
               'Get-GSAAppProtectionExclusionServicePrincipals', 
               'Export-GSAEdgeAddresses', 'Test-GSAServiceStatus', 
               'Test-DeviceEntraStatus', 'Test-GSAPrimaryRefreshToken', 
               'Test-GSAForwardingProfileRegistry', 
               'Test-GSAForwardingProfileTimestamp', 'Test-GSASecureDnsStatus', 
               'Test-GSAIPv6Status', 'Test-GSASyntheticRoutes', 
               'Test-GSAPrivateDnsResolver', 'Test-GSAVpnSplitDnsInteroperability', 
               'Test-GSAEventLog', 'Test-InternetConnectivity', 'Test-DnsResolution', 
               'Test-GSATenantInternetDnsResolution', 'Test-TLSConnection', 
               'Test-mTLSConnectivity', 'Test-ProxyDetection', 
               'Test-EntraIDConnectivity', 'Test-EntraIDUserAuthentication', 
               'Test-GSADiagnosticUriConnectivity', 'Test-GSAPrivateAccessRule', 
               'Test-GSAPrivateAccessTunnel', 
               'Test-GSAForwardingProfileAssignment', 
               'Test-GSAClientProfileConnectivity', 
               'Test-GSAPrivateAccessApplicationSegment', 
               'Test-GSAPrivateAccessApplication', 
               'Test-GSAIntelligentLocalAccessConfiguration', 
               'Test-GSAHomeNetworkSupport', 'Test-GSAAuthCertificate', 
               'Export-GSAAuthCertificate', 'Repair-GSAAuthCertificate'

# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = @()

# Variables to export from this module
# VariablesToExport = @()

# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
AliasesToExport = @()

# DSC resources to export from this module
# DscResourcesToExport = @()

# List of all modules packaged with this module
# ModuleList = @()

# List of all files packaged with this module
# FileList = @()

# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{

    PSData = @{

        # Tags applied to this module. These help with module discovery in online galleries.
        Tags = 'GSA','GlobalSecureAccess','Global-Secure-Access','MicrosoftEntra','Entra','EntraID','AzureAD','EntraInternetAccess','EntraPrivateAccess','PrivateAccess','InternetAccess','ZTNA','SSE','ZeroTrust','Troubleshooting','Diagnostics','Connectivity','HealthCheck','mTLS','DNS','Microsoft','Windows'

        # A URL to the license for this module.
        LicenseUri = 'https://github.com/michaelmsonne/GSAClientDiagnosticsToolkit/blob/main/LICENSE'

        # A URL to the main website for this project.
        ProjectUri = 'https://github.com/michaelmsonne/GSAClientDiagnosticsToolkit'

        # A URL to an icon representing this module.
        # IconUri = ''

        # ReleaseNotes of this module
        ReleaseNotes = '### Added
 
- Microsoft Graph-based checks, adapted to this module''s conventions:
  - `Test-GSAForwardingProfileAssignment` - tenant onboarding, forwarding profile enablement, and user/group assignment.
  - `Test-GSAClientProfileConnectivity` - local edge/diagnostic connectivity per forwarding profile channel (`m365`/`private`/`internet`), testing all three by default when `-ProfileType` is omitted.
  - `Test-GSAPrivateAccessApplicationSegment` - Private Access application enablement, assignment, and application segment (FQDN/IP/port/protocol) matching via Graph.
  - `Test-GSAPrivateAccessApplication` - end-to-end Private Access application check combining the segment check with a live tunnel test.
- Automatic interactive `Connect-MgGraph` sign-in fallback (via the optional `Microsoft.Graph.Authentication` module) when `-AccessToken` isn''t supplied to the Graph-based checks, reusing any already-active session.
- Local/offline Private Access checks: `Test-GSAPrivateAccessRule` (matches a target FQDN/IP + port + protocol against the locally cached forwarding profile''s rules) and `Test-GSAPrivateAccessTunnel` (verifies a live tunnel connection resolves to a synthetic `6.6.x.x` address and resolves via the GSA Private DNS resolver).
- `-PassThru` switch on the new Private Access and Graph-based functions so they stay silent by default and only return a `$true`/`$false` result when explicitly requested.
- `-LogLevel` parameter on public functions to override the module''s logging verbosity per call.
- New connectivity tests: `Test-GSAPrimaryRefreshToken`, `Test-GSAForwardingProfileRegistry`, `Test-GSAForwardingProfileTimestamp`, `Test-GSAServiceStatus`, `Test-GSASecureDnsStatus`, `Test-GSAIPv6Status`, `Test-GSASyntheticRoutes`, `Test-GSAPrivateDnsResolver`, `Test-GSAEventLog`, `Test-DeviceEntraStatus`, and `Test-EntraIDConnectivity`.
- `Test-GSATenantInternetDnsResolution` - validates `<tenantId>.internet.client.globalsecureaccess.microsoft.com` and `<tenantId>.internet-backup.client.globalsecureaccess.microsoft.com`, expects synthetic `6.6.0.0/16` answers (with CNAME aliases), compares against direct DNS (`-NoHostsFile`), and flags local hosts-file/private-IP overrides.
- Converted the original monolithic `GSAClientDiagnosticsToolkit.ps1` script into a proper PowerShell module (`src/GSAClientDiagnosticsToolkit.psd1`/`.psm1`) with `Public`/`Private` folder structure and `Invoke-GSAClientConnectivityCheck` as the orchestrator.
- Module manifest metadata: `LicenseUri`, `CompatiblePSEditions`, `HelpInfoURI`, and `ReleaseNotes`.
- Pester test suite (`tests/Public`, `tests/Private`) covering the module manifest/export consistency, private helper logic, and public function behavior via mocked dependencies.
- `Test-GSAAuthCertificate` - checks whether a valid GSA mTLS authentication certificate (subject ending in `gsa.client`) exists in the LocalMachine\My store and hasn''t expired, mirroring the client''s built-in "Authentication certificate exists"/"Authentication certificate is valid" Health check tests.
- `Export-GSAAuthCertificate` - read-only backup of the GSA authentication certificate(s) (password-protected `.pfx` with the private key when exportable, otherwise a public-key-only `.cer`), usable standalone or as the backup step reused by `Repair-GSAAuthCertificate`.
- `Repair-GSAAuthCertificate` - remediation for a missing/invalid authentication certificate: always backs up the certificate first via `Export-GSAAuthCertificate`, requires two separate confirmations before deleting it (standard `-WhatIf`/`-Confirm` plus typing the exact thumbprint), clears the `CertCommonName` registry value, and can optionally restart `GlobalSecureAccessEngineService` via `-RestartEngineService`.
- `Get-GSAAppProtectionExclusionServicePrincipals` - returns the known Global Secure Access-related service principals/app IDs to exclude in App Protection policies (based on field validation on Windows and iOS), and validates each App ID in-tenant via Microsoft Graph to report existence and current state.
- `Test-GSAIntelligentLocalAccessConfiguration` - checks Intelligent Local Access (ILA) Private Network definitions via Microsoft Graph (`networkAccess/privateNetworks`) for probe FQDNs that are publicly resolvable, and DNS server/expected IP addresses that are public rather than private (RFC1918) - a confirmed real-world root cause of GSA incorrectly bypassing Private Access traffic to a local connection for users who were never on the corporate network (e.g. on hotel/home Wi-Fi). Resolves each Private Network''s associated App IDs to friendly display names (via the same `tags/Any` filter the Entra portal uses) and flags App IDs that no longer resolve to a known ZTNA/Quick Access application. Public resolvability is checked via DNS-over-HTTPS instead of a classic port-53 query, since the latter can be silently intercepted/answered by the local GSA client (WFP driver) or a router''s own local DNS records; a resulting GSA synthetic `6.6.x.x` address is detected and reported as inconclusive rather than a false failure. Supports a `-FQDN` manual mode (with optional `-DnsServerAddress`/`-ExpectedIPAddress`) to check a single candidate FQDN without calling Microsoft Graph.
- `Test-GSAVpnSplitDnsInteroperability` - local/offline interoperability check for Cisco VPN + GSA private DNS/NRPT overlap scenarios that can produce `REFUSED` DNS lookups for a private suffix. Detects active Cisco adapter + matching NRPT rule + REFUSED probe lookup and recommends allowing source `6.6.0.0/16` in Cisco split-DNS/extended ACL source networks.
- `Test-GSAHomeNetworkSupport` - local/offline check of Private Access home network support ("Allow local subnet bypass"). Reads the Private Access channel of the cached forwarding profile and verifies that the `localNetwork.isLocalNetworkFeatureEnabled` setting is present (a missing setting suggests a client without home network support) and enabled, calculates the directly connected RFC1918 IPv4 subnets from active adapters (IP + mask, as the client does), and warns when a local subnet overlaps tunneled Private Access IP rules (corporate destinations that become unreachable while "Prefer Local Network" is on). See [Configure home network support for Microsoft Entra Private Access](https://learn.microsoft.com/en-us/entra/global-secure-access/how-to-configure-home-network-support?wt.mc_id=MVP_353010).
 
### Changed
 
- Refactored PowerShell scripts for improved readability and consistency.
- Enhanced logging and error handling across connectivity tests, including detailed DEBUG-level information for DNS chain retrieval, Entra ID status, GSA event log scanning, and service status checks.
 
### Fixed
 
- Incorrect `tenantId` reference in `Test-GSAForwardingProfileRegistry` logging.
- Noisy `Resolve-DnsName` output in `Test-GSAPrivateDnsResolver`.
- Missing/failed GSA service test result handling.
- `Select-Object -ExpandProperty` failing with "Property cannot be found" when Graph responses came back as `Hashtable` objects from `Invoke-MgGraphRequest` (as opposed to `PSCustomObject` from `Invoke-RestMethod`).'


        # Prerelease string of this module
        Prerelease = 'beta1'

        # Flag to indicate whether the module requires explicit user acceptance for install/update/save
        # RequireLicenseAcceptance = $false

        # External dependent modules of this module
        # ExternalModuleDependencies = @()

    } # End of PSData hashtable

 } # End of PrivateData hashtable

# HelpInfo URI of this module
HelpInfoURI = 'https://github.com/michaelmsonne/GSAClientDiagnosticsToolkit/blob/main/README.md'

# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''

}