GraceSolutions 1d21e707b9 Configure default SSH shell with precedence: PS7 > PS5 > unchanged
- Checks for PowerShell 7 at Program Files\PowerShell\7\pwsh.exe
- Falls back to PowerShell 5 at System32\WindowsPowerShell\v1.0\powershell.exe
- Leaves default shell unchanged if neither found
- Sets HKLM\SOFTWARE\OpenSSH\DefaultShell registry value
- Sets DefaultShellCommandOption to '-NoLogo -NoProfile -Command'
- Idempotent: only updates registry if value differs
2026-05-05 17:20:31 -04:00
2026-04-30 11:10:23 -04:00
2026-04-30 11:10:23 -04:00
2026-04-30 11:10:23 -04:00
2026-04-30 11:10:23 -04:00

Invoke-OpenSSHConfiguration

A PowerShell toolkit for automated installation and configuration of OpenSSH on Windows systems. Provides idempotent configuration of SSH server settings, public key authentication, certificate-based authentication using Windows certificate stores, and key pair generation.

Features

  • Automated Installation: Downloads and installs the latest Win32-OpenSSH MSI from GitHub, with dynamic OS architecture detection
  • Public Key Authentication: Idempotently manages administrators_authorized_keys with deduplication
  • Certificate Authentication: Exports Windows Root and Intermediate CA certificates to PEM format for OpenSSH trust
  • Key Pair Generation: Creates SSH host keys with configurable algorithm and key size
  • Configuration Management: Idempotently modifies sshd_config with proper encoding (ASCII, no BOM)
  • Elevation Handling: Automatically re-launches with elevated privileges when required

Requirements

  • Windows 10/11 or Windows Server 2016+
  • PowerShell 5.1 or later
  • Administrator privileges
  • Internet connectivity (for initial OpenSSH download)

Installation

Clone the repository and run the script directly:

git clone https://github.com/yourusername/Invoke-OpenSSHConfiguration.git
cd Invoke-OpenSSHConfiguration
.\Invoke-OpenSSHConfiguration.ps1 -Mode Server

Parameters

Parameter Type Description
-Mode String Installation mode: Client or Server
-PublicKeyList String[] Array of public keys to add to administrators_authorized_keys
-GenerateKeyPair Switch Generate SSH host key pair (opt-in)
-KeyType String Key algorithm: rsa, ecdsa, ed25519 (default: ed25519)
-KeyBits Int Key size: 256, 384, 521 (ECDSA) or 2048, 3072, 4096 (RSA)
-DisablePubkeyAuthentication Switch Disable public key authentication (enabled by default)
-DisablePasswordAuthentication Switch Disable password authentication (enabled by default)
-DisableCertificateAuthentication Switch Disable certificate authentication (enabled by default if CA bundle exists)
-TrustWindowsCertificateAuthorities Switch Export Windows CA certificates to PEM bundle
-CAInclusionExpression String Regex to filter CAs by Subject or Thumbprint (include matches)
-CAExclusionExpression String Regex to filter CAs by Subject or Thumbprint (exclude matches)
-SFTPSubsystemPath String Custom SFTP server path (default: sftp-server.exe, configured automatically)
-SSHPort Int SSH port number (default: 22, used for firewall rules)
-LogDirectory DirectoryInfo Custom log directory path
-ContinueOnError Switch Continue execution on non-fatal errors

Usage Examples

Basic Server Installation

.\Invoke-OpenSSHConfiguration.ps1 -Mode Server

Server with Public Key Authentication

$PublicKeys = @(
    'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExample1... user1@host',
    'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExample2... user2@host'
)

.\Invoke-OpenSSHConfiguration.ps1 -Mode Server `
    -PublicKeyList $PublicKeys `
    -EnablePubkeyAuthentication

Server with Certificate Authentication (Windows CA Trust)

