GraceSolutions e566ab15f1 Automatic service management and Windows Firewall rules
- Service auto-start and start now happen automatically (no switches)
- Windows Firewall rules created automatically per profile (Domain, Private, Public)
- Dynamic profile enumeration using [Microsoft.PowerShell.Cmdletization.GeneratedTypes.NetSecurity.Profile]
- Added -SSHPort parameter for custom port (default: 22)
- Idempotent firewall rule creation with update support
- Removed -EnableService and -StartService switches (now automatic)
2026-05-01 15:21:54 -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
-KeyType String Key algorithm: rsa, ecdsa, ed25519 (default: ed25519)
-KeyBits Int Key size: 256, 384, 521 (ECDSA) or 2048, 3072, 4096 (RSA)
-EnablePubkeyAuthentication Switch Enable PubkeyAuthentication yes in sshd_config
-DisablePasswordAuthentication Switch Disable password authentication (PasswordAuthentication no)
-EnableCertificateAuthentication Switch Configure TrustedUserCAKeys for certificate auth
-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

.\Invoke-OpenSSHConfiguration.ps1 -Mode Server `
    -PublicKeyList @('ssh-ed25519 AAAAC3NzaC1lZDI1NTE5... admin@corp') `
    -GenerateKeyPair `
    -KeyType ed25519 `
    -TrustWindowsCertificateAuthorities `
    -EnableCertificateAuthentication `
    -EnablePubkeyAuthentication `
    -DisablePasswordAuthentication `
    -LogDirectory 'C:\Logs\OpenSSH'

Hardened Server (Keys Only, No Passwords)

.\Invoke-OpenSSHConfiguration.ps1 -Mode Server `
    -EnablePubkeyAuthentication `
    -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)' `
    -EnableCertificateAuthentication

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

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

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

  • Password authentication control (-DisablePasswordAuthentication)
  • 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 timestamped backups)
  • Config validation (sshd -t) before restart with automatic rollback
  • CA selection via regex (-CAInclusionExpression, -CAExclusionExpression)
  • 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%