Skip to content

Commit a41e3a3

Browse files
committed
Install and use Microsoft provide OpenSSH
This replaces the OpenSSH which had been installed using OpenSSH-Win64.zip. The configuration file structure and location have changed slightly.
1 parent 695743b commit a41e3a3

File tree

11 files changed

+1107
-1389
lines changed

11 files changed

+1107
-1389
lines changed

lib/packer/config/templates/provision_windows2019.json.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@
147147
"inline": [
148148
"$ErrorActionPreference = \"Stop\";",
149149
"trap { $host.SetShouldExit(1) }",
150-
"Install-SSHD -SSHZipFile 'C:\\provision\\OpenSSH-Win64.zip'"
150+
"Install-SSHD"
151151
]
152152
},
153153
{

modules/BOSH.SSH/BOSH.SSH.Tests.ps1

Lines changed: 170 additions & 211 deletions
Large diffs are not rendered by default.

modules/BOSH.SSH/BOSH.SSH.psd1

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66
Copyright = '(c) 2017 BOSH'
77
Description = 'Install Microsoft SSHD'
88
PowerShellVersion = '4.0'
9-
FunctionsToExport = @('Install-SSHD',
10-
'Enable-SSHD',
11-
'Remove-SSHKeys')
9+
RequiredModules = @('BOSH.Utils')
10+
FunctionsToExport = @('Install-SSHD', 'Enable-SSHD', 'Remove-SSHKeys')
1211
CmdletsToExport = @()
1312
VariablesToExport = '*'
1413
AliasesToExport = @()

modules/BOSH.SSH/BOSH.SSH.psm1

Lines changed: 38 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,144 +1,71 @@
11
function Install-SSHD
22
{
3-
param (
4-
[string]$SSHZipFile = $( Throw "Provide an SSHD zipfile" )
5-
)
6-
7-
New-Item "$env:PROGRAMFILES\SSHTemp" -Type Directory -Force
8-
Open-Zip -ZipFile $SSHZipFile -OutPath "$env:PROGRAMFILES\SSHTemp"
9-
10-
$ConfigPath = "$env:PROGRAMFILES\SSHTemp\OpenSSH-Win64\sshd_config_default"
11-
$ModifiedConfigContents = Edit-DefaultOpenSSHConfig -ConfigPath $ConfigPath
12-
Remove-Item -Force $ConfigPath
13-
Out-File -FilePath $ConfigPath -InputObject $ModifiedConfigContents -Encoding UTF8
14-
15-
Move-Item -Force "$env:PROGRAMFILES\SSHTemp\OpenSSH-Win64" "$env:PROGRAMFILES\OpenSSH"
16-
Remove-Item -Force "$env:PROGRAMFILES\SSHTemp"
17-
18-
# Remove users from 'OpenSSH' before installing. The install process
19-
# will add back permissions for the NT AUTHORITY\Authenticated Users for some files
20-
Protect-Dir -path "$env:PROGRAMFILES\OpenSSH"
21-
22-
Push-Location "$env:PROGRAMFILES\OpenSSH"
23-
powershell -ExecutionPolicy Bypass -File install-sshd.ps1
24-
Pop-Location
3+
if (Get-OSVersion == "windows2019") {
4+
# Microsoft privided OpenSSH must be installed on Windows 2019
5+
# => https://learn.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse?tabs=powershell&pivots=windows-server-2019
6+
$sshPackages = @("OpenSSH.Client", "OpenSSH.Server")
7+
foreach ($sshPackage in $sshPackages)
8+
{
9+
Get-WindowsCapability -Online -Name "$sshPackage*" `
10+
| Where-Object { $_.State -eq "NotPresent" } `
11+
| Add-WindowsCapability -Online
12+
}
13+
}
2514

26-
# # Grant NT AUTHORITY\Authenticated Users access to .EXEs and the .DLL in OpenSSH
27-
$FileNames = @(
28-
"libcrypto.dll",
29-
"scp.exe",
30-
"sftp-server.exe",
31-
"sftp.exe",
32-
"ssh-add.exe",
33-
"ssh-agent.exe",
34-
"ssh-keygen.exe",
35-
"ssh-keyscan.exe",
36-
"ssh-shellhost.exe",
37-
"ssh.exe",
38-
"sshd.exe"
39-
)
40-
Invoke-CACL -FileNames $FileNames
15+
Edit-DefaultOpenSSHConfig
4116

4217
Set-Service -Name sshd -StartupType Disabled
43-
# ssh-agent is not the same as ssh-agent in *nix openssh
4418
Set-Service -Name ssh-agent -StartupType Disabled
4519
}
4620

4721
function Enable-SSHD
4822
{
49-
if ($null -eq (Get-NetFirewallRule | Where-Object { $_.DisplayName -ieq 'SSH' }))
50-
{
51-
"Creating firewall rule for SSH"
52-
New-NetFirewallRule -Protocol TCP -LocalPort 22 -Direction Inbound -Action Allow -DisplayName SSH
53-
}
54-
else
55-
{
56-
"Firewall rule for SSH already exists"
57-
}
58-
59-
$InfFilePath = "$env:WINDIR\Temp\enable-ssh.inf"
60-
61-
$InfFileContents = @'
62-
[Unicode]
63-
Unicode=yes
64-
[Version]
65-
signature=$CHICAGO$
66-
Revision=1
67-
[Registry Values]
68-
[System Access]
69-
[Privilege Rights]
70-
SeDenyNetworkLogonRight=*S-1-5-32-546
71-
SeAssignPrimaryTokenPrivilege=*S-1-5-19,*S-1-5-20,*S-1-5-80-3847866527-469524349-687026318-516638107-1125189541
72-
'@
73-
$LGPOPath = "$env:WINDIR\LGPO.exe"
74-
if (Test-Path $LGPOPath)
75-
{
76-
Out-File -FilePath $InfFilePath -Encoding unicode -InputObject $InfFileContents -Force
77-
Try
78-
{
79-
Invoke-LGPO -LGPOPath $LGPOPath -InfFilePath $InfFilePath
80-
}
81-
Catch
82-
{
83-
throw "LGPO.exe failed with: $_.Exception.Message"
84-
}
85-
}
86-
else
87-
{
88-
"Did not find $LGPOPath. Assuming existing security policies are sufficient to support ssh."
23+
# Remove existing OpenSSH firewall rule and recreate with '-Profile Any' option
24+
if (Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -ErrorAction SilentlyContinue) {
25+
"Removing firewall rule: 'OpenSSH-Server-In-TCP'"
26+
Remove-NetFirewallRule -Name "OpenSSH-Server-In-TCP"
8927
}
28+
Write-Output "Creating firewall rule 'OpenSSH-Server-In-TCP'"
29+
New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -Profile Any -LocalPort 22
9030

9131
Set-Service -Name sshd -StartupType Automatic
92-
# ssh-agent is not the same as ssh-agent in *nix openssh
9332
Set-Service -Name ssh-agent -StartupType Automatic
9433

9534
Remove-SSHKeys
9635
}
9736

9837
function Remove-SSHKeys
9938
{
100-
$SSHDir = "C:\Program Files\OpenSSH"
101-
102-
Push-Location $SSHDir
103-
New-Item -ItemType Directory -Path "$env:ProgramData\ssh" -ErrorAction Ignore
104-
10539
"Removing any existing host keys"
10640
Remove-Item -Path "$env:ProgramData\ssh\ssh_host_*" -ErrorAction Ignore
107-
Pop-Location
10841
}
10942

110-
function Invoke-CACL
43+
function Edit-DefaultOpenSSHConfig
11144
{
11245
param (
113-
[string[]] $FileNames = $( Throw "Files not provided" )
46+
[string]$ConfigPath = "$env:windir\System32\OpenSSH\sshd_config_default",
47+
[string]$GeneratedConfigPath = "$env:ProgramData\ssh\sshd_config"
11448
)
11549

116-
foreach ($name in $FileNames)
117-
{
118-
$path = Join-Path "$env:PROGRAMFILES\OpenSSH" $name
119-
cacls.exe $Path /E /P "NT AUTHORITY\Authenticated Users:R"
120-
}
121-
}
50+
Copy-Item -Path $ConfigPath -Destination "$ConfigPath.bak"
12251

123-
function Invoke-LGPO
124-
{
125-
param (
126-
[string]$LGPOPath = $( Throw "Provide LGPO path" ),
127-
[string]$InfFilePath = $( Throw "Provide Inf file path" )
128-
)
129-
& $LGPOPath /s $InfFilePath
130-
}
52+
$OriginalConfig = Get-Content $ConfigPath
53+
Write-Output "Original SSH config at $ConfigPath :"
54+
Write-Output $OriginalConfig
13155

132-
function Edit-DefaultOpenSSHConfig
133-
{
134-
param (
135-
[string]$ConfigPath = $( Throw "Provide openssh default config path" )
136-
)
56+
$ModifiedConfig = $OriginalConfig `
57+
| ForEach-Object{ $_ -replace ".*Match Group administrators.*", "#$&" } `
58+
| ForEach-Object{ $_ -replace ".*AllowGroups administrators.*", "#$&" } `
59+
| ForEach-Object{ $_ -replace ".*AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys.*", "#$&" } `
60+
| ForEach-Object{ $_ -replace "#RekeyLimit default none", "$&`r`n# Disable cipher to mitigate CVE-2023-48795`r`nCiphers [email protected]`r`n" }
13761

138-
$ModifiedConfig = Get-Content $ConfigPath `
139-
| ForEach-Object{ $_ -replace ".*Match Group administrators.*", "#$&" } `
140-
| ForEach-Object{ $_ -replace ".*AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys.*", "#$&" } `
141-
| ForEach-Object{ $_ -replace "#RekeyLimit default none", "$&`r`n# Disable cipher to mitigate CVE-2023-48795`r`nCiphers [email protected]`r`n" }
62+
Write-Output "Modified SSH config at $ConfigPath :"
63+
Write-Output $ModifiedConfig
64+
65+
Remove-Item -Force $ConfigPath
66+
Out-File -FilePath $ConfigPath -InputObject $ModifiedConfig -Encoding UTF8
14267

143-
return $ModifiedConfig
68+
# We need to make sure that the generated config is cleared, so our above changes are applied when the config
69+
# is next generated. If this isnt done, then we may have a config from the prior template.
70+
Remove-Item -Path $GeneratedConfigPath -ErrorAction Ignore
14471
}

modules/BOSH.Utils/BOSH.Utils.Tests.ps1

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
BeforeAll {
22
Import-Module ./BOSH.Utils.psm1
33

4+
$osVersion = "windows2019"
5+
46
# As of now, this function only supports DWords and Strings.
57
function Restore-RegistryState
68
{
@@ -328,7 +330,7 @@ Describe "BOSH.Utils" {
328330
$actualOSVersion = $null
329331

330332
{ Get-OSVersion | Set-Variable -Name "actualOSVersion" -Scope 1 } | Should -Not -Throw
331-
$actualOsVersion | Should -eq "windows2019"
333+
$actualOsVersion | Should -eq $osVersion
332334

333335
Assert-MockCalled Write-Log -Times 1 -Scope It -ParameterFilter { $Message -eq "Found OS version: Windows 2019" } -ModuleName BOSH.Utils
334336
Assert-MockCalled Get-OSVersionString -Times 1 -Scope It -ModuleName BOSH.Utils

spec/packer/config/aws_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@
190190
{"type" => "powershell", "inline" => ["$ErrorActionPreference = \"Stop\";", "trap { $host.SetShouldExit(1) }", "Remove-Account -User Provisioner"]},
191191
{"type" => "powershell", "inline" => ["$ErrorActionPreference = \"Stop\";", "trap { $host.SetShouldExit(1) }", "Protect-CFCell -IaaS aws"]},
192192
{"type" => "file", "source" => "../sshd/OpenSSH-Win64.zip", "destination" => "C:\\provision\\OpenSSH-Win64.zip"},
193-
{"type" => "powershell", "inline" => ["$ErrorActionPreference = \"Stop\";", "trap { $host.SetShouldExit(1) }", "Install-SSHD -SSHZipFile 'C:\\provision\\OpenSSH-Win64.zip'"]},
193+
{"type" => "powershell", "inline" => ["$ErrorActionPreference = \"Stop\";", "trap { $host.SetShouldExit(1) }", "Install-SSHD"]},
194194
{"type"=>"powershell", "inline"=> ["$ErrorActionPreference = \"Stop\";", "trap { $host.SetShouldExit(1) }", "Enable-SSHD"]},
195195
{"type" => "file", "source" => "build/agent.zip", "destination" => "C:\\provision\\agent.zip"},
196196
{"type" => "powershell", "inline" => ["$ErrorActionPreference = \"Stop\";", "trap { $host.SetShouldExit(1) }", "Install-Agent -IaaS aws -agentZipPath 'C:\\provision\\agent.zip'"]},

spec/packer/config/azure_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@
131131
{"type" => "powershell", "inline" => ["$ErrorActionPreference = \"Stop\";", "trap { $host.SetShouldExit(1) }", "Remove-Account -User Provisioner"]},
132132
{"type" => "powershell", "inline" => ["$ErrorActionPreference = \"Stop\";", "trap { $host.SetShouldExit(1) }", "Protect-CFCell -IaaS azure"]},
133133
{"type" => "file", "source" => "../sshd/OpenSSH-Win64.zip", "destination" => "C:\\provision\\OpenSSH-Win64.zip"},
134-
{"type" => "powershell", "inline" => ["$ErrorActionPreference = \"Stop\";", "trap { $host.SetShouldExit(1) }", "Install-SSHD -SSHZipFile 'C:\\provision\\OpenSSH-Win64.zip'"]},
134+
{"type" => "powershell", "inline" => ["$ErrorActionPreference = \"Stop\";", "trap { $host.SetShouldExit(1) }", "Install-SSHD"]},
135135
{"type"=>"powershell", "inline"=> ["$ErrorActionPreference = \"Stop\";", "trap { $host.SetShouldExit(1) }", "Enable-SSHD"]},
136136
{"type" => "file", "source" => "build/agent.zip", "destination" => "C:\\provision\\agent.zip"},
137137
{"type" => "powershell", "inline" => ["$ErrorActionPreference = \"Stop\";", "trap { $host.SetShouldExit(1) }", "Install-Agent -IaaS azure -agentZipPath 'C:\\provision\\agent.zip'"]},

spec/packer/config/gcp_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@
119119
{"type" => "powershell", "inline" => ["$ErrorActionPreference = \"Stop\";", "trap { $host.SetShouldExit(1) }", "Remove-Account -User Provisioner"]},
120120
{"type" => "powershell", "inline" => ["$ErrorActionPreference = \"Stop\";", "trap { $host.SetShouldExit(1) }", "Protect-CFCell -IaaS gcp"]},
121121
{"type" => "file", "source" => "../sshd/OpenSSH-Win64.zip", "destination" => "C:\\provision\\OpenSSH-Win64.zip"},
122-
{"type" => "powershell", "inline" => ["$ErrorActionPreference = \"Stop\";", "trap { $host.SetShouldExit(1) }", "Install-SSHD -SSHZipFile 'C:\\provision\\OpenSSH-Win64.zip'"]},
122+
{"type" => "powershell", "inline" => ["$ErrorActionPreference = \"Stop\";", "trap { $host.SetShouldExit(1) }", "Install-SSHD"]},
123123
{"type"=>"powershell", "inline"=> ["$ErrorActionPreference = \"Stop\";", "trap { $host.SetShouldExit(1) }", "Enable-SSHD"]},
124124
{"type" => "file", "source" => "build/agent.zip", "destination" => "C:\\provision\\agent.zip"},
125125
{"type" => "powershell", "inline" => ["$ErrorActionPreference = \"Stop\";", "trap { $host.SetShouldExit(1) }", "Install-Agent -IaaS gcp -agentZipPath 'C:\\provision\\agent.zip'"]},

stembuild/README.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,6 @@ You will need to construct `assets/StemcellAutomation.zip`. This file represents
240240
**assets/StemcellAutomation.zip files:**
241241
| File | Source / Description |
242242
|-|-|
243-
| OpenSSH-Win64.zip | https://github.com/PowerShell/Win32-OpenSSH/releases |
244243
| bosh-psmodules.zip | https://github.com/cloudfoundry/bosh-psmodules/tree/master/modules |
245244
| agent.zip | A zip constructed using various BOSH executables. See list of necessary files below. |
246245
| deps.json | A JSON file with the SHA256 checksums and optionally the version for each component in this zip. See format below. |
@@ -262,9 +261,6 @@ You will need to construct `assets/StemcellAutomation.zip`. This file represents
262261
**deps.json format:**
263262
```json
264263
{
265-
"OpenSSH-Win64.zip": {
266-
"sha": "SOME-SHA256"
267-
},
268264
"bosh-psmodules.zip": {
269265
"sha": "SOME-SHA256"
270266
},
@@ -280,7 +276,6 @@ You will need to construct `assets/StemcellAutomation.zip`. This file represents
280276

281277
Once you have these files, run:
282278
```bash
283-
OPENSSH_ZIP="OpenSSH-Win64.zip" \
284279
BOSH_PSMODULES_ZIP="bosh-psmodules.zip" \
285280
AGENT_ZIP="agent.zip" \
286281
DEPS_JSON="deps.json" \

0 commit comments

Comments
 (0)