.\Invoke-OpenSSHConfiguration.ps1 -Mode Server `
    -TrustWindowsCertificateAuthorities `
    -EnableCertificateAuthentication `
    -EnablePubkeyAuthentication

This exports all unexpired Root and Intermediate CA certificates from the Windows certificate store to C:\ProgramData\ssh\OpenSSH-TrustedCertificateAuthorities-LocalMachine.pem and configures sshd to trust them.

Generate Host Keys

# Generate Ed25519 key (recommended)
.\Invoke-OpenSSHConfiguration.ps1 -Mode Server -GenerateKeyPair

# Generate RSA 4096-bit key
.\Invoke-OpenSSHConfiguration.ps1 -Mode Server -GenerateKeyPair -KeyType rsa -KeyBits 4096

# Generate ECDSA 384-bit key
.\Invoke-OpenSSHConfiguration.ps1 -Mode Server -GenerateKeyPair -KeyType ecdsa -KeyBits 384

Full Server Configuration

# All auth methods enabled by default, just add keys and trust CAs
.\Invoke-OpenSSHConfiguration.ps1 -Mode Server `
    -PublicKeyList @('ssh-ed25519 AAAAC3NzaC1lZDI1NTE5... admin@corp') `
    -GenerateKeyPair `
    -KeyType ed25519 `
    -TrustWindowsCertificateAuthorities `
    -LogDirectory 'C:\Logs\OpenSSH'

Hardened Server (Keys Only, No Passwords)

# Disable password auth, keep pubkey and cert auth enabled
.\Invoke-OpenSSHConfiguration.ps1 -Mode Server `
    -DisablePasswordAuthentication

Selective CA Trust (Regex Filtering)

# Only trust CAs with "Corp" or "Enterprise" in the subject
.\Invoke-OpenSSHConfiguration.ps1 -Mode Server `
    -TrustWindowsCertificateAuthorities `
    -CAInclusionExpression '(Corp|Enterprise)'

# Trust all CAs except Microsoft root CAs
.\Invoke-OpenSSHConfiguration.ps1 -Mode Server `
    -TrustWindowsCertificateAuthorities `
    -CAExclusionExpression 'Microsoft'

# Trust specific CA by thumbprint pattern
.\Invoke-OpenSSHConfiguration.ps1 -Mode Server `
    -TrustWindowsCertificateAuthorities `
    -CAInclusionExpression '^A1B2C3'

Custom SFTP Server Path

SFTP subsystem is configured automatically. To use a custom path:

.\Invoke-OpenSSHConfiguration.ps1 -Mode Server `
    -SFTPSubsystemPath 'C:\Program Files\OpenSSH\sftp-server.exe'

File Locations

File Path Description
sshd_config C:\ProgramData\ssh\sshd_config SSH server configuration
sshd_config.backup.* C:\ProgramData\ssh\sshd_config.backup.* Timestamped config backups
administrators_authorized_keys C:\ProgramData\ssh\administrators_authorized_keys Authorized keys for admin users
CA Bundle C:\ProgramData\ssh\OpenSSH-TrustedCertificateAuthorities-LocalMachine.pem Trusted CA certificates
Generated Keys C:\ProgramData\ssh\keys\ Generated host key pairs
Logs %WINDIR%\Temp\Invoke-OpenSSHConfiguration\Logs\ Script execution logs

Certificate Authentication

The script bridges Windows certificate trust to OpenSSH by exporting CA certificates:

  1. Reads unexpired CA certificates from Cert:\LocalMachine\Root and Cert:\LocalMachine\CA
  2. Applies optional inclusion/exclusion regex filters on Subject and Thumbprint
  3. Filters for certificates with Basic Constraints CA flag
  4. Exports to PEM format bundle
  5. Configures TrustedUserCAKeys in sshd_config

Important: OpenSSH does NOT accept expired certificates. When CA certificates are renewed, re-run the script with -TrustWindowsCertificateAuthorities to update the PEM bundle.

Periodic CA Refresh

For automated CA refresh, create a scheduled task:

