Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
134c1b2
Add support for OpenSSH Servers on Windows
fdcastel Feb 23, 2026
26ce26e
Address PR #480 review feedback
fdcastel Mar 25, 2026
b54a26d
Add Windows ARM64 support to GitHub Actions workflows
fdcastel Mar 25, 2026
9ce9304
Fix Windows ARM64 integration test: increase timeout and add setup-go
fdcastel Mar 25, 2026
7d914e6
docs: Add Windows Server and Windows 11 ARM64 support to compatibilit…
fdcastel Mar 25, 2026
7250ab3
fix: Update copyright year to 2026 in logpath_windows.go
fdcastel Mar 25, 2026
c0fb2cd
fix: Address Copilot review comments on PR #480
fdcastel Mar 26, 2026
b6f8c0e
docs: Improve README with missing commands, Windows server install, a…
fdcastel Mar 28, 2026
4717edf
fix: Address PR #480 review feedback
fdcastel Mar 29, 2026
970adf4
fix: Improve OpenSSH version detection for LocalSystem account compat…
fdcastel Mar 29, 2026
07c9a3e
Remove LocalSystem account usage, standardize on opksshuser
fdcastel Mar 29, 2026
34c8ba2
refactor: Update GitHub Actions workflow for Windows to use matrix st…
fdcastel Mar 29, 2026
4eefaa3
gha-windows: add PATH verification for install/uninstall
fdcastel Mar 29, 2026
fa4c45a
gha-windows: fix timeout, update cache action, remove exit code annot…
fdcastel Mar 29, 2026
7dba4de
gha-windows: fix expected SSH failure step
fdcastel Mar 29, 2026
c3a8a36
gha-windows: improve PATH handling during OpenSSH Server installation
fdcastel Mar 30, 2026
d9a0d35
fix: Handle UTF-8 BOM in config file parsing
fdcastel Mar 30, 2026
8bc5801
Address Copilot review comments on PR #480
fdcastel Mar 30, 2026
ecfbee4
fix: Remove -AuthCmdUser from GHA workflow invocation
fdcastel Mar 30, 2026
df51ade
ci: Run only Pester tests for Windows in integration test matrix
fdcastel Mar 30, 2026
29f3b2a
ci: Move Pester tests to test-windows job, clean up integration test …
fdcastel Mar 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,53 @@ jobs:
- name: Run unit tests
shell: pwsh
run: go test ./...
- name: Run Pester tests
shell: pwsh
run: Invoke-Pester -Path scripts/windows/test -Output Detailed

# Check that binary can be built natively on Windows ARM64
build-windows-arm64:
name: Build Windows ARM64
runs-on: windows-11-arm
timeout-minutes: 5
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- name: Install Go
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version-file: 'go.mod'
- name: Install dependencies
run: go mod download
- name: Build Windows ARM64
shell: pwsh
run: go build -v -o opkssh-arm64.exe
- name: Test binary works
shell: pwsh
run: |
.\opkssh-arm64.exe --version

# Run Windows ARM64 unit tests
test-windows-arm64:
name: 'Windows ARM64 Tests'
runs-on: windows-11-arm
timeout-minutes: 8
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- name: Install Go
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version-file: 'go.mod'
- name: Install dependencies
run: go mod download
- name: Run unit tests
shell: pwsh
run: go test ./...

# Run integration tests
test:
Expand Down
159 changes: 159 additions & 0 deletions .github/workflows/gha-windows.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
name: Test GitHub Provider Windows

on:
push:

jobs:
build:
name: Test on ${{ matrix.name }}
runs-on: ${{ matrix.runner }}
permissions:
id-token: write
contents: read
timeout-minutes: ${{ matrix.timeout }}

strategy:
fail-fast: false
matrix:
include:
- name: Windows Server 2022
runner: windows-2022
timeout: 10
cache: true
- name: Windows Server 2025
runner: windows-2025
timeout: 10
cache: true
- name: Windows 11 ARM64
runner: windows-11-arm
timeout: 15
cache: false

steps:
- name: Install OpenSSH Server
run: |
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

- name: Create default OpenSSH config files
run: |
Start-Service sshd
Start-Sleep -Seconds 2
Stop-Service sshd

- name: Enable OpenSSH Server logs
run: |
$sshdConfig = "$env:ProgramData\ssh\sshd_config"
(Get-Content $sshdConfig -Raw).Replace('#SyslogFacility AUTH', 'SyslogFacility LOCAL0').Replace('#LogLevel INFO', 'LogLevel Debug3') |
Set-Content $sshdConfig

- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false

- name: Cache Go modules
if: matrix.cache
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: |
~/go/pkg/mod
~/.cache/go-build
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-

- name: Install Go
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version-file: 'go.mod'

