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)
This commit is contained in:
GraceSolutions
2026-05-01 15:21:54 -04:00
parent 825dfdab79
commit e566ab15f1
2 changed files with 70 additions and 38 deletions
+65 -28
View File
@@ -91,10 +91,8 @@
[String]$SFTPSubsystemPath, [String]$SFTPSubsystemPath,
[Parameter(Mandatory=$False)] [Parameter(Mandatory=$False)]
[Switch]$EnableService, [ValidateNotNullOrEmpty()]
[Int]$SSHPort = 22,
[Parameter(Mandatory=$False)]
[Switch]$StartService,
[Parameter(Mandatory=$False)] [Parameter(Mandatory=$False)]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
@@ -764,40 +762,79 @@ Switch (Test-ProcessElevationStatus)
} }
#endregion #endregion
#region Service Management #region Service Management (Automatic)
Switch ($EnableService.IsPresent -eq $True) $SSHDService = Get-Service -Name 'sshd' -ErrorAction SilentlyContinue
Switch ($Null -ine $SSHDService)
{ {
{($_ -eq $True)} {($_ -eq $True)}
{ {
$WriteLogMessage.Invoke(0, @("Configuring sshd service to start automatically. Please Wait...")) #region Configure Automatic Startup
$Null = Set-Service -Name 'sshd' -StartupType Automatic -ErrorAction SilentlyContinue Switch ($SSHDService.StartType -ine 'Automatic')
$WriteLogMessage.Invoke(0, @("sshd service configured for automatic startup.")) {
{($_ -eq $True)}
{
$WriteLogMessage.Invoke(0, @("Configuring sshd service to start automatically. Please Wait..."))
$Null = Set-Service -Name 'sshd' -StartupType Automatic -ErrorAction SilentlyContinue
$WriteLogMessage.Invoke(0, @("sshd service configured for automatic startup."))
}
}
#endregion
#region Start Service
Switch ($SSHDService.Status -ine 'Running')
{
{($_ -eq $True)}
{
$WriteLogMessage.Invoke(0, @("Starting sshd service. Please Wait..."))
$Null = Start-Service -Name 'sshd' -ErrorAction SilentlyContinue
$WriteLogMessage.Invoke(0, @("sshd service started."))
}
}
#endregion
} }
} }
#endregion
Switch ($StartService.IsPresent -eq $True) #region Windows Firewall Configuration (Automatic)
$FirewallRuleName = 'OpenSSH-Server-In-TCP'
$FirewallProfiles = [System.Enum]::GetValues([Microsoft.PowerShell.Cmdletization.GeneratedTypes.NetSecurity.Profile])
ForEach ($FirewallProfile In $FirewallProfiles)
{ {
{($_ -eq $True)} $ExistingRule = Get-NetFirewallRule -Name "$($FirewallRuleName)-$($FirewallProfile)" -ErrorAction SilentlyContinue
Switch ($Null -eq $ExistingRule)
{ {
$SSHDService = Get-Service -Name 'sshd' -ErrorAction SilentlyContinue {($_ -eq $True)}
Switch ($Null -ine $SSHDService)
{ {
{($_ -eq $True)} $WriteLogMessage.Invoke(0, @("Creating Windows Firewall rule for profile `"$($FirewallProfile)`". Please Wait..."))
{
Switch ($SSHDService.Status -ine 'Running')
{
{($_ -eq $True)}
{
$WriteLogMessage.Invoke(0, @("Starting sshd service. Please Wait..."))
$Null = Start-Service -Name 'sshd' -ErrorAction SilentlyContinue
$WriteLogMessage.Invoke(0, @("sshd service started."))
}
Default $FirewallRuleParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
{ $FirewallRuleParameters.Add('Name', "$($FirewallRuleName)-$($FirewallProfile)")
$WriteLogMessage.Invoke(0, @("sshd service is already running.")) $FirewallRuleParameters.Add('DisplayName', "OpenSSH SSH Server ($($FirewallProfile))")
} $FirewallRuleParameters.Add('Description', "Inbound rule for OpenSSH SSH Server on TCP port $($SSHPort) for $($FirewallProfile) profile")
$FirewallRuleParameters.Add('Enabled', 'True')
$FirewallRuleParameters.Add('Direction', 'Inbound')
$FirewallRuleParameters.Add('Protocol', 'TCP')
$FirewallRuleParameters.Add('LocalPort', $SSHPort)
$FirewallRuleParameters.Add('Profile', $FirewallProfile)
$FirewallRuleParameters.Add('Action', 'Allow')
$FirewallRuleParameters.Add('ErrorAction', 'SilentlyContinue')
$Null = New-NetFirewallRule @FirewallRuleParameters
$WriteLogMessage.Invoke(0, @("Windows Firewall rule created for profile `"$($FirewallProfile)`"."))
}
Default
{
Switch (($ExistingRule.Enabled -eq $False) -or ($ExistingRule.LocalPort -ne $SSHPort))
{
{($_ -eq $True)}
{
$WriteLogMessage.Invoke(0, @("Updating Windows Firewall rule for profile `"$($FirewallProfile)`". Please Wait..."))
$Null = Set-NetFirewallRule -Name "$($FirewallRuleName)-$($FirewallProfile)" -Enabled 'True' -LocalPort $SSHPort -ErrorAction SilentlyContinue
$WriteLogMessage.Invoke(0, @("Windows Firewall rule updated for profile `"$($FirewallProfile)`"."))
} }
} }
} }
+5 -10
View File
@@ -44,8 +44,7 @@ cd Invoke-OpenSSHConfiguration
| `-CAInclusionExpression` | String | Regex to filter CAs by Subject or Thumbprint (include matches) | | `-CAInclusionExpression` | String | Regex to filter CAs by Subject or Thumbprint (include matches) |
| `-CAExclusionExpression` | String | Regex to filter CAs by Subject or Thumbprint (exclude 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) | | `-SFTPSubsystemPath` | String | Custom SFTP server path (default: `sftp-server.exe`, configured automatically) |
| `-EnableService` | Switch | Set sshd service to automatic startup | | `-SSHPort` | Int | SSH port number (default: `22`, used for firewall rules) |
| `-StartService` | Switch | Start sshd service if not running |
| `-LogDirectory` | DirectoryInfo | Custom log directory path | | `-LogDirectory` | DirectoryInfo | Custom log directory path |
| `-ContinueOnError` | Switch | Continue execution on non-fatal errors | | `-ContinueOnError` | Switch | Continue execution on non-fatal errors |
@@ -105,8 +104,6 @@ This exports all unexpired Root and Intermediate CA certificates from the Window
-EnableCertificateAuthentication ` -EnableCertificateAuthentication `
-EnablePubkeyAuthentication ` -EnablePubkeyAuthentication `
-DisablePasswordAuthentication ` -DisablePasswordAuthentication `
-EnableService `
-StartService `
-LogDirectory 'C:\Logs\OpenSSH' -LogDirectory 'C:\Logs\OpenSSH'
``` ```
@@ -115,9 +112,7 @@ This exports all unexpired Root and Intermediate CA certificates from the Window
```powershell ```powershell
.\Invoke-OpenSSHConfiguration.ps1 -Mode Server ` .\Invoke-OpenSSHConfiguration.ps1 -Mode Server `
-EnablePubkeyAuthentication ` -EnablePubkeyAuthentication `
-DisablePasswordAuthentication ` -DisablePasswordAuthentication
-EnableService `
-StartService
``` ```
### Selective CA Trust (Regex Filtering) ### Selective CA Trust (Regex Filtering)
@@ -203,14 +198,12 @@ The toolkit includes reusable functions in `Toolkit\Functions\`:
### Current Gaps (Not Yet Implemented) ### Current Gaps (Not Yet Implemented)
**Server Configuration** **Server Configuration**
- Port configuration (change from default 22)
- User/group restrictions (AllowUsers, AllowGroups) - User/group restrictions (AllowUsers, AllowGroups)
- SSH banner/MOTD configuration - SSH banner/MOTD configuration
- ListenAddress binding to specific interfaces - ListenAddress binding to specific interfaces
**Security** **Security**
- No automatic ACL/permission setting on generated keys - No automatic ACL/permission setting on generated keys
- No Windows Firewall rule creation
**Management** **Management**
- No uninstall/rollback capability - No uninstall/rollback capability
@@ -218,7 +211,9 @@ The toolkit includes reusable functions in `Toolkit\Functions\`:
### Features Implemented ### Features Implemented
- ✅ Password authentication control (`-DisablePasswordAuthentication`) - ✅ Password authentication control (`-DisablePasswordAuthentication`)
- ✅ Service auto-start (`-EnableService`, `-StartService`) - ✅ 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 backup before modification (automatic timestamped backups)
- ✅ Config validation (`sshd -t`) before restart with automatic rollback - ✅ Config validation (`sshd -t`) before restart with automatic rollback
- ✅ CA selection via regex (`-CAInclusionExpression`, `-CAExclusionExpression`) - ✅ CA selection via regex (`-CAInclusionExpression`, `-CAExclusionExpression`)