@@ -1201,6 +1201,73 @@ jobs:
12011201 Remove-Item $scriptPath -ErrorAction SilentlyContinue
12021202 Remove-Item $outputFile -ErrorAction SilentlyContinue
12031203
1204+ - name : Dry-run wolfsshd as LocalSystem (cert store diagnostics)
1205+ if : matrix.server_key_source == 'store'
1206+ working-directory : ${{ github.workspace }}\wolfssh
1207+ shell : pwsh
1208+ run : |
1209+ # Run wolfsshd in non-daemon test mode AS LOCALSYSTEM via scheduled
1210+ # task. This captures the exact error that the service would hit.
1211+ $sshdPath = (Get-Content env:SSHD_PATH -ErrorAction SilentlyContinue)
1212+ if (-not $sshdPath -or -not (Test-Path $sshdPath)) {
1213+ Write-Host "Skipping: wolfsshd.exe not found"
1214+ exit 0
1215+ }
1216+ $sshdPathFull = (Resolve-Path $sshdPath).Path
1217+ $configPathFull = (Resolve-Path "sshd_config_test").Path
1218+ $port = ${{env.TEST_PORT}}
1219+
1220+ # Output goes to a temp file that LocalSystem can write to
1221+ $outFile = "$env:TEMP\wolfsshd-localsystem-dryrun.txt"
1222+
1223+ # We wrap the call in cmd /c so stdout+stderr go to the file
1224+ $cmdLine = "`"$sshdPathFull`" -D -t -d -f `"$configPathFull`" -p $port"
1225+ Write-Host "Will run as SYSTEM: $cmdLine"
1226+
1227+ # Create scheduled task to run as SYSTEM
1228+ $taskName = "WolfSSH-DryRunLocalSystem"
1229+ $action = New-ScheduledTaskAction `
1230+ -Execute "cmd.exe" `
1231+ -Argument "/c $cmdLine > `"$outFile`" 2>&1"
1232+ $principal = New-ScheduledTaskPrincipal `
1233+ -UserId "NT AUTHORITY\SYSTEM" `
1234+ -LogonType ServiceAccount -RunLevel Highest
1235+ $settings = New-ScheduledTaskSettingsSet `
1236+ -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
1237+
1238+ Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue
1239+ Register-ScheduledTask -TaskName $taskName -Action $action -Principal $principal -Settings $settings | Out-Null
1240+ Start-ScheduledTask -TaskName $taskName
1241+
1242+ # Wait for completion (wolfsshd -t exits quickly)
1243+ $timeout = 30
1244+ $elapsed = 0
1245+ while ($elapsed -lt $timeout) {
1246+ Start-Sleep -Seconds 1
1247+ $elapsed++
1248+ $task = Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue
1249+ if ($task.State -eq "Ready") { break }
1250+ }
1251+
1252+ # Get exit code
1253+ $taskInfo = Get-ScheduledTaskInfo -TaskName $taskName -ErrorAction SilentlyContinue
1254+ if ($taskInfo) {
1255+ Write-Host "Scheduled task last result: $($taskInfo.LastTaskResult)"
1256+ }
1257+
1258+ # Show output
1259+ Write-Host "=== wolfsshd dry-run as LocalSystem ==="
1260+ if (Test-Path $outFile) {
1261+ Get-Content $outFile
1262+ } else {
1263+ Write-Host "(no output file generated)"
1264+ }
1265+ Write-Host "=== end LocalSystem dry-run ==="
1266+
1267+ # Cleanup
1268+ Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue
1269+ Remove-Item $outFile -ErrorAction SilentlyContinue
1270+
12041271 - name : Start echoserver with cert store (cert store matrix – more debug logs)
12051272 if : matrix.server_key_source == 'store'
12061273 working-directory : ${{ github.workspace }}\wolfssh
@@ -1393,6 +1460,43 @@ jobs:
13931460 # Clear the env var so cleanup step doesn't try again
13941461 Add-Content -Path $env:GITHUB_ENV -Value "ECHOSERVER_PID="
13951462
1463+ - name : Validate wolfsshd config (non-daemon dry run)
1464+ working-directory : ${{ github.workspace }}\wolfssh
1465+ shell : pwsh
1466+ run : |
1467+ # Run wolfsshd in non-daemon test mode (-D -t -d) to validate
1468+ # config loading and cert store access. This gives us visible
1469+ # stdout/stderr output, unlike the service which logs to
1470+ # OutputDebugString.
1471+ $sshdPath = (Get-Content env:SSHD_PATH)
1472+ if (-not (Test-Path $sshdPath)) {
1473+ Write-Host "Skipping dry-run: wolfsshd.exe not found"
1474+ exit 0
1475+ }
1476+ $configPathFull = (Resolve-Path "sshd_config_test").Path
1477+ $port = ${{env.TEST_PORT}}
1478+
1479+ Write-Host "=== wolfsshd dry-run: $sshdPath -D -t -d -f $configPathFull -p $port ==="
1480+ $proc = Start-Process -FilePath $sshdPath `
1481+ -ArgumentList "-D", "-t", "-d", "-f", $configPathFull, "-p", $port `
1482+ -RedirectStandardOutput "wolfsshd_dryrun_out.txt" `
1483+ -RedirectStandardError "wolfsshd_dryrun_err.txt" `
1484+ -Wait -NoNewWindow -PassThru
1485+
1486+ Write-Host "Exit code: $($proc.ExitCode)"
1487+ Write-Host "=== stdout ==="
1488+ if (Test-Path wolfsshd_dryrun_out.txt) { Get-Content wolfsshd_dryrun_out.txt }
1489+ Write-Host "=== stderr ==="
1490+ if (Test-Path wolfsshd_dryrun_err.txt) { Get-Content wolfsshd_dryrun_err.txt }
1491+ Write-Host "=== end dry-run ==="
1492+
1493+ if ($proc.ExitCode -ne 0) {
1494+ Write-Host "WARNING: wolfsshd dry-run failed (exit $($proc.ExitCode))"
1495+ Write-Host "The service will likely also fail to start."
1496+ } else {
1497+ Write-Host "wolfsshd dry-run succeeded - config is valid"
1498+ }
1499+
13961500 - name : Start wolfSSHd as Windows service
13971501 working-directory : ${{ github.workspace }}\wolfssh
13981502 shell : pwsh
@@ -1501,6 +1605,10 @@ jobs:
15011605 # Create the service with proper binpath
15021606 # Note: sc.exe requires the binPath to have the executable path and arguments
15031607 # The entire command line goes in binPath, with the exe path in quotes
1608+ # We do NOT include -E <log> here because LocalSystem only has RX on
1609+ # the wolfssh directory and cannot create a log file. Debug output
1610+ # from the service goes to OutputDebugString; for visible diagnostics
1611+ # we rely on the "Validate wolfsshd config" dry-run step.
15041612 $binPath = "`"$sshdPathFull`" -f `"$configPathFull`" -p ${{env.TEST_PORT}}"
15051613 Write-Host "Creating service with binpath: $binPath"
15061614
0 commit comments