Enhanced OpenSSH configuration with certificate auth, service management, and security features

Features added:
- Certificate authentication with Windows CA trust bridge
- CA filtering via regex inclusion/exclusion expressions
- Password authentication disable option
- Service auto-start and start management
- Config backup before modification (timestamped)
- Config validation (sshd -t) with automatic rollback on failure
- SFTP subsystem configured by default
- Public key management with deduplication
- Key pair generation (ed25519, rsa, ecdsa)

Toolkit enhancements:
- ConvertFrom-CertificateToPEM: Added -IncludePrivateKey, -ThumbprintList, -CreateCABundle
- Updated coding standards in PowershellScripts.md

Documentation:
- Comprehensive README with examples and troubleshooting
- Added .augment folder to .gitignore
This commit is contained in:
GraceSolutions
2026-05-01 15:17:43 -04:00
parent cd982938d3
commit 825dfdab79
5 changed files with 1337 additions and 84 deletions
+547 -16
View File
@@ -43,22 +43,64 @@
[CmdletBinding(SupportsShouldProcess=$True)]
Param
(
(
[Parameter(Mandatory=$False)]
[ValidateNotNullOrEmpty()]
[Alias('TSVars', 'TSVs')]
[String[]]$TaskSequenceVariables,
[Alias('M')]
[ValidateSet('Client', 'Server')]
[String]$Mode,
[Parameter(Mandatory=$False)]
[ValidateNotNullOrEmpty()]
[Alias('TSVD', 'TSVDL')]
[String[]]$TSVariableDecodeList,
[Alias('PKL')]
[String[]]$PublicKeyList,
[Parameter(Mandatory=$False)]
[Switch]$GenerateKeyPair,
[Parameter(Mandatory=$False)]
[ValidateSet('rsa', 'ecdsa', 'ed25519')]
[String]$KeyType = 'ed25519',
[Parameter(Mandatory=$False)]
[ValidateSet(256, 384, 521, 2048, 3072, 4096)]
[Int]$KeyBits,
[Parameter(Mandatory=$False)]
[Switch]$EnablePubkeyAuthentication,
[Parameter(Mandatory=$False)]
[Switch]$DisablePasswordAuthentication,
[Parameter(Mandatory=$False)]
[Switch]$EnableCertificateAuthentication,
[Parameter(Mandatory=$False)]
[Switch]$TrustWindowsCertificateAuthorities,
[Parameter(Mandatory=$False)]
[ValidateNotNullOrEmpty()]
[String]$CAInclusionExpression,
[Parameter(Mandatory=$False)]
[ValidateNotNullOrEmpty()]
[String]$CAExclusionExpression,
[Parameter(Mandatory=$False)]
[ValidateNotNullOrEmpty()]
[String]$SFTPSubsystemPath,
[Parameter(Mandatory=$False)]
[Switch]$EnableService,
[Parameter(Mandatory=$False)]
[Switch]$StartService,
[Parameter(Mandatory=$False)]
[ValidateNotNullOrEmpty()]
[Alias('LogDir', 'LogPath')]
[System.IO.DirectoryInfo]$LogDirectory,
[Parameter(Mandatory=$False)]
[Switch]$ContinueOnError
)
@@ -110,9 +152,9 @@ Switch (Test-ProcessElevationStatus)
#region Set default parameter values
Switch ($True)
{
{([System.String]::IsNullOrEmpty($ExampleVariable) -eq $True) -or ([System.String]::IsNullOrWhiteSpace($ExampleVariable) -eq $True)}
{([System.String]::IsNullOrEmpty($Mode) -eq $True) -or ([System.String]::IsNullOrWhiteSpace($Mode) -eq $True)}
{
}
}
#endregion
@@ -230,13 +272,21 @@ Switch (Test-ProcessElevationStatus)
$StartProcessWithOutputParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
$StartProcessWithOutputParameters.FilePath = 'msiexec.exe'
#$StartProcessWithOutputParameters.WorkingDirectory = "$($Env:SystemDrive)\Users\Public\Documents"
$StartProcessWithOutputParameters.ArgumentList = New-Object -TypeName 'System.Collections.Generic.List[System.String]'
$StartProcessWithOutputParameters.ArgumentList.Add('/i')
$StartProcessWithOutputParameters.ArgumentList.Add("`"$($GitRepositoryReleaseAssetListItem.DestinationPath.FullName)`"")
Switch ($True)
{
{([System.String]::IsNullOrEmpty($Mode) -eq $False) -and ([System.String]::IsNullOrWhiteSpace($Mode) -eq $False)}
{
$StartProcessWithOutputParameters.ArgumentList.Add("ADDLOCAL=$($Mode)")
}
}
$StartProcessWithOutputParameters.ArgumentList.Add('/qn')
$StartProcessWithOutputParameters.ArgumentList.Add('/norestart')
$StartProcessWithOutputParameters.ArgumentList.Add("/l*v `"$($ExecutionLogPath.FullName)`"")
$StartProcessWithOutputParameters.ArgumentList.Add("/l*v `"$($ExecutionLogPath.FullName)`"")
$StartProcessWithOutputParameters.AcceptableExitCodeList = New-Object -TypeName 'System.Collections.Generic.List[System.String]'
$StartProcessWithOutputParameters.AcceptableExitCodeList.Add('0')
$StartProcessWithOutputParameters.AcceptableExitCodeList.Add('3010')
@@ -251,7 +301,7 @@ Switch (Test-ProcessElevationStatus)
$MSIProductInfo = Get-MSIPropertyList -Path ($GitRepositoryReleaseAssetListItem.DestinationPath.FullName)
$WriteLogMessage.Invoke(0, @("Attempting to release binary $($GitRepositoryReleaseAssetListCounter) of $($GitRepositoryReleaseAssetListCount). Please Wait...", "Manufacturer: $($MSIProductInfo.Manufacturer)", "ProductName: $($MSIProductInfo.ProductName)", "ProductVersion: $($MSIProductInfo.ProductVersion)", "Product Language: $($MSIProductInfo.ProductLanguage)"))
$WriteLogMessage.Invoke(0, @("Attempting to install release binary $($GitRepositoryReleaseAssetListCounter) of $($GitRepositoryReleaseAssetListCount). Please Wait...", "Manufacturer: $($MSIProductInfo.Manufacturer)", "ProductName: $($MSIProductInfo.ProductName)", "ProductVersion: $($MSIProductInfo.ProductVersion)", "Product Language: $($MSIProductInfo.ProductLanguage)"))
$StartProcessWithOutputResult = Start-ProcessWithOutput @StartProcessWithOutputParameters
@@ -268,11 +318,492 @@ Switch (Test-ProcessElevationStatus)
{
{($_ -eq $True)}
{
###Do configuration stuff here
#PublicKeys - New and from list idepotent
#Certs - From windows store to PEM
#Options etc
#region Define OpenSSH Paths and Settings
[System.IO.DirectoryInfo]$OpenSSHProgramDataDirectory = [System.IO.Path]::Combine($Env:ProgramData, 'ssh')
[System.IO.FileInfo]$SSHDConfigPath = [System.IO.Path]::Combine($OpenSSHProgramDataDirectory.FullName, 'sshd_config')
[System.IO.FileInfo]$AdministratorsAuthorizedKeysPath = [System.IO.Path]::Combine($OpenSSHProgramDataDirectory.FullName, 'administrators_authorized_keys')
[System.Text.Encoding]$OpenSSHFileEncoding = [System.Text.Encoding]::ASCII
#endregion
#region Generate Key Pair
Switch ($GenerateKeyPair.IsPresent)
{
{($_ -eq $True)}
{
$WriteLogMessage.Invoke(0, @("Attempting to generate SSH key pair. Please Wait..."))
[System.IO.DirectoryInfo]$SSHKeyDirectory = [System.IO.Path]::Combine($OpenSSHProgramDataDirectory.FullName, 'keys')
Switch ($SSHKeyDirectory.Exists)
{
{($_ -eq $False)}
{
$WriteLogMessage.Invoke(0, @("Attempting to create directory `"$($SSHKeyDirectory.FullName)`". Please Wait..."))
$Null = [System.IO.Directory]::CreateDirectory($SSHKeyDirectory.FullName)
}
}
$KeyFileName = "ssh_host_$($KeyType)_key"
[System.IO.FileInfo]$PrivateKeyPath = [System.IO.Path]::Combine($SSHKeyDirectory.FullName, $KeyFileName)
[System.IO.FileInfo]$PublicKeyPath = [System.IO.Path]::Combine($SSHKeyDirectory.FullName, "$($KeyFileName).pub")
Switch ($PrivateKeyPath.Exists)
{
{($_ -eq $True)}
{
$WriteLogMessage.Invoke(0, @("SSH key pair already exists at `"$($PrivateKeyPath.FullName)`". Skipping generation."))
}
Default
{
$SSHKeygenArgumentList = New-Object -TypeName 'System.Collections.Generic.List[System.String]'
$SSHKeygenArgumentList.Add('-t')
$SSHKeygenArgumentList.Add($KeyType)
Switch (($Null -ine $KeyBits) -and ($KeyBits -gt 0))
{
{($_ -eq $True)}
{
$SSHKeygenArgumentList.Add('-b')
$SSHKeygenArgumentList.Add($KeyBits.ToString())
}
}
$SSHKeygenArgumentList.Add('-f')
$SSHKeygenArgumentList.Add("`"$($PrivateKeyPath.FullName)`"")
$SSHKeygenArgumentList.Add('-N')
$SSHKeygenArgumentList.Add('""')
$SSHKeygenArgumentList.Add('-C')
$SSHKeygenArgumentList.Add("`"$($Env:COMPUTERNAME)`"")
$StartProcessWithOutputParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
$StartProcessWithOutputParameters.FilePath = 'ssh-keygen.exe'
$StartProcessWithOutputParameters.ArgumentList = $SSHKeygenArgumentList
$StartProcessWithOutputParameters.AcceptableExitCodeList = New-Object -TypeName 'System.Collections.Generic.List[System.String]'
$StartProcessWithOutputParameters.AcceptableExitCodeList.Add('0')
$StartProcessWithOutputParameters.CreateNoWindow = $True
$StartProcessWithOutputParameters.LogOutput = $True
$StartProcessWithOutputParameters.ContinueOnError = $False
$StartProcessWithOutputParameters.Verbose = $True
$WriteLogMessage.Invoke(0, @("Generating $($KeyType) key pair at `"$($PrivateKeyPath.FullName)`". Please Wait..."))
$StartProcessWithOutputResult = Start-ProcessWithOutput @StartProcessWithOutputParameters
$WriteLogMessage.Invoke(0, @("SSH key pair generated successfully."))
}
}
}
}
#endregion
#region Add Public Keys
Switch (($Null -ine $PublicKeyList) -and ($PublicKeyList.Count -gt 0))
{
{($_ -eq $True)}
{
$WriteLogMessage.Invoke(0, @("Attempting to add $($PublicKeyList.Count) public key(s) to authorized_keys. Please Wait..."))
$ExistingAuthorizedKeys = New-Object -TypeName 'System.Collections.Generic.HashSet[System.String]'
Switch ($AdministratorsAuthorizedKeysPath.Exists)
{
{($_ -eq $True)}
{
$ExistingContent = [System.IO.File]::ReadAllLines($AdministratorsAuthorizedKeysPath.FullName)
ForEach ($Line In $ExistingContent)
{
Switch (([System.String]::IsNullOrEmpty($Line) -eq $False) -and ([System.String]::IsNullOrWhiteSpace($Line) -eq $False))
{
{($_ -eq $True)}
{
$Null = $ExistingAuthorizedKeys.Add($Line.Trim())
}
}
}
}
}
$KeysToAdd = New-Object -TypeName 'System.Collections.Generic.List[System.String]'
$PublicKeyListCounter = 1
ForEach ($PublicKey In $PublicKeyList)
{
$PublicKeyTrimmed = $PublicKey.Trim()
Switch ($ExistingAuthorizedKeys.Contains($PublicKeyTrimmed))
{
{($_ -eq $True)}
{
$WriteLogMessage.Invoke(0, @("Public key $($PublicKeyListCounter) of $($PublicKeyList.Count) already exists. Skipping."))
}
Default
{
$WriteLogMessage.Invoke(0, @("Adding public key $($PublicKeyListCounter) of $($PublicKeyList.Count)."))
$KeysToAdd.Add($PublicKeyTrimmed)
}
}
$PublicKeyListCounter++
}
Switch ($KeysToAdd.Count -gt 0)
{
{($_ -eq $True)}
{
$WriteLogMessage.Invoke(0, @("Appending $($KeysToAdd.Count) new public key(s) to `"$($AdministratorsAuthorizedKeysPath.FullName)`". Please Wait..."))
$Null = [System.IO.File]::AppendAllLines($AdministratorsAuthorizedKeysPath.FullName, $KeysToAdd, $OpenSSHFileEncoding)
$WriteLogMessage.Invoke(0, @("Public keys added successfully."))
}
}
}
}
#endregion
#region Export Windows CA Certificates to PEM
Switch ($TrustWindowsCertificateAuthorities.IsPresent)
{
{($_ -eq $True)}
{
$WriteLogMessage.Invoke(0, @("Attempting to export Windows CA certificates to PEM format. Please Wait..."))
$CertificateExpirationThreshold = Get-Date
$CertificateStorePathList = New-Object -TypeName 'System.Collections.Generic.List[System.String]'
$CertificateStorePathList.Add('Cert:\LocalMachine\Root')
$CertificateStorePathList.Add('Cert:\LocalMachine\CA')
$CACertificates = Get-ChildItem -Path $CertificateStorePathList | Where-Object {($_.NotAfter -gt $CertificateExpirationThreshold) -and ($_.Extensions | Where-Object {($_.Oid.FriendlyName -iin @('Basic Constraints')) -and ($_.CertificateAuthority -eq $True)})}
#region Apply CA Inclusion Filter
Switch (([System.String]::IsNullOrEmpty($CAInclusionExpression) -eq $False) -and ([System.String]::IsNullOrWhiteSpace($CAInclusionExpression) -eq $False))
{
{($_ -eq $True)}
{
$WriteLogMessage.Invoke(0, @("Applying CA inclusion filter: `"$($CAInclusionExpression)`""))
$CACertificates = $CACertificates | Where-Object {($_.Subject -imatch $CAInclusionExpression) -or ($_.Thumbprint -imatch $CAInclusionExpression)}
}
}
#endregion
#region Apply CA Exclusion Filter
Switch (([System.String]::IsNullOrEmpty($CAExclusionExpression) -eq $False) -and ([System.String]::IsNullOrWhiteSpace($CAExclusionExpression) -eq $False))
{
{($_ -eq $True)}
{
$WriteLogMessage.Invoke(0, @("Applying CA exclusion filter: `"$($CAExclusionExpression)`""))
$CACertificates = $CACertificates | Where-Object {($_.Subject -inotmatch $CAExclusionExpression) -and ($_.Thumbprint -inotmatch $CAExclusionExpression)}
}
}
#endregion
$CACertificatesCount = ($CACertificates | Measure-Object).Count
$WriteLogMessage.Invoke(0, @("Found $($CACertificatesCount) CA certificate(s) matching criteria."))
Switch ($CACertificatesCount -gt 0)
{
{($_ -eq $True)}
{
$ConvertFromCertificateToPEMParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
$ConvertFromCertificateToPEMParameters.CertificateList = $CACertificates
$ConvertFromCertificateToPEMParameters.Export = $True
$ConvertFromCertificateToPEMParameters.ExportRootDirectory = $OpenSSHProgramDataDirectory.FullName
$ConvertFromCertificateToPEMParameters.CreateCABundle = $True
$ConvertFromCertificateToPEMParameters.CABundleFileName = 'OpenSSH-TrustedCertificateAuthorities-LocalMachine.pem'
$ConvertFromCertificateToPEMParameters.ContinueOnError = $False
$ConvertFromCertificateToPEMParameters.Verbose = $True
$ConvertFromCertificateToPEMResult = ConvertFrom-CertificateToPEM @ConvertFromCertificateToPEMParameters
$CABundleResult = $ConvertFromCertificateToPEMResult | Where-Object {($_.Type -ieq 'CABundle')}
Switch ($Null -ine $CABundleResult)
{
{($_ -eq $True)}
{
$WriteLogMessage.Invoke(0, @("CA bundle exported successfully to `"$($CABundleResult.Path)`" with $($CABundleResult.CertificateCount) certificate(s)."))
}
}
}
}
}
}
#endregion
#region Configure sshd_config
Switch ($SSHDConfigPath.Exists)
{
{($_ -eq $True)}
{
$WriteLogMessage.Invoke(0, @("Attempting to configure sshd_config at `"$($SSHDConfigPath.FullName)`". Please Wait..."))
#region Backup Existing Configuration
$SSHDConfigBackupPath = [System.IO.FileInfo][System.IO.Path]::Combine($OpenSSHProgramDataDirectory.FullName, "sshd_config.backup.$($GetCurrentDateTimeFileFormat.Invoke())")
$WriteLogMessage.Invoke(0, @("Creating backup of sshd_config to `"$($SSHDConfigBackupPath.FullName)`". Please Wait..."))
$Null = [System.IO.File]::Copy($SSHDConfigPath.FullName, $SSHDConfigBackupPath.FullName, $True)
$WriteLogMessage.Invoke(0, @("Backup created successfully."))
#endregion
$SSHDConfigContent = [System.IO.File]::ReadAllText($SSHDConfigPath.FullName)
$SSHDConfigModified = $False
#region Enable PubkeyAuthentication
Switch ($EnablePubkeyAuthentication.IsPresent -eq $True)
{
{($_ -eq $True)}
{
$PubkeyAuthPattern = '(?m)^#?\s*PubkeyAuthentication\s+.*$'
$PubkeyAuthReplacement = 'PubkeyAuthentication yes'
Switch ($SSHDConfigContent -imatch $PubkeyAuthPattern)
{
{($_ -eq $True)}
{
$SSHDConfigContent = [System.Text.RegularExpressions.Regex]::Replace($SSHDConfigContent, $PubkeyAuthPattern, $PubkeyAuthReplacement)
$SSHDConfigModified = $True
$WriteLogMessage.Invoke(0, @("Enabled PubkeyAuthentication."))
}
Default
{
$SSHDConfigContent = $SSHDConfigContent + "`r`n$($PubkeyAuthReplacement)"
$SSHDConfigModified = $True
$WriteLogMessage.Invoke(0, @("Added PubkeyAuthentication setting."))
}
}
}
}
#endregion
#region Disable PasswordAuthentication
Switch ($DisablePasswordAuthentication.IsPresent -eq $True)
{
{($_ -eq $True)}
{
$PasswordAuthPattern = '(?m)^#?\s*PasswordAuthentication\s+.*$'
$PasswordAuthReplacement = 'PasswordAuthentication no'
Switch ($SSHDConfigContent -imatch $PasswordAuthPattern)
{
{($_ -eq $True)}
{
$SSHDConfigContent = [System.Text.RegularExpressions.Regex]::Replace($SSHDConfigContent, $PasswordAuthPattern, $PasswordAuthReplacement)
$SSHDConfigModified = $True
$WriteLogMessage.Invoke(0, @("Disabled PasswordAuthentication."))
}
Default
{
$SSHDConfigContent = $SSHDConfigContent + "`r`n$($PasswordAuthReplacement)"
$SSHDConfigModified = $True
$WriteLogMessage.Invoke(0, @("Added PasswordAuthentication setting (disabled)."))
}
}
}
}
#endregion
#region Configure SFTP Subsystem (Default)
$SFTPPath = $SFTPSubsystemPath
Switch (([System.String]::IsNullOrEmpty($SFTPPath) -eq $True) -or ([System.String]::IsNullOrWhiteSpace($SFTPPath) -eq $True))
{
{($_ -eq $True)}
{
$SFTPPath = 'sftp-server.exe'
}
}
$SubsystemPattern = '(?m)^#?\s*Subsystem\s+sftp\s+.*$'
$SubsystemReplacement = "Subsystem sftp $($SFTPPath)"
Switch ($SSHDConfigContent -imatch $SubsystemPattern)
{
{($_ -eq $True)}
{
$CurrentSubsystemMatch = [System.Text.RegularExpressions.Regex]::Match($SSHDConfigContent, $SubsystemPattern)
Switch ($CurrentSubsystemMatch.Value -ine $SubsystemReplacement)
{
{($_ -eq $True)}
{
$SSHDConfigContent = [System.Text.RegularExpressions.Regex]::Replace($SSHDConfigContent, $SubsystemPattern, $SubsystemReplacement)
$SSHDConfigModified = $True
$WriteLogMessage.Invoke(0, @("Configured SFTP subsystem: $($SFTPPath)"))
}
}
}
Default
{
$SSHDConfigContent = $SSHDConfigContent + "`r`n$($SubsystemReplacement)"
$SSHDConfigModified = $True
$WriteLogMessage.Invoke(0, @("Added SFTP subsystem configuration."))
}
}
#endregion
#region Configure TrustedUserCAKeys for Certificate Authentication
Switch (($EnableCertificateAuthentication.IsPresent -eq $True) -and ($TrustWindowsCertificateAuthorities.IsPresent -eq $True))
{
{($_ -eq $True)}
{
[System.IO.FileInfo]$CABundlePath = [System.IO.Path]::Combine($OpenSSHProgramDataDirectory.FullName, 'OpenSSH-TrustedCertificateAuthorities-LocalMachine.pem')
Switch ($CABundlePath.Exists)
{
{($_ -eq $True)}
{
$TrustedCAKeysPattern = '(?m)^#?\s*TrustedUserCAKeys\s+.*$'
$TrustedCAKeysReplacement = "TrustedUserCAKeys $($CABundlePath.FullName)"
Switch ($SSHDConfigContent -imatch $TrustedCAKeysPattern)
{
{($_ -eq $True)}
{
$SSHDConfigContent = [System.Text.RegularExpressions.Regex]::Replace($SSHDConfigContent, $TrustedCAKeysPattern, $TrustedCAKeysReplacement)
$SSHDConfigModified = $True
$WriteLogMessage.Invoke(0, @("Configured TrustedUserCAKeys to `"$($CABundlePath.FullName)`"."))
}
Default
{
$SSHDConfigContent = $SSHDConfigContent + "`r`n$($TrustedCAKeysReplacement)"
$SSHDConfigModified = $True
$WriteLogMessage.Invoke(0, @("Added TrustedUserCAKeys setting."))
}
}
}
}
}
}
#endregion
#region Write sshd_config if Modified
Switch ($SSHDConfigModified -eq $True)
{
{($_ -eq $True)}
{
$WriteLogMessage.Invoke(0, @("Writing updated sshd_config. Please Wait..."))
[System.IO.File]::WriteAllText($SSHDConfigPath.FullName, $SSHDConfigContent, $OpenSSHFileEncoding)
$WriteLogMessage.Invoke(0, @("sshd_config updated successfully."))
#region Validate Configuration
$WriteLogMessage.Invoke(0, @("Validating sshd_config with sshd -t. Please Wait..."))
$SSHDExePath = [System.IO.FileInfo][System.IO.Path]::Combine($Env:ProgramFiles, 'OpenSSH', 'sshd.exe')
Switch ($SSHDExePath.Exists -eq $True)
{
{($_ -eq $True)}
{
$ValidateConfigParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
$ValidateConfigParameters.FilePath = $SSHDExePath.FullName
$ValidateConfigParameters.ArgumentList = New-Object -TypeName 'System.Collections.Generic.List[System.String]'
$ValidateConfigParameters.ArgumentList.Add('-t')
$ValidateConfigParameters.AcceptableExitCodeList = New-Object -TypeName 'System.Collections.Generic.List[System.String]'
$ValidateConfigParameters.AcceptableExitCodeList.Add('0')
$ValidateConfigParameters.CreateNoWindow = $True
$ValidateConfigParameters.LogOutput = $True
$ValidateConfigParameters.ContinueOnError = $True
$ValidateConfigParameters.Verbose = $True
$ValidateConfigResult = Start-ProcessWithOutput @ValidateConfigParameters
Switch ($ValidateConfigResult.ExitCode -eq 0)
{
{($_ -eq $True)}
{
$WriteLogMessage.Invoke(0, @("sshd_config validation passed."))
$WriteLogMessage.Invoke(0, @("Attempting to restart sshd service to apply configuration changes. Please Wait..."))
$Null = Restart-Service -Name 'sshd' -Force -ErrorAction SilentlyContinue
$WriteLogMessage.Invoke(0, @("sshd service restarted."))
}
Default
{
$WriteLogMessage.Invoke(2, @("sshd_config validation failed. Restoring backup..."))
$Null = [System.IO.File]::Copy($SSHDConfigBackupPath.FullName, $SSHDConfigPath.FullName, $True)
$WriteLogMessage.Invoke(0, @("Backup restored. Configuration changes reverted."))
}
}
}
Default
{
$WriteLogMessage.Invoke(1, @("sshd.exe not found at `"$($SSHDExePath.FullName)`". Skipping validation."))
$WriteLogMessage.Invoke(0, @("Attempting to restart sshd service to apply configuration changes. Please Wait..."))
$Null = Restart-Service -Name 'sshd' -Force -ErrorAction SilentlyContinue
$WriteLogMessage.Invoke(0, @("sshd service restarted."))
}
}
#endregion
}
Default
{
$WriteLogMessage.Invoke(0, @("No changes required to sshd_config."))
}
}
#endregion
}
}
#endregion
#region Service Management
Switch ($EnableService.IsPresent -eq $True)
{
{($_ -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."))
}
}
Switch ($StartService.IsPresent -eq $True)
{
{($_ -eq $True)}
{
$SSHDService = Get-Service -Name 'sshd' -ErrorAction SilentlyContinue
Switch ($Null -ine $SSHDService)
{
{($_ -eq $True)}
{
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
{
$WriteLogMessage.Invoke(0, @("sshd service is already running."))
}
}
}
}
}
}
#endregion
}
}
#endregion