$Action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-ExecutionPolicy Bypass -File "C:\Scripts\Invoke-OpenSSHConfiguration.ps1" -TrustWindowsCertificateAuthorities'
$Trigger = New-ScheduledTaskTrigger -Daily -At '3:00AM'
$Principal = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -LogonType ServiceAccount -RunLevel Highest
Register-ScheduledTask -TaskName 'OpenSSH-CA-Refresh' -Action $Action -Trigger $Trigger -Principal $Principal

Toolkit Functions

The toolkit includes reusable functions in Toolkit\Functions\:

Function Description
ConvertFrom-CertificateToPEM Converts X.509 certificates to PEM format
Get-GitRepositoryRelease Downloads releases from GitHub repositories
Get-CurrentUser Retrieves current user session information
Start-ProcessWithOutput Executes processes with output capture and logging
Get-InstalledSoftware Queries installed software from registry
Get-MSIPropertyList Reads MSI file properties

Known Limitations

Current Gaps (Not Yet Implemented)

Server Configuration

  • User/group restrictions (AllowUsers, AllowGroups)
  • SSH banner/MOTD configuration
  • ListenAddress binding to specific interfaces

Security

  • No automatic ACL/permission setting on generated keys

Management

  • No uninstall/rollback capability
  • No certificate expiry warnings

Features Implemented

  • Authentication methods enabled by default (opt-out via -Disable* switches)
    • PubKey, Password, Certificate auth all enabled unless explicitly disabled
  • Key generation opt-in (-GenerateKeyPair)
  • Service auto-start and start (automatic, no switches needed)
  • Windows Firewall rules (automatic per-profile: Domain, Private, Public)
  • Port configuration (-SSHPort, default 22)
  • Config backup before modification (automatic, keeps last 3)
  • Config validation (sshd -t) before restart with automatic rollback
  • CA selection via regex (-CAInclusionExpression, -CAExclusionExpression)
  • Session user certificate access (reads from HKEY_USERS when running as SYSTEM)
  • SFTP subsystem (configured automatically, custom path via -SFTPSubsystemPath)

Troubleshooting

Script Re-launches in New Window

The script automatically elevates to administrator. This is expected behavior.

Public Keys Not Working

  1. Verify the key format is correct (starts with ssh-rsa, ssh-ed25519, etc.)
  2. Check C:\ProgramData\ssh\administrators_authorized_keys file permissions
  3. Ensure PubkeyAuthentication yes is in sshd_config

Certificate Authentication Not Working

  1. Verify CA certificates are not expired
  2. Check the PEM bundle exists at C:\ProgramData\ssh\OpenSSH-TrustedCertificateAuthorities-LocalMachine.pem
  3. Verify TrustedUserCAKeys path in sshd_config
  4. Run sshd -t to validate configuration

Service Won't Start

  1. Check Windows Event Viewer for sshd errors
  2. Validate config: & 'C:\Program Files\OpenSSH\sshd.exe' -t
  3. Ensure no port conflicts on TCP 22

Project Structure

Invoke-OpenSSHConfiguration/
├── Invoke-OpenSSHConfiguration.ps1    # Main script
├── README.md                          # This file
├── Content/                           # Additional content files
├── Toolkit/
│   ├── Toolkit.ps1                    # Core toolkit initialization
│   ├── Functions/                     # Reusable PowerShell functions
│   │   ├── ConvertFrom-CertificateToPEM.ps1
│   │   ├── Get-GitRepositoryRelease.ps1
│   │   ├── Get-CurrentUser.ps1
│   │   └── ...
│   ├── Modules/                       # PowerShell modules
│   └── Tools/                         # External tools
└── .augment/
    └── rules/                         # Coding standards

Contributing

  1. Follow the coding standards in .augment/rules/PowershellScripts.md
  2. Use the established patterns (OrderedDictionary, Switch statements, etc.)
  3. Test changes with -Verbose flag
  4. Update documentation for new parameters

License

[Add your license here]

Acknowledgments

S
Description
Dynamically downloads, installs/updates and configures the OpenSSH server on Windows clients and servers using the MSI installation package.
Readme GPL-3.0 515 KiB
Languages
PowerShell 100%