From 9fd0cdab045930a47242553eab6d55e5e276f8da Mon Sep 17 00:00:00 2001 From: bingbing8 Date: Mon, 15 May 2017 17:36:22 -0700 Subject: [PATCH] Source snapshot from Powershell/openssh-portable:latestw_all --- appveyor.yml | 2 +- contrib/win32/openssh/OpenSSHTestHelper.psm1 | 83 +++++++++++-- contrib/win32/openssh/version.rc | Bin 4066 -> 4066 bytes contrib/win32/win32compat/console.c | 2 +- contrib/win32/win32compat/misc.c | 3 +- contrib/win32/win32compat/w32-sshfileperm.c | 28 ++--- .../Authorized_keys_fileperm.Tests.ps1 | 2 +- regress/pesterTests/Cfginclude.Tests.ps1 | 2 +- .../pesterTests/Hostkey_fileperm.Tests.ps1 | 2 +- regress/pesterTests/KeyUtils.Tests.ps1 | 15 ++- regress/pesterTests/PortForwarding.Tests.ps1 | 70 +++++------ regress/pesterTests/README.md | 26 ++++- regress/pesterTests/SCP.Tests.ps1 | 17 +-- regress/pesterTests/SFTP.Tests.ps1 | 35 ++---- regress/pesterTests/SSH.Tests.ps1 | 109 +++++++++++++----- .../pesterTests/Userkey_fileperm.Tests.ps1 | 2 +- regress/pesterTests/ssh_config | 5 + 17 files changed, 261 insertions(+), 142 deletions(-) create mode 100644 regress/pesterTests/ssh_config diff --git a/appveyor.yml b/appveyor.yml index 6868113..d4c5beb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 0.0.13.0.{build} +version: 0.0.14.0.{build} image: Visual Studio 2015 branches: diff --git a/contrib/win32/openssh/OpenSSHTestHelper.psm1 b/contrib/win32/openssh/OpenSSHTestHelper.psm1 index cec2f71..37f60be 100644 --- a/contrib/win32/openssh/OpenSSHTestHelper.psm1 +++ b/contrib/win32/openssh/OpenSSHTestHelper.psm1 @@ -119,6 +119,8 @@ WARNING: Following changes will be made to OpenSSH configuration - will be replaced with a test sshd_config - $HOME\.ssh\known_hosts will be backed up as known_hosts.ori - will be replaced with a test known_hosts + - $HOME\.ssh\config will be backed up as config.ori + - will be replaced with a test config - sshd test listener will be on port 47002 - $HOME\.ssh\known_hosts will be modified with test host key entry - test accounts - ssouser, pubkeyuser, and passwduser will be added @@ -172,17 +174,23 @@ WARNING: Following changes will be made to OpenSSH configuration #Backup existing known_hosts and replace with test version #TODO - account for custom known_hosts locations - $knowHostsDirectoryPath = Join-Path $home .ssh - $knowHostsFilePath = Join-Path $knowHostsDirectoryPath known_hosts - if(-not (Test-Path $knowHostsDirectoryPath -PathType Container)) + $dotSshDirectoryPath = Join-Path $home .ssh + $knowHostsFilePath = Join-Path $dotSshDirectoryPath known_hosts + if(-not (Test-Path $dotSshDirectoryPath -PathType Container)) { - New-Item -ItemType Directory -Path $knowHostsDirectoryPath -Force -ErrorAction SilentlyContinue | out-null + New-Item -ItemType Directory -Path $dotSshDirectoryPath -Force -ErrorAction SilentlyContinue | out-null } - if ((Test-Path $knowHostsFilePath -PathType Leaf) -and (-not (Test-Path (Join-Path $knowHostsDirectoryPath known_hosts.ori) -PathType Leaf))) { - Copy-Item $knowHostsFilePath (Join-Path $knowHostsDirectoryPath known_hosts.ori) -Force + if ((Test-Path $knowHostsFilePath -PathType Leaf) -and (-not (Test-Path (Join-Path $dotSshDirectoryPath known_hosts.ori) -PathType Leaf))) { + Copy-Item $knowHostsFilePath (Join-Path $dotSshDirectoryPath known_hosts.ori) -Force } Copy-Item (Join-Path $Script:E2ETestDirectory known_hosts) $knowHostsFilePath -Force + $sshConfigFilePath = Join-Path $dotSshDirectoryPath config + if ((Test-Path $sshConfigFilePath -PathType Leaf) -and (-not (Test-Path (Join-Path $dotSshDirectoryPath config.ori) -PathType Leaf))) { + Copy-Item $sshConfigFilePath (Join-Path $dotSshDirectoryPath config.ori) -Force + } + Copy-Item (Join-Path $Script:E2ETestDirectory ssh_config) $sshConfigFilePath -Force + # create test accounts #TODO - this is Windows specific. Need to be in PAL foreach ($user in $OpenSSHTestAccounts) @@ -212,6 +220,7 @@ WARNING: Following changes will be made to OpenSSH configuration $testPriKeypath = Join-Path $Script:E2ETestDirectory sshtest_userssokey_ed25519 Cleanup-SecureFileACL -FilePath $testPriKeypath -owner $owner cmd /c "ssh-add $testPriKeypath 2>&1 >> $Script:TestSetupLogFile" + Backup-OpenSSHTestInfo } #TODO - this is Windows specific. Need to be in PAL function Get-LocalUserProfile @@ -314,6 +323,14 @@ function Cleanup-OpenSSHTestEnvironment Remove-Item $originKnowHostsPath -Force -ErrorAction SilentlyContinue } + #Restore ssh_config + $originConfigPath = Join-Path $home .ssh\config.ori + if (Test-Path $originConfigPath) + { + Copy-Item $originConfigPath (Join-Path $home .ssh\config) -Force -ErrorAction SilentlyContinue + Remove-Item $originConfigPath -Force -ErrorAction SilentlyContinue + } + #Delete accounts foreach ($user in $OpenSSHTestAccounts) { @@ -395,7 +412,7 @@ function Run-OpenSSHE2ETest # Discover all CI tests and run them. Push-Location $Script:E2ETestDirectory Write-Log -Message "Running OpenSSH E2E tests..." - $testFolders = Get-ChildItem *.tests.ps1 -Recurse -Exclude SSHDConfig.tests.ps1, SSH.Tests.ps1 | ForEach-Object{ Split-Path $_.FullName} | Sort-Object -Unique + $testFolders = Get-ChildItem *.tests.ps1 -Recurse | ForEach-Object{ Split-Path $_.FullName} | Sort-Object -Unique Invoke-Pester $testFolders -OutputFormat NUnitXml -OutputFile $Script:E2ETestResultsFile -Tag 'CI' Pop-Location } @@ -439,6 +456,56 @@ function Run-OpenSSHUnitTest $testfailed } +function Backup-OpenSSHTestInfo +{ + param + ( + [string] $BackupFile = $null + ) + + if ($Global:OpenSSHTestInfo -eq $null) { + Throw "`$OpenSSHTestInfo is null. Did you run Setup-OpenSSHTestEnvironment yet?" + } + + $testInfo = $Global:OpenSSHTestInfo + + if ([String]::IsNullOrEmpty($BackupFile)) { + $BackupFile = Join-Path $testInfo["TestDataPath"] "OpenSSHTestInfo_backup.txt" + } + + $null | Set-Content $BackupFile + + foreach ($key in $testInfo.Keys) { + $value = $testInfo[$key] + Add-Content $BackupFile "$key,$value" + } +} + +function Recover-OpenSSHTestInfo +{ + param + ( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $BackupFile + ) + + if($Global:OpenSSHTestInfo -ne $null) + { + $Global:OpenSSHTestInfo.Clear() + $Global:OpenSSHTestInfo = $null + } + + $Global:OpenSSHTestInfo = @{} + + $entries = Get-Content $BackupFile + + foreach ($entry in $entries) { + $data = $entry.Split(",") + $Global:OpenSSHTestInfo[$data[0]] = $data[1] + } +} + <# Write-Log #> @@ -460,4 +527,4 @@ function Write-Log } } -Export-ModuleMember -Function Setup-OpenSSHTestEnvironment, Cleanup-OpenSSHTestEnvironment, Run-OpenSSHUnitTest, Run-OpenSSHE2ETest +Export-ModuleMember -Function Setup-OpenSSHTestEnvironment, Cleanup-OpenSSHTestEnvironment, Run-OpenSSHUnitTest, Run-OpenSSHE2ETest, Backup-OpenSSHTestInfo, Recover-OpenSSHTestInfo diff --git a/contrib/win32/openssh/version.rc b/contrib/win32/openssh/version.rc index 4479e82d0ac9750a58960403d6a5119b0fb86eb0..45e92789e078ae23b6874c00174ae46a15d63342 100644 GIT binary patch delta 44 ucmaDP|44qr6b?p{$x}Iu8BI2yAceCount; i++) { + /*for (DWORD i = 0; i < dacl->AceCount; i++) { PVOID current_ace = NULL; PACE_HEADER current_aceHeader = NULL; PSID current_trustee_sid = NULL; @@ -152,10 +153,10 @@ check_secure_file_permission(const char *name, struct passwd * pw) // Not interested ACE continue; } - } + }*/ /*no need to check administrators group, owner account, user account and system account*/ - if (IsWellKnownSid(current_trustee_sid, WinBuiltinAdministratorsSid) || + /*if (IsWellKnownSid(current_trustee_sid, WinBuiltinAdministratorsSid) || IsWellKnownSid(current_trustee_sid, WinLocalSystemSid) || EqualSid(current_trustee_sid, owner_sid) || EqualSid(current_trustee_sid, user_sid) || @@ -188,7 +189,7 @@ cleanup: FreeSid(user_sid); if(name_utf16) free(name_utf16); - return ret; + return ret;*/ } static BOOL @@ -267,7 +268,8 @@ done: int set_secure_file_permission(const char *name, struct passwd * pw) { - PSECURITY_DESCRIPTOR pSD = NULL; + return 0; + /*PSECURITY_DESCRIPTOR pSD = NULL; PSID owner_sid = NULL; PACL dacl = NULL; wchar_t *name_utf16 = NULL, *sid_utf16 = NULL, sddl[256]; @@ -327,10 +329,10 @@ set_secure_file_permission(const char *name, struct passwd * pw) errno = ENOMEM; ret = -1; goto cleanup; - } + }*/ /*Set the owner sid and acl of the file.*/ - if ((error_code = SetNamedSecurityInfoW(name_utf16, SE_FILE_OBJECT, + /*if ((error_code = SetNamedSecurityInfoW(name_utf16, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION, owner_sid, NULL, dacl, NULL)) != ERROR_SUCCESS) { debug3("failed to set the owner sid and dacl of file %s with error code: %d", name, error_code); @@ -348,5 +350,5 @@ cleanup: if (owner_sid) FreeSid(owner_sid); - return ret; + return ret;*/ } diff --git a/regress/pesterTests/Authorized_keys_fileperm.Tests.ps1 b/regress/pesterTests/Authorized_keys_fileperm.Tests.ps1 index 7c0bde2..3e92990 100644 --- a/regress/pesterTests/Authorized_keys_fileperm.Tests.ps1 +++ b/regress/pesterTests/Authorized_keys_fileperm.Tests.ps1 @@ -1,5 +1,5 @@ Import-Module $PSScriptRoot\CommonUtils.psm1 -Force -Describe "Tests for authorized_keys file permission" -Tags "CI" { +Describe "Tests for authorized_keys file permission" -Tags "Scenario" { BeforeAll { if($OpenSSHTestInfo -eq $null) { diff --git a/regress/pesterTests/Cfginclude.Tests.ps1 b/regress/pesterTests/Cfginclude.Tests.ps1 index 391b453..9e472c9 100644 --- a/regress/pesterTests/Cfginclude.Tests.ps1 +++ b/regress/pesterTests/Cfginclude.Tests.ps1 @@ -1,4 +1,4 @@ -Describe "Tests for ssh config" -Tags "CI" { +Describe "Tests for ssh config" -Tags "Scenario" { BeforeAll { if($OpenSSHTestInfo -eq $null) { diff --git a/regress/pesterTests/Hostkey_fileperm.Tests.ps1 b/regress/pesterTests/Hostkey_fileperm.Tests.ps1 index 7a0d2da..821b772 100644 --- a/regress/pesterTests/Hostkey_fileperm.Tests.ps1 +++ b/regress/pesterTests/Hostkey_fileperm.Tests.ps1 @@ -1,5 +1,5 @@ Import-Module $PSScriptRoot\CommonUtils.psm1 -Force -Describe "Tests for host keys file permission" -Tags "CI" { +Describe "Tests for host keys file permission" -Tags "Scenario" { BeforeAll { if($OpenSSHTestInfo -eq $null) { diff --git a/regress/pesterTests/KeyUtils.Tests.ps1 b/regress/pesterTests/KeyUtils.Tests.ps1 index 0860694..c26a247 100644 --- a/regress/pesterTests/KeyUtils.Tests.ps1 +++ b/regress/pesterTests/KeyUtils.Tests.ps1 @@ -2,7 +2,7 @@ $tI = 0 $suite = "keyutils" -Describe "E2E scenarios for ssh key management" -Tags "CI" { +Describe "E2E scenarios for ssh key management" -Tags "Scenario" { BeforeAll { if($OpenSSHTestInfo -eq $null) { @@ -14,6 +14,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" { { $null = New-Item $testDir -ItemType directory -Force -ErrorAction SilentlyContinue } + $keypassphrase = "testpassword" $keytypes = @("rsa","dsa","ecdsa","ed25519") #only validate owner and ACE of the file @@ -36,8 +37,12 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" { } BeforeEach { - $tI++; - } + $stderrFile=Join-Path $testDir "$tC.$tI.stderr.txt" + $stdoutFile=Join-Path $testDir "$tC.$tI.stdout.txt" + $logFile = Join-Path $testDir "$tC.$tI.log.txt" + } + + AfterEach {$tI++;} Context "$tC - ssh-keygen all key types" { @@ -124,6 +129,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" { #ensure added keys are listed $allkeys = ssh-add -L + $allkeys | Set-Content (Join-Path $testDir "$tC.$tI.allkeyonAdd.txt") foreach($type in $keytypes) { @@ -141,7 +147,8 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" { #check keys are deleted $allkeys = ssh-add -L - + $allkeys | Set-Content (Join-Path $testDir "$tC.$tI.allkeyonDelete.txt") + foreach($type in $keytypes) { $keyPath = Join-Path $testDir "id_$type" diff --git a/regress/pesterTests/PortForwarding.Tests.ps1 b/regress/pesterTests/PortForwarding.Tests.ps1 index 8fd2ff1..44fbcc4 100644 --- a/regress/pesterTests/PortForwarding.Tests.ps1 +++ b/regress/pesterTests/PortForwarding.Tests.ps1 @@ -1,48 +1,36 @@ - -Describe "Tests for portforwarding" -Tags "CI" { +$tC = 1 +$tI = 0 +$suite = "portfwd" + +Describe "E2E scenarios for port forwarding" -Tags "CI" { BeforeAll { - - if($OpenSSHTestInfo -eq $null) + $testDir = Join-Path $OpenSSHTestInfo["TestDataPath"] $suite + if(-not (Test-Path $testDir)) { - Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment." + $null = New-Item $testDir -ItemType directory -Force -ErrorAction SilentlyContinue } - $fileName = "test.txt" - $filePath = Join-Path ${TestDrive} $fileName - $logName = "log.txt" - $logPath = Join-Path ${TestDrive} $logName - $server = $OpenSSHTestInfo["Target"] - $port = $OpenSSHTestInfo["Port"] - $ssouser = $OpenSSHTestInfo["SSOUser"] - - $testData = @( - @{ - Title = "Local port forwarding" - Options = "-L 5432:127.0.0.1:47001" - FwdedPort = 5432 - - }, - @{ - Title = "Remote port forwarding" - Options = "-R 5432:127.0.0.1:47001" - FwdedPort = 5432 - } - ) } - AfterEach { - Remove-Item -Path $filePath -Force -ea silentlycontinue - Remove-Item -Path $logPath -Force -ea silentlycontinue - } + BeforeEach { + $stderrFile=Join-Path $testDir "$tC.$tI.stderr.txt" + $stdoutFile=Join-Path $testDir "$tC.$tI.stdout.txt" + $logFile = Join-Path $testDir "$tC.$tI.log.txt" + } + AfterEach {$tI++;} - It '' -TestCases:$testData { - param([string]$Title, $Options, $FwdedPort) - - $str = "ssh -p $($port) -E $logPath $($Options) $($ssouser)@$($server) powershell.exe Test-WSMan -computer 127.0.0.1 -port $FwdedPort > $filePath" - # TODO - move this to PAL - cmd /c $str - #validate file content. - $content = Get-Content $filePath - $content -like "wsmid*" | Should Not Be $null - } - + Context "$tC - Basic port forwarding scenarios" { + BeforeAll {$tI=1} + AfterAll{$tC++} + + #TODO - this relies on winrm (that is windows specific) + It "$tC.$tI - local port forwarding" { + ssh -L 5432:127.0.0.1:47001 test_target powershell.exe Test-WSMan -computer 127.0.0.1 -port 5432 | Set-Content $stdoutFile + $stdoutFile | Should Contain "wsmid" + } + + It "$tC.$tI - remote port forwarding" { + ssh -R 5432:127.0.0.1:47001 test_target powershell.exe Test-WSMan -computer 127.0.0.1 -port 5432 | Set-Content $stdoutFile + $stdoutFile | Should Contain "wsmid" + } + } } diff --git a/regress/pesterTests/README.md b/regress/pesterTests/README.md index 9d41eac..eabdd5a 100644 --- a/regress/pesterTests/README.md +++ b/regress/pesterTests/README.md @@ -1,4 +1,4 @@ -Run OpenSSH Pester Tests: +Run OpenSSH Pester Tests: ================================== #### To setup the test environment before test run: @@ -40,3 +40,27 @@ $OpenSSHTestInfo["DebugMode"] = $true ```powershell Cleanup-OpenSSHTestEnvironment ``` + + +#### Guidelines for writing Pester based OpenSSH test cases +Follow these simple steps for test case indexing +- Initialize the following variables at start +``` + $tC = 1 + $tI = 0 +``` +- Place the following blocks in Describe +``` + BeforeEach { + $stderrFile=Join-Path $testDir "$tC.$tI.stderr.txt" + $stdoutFile=Join-Path $testDir "$tC.$tI.stdout.txt" + $logFile = Join-Path $testDir "$tC.$tI.log.txt" + } + AfterEach {$tI++;} +``` +- Place the following blocks in each Context +``` + BeforeAll {$tI=1} + AfterAll{$tC++} +``` +- Prefix any test out file with $tC.$tI. You may use pre-created $stderrFile, $stdoutFile, $logFile for this purpose diff --git a/regress/pesterTests/SCP.Tests.ps1 b/regress/pesterTests/SCP.Tests.ps1 index f013849..3f7c994 100644 --- a/regress/pesterTests/SCP.Tests.ps1 +++ b/regress/pesterTests/SCP.Tests.ps1 @@ -8,11 +8,6 @@ Describe "Tests for scp command" -Tags "CI" { Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment." } - if(-not (Test-Path $OpenSSHTestInfo["TestDataPath"])) - { - $null = New-Item $OpenSSHTestInfo["TestDataPath"] -ItemType directory -Force -ErrorAction SilentlyContinue - } - $fileName1 = "test.txt" $fileName2 = "test2.txt" $SourceDirName = "SourceDir" @@ -46,12 +41,12 @@ Describe "Tests for scp command" -Tags "CI" { @{ Title = 'Simple copy local file to remote file' Source = $SourceFilePath - Destination = "$($ssouser)@$($server):$DestinationFilePath" + Destination = "test_target:$DestinationFilePath" Options = "-P $port -S $sshcmd" }, @{ Title = 'Simple copy remote file to local file' - Source = "$($ssouser)@$($server):$SourceFilePath" + Source = "test_target:$SourceFilePath" Destination = $DestinationFilePath Options = "-P $port -p -c aes128-ctr -C" }, @@ -64,12 +59,12 @@ Describe "Tests for scp command" -Tags "CI" { @{ Title = 'simple copy local file to remote dir' Source = $SourceFilePath - Destination = "$($ssouser)@$($server):$DestinationDir" + Destination = "test_target:$DestinationDir" Options = "-P $port -C -q" }<#, @{ Title = 'simple copy remote file to local dir' - Source = "$($ssouser)@$($server):$SourceFilePath" + Source = "test_target:$SourceFilePath" Destination = $DestinationDir Options = "-P $port " }#> @@ -79,7 +74,7 @@ Describe "Tests for scp command" -Tags "CI" { @{ Title = 'copy from local dir to remote dir' Source = $sourceDir - Destination = "$($ssouser)@$($server):$DestinationDir" + Destination = "test_target:$DestinationDir" Options = "-P $port -r -p -c aes128-ctr" }, @{ @@ -90,7 +85,7 @@ Describe "Tests for scp command" -Tags "CI" { }, @{ Title = 'copy from remote dir to local dir' - Source = "$($ssouser)@$($server):$sourceDir" + Source = "test_target:$sourceDir" Destination = $DestinationDir Options = "-P $port -C -r -q" } diff --git a/regress/pesterTests/SFTP.Tests.ps1 b/regress/pesterTests/SFTP.Tests.ps1 index 9f82e0f..a12c532 100644 --- a/regress/pesterTests/SFTP.Tests.ps1 +++ b/regress/pesterTests/SFTP.Tests.ps1 @@ -5,11 +5,6 @@ Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment." } - if(-not (Test-Path $OpenSSHTestInfo["TestDataPath"])) - { - $null = New-Item $OpenSSHTestInfo["TestDataPath"] -ItemType directory -Force -ErrorAction SilentlyContinue - } - $rootDirectory = "$($OpenSSHTestInfo["TestDataPath"])\SFTP" $outputFileName = "output.txt" @@ -41,7 +36,6 @@ $testData1 = @( @{ title = "put, ls for non-unicode file names" - logonstr = "$($ssouser)@$($server)" options = '' commands = "put $tempFilePath $serverDirectory ls $serverDirectory" @@ -49,7 +43,6 @@ }, @{ title = "get, ls for non-unicode file names" - logonstr = "$($ssouser)@$($server)" options = '' commands = "get $tempFilePath $clientDirectory ls $clientDirectory" @@ -57,7 +50,6 @@ }, @{ title = "mput, ls for non-unicode file names" - logonstr = "$($ssouser)@$($server)" options = '' commands = "mput $tempFilePath $serverDirectory ls $serverDirectory" @@ -65,7 +57,6 @@ }, @{ title = "mget, ls for non-unicode file names" - logonstr = "$($ssouser)@$($server)" options = '' commands = "mget $tempFilePath $clientDirectory ls $clientDirectory" @@ -73,7 +64,6 @@ }, @{ title = "mkdir, cd, pwd for non-unicode directory names" - logonstr = "$($ssouser)@$($server)" options = '' commands = "cd $serverdirectory mkdir server_test_dir @@ -83,7 +73,6 @@ }, @{ Title = "lmkdir, lcd, lpwd for non-unicode directory names" - LogonStr = "$($ssouser)@$($server)" Options = '' Commands = "lcd $clientDirectory lmkdir client_test_dir @@ -93,7 +82,6 @@ }, @{ title = "put, ls for unicode file names" - logonstr = "$($ssouser)@$($server)" options = '' commands = "put $tempUnicodeFilePath $serverDirectory ls $serverDirectory" @@ -101,7 +89,6 @@ }, @{ title = "get, ls for unicode file names" - logonstr = "$($ssouser)@$($server)" options = '' commands = "get $tempUnicodeFilePath $clientDirectory ls $clientDirectory" @@ -109,7 +96,6 @@ }, @{ title = "mput, ls for unicode file names" - logonstr = "$($ssouser)@$($server)" options = '' commands = "mput $tempUnicodeFilePath $serverDirectory ls $serverDirectory" @@ -117,7 +103,6 @@ }, @{ title = "mget, ls for unicode file names" - logonstr = "$($ssouser)@$($server)" options = '' commands = "mget $tempUnicodeFilePath $clientDirectory ls $clientDirectory" @@ -125,7 +110,6 @@ }, @{ title = "mkdir, cd, pwd for unicode directory names" - logonstr = "$($ssouser)@$($server)" options = '' commands = "cd $serverdirectory mkdir server_test_dir_язык @@ -135,7 +119,6 @@ }, @{ Title = "lmkdir, lcd, lpwd for unicode directory names" - LogonStr = "$($ssouser)@$($server)" Options = '' Commands = "lcd $clientDirectory lmkdir client_test_dir_язык @@ -149,7 +132,6 @@ $testData2 = @( @{ title = "rm, rmdir, rename for unicode file, directory" - logonstr = "$($ssouser)@$($server)" options = '-b $batchFilePath' tmpFileName1 = $tempUnicodeFileName @@ -164,7 +146,6 @@ }, @{ title = "rm, rmdir, rename for non-unicode file, directory" - logonstr = "$($ssouser)@$($server)" options = '-b $batchFilePath' tmpFileName1 = $tempFileName @@ -223,10 +204,10 @@ } It '<Title>' -TestCases:$testData1 { - param([string]$Title, $LogonStr, $Options, $Commands, $ExpectedOutput) + param([string]$Title, $Options, $Commands, $ExpectedOutput) Set-Content $batchFilePath -Encoding UTF8 -value $Commands - $str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P $port $($Options) -b $batchFilePath $($LogonStr) > $outputFilePath") + $str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P $port $($Options) -b $batchFilePath test_target > $outputFilePath") iex $str #validate file content. @@ -234,14 +215,14 @@ } It '<Title>' -TestCases:$testData2 { - param([string]$Title, $LogonStr, $Options, $tmpFileName1, $tmpFilePath1, $tmpFileName2, $tmpFilePath2, $tmpDirectoryName1, $tmpDirectoryPath1, $tmpDirectoryName2, $tmpDirectoryPath2) + param([string]$Title, $Options, $tmpFileName1, $tmpFilePath1, $tmpFileName2, $tmpFilePath2, $tmpDirectoryName1, $tmpDirectoryPath1, $tmpDirectoryName2, $tmpDirectoryPath2) #rm (remove file) $commands = "mkdir $tmpDirectoryPath1 put $tmpFilePath1 $tmpDirectoryPath1 ls $tmpDirectoryPath1" Set-Content $batchFilePath -Encoding UTF8 -value $commands - $str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P $port $($Options) $($LogonStr) > $outputFilePath") + $str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P $port $($Options) test_target > $outputFilePath") iex $str Test-Path (join-path $tmpDirectoryPath1 $tmpFileName1) | Should be $true @@ -250,7 +231,7 @@ pwd " Set-Content $batchFilePath -Encoding UTF8 -value $commands - $str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P $port $($Options) $($LogonStr) > $outputFilePath") + $str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P $port $($Options) test_target > $outputFilePath") iex $str Test-Path (join-path $tmpDirectoryPath1 $tmpFileName1) | Should be $false @@ -261,7 +242,7 @@ ls $tmpDirectoryPath1 pwd" Set-Content $batchFilePath -Encoding UTF8 -value $commands - $str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P $port $($Options) $($LogonStr) > $outputFilePath") + $str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P $port $($Options) test_target > $outputFilePath") iex $str Test-Path (join-path $tmpDirectoryPath1 $tmpFileName2) | Should be $true @@ -271,7 +252,7 @@ rename $tmpDirectoryPath1 $tmpDirectoryPath2 ls $serverDirectory" Set-Content $batchFilePath -Encoding UTF8 -value $commands - $str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P $port $($Options) $($LogonStr) > $outputFilePath") + $str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P $port $($Options) test_target > $outputFilePath") iex $str Test-Path $tmpDirectoryPath2 | Should be $true @@ -280,7 +261,7 @@ $commands = "rmdir $tmpDirectoryPath2 ls $serverDirectory" Set-Content $batchFilePath -Encoding UTF8 -value $commands - $str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P $port $($Options) $($LogonStr) > $outputFilePath") + $str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P $port $($Options) test_target > $outputFilePath") iex $str Test-Path $tmpDirectoryPath2 | Should be $false } diff --git a/regress/pesterTests/SSH.Tests.ps1 b/regress/pesterTests/SSH.Tests.ps1 index d6c910d..17434df 100644 --- a/regress/pesterTests/SSH.Tests.ps1 +++ b/regress/pesterTests/SSH.Tests.ps1 @@ -2,31 +2,26 @@ #todo: -S -F -V -e $tC = 1 $tI = 0 +$suite = "sshclient" -Describe "ssh client tests" -Tags "CI" { +Describe "E2E scenarios for ssh client" -Tags "CI" { BeforeAll { if($OpenSSHTestInfo -eq $null) { Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment." } - if(-not (Test-Path $OpenSSHTestInfo["TestDataPath"])) - { - $null = New-Item $OpenSSHTestInfo["TestDataPath"] -ItemType directory -Force -ErrorAction SilentlyContinue - } - $server = $OpenSSHTestInfo["Target"] $port = $OpenSSHTestInfo["Port"] $ssouser = $OpenSSHTestInfo["SSOUser"] - $sshCmdDefault = "ssh -p $port $($ssouser)@$($server)" - $testDir = Join-Path $OpenSSHTestInfo["TestDataPath"] "ssh" + $testDir = Join-Path $OpenSSHTestInfo["TestDataPath"] $suite if(-not (Test-Path $testDir)) { $null = New-Item $testDir -ItemType directory -Force -ErrorAction SilentlyContinue } - $testData = @( + <#$testData = @( @{ Title = 'Simple logon no option'; LogonStr = "$($server.localAdminUserName)@$($server.MachineName)" @@ -55,51 +50,60 @@ Describe "ssh client tests" -Tags "CI" { LogonStr = "$($server.localAdminUserName)@$($server.MachineName)" Options = '-i $identifyFile -c aes256-ctr' }, - <# -V does not redirect to file + -V does not redirect to file @{ Title = "logon using -i -V option" LogonStr = "$($server.localAdminUserName)@$($server.MachineName)" Options = '-i $identifyFile -V' SkipVerification = $true - },#> + }, @{ Title = 'logon using -i -l option' LogonStr = $server.MachineName Options = '-i $identifyFile -l $($server.localAdminUserName)' } - ) + )#> } BeforeEach { - $tI++; - $tFile=Join-Path $testDir "$tC.$tI.txt" + $stderrFile=Join-Path $testDir "$tC.$tI.stderr.txt" + $stdoutFile=Join-Path $testDir "$tC.$tI.stdout.txt" + $logFile = Join-Path $testDir "$tC.$tI.log.txt" } + AfterEach {$tI++;} + Context "$tC - Basic Scenarios" { BeforeAll {$tI=1} AfterAll{$tC++} It "$tC.$tI - test version" { - iex "cmd /c `"ssh -V 2> $tFile`"" - $tFile | Should Contain "OpenSSH_" + iex "cmd /c `"ssh -V 2> $stderrFile`"" + $stderrFile | Should Contain "OpenSSH_" } It "$tC.$tI - test help" { - iex "cmd /c `"ssh -? 2> $tFile`"" - $tFile | Should Contain "usage: ssh" + iex "cmd /c `"ssh -? 2> $stderrFile`"" + $stderrFile | Should Contain "usage: ssh" } It "$tC.$tI - remote echo command" { iex "$sshDefaultCmd echo 1234" | Should Be "1234" } - It "$tC.$tI - exit code" { - ssh -p $port $ssouser@$server exit 0 - $LASTEXITCODE | Should Be 0 - ssh -p $port $ssouser@$server exit 21 - $LASTEXITCODE | Should Be 21 + } + + 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 + } } } @@ -109,12 +113,12 @@ Describe "ssh client tests" -Tags "CI" { AfterAll{$tC++} It "$tC.$tI - stdout to file" { - iex "$sshDefaultCmd powershell get-process > $tFile" - $tFile | Should Contain "ProcessName" + ssh test_target powershell get-process > $stdoutFile + $stdoutFile | Should Contain "ProcessName" } It "$tC.$tI - stdout to PS object" { - $o = iex "$sshDefaultCmd echo 1234" + $o = ssh test_target echo 1234 $o | Should Be "1234" } @@ -130,16 +134,63 @@ Describe "ssh client tests" -Tags "CI" { BeforeAll {$tI=1} AfterAll{$tC++} - It "$tC.$tI - verbose to file" { - $logFile = Join-Path $testDir "$tC.$tI.log.txt" - $o = ssh -p $port -v -E $logFile $ssouser@$server echo 1234 + It "$tC.$tI - verbose to file (-v -E)" { + $o = ssh -v -E $logFile test_target echo 1234 $o | Should Be "1234" #TODO - checks below are very inefficient (time taking). $logFile | Should Contain "OpenSSH_" $logFile | Should Contain "Exit Status 0" } + + It "$tC.$tI - cipher options (-c)" { + #bad cipher + iex "cmd /c `"ssh -c bad_cipher test_target echo 1234 2>$stderrFile`"" + $stderrFile | Should Contain "Unknown cipher type" + #good cipher, ensure cipher is used from debug logs + $o = ssh -c aes256-ctr -v -E $logFile test_target echo 1234 + $o | Should Be "1234" + $logFile | Should Contain "kex: server->client cipher: aes256-ctr" + $logFile | Should Contain "kex: client->server cipher: aes256-ctr" + } + + It "$tC.$tI - ssh_config (-F)" { + #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 + iex "cmd /c `"ssh -F $badConfigFile test_target echo 1234 2>$stderrFile`"" + $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" + } + + 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]" + } } + + + <#Context "Key is not secured in ssh-agent on server" { BeforeAll { $identifyFile = $client.clientPrivateKeyPaths[0] diff --git a/regress/pesterTests/Userkey_fileperm.Tests.ps1 b/regress/pesterTests/Userkey_fileperm.Tests.ps1 index ed7fe80..ee45e20 100644 --- a/regress/pesterTests/Userkey_fileperm.Tests.ps1 +++ b/regress/pesterTests/Userkey_fileperm.Tests.ps1 @@ -1,5 +1,5 @@ Import-Module $PSScriptRoot\CommonUtils.psm1 -Force -Describe "Tests for user Key file permission" -Tags "CI" { +Describe "Tests for user Key file permission" -Tags "Scenario" { BeforeAll { if($OpenSSHTestInfo -eq $null) { diff --git a/regress/pesterTests/ssh_config b/regress/pesterTests/ssh_config new file mode 100644 index 0000000..2b2347c --- /dev/null +++ b/regress/pesterTests/ssh_config @@ -0,0 +1,5 @@ +# host alias for OpenSSH E2E tests +Host test_target + HostName localhost + Port 47002 + User sshtest_ssouser