MegaBites-AI/Windows-powershell
0372
1# Copyright (c) Microsoft Corporation.2# Licensed under the MIT License.3 4Describe "SSHRemoting Basic Tests" -tags CI {5 6 # SSH remoting is set up to automatically authenticate current user via SSH keys7 # All tests connect back to localhost machine8 9 $script:TestConnectingTimeout = 5000 # Milliseconds10 11 function RestartSSHDService12 {13 if ($IsWindows)14 {15 Write-Verbose -Verbose "Restarting Windows SSHD service..."16 Restart-Service sshd17 Write-Verbose -Verbose "SSHD service status: $(Get-Service sshd | Out-String)"18 }19 else20 {21 Write-Verbose -Verbose "Restarting Unix SSHD service..."22 sudo service ssh restart23 $status = sudo service ssh status24 Write-Verbose -Verbose "SSHD service status: $status"25 }26 }27 28 function TryNewPSSession29 {30 param(31 [string[]] $HostName,32 [string[]] $Name,33 [int] $Port,34 [string] $UserName,35 [string] $KeyFilePath,36 [string] $Subsystem37 )38 39 Write-Verbose -Verbose "Starting TryNewPSSession ..."40 41 # Try creating a new SSH connection42 $timeout = $script:TestConnectingTimeout43 $connectionError = $null44 $session = $null45 $count = 046 while (($null -eq $session) -and ($count++ -lt 2))47 {48 $session = New-PSSession @PSBoundParameters -ConnectingTimeout $timeout -ErrorVariable connectionError -ErrorAction SilentlyContinue49 if ($null -eq $session)50 {51 Write-Verbose -Verbose "SSH New-PSSession remoting connect failed."52 53 if ($count -eq 1)54 {55 # Try restarting sshd service56 RestartSSHDService57 }58 }59 }60 61 if ($null -eq $session)62 {63 $message = "New-PSSession unable to connect to SSH remoting endpoint after two attempts. Error: $($connectionError.Exception.Message)"64 throw [System.Management.Automation.PSInvalidOperationException]::new($message)65 }66 67 Write-Verbose -Verbose "SSH New-PSSession remoting connect succeeded."68 Write-Output $session69 }70 71 function TryNewPSSessionHash72 {73 param (74 [hashtable[]] $SSHConnection,75 [string[]] $Name76 )77 78 Write-Verbose -Verbose "Starting TryNewPSSessionHash ..."79 80 foreach ($connect in $SSHConnection)81 {82 $connect.Add('ConnectingTimeout', $script:TestConnectingTimeout)83 }84 85 # Try creating a new SSH connection86 $connectionError = $null87 $session = $null88 $count = 089 while (($null -eq $session) -and ($count++ -lt 2))90 {91 $session = New-PSSession @PSBoundParameters -ErrorVariable connectionError -ErrorAction SilentlyContinue92 if ($null -eq $session)93 {94 Write-Verbose -Verbose "SSH New-PSSession remoting connect failed."95 96 if ($count -eq 1)97 {98 # Try restarting sshd service99 RestartSSHDService100 }101 }102 }103 104 if ($null -eq $session)105 {106 $message = "New-PSSession unable to connect to SSH remoting endpoint after two attempts. Error: $($connectionError.Exception.Message)"107 throw [System.Management.Automation.PSInvalidOperationException]::new($message)108 }109 110 Write-Verbose -Verbose "SSH New-PSSession remoting connect succeeded."111 Write-Output $session112 }113 114 function VerifySession {115 param (116 [System.Management.Automation.Runspaces.PSSession] $session117 )118 119 if ($null -eq $session)120 {121 return122 }123 124 Write-Verbose -Verbose "VerifySession called for session: $($session.Id)"125 126 $session.State | Should -BeExactly 'Opened'127 $session.ComputerName | Should -BeExactly 'localhost'128 $session.Transport | Should -BeExactly 'SSH'129 Write-Verbose -Verbose "Invoking whoami"130 Invoke-Command -Session $session -ScriptBlock { whoami } | Should -BeExactly $(whoami)131 Write-Verbose -Verbose "Invoking PSSenderInfo"132 $psRemoteVersion = Invoke-Command -Session $session -ScriptBlock { $PSSenderInfo.ApplicationArguments.PSVersionTable.PSVersion }133 $psRemoteVersion.Major | Should -BeExactly $PSVersionTable.PSVersion.Major134 $psRemoteVersion.Minor | Should -BeExactly $PSVersionTable.PSVersion.Minor135 Write-Verbose -Verbose "VerifySession complete"136 }137 138 Context "New-PSSession Tests" {139 140 AfterEach {141 Write-Verbose -Verbose "Starting New-PSSession AfterEach"142 if ($script:session -ne $null) { Remove-PSSession -Session $script:session }143 if ($script:sessions -ne $null) { Remove-PSSession -Session $script:sessions }144 Write-Verbose -Verbose "AfterEach complete"145 }146 147 It "Verifies new connection with implicit current User" {148 Write-Verbose -Verbose "It Starting: Verifies new connection with implicit current User"149 $script:session = TryNewPSSession -HostName localhost150 $script:session | Should -Not -BeNullOrEmpty151 VerifySession $script:session152 Write-Verbose -Verbose "It Complete"153 }154 155 It "Verifies new connection with explicit User parameter" {156 Write-Verbose -Verbose "It Starting: Verifies new connection with explicit User parameter"157 $script:session = TryNewPSSession -HostName localhost -UserName (whoami)158 $script:session | Should -Not -BeNullOrEmpty159 VerifySession $script:session160 Write-Verbose -Verbose "It Complete"161 }162 163 It "Verifies explicit Name parameter" {164 Write-Verbose -Verbose "It Starting: Verifies explicit Name parameter"165 $sessionName = 'TestSessionNameA'166 $script:session = TryNewPSSession -HostName localhost -Name $sessionName167 $script:session | Should -Not -BeNullOrEmpty168 VerifySession $script:session169 $script:session.Name | Should -BeExactly $sessionName170 Write-Verbose -Verbose "It Complete"171 }172 173 It "Verifies explicit Port parameter" {174 Write-Verbose -Verbose "It Starting: Verifies explicit Port parameter"175 $portNum = 22176 $script:session = TryNewPSSession -HostName localhost -Port $portNum177 $script:session | Should -Not -BeNullOrEmpty178 VerifySession $script:session179 Write-Verbose -Verbose "It Complete"180 }181 182 It "Verifies explicit Options parameter" {183 $options = @{"Port"="22"}184 $script:session = New-PSSession -HostName localhost -Options $options -ErrorVariable err185 $err | Should -HaveCount 0186 VerifySession $script:session187 }188 189 It "Verifies explicit Subsystem parameter" {190 Write-Verbose -Verbose "It Starting: Verifies explicit Subsystem parameter"191 $portNum = 22192 $subSystem = 'powershell'193 $script:session = TryNewPSSession -HostName localhost -Port $portNum -SubSystem $subSystem194 $script:session | Should -Not -BeNullOrEmpty195 VerifySession $script:session196 Write-Verbose -Verbose "It Complete"197 }198 199 It "Verifies explicit KeyFilePath parameter" {200 Write-Verbose -Verbose "It Starting: Verifies explicit KeyFilePath parameter"201 $keyFilePath = "$HOME/.ssh/id_rsa"202 $portNum = 22203 $subSystem = 'powershell'204 $script:session = TryNewPSSession -HostName localhost -Port $portNum -SubSystem $subSystem -KeyFilePath $keyFilePath205 $script:session | Should -Not -BeNullOrEmpty206 VerifySession $script:session207 Write-Verbose -Verbose "It Complete"208 }209 210 It "Verifies SSHConnection hash table parameters" {211 Write-Verbose -Verbose "It Starting: Verifies SSHConnection hash table parameters"212 $sshConnection = @(213 @{214 HostName = 'localhost'215 UserName = whoami216 Port = 22217 KeyFilePath = "$HOME/.ssh/id_rsa"218 Subsystem = 'powershell'219 },220 @{221 HostName = 'localhost'222 KeyFilePath = "$HOME/.ssh/id_rsa"223 Subsystem = 'powershell'224 })225 $script:sessions = TryNewPSSessionHash -SSHConnection $sshConnection -Name 'Connection1','Connection2'226 $script:sessions | Should -HaveCount 2227 $script:sessions[0].Name | Should -BeLike 'Connection*'228 $script:sessions[1].Name | Should -BeLike 'Connection*'229 VerifySession $script:sessions[0]230 VerifySession $script:sessions[1]231 Write-Verbose -Verbose "It Complete"232 }233 234 It "Verifies the 'pwshconfig' configured endpoint." {235 Write-Verbose -Verbose "It Starting: Verifies the 'pwshconfig' configured endpoint."236 $script:session = TryNewPSSession -HostName localhost -Subsystem 'pwshconfig'237 $script:session | Should -Not -BeNullOrEmpty238 # Configured session should be in ConstrainedLanguage mode.239 $sessionLangMode = Invoke-Command -Session $script:session -ScriptBlock { "$($ExecutionContext.SessionState.LanguageMode)" }240 $sessionLangMode | Should -BeExactly "ConstrainedLanguage"241 Write-Verbose -Verbose "It Complete"242 }243 244 <#245 It "Verifes that 'pwshbroken' throws expected error for missing config file." {246 Write-Verbose -Verbose "It Starting: Verifes that 'pwshbroken' throws expected error for missing config file."247 { $script:session = TryNewPSSession -HostName localhost -Subsystem 'pwshbroken' } | Should -Throw248 $script:session = $null249 Write-Verbose -Verbose "It Complete"250 }251 #>252 }253 254 function TryCreateRunspace255 {256 param (257 [string] $UserName,258 [string] $ComputerName,259 [string] $KeyFilePath,260 [int] $Port,261 [string] $Subsystem262 )263 264 Write-Verbose -Verbose "Starting TryCreateRunspace ..."265 266 $timeout = $script:TestConnectingTimeout267 $connectionError = $null268 $count = 0269 $rs = $null270 $ci = [System.Management.Automation.Runspaces.SSHConnectionInfo]::new($UserName, $ComputerName, $KeyFilePath, $Port, $Subsystem, $timeout)271 while (($null -eq $rs) -and ($count++ -lt 2))272 {273 try274 {275 $rs = [runspacefactory]::CreateRunspace($host, $ci)276 $null = $rs.Open()277 }278 catch279 {280 $connectionError = $_281 $rs = $null282 Write-Verbose -Verbose "SSH Runspace Open remoting connect failed."283 284 if ($count -eq 1)285 {286 # Try restarting sshd service287 RestartSSHDService288 }289 }290 }291 292 if (($null -eq $rs) -or !($rs -is [runspace]))293 {294 $message = "Runspace open unable to connect to SSH remoting endpoint after two attempts. Error: $($connectionError.Message)"295 throw [System.Management.Automation.PSInvalidOperationException]::new($message)296 }297 298 Write-Verbose -Verbose "SSH Runspace Open remoting connect succeeded."299 Write-Output $rs300 }301 302 function VerifyRunspace {303 param (304 [runspace] $rs305 )306 307 if ($null -eq $rs)308 {309 return310 }311 312 Write-Verbose -Verbose "VerifyRunspace called for runspace: $($rs.Id)"313 314 $rs.RunspaceStateInfo.State | Should -BeExactly 'Opened'315 $rs.RunspaceAvailability | Should -BeExactly 'Available'316 $rs.RunspaceIsRemote | Should -BeTrue317 $ps = [powershell]::Create()318 try319 {320 Write-Verbose -Verbose "VerifyRunspace: Invoking PSSenderInfo"321 $ps.Runspace = $rs322 $psRemoteVersion = $ps.AddScript('$PSSenderInfo.ApplicationArguments.PSVersionTable.PSVersion').Invoke()323 $psRemoteVersion.Major | Should -BeExactly $PSVersionTable.PSVersion.Major324 $psRemoteVersion.Minor | Should -BeExactly $PSVersionTable.PSVersion.Minor325 326 $ps.Commands.Clear()327 Write-Verbose -Verbose "VerifyRunspace: Invoking whoami"328 $ps.AddScript('whoami').Invoke() | Should -BeExactly $(whoami)329 Write-Verbose -Verbose "VerifyRunspace complete"330 }331 finally332 {333 $ps.Dispose()334 }335 }336 337 Context "SSH Remoting API Tests" {338 339 AfterEach {340 Write-Verbose -Verbose "Starting Runspace close AfterEach"341 if (($script:rs -ne $null) -and ($script:rs -is [runspace])) { $script:rs.Dispose() }342 Write-Verbose -Verbose "AfterEach complete"343 }344 345 $testCases = @(346 @{347 testName = 'Verifies connection with implicit user'348 UserName = $null349 ComputerName = 'localhost'350 KeyFilePath = $null351 Port = 0352 Subsystem = $null353 },354 @{355 testName = 'Verifies connection with UserName'356 UserName = whoami357 ComputerName = 'localhost'358 KeyFilePath = $null359 Port = 0360 Subsystem = $null361 },362 @{363 testName = 'Verifies connection with KeyFilePath'364 UserName = whoami365 ComputerName = 'localhost'366 KeyFilePath = "$HOME/.ssh/id_rsa"367 Port = 0368 Subsystem = $null369 },370 @{371 testName = 'Verifies connection with Port specified'372 UserName = whoami373 ComputerName = 'localhost'374 KeyFilePath = "$HOME/.ssh/id_rsa"375 Port = 22376 Subsystem = $null377 },378 @{379 testName = 'Verifies connection with Subsystem specified'380 UserName = whoami381 ComputerName = 'localhost'382 KeyFilePath = "$HOME/.ssh/id_rsa"383 Port = 22384 Subsystem = 'powershell'385 }386 )387 388 It "<testName>" -TestCases $testCases {389 param (390 $UserName,391 $ComputerName,392 $KeyFilePath,393 $Port,394 $SubSystem,395 $TestName396 )397 398 Write-Verbose -Verbose "It Starting: $TestName"399 $script:rs = TryCreateRunspace -UserName $UserName -ComputerName $ComputerName -KeyFilePath $KeyFilePath -Port $Port -Subsystem $Subsystem400 $script:rs | Should -Not -BeNullOrEmpty401 VerifyRunspace $script:rs402 Write-Verbose -Verbose "It Complete"403 }404 }405}406 