- name: Install dependencies
run: go mod download

- name: Build opkssh
run: go build -v -o opkssh.exe

Comment on lines +70 to +75
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This workflow runs go mod download/go build without first pinning the Go toolchain via actions/setup-go (unlike the repo’s other workflows). Windows runner images can change their preinstalled Go version over time, which can make CI flaky or inconsistent with go.mod’s toolchain. Add a setup-go step using go-version-file: go.mod for reproducibility.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Added actions/setup-go@v6.3.0 with go-version-file: 'go.mod' to both gha-windows.yml and gha-windows-2025.yml, matching the pattern used by the other workflows in this repo.

- name: Install opkssh with local binary
run: |
powershell -ExecutionPolicy Bypass -File "scripts/windows/Install-OpksshServer.ps1" `
-InstallFrom "$PWD\opkssh.exe" `
-NoSshdRestart `
-Verbose

- name: Verify system PATH after install
run: |
$installDir = 'C:\Program Files\opkssh'
$regPath = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
$systemPath = (Get-ItemProperty -Path $regPath -Name Path).Path
$folders = $systemPath -split [IO.Path]::PathSeparator
$found = $folders | Where-Object { $_.TrimEnd([IO.Path]::DirectorySeparatorChar) -eq $installDir }
if (-not $found) {
throw "FAIL: '$installDir' was NOT found in the system PATH after install"
}
Write-Host "PASS: '$installDir' is in the system PATH after install"

- name: Add GitHub provider to opkssh configuration
run: |
$providersPath = 'C:\ProgramData\opk\providers'
if ((Get-Content -Path $providersPath -Raw) -notmatch "`r?`n$") {
Add-Content -Path $providersPath -Value ''
}
Add-Content -Path $providersPath -Value 'https://token.actions.githubusercontent.com github oidc'

- name: Add current repository to policy
run: |
& 'C:\Program Files\opkssh\opkssh.exe' add runneradmin "repo:${env:GITHUB_REPOSITORY}:ref:${env:GITHUB_REF}" https://token.actions.githubusercontent.com

- name: Start SSH service
run: Start-Service sshd

- name: Test SSH connection without opkssh (should fail)
run: |
ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no runneradmin@localhost dir 2>&1
if ($LASTEXITCODE -eq 0) { throw "SSH should have failed but succeeded" }
Write-Host "SSH correctly rejected without opkssh (exit code: $LASTEXITCODE)"
exit 0

- name: Login with GitHub OIDC
run: |
& 'C:\Program Files\opkssh\opkssh.exe' login github --print-id-token

- name: Test SSH connection with opkssh (should pass)
run: |
ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no runneradmin@localhost dir

- name: Debug - Dump opkssh config
run: |
Get-ChildItem 'C:\ProgramData\opk' -Recurse -ErrorAction Continue
Get-Content 'C:\ProgramData\opk\providers' -ErrorAction Continue
Get-Content 'C:\ProgramData\opk\auth_id' -ErrorAction Continue
if: always()

- name: Debug - Dump opkssh logs
run: |
Get-Content 'C:\ProgramData\opk\logs\opkssh.log' -ErrorAction Continue
if: always()

- name: Debug - Dump sshd logs
run: |
Get-Content 'C:\ProgramData\ssh\logs\sshd.log' -ErrorAction Continue
if: always()

- name: Uninstall opkssh
run: |
powershell -ExecutionPolicy Bypass -File "scripts/windows/Uninstall-OpksshServer.ps1" `
-Force `
-NoSshdRestart `
-Verbose

- name: Verify system PATH after uninstall
run: |
$installDir = 'C:\Program Files\opkssh'
$regPath = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
$systemPath = (Get-ItemProperty -Path $regPath -Name Path).Path
$folders = $systemPath -split [IO.Path]::PathSeparator
$found = $folders | Where-Object { $_.TrimEnd([IO.Path]::DirectorySeparatorChar) -eq $installDir }
if ($found) {
throw "FAIL: '$installDir' is still in the system PATH after uninstall"
}
Write-Host "PASS: '$installDir' was correctly removed from the system PATH after uninstall"
8 changes: 4 additions & 4 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ builds:
goarch:
- amd64
- arm64
# Ignore some builds until they are not tested
ignore:
- goos: windows
goarch: arm64

# Make binaries available with the same naming format as before
archives:
Expand Down Expand Up @@ -77,3 +73,7 @@ changelog:
release:
draft: true
make_latest: true
extra_files:
- glob: scripts/windows/Install-OpksshServer.ps1
- glob: scripts/windows/Uninstall-OpksshServer.ps1
Comment thread
fdcastel marked this conversation as resolved.
- glob: scripts/windows/Test-OpksshInstallation.ps1
Loading
Loading