parts/k8s/windowsinstallopensshfunc.ps1 (74 lines of code) (raw):
function
Install-OpenSSH {
Param(
[Parameter(Mandatory = $true)][string[]]
$SSHKeys
)
$adminpath = "c:\ProgramData\ssh"
$adminfile = "administrators_authorized_keys"
$sshdService = Get-Service | ? Name -like 'sshd'
if ($sshdService.Count -eq 0)
{
Write-Log "Installing OpenSSH"
$isAvailable = Get-WindowsCapability -Online | ? Name -like 'OpenSSH*'
if (!$isAvailable) {
throw "OpenSSH is not available on this machine"
}
# Somehow openssh client got added to Windows 2019 base image.
# Remove openssh client in order to install the server.
Remove-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
}
else
{
if ($sshdService.Status -ne 'Running') {
Write-Log "OpenSSH Server service detected but not running. Reinstalling OpenSSH..."
# Somehow openssh client got added to Windows 2019 base image.
# Remove openssh client in order to install the server.
Remove-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Remove-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
}
else {
Write-Log "OpenSSH Server service detected and running - skipping online install..."
}
}
# It’s by design that files within the C:\Windows\System32\ folder are not modifiable.
# When the OpenSSH Server starts, it copies C:\windows\system32\openssh\sshd_config_default to C:\programdata\ssh\sshd_config, if the file does not already exist.
$OriginalConfigPath = "C:\windows\system32\OpenSSH\sshd_config_default"
$ConfigDirectory = "C:\programdata\ssh"
New-Item -ItemType Directory -Force -Path $ConfigDirectory
$ConfigPath = $ConfigDirectory + "\sshd_config"
Write-Log "Updating $ConfigPath for CVE-2023-48795"
$ModifiedConfigContents = Get-Content $OriginalConfigPath `
| %{ $_ -replace "#RekeyLimit default none", "$&`r`n# Disable cipher to mitigate CVE-2023-48795`r`nCiphers -chacha20-poly1305@openssh.com`r`nMacs -*-etm@openssh.com`r`n" }
Write-Log "Updating $ConfigPath for CVE-2006-5051"
$ModifiedConfigContents = $ModifiedConfigContents.Replace("#LoginGraceTime 2m", "LoginGraceTime 0")
Stop-Service sshd
Out-File -FilePath $ConfigPath -InputObject $ModifiedConfigContents -Encoding UTF8
Start-Service sshd
if (!(Test-Path "$adminpath")) {
Write-Log "Created new file and text content added"
New-Item -path $adminpath -name $adminfile -type "file" -value ""
}
Write-Log "$adminpath found."
Write-Log "Adding keys to: $adminpath\$adminfile ..."
$SSHKeys | foreach-object {
Add-Content $adminpath\$adminfile $_
}
Write-Log "Setting required permissions..."
icacls $adminpath\$adminfile /remove "NT AUTHORITY\Authenticated Users"
icacls $adminpath\$adminfile /inheritance:r
icacls $adminpath\$adminfile /grant SYSTEM:`(F`)
icacls $adminpath\$adminfile /grant BUILTIN\Administrators:`(F`)
Write-Log "Restarting sshd service..."
Restart-Service sshd
# OPTIONAL but recommended:
Set-Service -Name sshd -StartupType 'Automatic'
# Confirm the Firewall rule is configured. It should be created automatically by setup.
$firewall = Get-NetFirewallRule -Name *ssh*
if (!$firewall) {
throw "OpenSSH is firewall is not configured properly"
}
Write-Log "OpenSSH installed and configured successfully"
}