Public/Start-NSPFortiClientToolkit.ps1
|
function Start-NSPFortiClientToolkit { <# .SYNOPSIS The FortiClient Connection Troubleshooting Toolkit menu - run it ON the machine with the connection problem (typically over a remote session): readiness check, pre-attempt monitoring (detached captures and block auditing that survive a dropped session), firewall/EDR sweep, blocked-connection review, and the FortiGate-side CLI commands. .DESCRIPTION Moved from the zip-era FCT-Toolkit.ps1; the menu is unchanged. Typical flow for a live IKEv2 failure: 1 (readiness) and 2 (monitoring) before the attempt, 7 (FortiGate CLI) on the FortiGate side, the user tries to connect, then 3 and 4. Relaunches elevated if needed. .PARAMETER OutputRoot Where reports and captures go (Reports\ and Captures\ under it). .PARAMETER SeedAnswersJson Accepted for the NSP launcher contract; this toolkit has no answers of its own yet. .PARAMETER SeedOnly Merge -SeedAnswersJson and return without opening the menu. .PARAMETER NoElevate Do not relaunch elevated. .EXAMPLE Start-NSPFortiClientToolkit #> [CmdletBinding()] param( [string]$OutputRoot = 'C:\Admin\FCTToolkit\Output', [string]$SeedAnswersJson, [switch]$SeedOnly, [switch]$NoElevate ) Use-NSPFortiClientDependency if ($SeedOnly) { $null = Import-NSPToolSeedAnswers -Tool FortiClient -SeedAnswersJson $SeedAnswersJson return } if (-not $NoElevate) { $manifest = (Join-Path $script:ModuleRoot 'NSP.FortiClient.psd1').Replace("'", "''") $relaunch = "Import-Module '$manifest'; Start-NSPFortiClientToolkit" if ($PSBoundParameters.ContainsKey('OutputRoot')) { $relaunch += " -OutputRoot '$($OutputRoot.Replace("'", "''"))'" } if (Invoke-NSPElevated -Command $relaunch -NoExit) { return } } if ($SeedAnswersJson) { $null = Import-NSPToolSeedAnswers -Tool FortiClient -SeedAnswersJson $SeedAnswersJson } $captureDir = Join-Path $OutputRoot 'Captures' $reportDir = Join-Path $OutputRoot 'Reports' foreach ($dir in @($OutputRoot, $captureDir, $reportDir)) { if (-not (Test-Path -LiteralPath $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null } } Set-NSPConsoleMaximized -ErrorAction SilentlyContinue $version = [string]$ExecutionContext.SessionState.Module.Version $versionLabel = (Get-NSPToolVersionStatus -ToolKey 'NSP.FortiClient' -Version $version).Label # ----- zip-era FCT-Toolkit.ps1 menu (the scripts are called through their module functions) ----- while ($true) { Write-Host "" Write-Host "================================================" Write-Host " FortiClient Connection Troubleshooting Toolkit $versionLabel" Write-Host "================================================" Write-Host "*** Before the Attempt ***" Write-Host " 1. Readiness Check - pre-attempt snapshot (services, ports, adapters, events)" Write-Host " 2. Start Pre-Attempt Monitoring - Live Capture and/or Block Auditing (1/2/both)" Write-Host " 3. Firewall / EDR Check - static sweep of firewall rules, security products, EDR/VPN agents" Write-Host "" Write-Host "*** After the Attempt ***" Write-Host " 4. Show Blocked Connections - read back blocked-connection events" Write-Host " 5. Stop Live Capture Early - drop the STOP flag for any running capture" Write-Host " 6. Disable Block Auditing - turn logging back off (cleanup)" Write-Host "" Write-Host "*** FortiGate ***" Write-Host " 7. FortiGate CLI Commands - generate + copy commands using this machine's public IP" Write-Host "" Write-Host " Q. Quit" Write-Host "================================================" Write-Host " Output folder: $OutputRoot" Write-Host "" $choice = Read-Host "Select an option" switch -Regex ("$choice".Trim()) { '^1$' { $mins = Read-Host "Look back how many minutes in the event logs? [30]" if ([string]::IsNullOrWhiteSpace($mins)) { $mins = 30 } Test-NSPFortiClientIKEv2Readiness -SinceMinutes ([int]$mins) ` -OutputPath (Join-Path $reportDir "FortiClient_IKEv2_Readiness_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt") } '^2$' { Write-Host " 1. Live Capture only (state + packet capture)" Write-Host " 2. Block Auditing only (WFP block logging)" Write-Host " 3. Both (recommended)" $monSel = Read-Host "Enable which? [3]" if ([string]::IsNullOrWhiteSpace($monSel)) { $monSel = "3" } if ($monSel -in @("1", "3")) { $mins = Read-Host "Capture for how many minutes? [10]" if ([string]::IsNullOrWhiteSpace($mins)) { $mins = 10 } Start-NSPFortiClientIKEv2Capture -DurationMinutes ([int]$mins) -OutputDir $captureDir Start-NSPFortiClientPacketCapture -DurationMinutes ([int]$mins) -OutputDir $captureDir } if ($monSel -in @("2", "3")) { Test-NSPFortiClientFirewallBlocking -EnableBlockAuditing } if ($monSel -notin @("1", "2", "3")) { Write-Host "Invalid selection - nothing enabled." -ForegroundColor Yellow } } '^3$' { Test-NSPFortiClientFirewallBlocking } '^4$' { $mins = Read-Host "Look back how many minutes? [30]" if ([string]::IsNullOrWhiteSpace($mins)) { $mins = 30 } Test-NSPFortiClientFirewallBlocking -ShowBlockedEvents -SinceMinutes ([int]$mins) } '^5$' { Stop-NSPFortiClientCapture -CaptureDir $captureDir } '^6$' { Test-NSPFortiClientFirewallBlocking -DisableBlockAuditing } '^7$' { Show-NSPFortiGateCLICommand } '^[Qq](uit)?$' { Write-Host "Goodbye." -ForegroundColor Gray return } default { Write-Host "Invalid selection." -ForegroundColor Yellow } } } } |