2017-06-27 06:58:29 +02:00
|
|
|
|
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
|
|
|
|
|
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
|
|
|
|
|
#todo: -i -q -v -l -c -C
|
2016-12-19 23:48:14 +01:00
|
|
|
|
#todo: -S -F -V -e
|
2017-05-10 23:47:03 +02:00
|
|
|
|
$tC = 1
|
2017-04-15 01:15:32 +02:00
|
|
|
|
$tI = 0
|
2017-05-12 23:09:50 +02:00
|
|
|
|
$suite = "sshclient"
|
2017-04-15 01:15:32 +02:00
|
|
|
|
|
2017-05-12 19:31:59 +02:00
|
|
|
|
Describe "E2E scenarios for ssh client" -Tags "CI" {
|
2016-12-19 23:48:14 +01:00
|
|
|
|
BeforeAll {
|
2017-04-15 01:15:32 +02:00
|
|
|
|
if($OpenSSHTestInfo -eq $null)
|
|
|
|
|
{
|
2017-06-27 06:58:29 +02:00
|
|
|
|
Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
|
2017-04-15 01:15:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$server = $OpenSSHTestInfo["Target"]
|
|
|
|
|
$port = $OpenSSHTestInfo["Port"]
|
|
|
|
|
$ssouser = $OpenSSHTestInfo["SSOUser"]
|
|
|
|
|
|
2017-05-12 23:09:50 +02:00
|
|
|
|
$testDir = Join-Path $OpenSSHTestInfo["TestDataPath"] $suite
|
2017-04-15 01:15:32 +02:00
|
|
|
|
if(-not (Test-Path $testDir))
|
|
|
|
|
{
|
|
|
|
|
$null = New-Item $testDir -ItemType directory -Force -ErrorAction SilentlyContinue
|
|
|
|
|
}
|
2017-06-27 06:58:29 +02:00
|
|
|
|
$platform = Get-Platform
|
|
|
|
|
$skip = ($platform -eq [PlatformType]::Windows) -and ($PSVersionTable.PSVersion.Major -le 2)
|
2016-12-19 23:48:14 +01:00
|
|
|
|
|
2017-05-12 23:09:50 +02:00
|
|
|
|
<#$testData = @(
|
2016-12-19 23:48:14 +01:00
|
|
|
|
@{
|
2017-01-27 19:47:20 +01:00
|
|
|
|
Title = 'Simple logon no option';
|
2016-12-19 23:48:14 +01:00
|
|
|
|
LogonStr = "$($server.localAdminUserName)@$($server.MachineName)"
|
2017-01-27 19:47:20 +01:00
|
|
|
|
Options = ""
|
2016-12-19 23:48:14 +01:00
|
|
|
|
},
|
|
|
|
|
@{
|
|
|
|
|
Title = 'Simple logon using -C -l option'
|
|
|
|
|
LogonStr = $server.MachineName
|
|
|
|
|
Options = "-C -l $($server.localAdminUserName)"
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
$testData1 = @(
|
|
|
|
|
@{
|
|
|
|
|
Title = "logon using -i -q option"
|
|
|
|
|
LogonStr = "$($server.localAdminUserName)@$($server.MachineName)"
|
|
|
|
|
Options = '-i $identifyFile -q'
|
|
|
|
|
},
|
|
|
|
|
@{
|
2017-01-27 19:47:20 +01:00
|
|
|
|
Title = "logon using -i option"
|
2016-12-19 23:48:14 +01:00
|
|
|
|
LogonStr = "$($server.localAdminUserName)@$($server.MachineName)"
|
2017-01-27 19:47:20 +01:00
|
|
|
|
Options = '-i $identifyFile'
|
2016-12-19 23:48:14 +01:00
|
|
|
|
},
|
|
|
|
|
@{
|
|
|
|
|
Title = "logon using -i -c option"
|
|
|
|
|
LogonStr = "$($server.localAdminUserName)@$($server.MachineName)"
|
|
|
|
|
Options = '-i $identifyFile -c aes256-ctr'
|
|
|
|
|
},
|
2017-05-12 23:09:50 +02:00
|
|
|
|
-V does not redirect to file
|
2016-12-19 23:48:14 +01:00
|
|
|
|
@{
|
|
|
|
|
Title = "logon using -i -V option"
|
|
|
|
|
LogonStr = "$($server.localAdminUserName)@$($server.MachineName)"
|
|
|
|
|
Options = '-i $identifyFile -V'
|
|
|
|
|
SkipVerification = $true
|
2017-05-12 23:09:50 +02:00
|
|
|
|
},
|
2016-12-19 23:48:14 +01:00
|
|
|
|
@{
|
|
|
|
|
Title = 'logon using -i -l option'
|
|
|
|
|
LogonStr = $server.MachineName
|
|
|
|
|
Options = '-i $identifyFile -l $($server.localAdminUserName)'
|
|
|
|
|
}
|
2017-05-12 23:09:50 +02:00
|
|
|
|
)#>
|
2016-12-19 23:48:14 +01:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-15 01:15:32 +02:00
|
|
|
|
BeforeEach {
|
2017-05-12 19:31:59 +02:00
|
|
|
|
$stderrFile=Join-Path $testDir "$tC.$tI.stderr.txt"
|
|
|
|
|
$stdoutFile=Join-Path $testDir "$tC.$tI.stdout.txt"
|
|
|
|
|
$logFile = Join-Path $testDir "$tC.$tI.log.txt"
|
2017-04-15 01:15:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-05-12 23:09:50 +02:00
|
|
|
|
AfterEach {$tI++;}
|
|
|
|
|
|
2017-05-10 23:47:03 +02:00
|
|
|
|
Context "$tC - Basic Scenarios" {
|
2017-04-15 01:15:32 +02:00
|
|
|
|
|
|
|
|
|
BeforeAll {$tI=1}
|
2017-05-10 23:47:03 +02:00
|
|
|
|
AfterAll{$tC++}
|
2017-04-15 01:15:32 +02:00
|
|
|
|
|
2017-05-10 23:47:03 +02:00
|
|
|
|
It "$tC.$tI - test version" {
|
2017-05-12 19:31:59 +02:00
|
|
|
|
iex "cmd /c `"ssh -V 2> $stderrFile`""
|
|
|
|
|
$stderrFile | Should Contain "OpenSSH_"
|
2017-04-15 01:15:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-05-10 23:47:03 +02:00
|
|
|
|
It "$tC.$tI - test help" {
|
2017-05-12 19:31:59 +02:00
|
|
|
|
iex "cmd /c `"ssh -? 2> $stderrFile`""
|
|
|
|
|
$stderrFile | Should Contain "usage: ssh"
|
2017-04-15 01:15:32 +02:00
|
|
|
|
}
|
2017-05-10 23:47:03 +02:00
|
|
|
|
|
|
|
|
|
It "$tC.$tI - remote echo command" {
|
2017-04-15 01:15:32 +02:00
|
|
|
|
iex "$sshDefaultCmd echo 1234" | Should Be "1234"
|
|
|
|
|
}
|
2017-05-10 23:47:03 +02:00
|
|
|
|
|
2017-05-12 19:31:59 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Context "$tC - exit code (exit-status.sh)" {
|
|
|
|
|
BeforeAll {$tI=1}
|
|
|
|
|
AfterAll{$tC++}
|
|
|
|
|
|
|
|
|
|
It "$tC.$tI - various exit codes" {
|
|
|
|
|
foreach ($i in (0,1,4,5,44)) {
|
|
|
|
|
ssh -p $port $ssouser@$server exit $i
|
|
|
|
|
$LASTEXITCODE | Should Be $i
|
|
|
|
|
}
|
2017-05-10 23:47:03 +02:00
|
|
|
|
}
|
2017-04-15 01:15:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-05-10 23:47:03 +02:00
|
|
|
|
Context "$tC - Redirection Scenarios" {
|
2017-04-15 01:15:32 +02:00
|
|
|
|
|
|
|
|
|
BeforeAll {$tI=1}
|
2017-05-10 23:47:03 +02:00
|
|
|
|
AfterAll{$tC++}
|
2017-04-15 01:15:32 +02:00
|
|
|
|
|
2017-06-27 06:58:29 +02:00
|
|
|
|
It "$tC.$tI - stdout to file" -skip:$skip {
|
2017-05-12 23:09:50 +02:00
|
|
|
|
ssh test_target powershell get-process > $stdoutFile
|
2017-05-12 19:31:59 +02:00
|
|
|
|
$stdoutFile | Should Contain "ProcessName"
|
2017-04-15 01:15:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-05-10 23:47:03 +02:00
|
|
|
|
It "$tC.$tI - stdout to PS object" {
|
2017-05-12 23:09:50 +02:00
|
|
|
|
$o = ssh test_target echo 1234
|
2017-04-15 01:15:32 +02:00
|
|
|
|
$o | Should Be "1234"
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-10 23:47:03 +02:00
|
|
|
|
<#It "$tC.$tI - stdin from PS object" {
|
2017-04-15 01:15:32 +02:00
|
|
|
|
#if input redirection doesn't work, this would hang
|
|
|
|
|
0 | ssh -p $port $ssouser@$server pause
|
|
|
|
|
$true | Should Be $true
|
|
|
|
|
}#>
|
2016-12-19 23:48:14 +01:00
|
|
|
|
}
|
|
|
|
|
|
2017-05-10 23:47:03 +02:00
|
|
|
|
Context "$tC - cmdline parameters" {
|
2017-04-15 01:15:32 +02:00
|
|
|
|
|
|
|
|
|
BeforeAll {$tI=1}
|
2017-05-10 23:47:03 +02:00
|
|
|
|
AfterAll{$tC++}
|
2017-04-15 01:15:32 +02:00
|
|
|
|
|
2017-05-12 23:09:50 +02:00
|
|
|
|
It "$tC.$tI - verbose to file (-v -E)" {
|
|
|
|
|
$o = ssh -v -E $logFile test_target echo 1234
|
2017-04-15 01:15:32 +02:00
|
|
|
|
$o | Should Be "1234"
|
|
|
|
|
#TODO - checks below are very inefficient (time taking).
|
|
|
|
|
$logFile | Should Contain "OpenSSH_"
|
|
|
|
|
$logFile | Should Contain "Exit Status 0"
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-12 19:31:59 +02:00
|
|
|
|
|
2017-05-12 23:09:50 +02:00
|
|
|
|
It "$tC.$tI - cipher options (-c)" {
|
2017-05-12 19:31:59 +02:00
|
|
|
|
#bad cipher
|
2017-05-12 23:09:50 +02:00
|
|
|
|
iex "cmd /c `"ssh -c bad_cipher test_target echo 1234 2>$stderrFile`""
|
2017-05-12 19:31:59 +02:00
|
|
|
|
$stderrFile | Should Contain "Unknown cipher type"
|
|
|
|
|
#good cipher, ensure cipher is used from debug logs
|
2017-05-12 23:09:50 +02:00
|
|
|
|
$o = ssh -c aes256-ctr -v -E $logFile test_target echo 1234
|
2017-05-12 19:31:59 +02:00
|
|
|
|
$o | Should Be "1234"
|
|
|
|
|
$logFile | Should Contain "kex: server->client cipher: aes256-ctr"
|
|
|
|
|
$logFile | Should Contain "kex: client->server cipher: aes256-ctr"
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-12 23:09:50 +02:00
|
|
|
|
It "$tC.$tI - ssh_config (-F)" {
|
2017-05-12 19:31:59 +02:00
|
|
|
|
#ensure -F is working by pointing to a bad configuration
|
|
|
|
|
$badConfigFile = Join-Path $testDir "$tC.$tI.bad_ssh_config"
|
|
|
|
|
"bad_config_line" | Set-Content $badConfigFile
|
2017-05-12 23:09:50 +02:00
|
|
|
|
iex "cmd /c `"ssh -F $badConfigFile test_target echo 1234 2>$stderrFile`""
|
2017-05-12 19:31:59 +02:00
|
|
|
|
$stderrFile | Should Contain "bad_ssh_config"
|
|
|
|
|
$stderrFile | Should Contain "bad_config_line"
|
|
|
|
|
$stderrFile | Should Contain "bad configuration options"
|
|
|
|
|
|
|
|
|
|
#try with a proper configuration file. Put it on a unicode path with unicode content
|
|
|
|
|
#so we can test the Unicode support simultaneously
|
|
|
|
|
$goodConfigFile = Join-Path $testDir "$tC.$tI.Очень_хорошо_ssh_config"
|
|
|
|
|
"#this is a Unicode comment because it contains русский язык" | Set-Content $goodConfigFile -Encoding UTF8
|
|
|
|
|
"Host myhost" | Add-Content $goodConfigFile
|
|
|
|
|
" HostName $server" | Add-Content $goodConfigFile
|
|
|
|
|
" Port $port" | Add-Content $goodConfigFile
|
|
|
|
|
" User $ssouser" | Add-Content $goodConfigFile
|
|
|
|
|
$o = ssh -F $goodConfigFile myhost echo 1234
|
|
|
|
|
$o | Should Be "1234"
|
|
|
|
|
}
|
2017-05-12 23:09:50 +02:00
|
|
|
|
|
|
|
|
|
It "$tC.$tI - IP options - (-4) (-6)" {
|
|
|
|
|
# TODO - this test assumes target is localhost.
|
|
|
|
|
# make it work independent of target
|
|
|
|
|
#-4
|
|
|
|
|
$o = ssh -4 -v -E $logFile test_target echo 1234
|
|
|
|
|
$o | Should Be "1234"
|
|
|
|
|
$logFile | Should Contain "[127.0.0.1]"
|
|
|
|
|
#-4
|
|
|
|
|
$o = ssh -6 -v -E $logFile test_target echo 1234
|
|
|
|
|
$o | Should Be "1234"
|
|
|
|
|
$logFile | Should Contain "[::1]"
|
|
|
|
|
}
|
2017-04-15 01:15:32 +02:00
|
|
|
|
}
|
2017-05-12 19:31:59 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-04-15 01:15:32 +02:00
|
|
|
|
<#Context "Key is not secured in ssh-agent on server" {
|
2016-12-19 23:48:14 +01:00
|
|
|
|
BeforeAll {
|
|
|
|
|
$identifyFile = $client.clientPrivateKeyPaths[0]
|
|
|
|
|
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AfterEach {
|
|
|
|
|
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
It '<Title>' -TestCases:$testData1 {
|
|
|
|
|
param([string]$Title, $LogonStr, $Options, $SkipVerification = $false)
|
|
|
|
|
|
|
|
|
|
$str = $ExecutionContext.InvokeCommand.ExpandString(".\ssh $($Options) $($LogonStr) hostname > $filePath")
|
|
|
|
|
$client.RunCmd($str)
|
|
|
|
|
#validate file content.
|
|
|
|
|
Get-Content $filePath | Should be $server.MachineName
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Context "Key is secured in ssh-agent" {
|
|
|
|
|
BeforeAll {
|
|
|
|
|
$server.SecureHostKeys($server.PrivateHostKeyPaths)
|
|
|
|
|
$identifyFile = $client.clientPrivateKeyPaths[0]
|
|
|
|
|
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AfterAll {
|
|
|
|
|
$Server.CleanupHostKeys()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AfterEach {
|
|
|
|
|
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
It '<Title>' -TestCases:$testData1 {
|
|
|
|
|
param([string]$Title, $LogonStr, $Options, $SkipVerification = $false)
|
|
|
|
|
|
|
|
|
|
$str = $ExecutionContext.InvokeCommand.ExpandString(".\ssh $Options $LogonStr hostname > $filePath")
|
|
|
|
|
$client.RunCmd($str)
|
|
|
|
|
#validate file content.
|
|
|
|
|
Get-Content $filePath | Should be $server.MachineName
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Context "Single signon on client and keys secured in ssh-agent on server" {
|
|
|
|
|
BeforeAll {
|
|
|
|
|
$Server.SecureHostKeys($server.PrivateHostKeyPaths)
|
|
|
|
|
$identifyFile = $client.clientPrivateKeyPaths[0]
|
|
|
|
|
#setup single signon
|
|
|
|
|
.\ssh-add.exe $identifyFile
|
|
|
|
|
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AfterAll {
|
|
|
|
|
$Server.CleanupHostKeys()
|
|
|
|
|
|
|
|
|
|
#cleanup single signon
|
|
|
|
|
.\ssh-add.exe -D
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AfterEach {
|
|
|
|
|
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
It '<Title>' -TestCases:$testData {
|
|
|
|
|
param([string]$Title, $LogonStr, $Options)
|
|
|
|
|
|
|
|
|
|
$str = ".\ssh $($Options) $($LogonStr) hostname > $filePath"
|
|
|
|
|
$client.RunCmd($str)
|
|
|
|
|
#validate file content.
|
|
|
|
|
Get-Content $filePath | Should be $server.MachineName
|
|
|
|
|
}
|
2017-01-12 06:54:44 +01:00
|
|
|
|
}
|
|
|
|
|
Context "password authentication" {
|
|
|
|
|
BeforeAll {
|
|
|
|
|
$client.AddPasswordSetting($server.localAdminPassword)
|
|
|
|
|
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AfterAll {
|
|
|
|
|
$client.CleanupPasswordSetting()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AfterEach {
|
|
|
|
|
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
It '<Title>' -TestCases:$testData {
|
|
|
|
|
param([string]$Title, $LogonStr, $Options)
|
|
|
|
|
|
|
|
|
|
$str = ".\ssh $($Options) $($LogonStr) hostname > $filePath"
|
|
|
|
|
$client.RunCmd($str)
|
|
|
|
|
#validate file content.
|
|
|
|
|
Get-Content $filePath | Should be $server.MachineName
|
|
|
|
|
}
|
2017-04-15 01:15:32 +02:00
|
|
|
|
}#>
|
2016-12-19 23:48:14 +01:00
|
|
|
|
}
|