openssh-portable/contrib/win32/openssh/OpenSSHTestHelper.psm1
Paul Higinbotham d9a9b3ce88
Add AzDevOps CI implementations (#631)
* Fix yaml indentation

* More format fixes

* Temporarily remove compliance reference

* Fix test job

* Fix job name

* Update image pool

* Add build results copy

* Fix build copy typo

* Param fix

* Fix build artifact download

* Remove unneeded dir from install

* Fix Pester version comaptible with tests

* Fix unit tests

* Fix unit test location

* Fix unit test path

* Disable Bash tests

* Fix testpassed

* Re-enable CygWin bash tests

* Fix cygwin check error

* Typo

* Debug bash tests

* Save config.h from build for bash tests

* Fix config.h copy

* Change test clean up

* Allow some tests to run after others fail

* Reinstate Invoke-AzDOBuild

* Fix syntax errors

* Restore opensshtestinfo

* Fix typo

* Upload bash test results

* Debug bash tests 1

* Debug 2

* Remove debug code

* Fix test path error

* Set Pester version to 3.4.6 for AppVeyor runs
2022-11-14 13:14:50 -08:00

832 lines
32 KiB
PowerShell

$ErrorActionPreference = 'Stop'
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -Force
Import-Module $PSScriptRoot\OpenSSHUtils -Force
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
# test environment parameters initialized with defaults
$SetupTestResultsFileName = "setupTestResults.xml"
$UninstallTestResultsFileName = "UninstallTestResults.xml"
$E2ETestResultsFileName = "E2ETestResults.xml"
$UnitTestResultsFileName = "UnitTestResults.txt"
$TestSetupLogFileName = "TestSetupLog.txt"
$SSOUser = "sshtest_ssouser"
$PubKeyUser = "sshtest_pubkeyuser"
$PasswdUser = "sshtest_passwduser"
$AdminUser = "sshtest_adminuser"
$NonAdminUser = "sshtest_nonadminuser"
$OpenSSHTestAccountsPassword = "Bulldog_123456"
$OpenSSHTestAccounts = $Script:SSOUser, $Script:PubKeyUser, $Script:PasswdUser, $Script:AdminUser, $Script:NonAdminUser
$SSHDTestSvcName = "sshdTestSvc"
$Script:TestDataPath = "$env:SystemDrive\OpenSSHTests"
$Script:SetupTestResultsFile = Join-Path $TestDataPath $SetupTestResultsFileName
$Script:UninstallTestResultsFile = Join-Path $TestDataPath $UninstallTestResultsFileName
$Script:E2ETestResultsFile = Join-Path $TestDataPath $E2ETestResultsFileName
$Script:UnitTestResultsFile = Join-Path $TestDataPath $UnitTestResultsFileName
$Script:TestSetupLogFile = Join-Path $TestDataPath $TestSetupLogFileName
$Script:E2ETestDirectory = Join-Path $repositoryRoot.FullName -ChildPath "regress\pesterTests"
$Script:E2ETestDataDirectory = Join-Path $Script:E2ETestDirectory data
$Script:WindowsInBox = $false
$Script:NoLibreSSL = $false
$Script:EnableAppVerifier = $true
$Script:PostmortemDebugging = $false
<#
.Synopsis
Set-OpenSSHTestEnvironment
TODO - split these steps into client and server side
#>
function Set-OpenSSHTestEnvironment
{
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
param
(
[string] $OpenSSHBinPath,
[string] $TestDataPath = "$env:SystemDrive\OpenSSHTests",
[Switch] $DebugMode,
[Switch] $NoAppVerifier,
[Switch] $PostmortemDebugging,
[Switch] $NoLibreSSL
)
$params = $PSBoundParameters
$params.Remove("DebugMode") | Out-Null
$params.Remove("NoAppVerifier") | Out-Null
$params.Remove("PostmortemDebugging") | Out-Null
if($PSBoundParameters.ContainsKey("Verbose"))
{
$verboseInfo = ($PSBoundParameters['Verbose']).IsPresent
}
Set-BasicTestInfo @params
$Global:OpenSSHTestInfo.Add("Target", "localhost") # test listener name
$Global:OpenSSHTestInfo.Add("Port", "47002") # test listener port
$Global:OpenSSHTestInfo.Add("SSOUser", $SSOUser) # test user with single sign on capability
$Global:OpenSSHTestInfo.Add("PubKeyUser", $PubKeyUser) # test user to be used with explicit key for key auth
$Global:OpenSSHTestInfo.Add("PasswdUser", $PasswdUser) # test user to be used for password auth
$Global:OpenSSHTestInfo.Add("AdminUser", $AdminUser) # test user to be used for admin logging tests
$Global:OpenSSHTestInfo.Add("NonAdminUser", $NonAdminUser) # test user to be used for non-admin logging tests
$Global:OpenSSHTestInfo.Add("TestAccountPW", $OpenSSHTestAccountsPassword) # common password for all test accounts
$Global:OpenSSHTestInfo.Add("DebugMode", $DebugMode.IsPresent) # run openssh E2E in debug mode
$Global:OpenSSHTestInfo.Add("DelayTime", 3) # delay between stoppig sshd service and trying to access log files
$Script:EnableAppVerifier = -not ($NoAppVerifier.IsPresent)
if($Script:WindowsInBox = $true)
{
$Script:EnableAppVerifier = $false
}
$Global:OpenSSHTestInfo.Add("EnableAppVerifier", $Script:EnableAppVerifier)
if($Script:EnableAppVerifier)
{
$Script:PostmortemDebugging = $PostmortemDebugging.IsPresent
}
$Global:OpenSSHTestInfo.Add("PostmortemDebugging", $Script:PostmortemDebugging)
$description = @"
WARNING: Following changes will be made to OpenSSH configuration
- $HOME\.ssh\known_hosts will be amended with test endpoint entries
- $HOME\.ssh\config will be amended with test endpoint entries
- sshd test listener will be on port 47002
- test accounts - ssouser, pubkeyuser, and passwduser will be added
- Setup single signon for ssouser
- To cleanup - Run Clear-OpenSSHTestEnvironment
"@
$prompt = "Are you sure you want to perform the above operations?"
$caption = $description
if(-not $pscmdlet.ShouldProcess($description, $prompt, $caption))
{
Write-Host "User decided not to make the changes."
return
}
Install-OpenSSHTestDependencies
##### START: install sshd test service
#delete service if exists
if (Get-Service $SSHDTestSvcName -ErrorAction SilentlyContinue)
{
Stop-Service $SSHDTestSvcName
sc.exe delete $SSHDTestSvcName 1>$null
}
#prepare config directory
$testSvcConfigDir = Join-Path $Global:OpenSSHTestInfo["TestDataPath"] "serviceconfig"
Remove-Item $testSvcConfigDir -Force -Recurse -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Path $testSvcConfigDir
$Global:OpenSSHTestInfo["ServiceConfigDir"] = $testSvcConfigDir
#copy sshd_config
$testSshdConfig = Join-Path $testSvcConfigDir sshd_config
Copy-Item (Join-Path $Script:E2ETestDataDirectory sshd_config) $testSshdConfig -Force
$con = (Get-Content $testSshdConfig | Out-String).Replace("___TEST_SERVICE_CONFIG_DIR___", $testSvcConfigDir)
Set-Content -Path $testSshdConfig -Value "$con" -Force
if($DebugMode) {
$con = (Get-Content $testSshdConfig | Out-String).Replace("#SyslogFacility AUTH","SyslogFacility LOCAL0")
Set-Content -Path $testSshdConfig -Value "$con" -Force
}
#copy sshtest keys
Copy-Item "$($Script:E2ETestDataDirectory)\sshtest*hostkey*" $testSvcConfigDir -Force
#copy ca pubkey to ssh config path
Copy-Item "$($Script:E2ETestDataDirectory)\sshtest_ca_userkeys.pub" $testSvcConfigDir -Force
$acl = New-Object System.Security.AccessControl.DirectorySecurity
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("Administrators","FullControl","Allow")
$acl.AddAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("System","FullControl","Allow")
$acl.AddAccessRule($rule)
$acl.SetAccessRuleProtection($true, $true)
Get-ChildItem $testSvcConfigDir | foreach {$acl | set-acl $_.FullName}
$SSHDTestSvcNameCmdLine = (Join-Path $script:OpenSSHBinPath 'sshd.exe') + " -f " + $testSshdConfig
New-Service -Name $SSHDTestSvcName -DisplayName "OpenSSH SSH Test Server for E2E tests" -BinaryPathName $SSHDTestSvcNameCmdLine -StartupType Manual | Out-Null
sc.exe privs $SSHDTestSvcName SeAssignPrimaryTokenPrivilege/SeTcbPrivilege/SeBackupPrivilege/SeRestorePrivilege/SeImpersonatePrivilege
Start-Service $SSHDTestSvcName
##### END: install sshd test service
#copy ca private key to test dir
$ca_priv_key = (Join-Path $Global:OpenSSHTestInfo["TestDataPath"] sshtest_ca_userkeys)
Copy-Item (Join-Path $Script:E2ETestDataDirectory sshtest_ca_userkeys) $ca_priv_key -Force
Repair-UserSshConfigPermission -FilePath $ca_priv_key -confirm:$false
$Global:OpenSSHTestInfo["CA_Private_Key"] = $ca_priv_key
$sshAgentSvc = Get-service ssh-agent
if($sshAgentSvc.StartType -eq [System.ServiceProcess.ServiceStartMode]::Disabled)
{
Set-service ssh-agent -StartupType Manual
}
Start-Service ssh-agent
#Prepare user config - known_hosts and ssh_config
$dotSshDirectoryPath = Join-Path $home .ssh
if(-not (Test-Path $dotSshDirectoryPath -PathType Container))
{
New-Item -ItemType Directory -Path $dotSshDirectoryPath -Force -ErrorAction SilentlyContinue | out-null
}
$knowHostsFilePath = Join-Path $dotSshDirectoryPath known_hosts
if (-not (Test-Path $knowHostsFilePath -PathType Leaf)) {
Copy-Item (Join-Path $Script:E2ETestDataDirectory known_hosts) $knowHostsFilePath -Force
}
$con = Get-Content $knowHostsFilePath
if (($con -eq $null) -or (-not($con.Contains("###OpenSSHE2ETests")))) {
Get-Content (Join-Path $Script:E2ETestDataDirectory known_hosts) | Add-Content $knowHostsFilePath
}
$sshConfigFilePath = Join-Path $dotSshDirectoryPath config
if (-not (Test-Path (Join-Path $dotSshDirectoryPath config) -PathType Leaf)) {
Copy-Item (Join-Path $Script:E2ETestDataDirectory ssh_config) $sshConfigFilePath -Force
}
$con = Get-Content $sshConfigFilePath
if (($con -eq $null) -or (-not($con.Contains("###OpenSSHE2ETests")))) {
Get-Content (Join-Path $Script:E2ETestDataDirectory ssh_config) | Add-Content $sshConfigFilePath
}
Copy-Item (Join-Path $Script:E2ETestDataDirectory ssh_config) $sshConfigFilePath -Force
Repair-UserSshConfigPermission -FilePath $sshConfigFilePath -confirm:$false
# create test accounts
#TODO - this is Windows specific. Need to be in PAL
foreach ($user in $OpenSSHTestAccounts)
{
try
{
$objUser = New-Object System.Security.Principal.NTAccount($user)
$strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
}
catch
{
#only add the local user when it does not exists on the machine
net user $user $Script:OpenSSHTestAccountsPassword /ADD 2>&1 >> $Script:TestSetupLogFile
}
}
#setup single sign on for ssouser
$ssouserProfile = Get-LocalUserProfile -User $SSOUser
$Global:OpenSSHTestInfo.Add("SSOUserProfile", $ssouserProfile)
$PubKeyUserProfile = Get-LocalUserProfile -User $PubKeyUser
$Global:OpenSSHTestInfo.Add("PubKeyUserProfile", $PubKeyUserProfile)
$AdminUserProfile = Get-LocalUserProfile -User $AdminUser
$Global:OpenSSHTestInfo.Add("AdminUserProfile", $AdminUserProfile)
$NonAdminUserProfile = Get-LocalUserProfile -User $NonAdminUser
$Global:OpenSSHTestInfo.Add("NonAdminUserProfile", $NonAdminUserProfile)
#make $AdminUser admin
net localgroup Administrators $AdminUser /add
New-Item -ItemType Directory -Path (Join-Path $ssouserProfile .ssh) -Force -ErrorAction SilentlyContinue | out-null
$authorizedKeyPath = Join-Path $ssouserProfile .ssh\authorized_keys
$testPubKeyPath = Join-Path $Script:E2ETestDataDirectory sshtest_userssokey_ed25519.pub
Copy-Item $testPubKeyPath $authorizedKeyPath -Force -ErrorAction SilentlyContinue
Repair-AuthorizedKeyPermission -FilePath $authorizedKeyPath -confirm:$false
copy-item (Join-Path $Script:E2ETestDataDirectory sshtest_userssokey_ed25519) $Global:OpenSSHTestInfo["TestDataPath"]
$testPriKeypath = Join-Path $Global:OpenSSHTestInfo["TestDataPath"] sshtest_userssokey_ed25519
cmd /c "ssh-add -D 2>&1 >> $Script:TestSetupLogFile"
Repair-UserKeyPermission -FilePath $testPriKeypath -confirm:$false
cmd /c "ssh-add $testPriKeypath 2>&1 >> $Script:TestSetupLogFile"
#Enable AppVerifier
if($Script:EnableAppVerifier)
{
# clear all applications in application verifier first
& $env:windir\System32\appverif.exe -disable * -for * | out-null
Get-ChildItem "$($script:OpenSSHBinPath)\*.exe" | % {
& $env:windir\System32\appverif.exe -verify $_.Name | out-null
}
if($Script:PostmortemDebugging -and (Test-path $Script:WindbgPath))
{
# enable Postmortem debugger
New-ItemProperty "HKLM:Software\Microsoft\Windows NT\CurrentVersion\AeDebug" -Name Debugger -Type String -Value "`"$Script:WindbgPath`" -p %ld -e %ld -g" -Force -ErrorAction SilentlyContinue | Out-Null
New-ItemProperty "HKLM:Software\Microsoft\Windows NT\CurrentVersion\AeDebug" -Name Auto -Type String -Value "1" -Force -ErrorAction SilentlyContinue | Out-Null
}
}
}
function Set-BasicTestInfo
{
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
param
(
[string] $OpenSSHBinPath,
[string] $TestDataPath = "$env:SystemDrive\OpenSSHTests",
[Switch] $NoLibreSSL
)
if($Global:OpenSSHTestInfo -ne $null)
{
$Global:OpenSSHTestInfo.Clear()
$Global:OpenSSHTestInfo = $null
}
$Script:TestDataPath = $TestDataPath;
$Script:E2ETestResultsFile = Join-Path $TestDataPath $E2ETestResultsFileName
$Script:SetupTestResultsFile = Join-Path $TestDataPath $SetupTestResultsFileName
$Script:UninstallTestResultsFile = Join-Path $TestDataPath $UninstallTestResultsFileName
$Script:UnitTestResultsFile = Join-Path $TestDataPath $UnitTestResultsFileName
$Script:TestSetupLogFile = Join-Path $TestDataPath $TestSetupLogFileName
$Script:UnitTestDirectory = Get-UnitTestDirectory
$Script:NoLibreSSL = $NoLibreSSL.IsPresent
$Global:OpenSSHTestInfo = @{
"TestDataPath" = $TestDataPath; # openssh tests path
"TestSetupLogFile" = $Script:TestSetupLogFile; # openssh test setup log file
"E2ETestResultsFile" = $Script:E2ETestResultsFile; # openssh E2E test results file
"SetupTestResultsFile" = $Script:SetupTestResultsFile; # openssh setup test test results file
"UninstallTestResultsFile" = $Script:UninstallTestResultsFile; # openssh Uninstall test test results file
"UnitTestResultsFile" = $Script:UnitTestResultsFile; # openssh unittest test results file
"E2ETestDirectory" = $Script:E2ETestDirectory # the directory of E2E tests
"UnitTestDirectory" = $Script:UnitTestDirectory # the directory of unit tests
"NoLibreSSL" = $Script:NoLibreSSL
"WindowsInBox" = $Script:WindowsInBox
}
#if user does not set path, pick it up
if([string]::IsNullOrEmpty($OpenSSHBinPath))
{
$sshcmd = get-command ssh.exe -ErrorAction SilentlyContinue
if($sshcmd -eq $null)
{
Throw "Cannot find ssh.exe. Please specify -OpenSSHBinPath to the OpenSSH installed location."
}
else
{
$dirToCheck = split-path $sshcmd.Path
$description = "Pick up ssh.exe from $dirToCheck."
$prompt = "Are you sure you want to pick up ssh.exe from $($dirToCheck)?"
$caption = "Found ssh.exe from $dirToCheck"
if(-not $pscmdlet.ShouldProcess($description, $prompt, $caption))
{
Write-Host "User decided not to pick up ssh.exe from $dirToCheck. Please specify -OpenSSHBinPath to the OpenSSH installed location."
return
}
$script:OpenSSHBinPath = $dirToCheck
}
}
else
{
$script:OpenSSHBinPath = (Resolve-Path -Path $OpenSSHBinPath -ErrorAction Stop).Path
if (-not (Test-Path (Join-Path $script:OpenSSHBinPath ssh.exe) -PathType Leaf))
{
Throw "Cannot find OpenSSH binaries under $OpenSSHBinPath. Please specify -OpenSSHBinPath to the OpenSSH installed location"
}
}
$Global:OpenSSHTestInfo.Add("OpenSSHBinPath", $script:OpenSSHBinPath)
if (-not ($env:Path.ToLower().Contains($script:OpenSSHBinPath.ToLower())))
{
$env:Path = "$($script:OpenSSHBinPath);$($env:path)"
}
$acl = get-acl (join-path $script:OpenSSHBinPath "ssh.exe")
if($acl.Owner -ieq "NT SERVICE\TrustedInstaller")
{
$Script:WindowsInBox = $true
$Global:OpenSSHTestInfo["WindowsInBox"]= $true
}
Install-OpenSSHTestDependencies -TestHarness
if(-not (Test-path $TestDataPath -PathType Container))
{
New-Item -ItemType Directory -Path $TestDataPath -Force -ErrorAction SilentlyContinue | out-null
}
}
#TODO - this is Windows specific. Need to be in PAL
function Get-LocalUserProfile
{
param([string]$User)
$sid = Get-UserSID -User $User
$userProfileRegistry = Join-Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" $sid
if (-not (Test-Path $userProfileRegistry) ) {
#create profile
if (-not($env:DISPLAY)) { $env:DISPLAY = 1 }
$askpass_util = Join-Path $Script:E2ETestDirectory "utilities\askpass_util\askpass_util.exe"
$env:SSH_ASKPASS=$askpass_util
$env:ASKPASS_PASSWORD=$OpenSSHTestAccountsPassword
$env:SSH_ASKPASS_REQUIRE="prefer"
$ret = ssh -p 47002 "$User@localhost" echo %userprofile%
if ($env:DISPLAY -eq 1) { Remove-Item env:\DISPLAY }
Remove-item "env:SSH_ASKPASS" -ErrorAction SilentlyContinue
Remove-item "env:ASKPASS_PASSWORD" -ErrorAction SilentlyContinue
Remove-item "env:SSH_ASKPASS_REQUIRE" -ErrorAction SilentlyContinue
}
(Get-ItemProperty -Path $userProfileRegistry -Name 'ProfileImagePath').ProfileImagePath
}
<#
.SYNOPSIS
This function installs the tools required by our tests
1) Pester for running the tests
2) Windbg for postmortem debugging
#>
function Install-OpenSSHTestDependencies
{
[CmdletBinding()]
param ([Switch] $TestHarness)
#$isOpenSSHUtilsAvailable = Get-Module 'OpenSSHUtils' -ListAvailable
#if (-not ($isOpenSSHUtilsAvailable))
#{
Write-Log -Message "Installing Module OpenSSHUtils..."
Install-OpenSSHUtilsModule -SourceDir $PSScriptRoot
#}
Import-Module OpensshUtils -Force
if($Script:WindowsInBox)
{
return
}
# Install chocolatey
if(-not (Get-Command "choco" -ErrorAction SilentlyContinue))
{
Write-Log -Message "Chocolatey not present. Installing chocolatey."
Invoke-Expression ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) 2>&1 >> $Script:TestSetupLogFile
}
# Pester 5.x is not compatible with tests.
$InstalledPesters = Get-Module -Name 'Pester' -ListAvailable | Where-Object { $_.Version -lt '5.0' }
if ($InstalledPesters.Count -eq 0)
{
Write-Log -Message "Installing Pester..."
# Install-Module -Name 'Pester' -RequiredVersion 3.4.6
choco install Pester --version 3.4.6 -y --force --limitoutput 2>&1 >> $Script:TestSetupLogFile
}
if($TestHarness)
{
return
}
if($Script:PostmortemDebugging -or (($OpenSSHTestInfo -ne $null) -and ($OpenSSHTestInfo["PostmortemDebugging"])))
{
$folderName = "x86"
$pathroot = $env:ProgramFiles
if($env:PROCESSOR_ARCHITECTURE -ieq "AMD64")
{
$folderName = "x64"
$pathroot = ${env:ProgramFiles(x86)}
}
$Script:WindbgPath = "$pathroot\Windows Kits\8.1\Debuggers\$folderName\windbg.exe"
if(-not (Test-Path $Script:WindbgPath))
{
$Script:WindbgPath = "$pathroot\Windows Kits\10\Debuggers\$folderName\windbg.exe"
if(-not (Test-Path $Script:WindbgPath))
{
choco install windbg -y --force --limitoutput 2>&1 >> $Script:TestSetupLogFile
}
}
}
if(($Script:EnableAppVerifier -or (($OpenSSHTestInfo -ne $null) -and ($OpenSSHTestInfo["EnableAppVerifier"]))) -and (-not (Test-path $env:windir\System32\appverif.exe)))
{
choco install appverifier -y --force --limitoutput 2>&1 >> $Script:TestSetupLogFile
}
}
function Install-OpenSSHUtilsModule
{
[CmdletBinding()]
param(
[string]$TargetDir = (Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell\Modules\OpenSSHUtils"),
[string]$SourceDir)
$manifestFile = Join-Path -Path $SourceDir -ChildPath OpenSSHUtils.psd1
$moduleFile = Join-Path -Path $SourceDir -ChildPath OpenSSHUtils.psm1
$targetDirectory = $TargetDir
$manifest = Test-ModuleManifest -Path $manifestFile -WarningAction SilentlyContinue -ErrorAction Stop
if ($PSVersionTable.PSVersion.Major -ge 5)
{
$targetDirectory = Join-Path -Path $targetDir -ChildPath $manifest.Version.ToString()
}
$modulePath = Join-Path -Path $env:ProgramFiles -ChildPath WindowsPowerShell\Modules
if(-not (Test-Path "$targetDirectory" -PathType Container))
{
New-Item -ItemType Directory -Path "$targetDirectory" -Force -ErrorAction SilentlyContinue | out-null
}
Copy-item "$manifestFile" -Destination "$targetDirectory" -Force -ErrorAction SilentlyContinue | out-null
Copy-item "$moduleFile" -Destination "$targetDirectory" -Force -ErrorAction SilentlyContinue | out-null
if ($PSVersionTable.PSVersion.Major -lt 4)
{
$modulePaths = [Environment]::GetEnvironmentVariable('PSModulePath', 'Machine') -split ';'
if ($modulePaths -notcontains $modulePath)
{
Write-Verbose -Message "Adding '$modulePath' to PSModulePath."
$modulePaths = @(
$modulePath
$modulePaths
)
$newModulePath = $modulePaths -join ';'
[Environment]::SetEnvironmentVariable('PSModulePath', $newModulePath, 'Machine')
$env:PSModulePath += ";$modulePath"
}
}
}
function Uninstall-OpenSSHUtilsModule
{
[CmdletBinding()]
param([string]$TargetDir = (Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell\Modules\OpenSSHUtils"))
if(Test-Path $TargetDir -PathType Container)
{
Remove-item $TargetDir -Recurse -Force -ErrorAction SilentlyContinue | out-null
}
}
<#
.Synopsis
Get-UserSID
#>
function Get-UserSID
{
param
(
[string]$Domain,
[string]$User
)
if([string]::IsNullOrEmpty($Domain))
{
$objUser = New-Object System.Security.Principal.NTAccount($User)
}
else
{
$objUser = New-Object System.Security.Principal.NTAccount($Domain, $User)
}
$strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
$strSID.Value
}
<#
.Synopsis
Clear-OpenSSHTestEnvironment
#>
function Clear-OpenSSHTestEnvironment
{
Write-Verbose -Verbose -Message "Running Clear-OpenSSHTestEnvironment..."
if ($Global:OpenSSHTestInfo -eq $null) {
throw "OpenSSHTestInfo is not set. Did you run Set-OpenSShTestEnvironment?"
}
$sshBinPath = $Global:OpenSSHTestInfo["OpenSSHBinPath"]
# .exe - Windows specific. TODO - PAL
if (-not (Test-Path (Join-Path $sshBinPath ssh.exe) -PathType Leaf))
{
Throw "Cannot find OpenSSH binaries under $script:OpenSSHBinPath. "
}
if($Global:OpenSSHTestInfo["EnableAppVerifier"] -and (Test-path $env:windir\System32\appverif.exe))
{
# clear all applications in application verifier
& $env:windir\System32\appverif.exe -disable * -for * | out-null
}
if($Global:OpenSSHTestInfo["PostmortemDebugging"])
{
Remove-ItemProperty "HKLM:Software\Microsoft\Windows NT\CurrentVersion\AeDebug" -Name Debugger -ErrorAction SilentlyContinue -Force | Out-Null
Remove-ItemProperty "HKLM:Software\Microsoft\Windows NT\CurrentVersion\AeDebug" -Name Auto -ErrorAction SilentlyContinue -Force | Out-Null
}
#delete service if exists
if (Get-Service $SSHDTestSvcName -ErrorAction SilentlyContinue)
{
Stop-Service $SSHDTestSvcName
sc.exe delete $SSHDTestSvcName 1>$null
}
#Delete accounts
foreach ($user in $OpenSSHTestAccounts)
{
net user $user /delete
}
# remove registered keys
cmd /c "ssh-add -d (Join-Path $Script:E2ETestDataDirectory sshtest_userssokey_ed25519) 2>&1 >> $Script:TestSetupLogFile"
if($Global:OpenSSHTestInfo -ne $null)
{
$Global:OpenSSHTestInfo.Clear()
$Global:OpenSSHTestInfo = $null
}
$isOpenSSHUtilsAvailable = Get-Module 'OpenSSHUtils' -ListAvailable
if ($isOpenSSHUtilsAvailable)
{
Write-Log -Message "Uninstalling Module OpenSSHUtils..."
Uninstall-OpenSSHUtilsModule
}
}
<#
.Synopsis
Get-UnitTestDirectory.
#>
function Get-UnitTestDirectory
{
[CmdletBinding()]
param
(
[ValidateSet('Debug', 'Release')]
[string]$Configuration = "Release",
[ValidateSet('x86', 'x64', '')]
[string]$NativeHostArch = ""
)
[string] $platform = $env:PROCESSOR_ARCHITECTURE
if(-not [String]::IsNullOrEmpty($NativeHostArch))
{
$folderName = $NativeHostArch
if($NativeHostArch -eq 'x86')
{
$folderName = "Win32"
}
}
else
{
if($platform -ieq "AMD64")
{
$folderName = "x64"
}
else
{
$folderName = "Win32"
}
}
if([String]::IsNullOrEmpty($Configuration))
{
if( $folderName -ieq "Win32" )
{
$RealConfiguration = "Debug"
}
else
{
$RealConfiguration = "Release"
}
}
else
{
$RealConfiguration = $Configuration
}
$unitTestdir = Join-Path $repositoryRoot.FullName -ChildPath "bin\$folderName\$RealConfiguration"
$unitTestDir
}
<#
.Synopsis
Run OpenSSH Setup tests.
#>
function Invoke-OpenSSHSetupTest
{
# Tests are not compatible with latest Pester 5.x.
Import-Module -Name 'Pester' -MaximumVersion 4.9.9 -Force -Global
# Discover all CI tests and run them.
Push-Location $Script:E2ETestDirectory
Write-Log -Message "Running OpenSSH Setup tests..."
$testFolders = @(Get-ChildItem *.tests.ps1 -Recurse | ForEach-Object{ Split-Path $_.FullName} | Sort-Object -Unique)
Invoke-Pester $testFolders -OutputFormat NUnitXml -OutputFile $Script:SetupTestResultsFile -Tag 'Setup' -PassThru
Pop-Location
}
<#
.Synopsis
Run OpenSSH uninstall tests.
#>
function Invoke-OpenSSHUninstallTest
{
# Tests are not compatible with latest Pester 5.x.
Import-Module -Name 'Pester' -MaximumVersion 4.9.9 -Force -Global
# Discover all CI tests and run them.
Push-Location $Script:E2ETestDirectory
Write-Log -Message "Running OpenSSH Uninstall tests..."
$testFolders = @(Get-ChildItem *.tests.ps1 -Recurse | ForEach-Object{ Split-Path $_.FullName} | Sort-Object -Unique)
Invoke-Pester $testFolders -OutputFormat NUnitXml -OutputFile $Script:UninstallTestResultsFile -Tag 'Uninstall' -PassThru
Pop-Location
}
<#
.Synopsis
Run OpenSSH pester tests.
#>
function Invoke-OpenSSHE2ETest
{
[CmdletBinding()]
param (
[ValidateSet('CI', 'Scenario')]
[string]$pri = "CI"
)
# Tests are not compatible with latest Pester 5.x.
Import-Module -Name 'Pester' -MaximumVersion 4.9.9 -Force -Global
# Discover all CI tests and run them.
Push-Location $Script:E2ETestDirectory
Write-Log -Message "Running OpenSSH E2E tests..."
$testFolders = @(Get-ChildItem *.tests.ps1 -Recurse | ForEach-Object{ Split-Path $_.FullName} | Sort-Object -Unique)
Invoke-Pester $testFolders -OutputFormat NUnitXml -OutputFile $Script:E2ETestResultsFile -Tag $pri -PassThru
Pop-Location
}
<#
.Synopsis
Run UNIX bash tests using CYGWIN.
#>
function Invoke-OpenSSHBashTests
{
[string]$bashPath = [string]::Empty
# Check for cygwin
if (Test-Path $env:SystemDrive\cygwin\bin\sh.exe) {
$bashPath = "$env:SystemDrive\cygwin\bin\sh.exe"
} elseif (Test-Path $env:SystemDrive\cygwin64\bin\sh.exe) {
$bashPath = "$env:SystemDrive\cygwin64\bin\sh.exe"
} elseif (Test-Path $env:SystemDrive\tools\cygwin\bin\sh.exe) {
$bashPath = "$env:SystemDrive\tools\cygwin\bin\sh.exe"
} else {
# Install cygwin
Write-Host "Installing cygwin using chocolatey to $env:SystemDrive\cygwin folder"
choco install cygwin -y --params "/InstallDir:$env:SystemDrive\cygwin\ /NoStartMenu"
if (Test-Path $env:SystemDrive\cygwin\bin\sh.exe) {
$bashPath = "$env:SystemDrive\cygwin\bin\sh.exe"
} else {
Write-Error "Failed to install cygwin to $env:SystemDrive\cygwin folder" -ErrorAction Stop
return
}
}
$bashTestDirectory = Join-Path $repositoryRoot.FullName -ChildPath "regress"
& "$PSScriptRoot\bash_tests_iterator.ps1" -OpenSSHBinPath $Script:OpenSSHBinPath -BashTestsPath $bashTestDirectory -ShellPath $bashPath -ArtifactsDirectoryPath $bashTestDirectory
}
<#
.Synopsis
Run openssh unit tests.
#>
function Invoke-OpenSSHUnitTest
{
param (
[string] $UnitTestDirectory = ""
)
# Discover all CI tests and run them.
if (! [string]::IsNullOrEmpty($UnitTestDirectory) -and (Test-Path -Path $UnitTestDirectory))
{
$Script:UnitTestDirectory = $UnitTestDirectory
$OpenSSHTestInfo["UnitTestDirectory"] = $UnitTestDirectory
}
elseif ([string]::Isnullorempty($Script:UnitTestDirectory))
{
$Script:UnitTestDirectory = $OpenSSHTestInfo["UnitTestDirectory"]
}
Push-Location $Script:UnitTestDirectory
Write-Log -Message "Running OpenSSH unit tests..."
if (Test-Path $Script:UnitTestResultsFile)
{
$null = Remove-Item -Path $Script:UnitTestResultsFile -Force -ErrorAction SilentlyContinue
}
$testFolders = Get-ChildItem -filter unittest-*.exe -Recurse |
ForEach-Object{ Split-Path $_.FullName} |
Sort-Object -Unique
$testfailed = $false
if ($testFolders -ne $null)
{
$testFolders | % {
$unittestFile = "$(Split-Path $_ -Leaf).exe"
$unittestFilePath = join-path $_ $unittestFile
if(Test-Path $unittestFilePath -pathtype leaf)
{
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = "$unittestFilePath"
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.WorkingDirectory = "$_"
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
$p.WaitForExit()
$errorCode = $p.ExitCode
Write-Host "Running unit test: $unittestFile ..."
if(-not [String]::IsNullOrWhiteSpace($stdout))
{
Add-Content $Script:UnitTestResultsFile $stdout
}
if(-not [String]::IsNullOrWhiteSpace($stderr))
{
Add-Content $Script:UnitTestResultsFile $stderr
}
if ($errorCode -ne 0)
{
$testfailed = $true
$errorMessage = "$unittestFile failed.`nExitCode: $errorCode. Detail test log is at $($Script:UnitTestResultsFile)."
Write-Warning $errorMessage
}
else
{
Write-Host "$unittestFile passed!"
}
}
}
}
Pop-Location
$testfailed
}
<#
Write-Log
#>
function Write-Log
{
param
(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $Message
)
if (-not (Test-Path (Split-Path $Script:TestSetupLogFile) -PathType Container))
{
$null = New-Item -ItemType Directory -Path (Split-Path $Script:TestSetupLogFile) -Force -ErrorAction SilentlyContinue | out-null
}
if (-not ([string]::IsNullOrEmpty($Script:TestSetupLogFile)))
{
Add-Content -Path $Script:TestSetupLogFile -Value $Message
}
# Write message to verbose stream.
Write-Verbose -Verbose -Message $Message
}
Export-ModuleMember -Function Set-BasicTestInfo, Set-OpenSSHTestEnvironment, Clear-OpenSSHTestEnvironment, Invoke-OpenSSHSetupTest, Invoke-OpenSSHUnitTest, Invoke-OpenSSHE2ETest, Invoke-OpenSSHUninstallTest, Invoke-OpenSSHBashTests