VMware Cloud Community
piercj2
Enthusiast
Enthusiast
Jump to solution

Try / Catch not working as expected for Invoke-SSHStreamExpectSecureAction

Hi, i'm trying to verify SSH and root credentials for multiple different systems.

The below script takes as input a .csv file containing the IP of the target systems and associated ssh and root credentials.

The output of the script is a second array, containing the verified Credentials, if any Password is incorrect, this is flagged in the array.

The Try/Catch below is not working as expected for privileged credentials, that is when an incorrect privileged mode password is entered, the expected "Incorrect privileged password passed" is not entered into the results array.

 

Function Check-Creds {
<#
.SYNOPSIS
Read text file containing System Manager Credentials and returns verify Credentials are working

.EXAMPLE
Check-Creds -Path C:\temp\list.csv
.NOTE
.csv file has the following column headings, VIP_FQDN,VIP_IP,Username,Password,RootUser,RootPass
#>

param(
[Parameter(Mandatory)]
[System.IO.FileInfo]$Path
)

If (!(Get-Module -ListAvailable Posh-SSH)) {
find-Module -Name Posh-SSH | Install-Module -Scope CurrentUser -Confirm:$false
}

If (!(Get-module -ListAvailable "ImportExcel")) {
Find-Module -Name ImportExcel | Install-Module -Scope CurrentUser
}


$systemMgmtArray = @()
$systemMgmtArray = Import-Csv $Path
$resultsArray = @()

$count = $systemMgmtArray | Measure-Object
$i = 1

foreach ($item in $systemMgmtArray){
Write-Progress -Activity "Checking Credentials of System Managers" -Status "Working on $($item.VIP_FQDN)" -PercentComplete (($i*100)/$count.Count)

$resultsProperty = [ordered] @{
'VIP_FQDN'=$item.VIP_FQDN
'VIP_IP' = $item.VIP_IP
}

$sshTarget = $item.VIP_IP
$sshUsername = $item.Username
$password = $item.Password
$sshPassword = $password | ConvertTo-SecureString -AsPlainText -Force
$sshPassword.MakeReadOnly()
$sshCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $sshUsername,$sshPassword
$sshCredential = Get-Credential -Credential $sshCred
$rootUser = $item.RootUser
$rootPass = $item.RootPass
$sshRootPass = $rootPass | ConvertTo-SecureString -AsPlainText -Force
$sshRootPass.MakeReadOnly()

Write-Host "Connecting to $($item.VIP_FQDN)"
$sshSession = New-SSHSession -ComputerName $item.VIP_IP -Credential $sshCredential -AcceptKey:$true

if ($sshSession.Connected -like "True") {
$resultsProperty.Add("Username",$sshUsername)
$resultsProperty.Add("Password",$password)
Write-Host "SSh session to $($item.VIP_FQDN) is connected, checking $($rootUser) credentials now"
try {
$sshStream = New-SSHShellStream -index $sshSession.SessionId
Invoke-SSHStreamExpectSecureAction -ShellStream $SSHStream -Command 'st en' -ExpectString "Password:" -SecureAction ($sshRootPass) -Verbose
$sshStream.read()
$sshStream.WriteLine("pwd")
Start-Sleep -Seconds 3
$sshStream.Read()
Start-Sleep -Seconds 3

$resultsProperty.Add("RootUser",$rootUser)
$resultsProperty.Add("RootPass",$rootPass)
} catch {
$_.exception.Message
Write-Host "Unable to enter Privileged mode, incorrect $($item.RootUser) password supplied"
$resultsProperty.Add("RootUser",$rootUser)
$resultsProperty.Add("RootPass","Incorrect privileged password passed")
}

Write-Host " Disconnecting ssh session to $($item.VIP_FQDN) "
Remove-SSHSession -SessionId $sshSession.SessionId | Out-Null
Write-Host ""

} else {
Write-host "Password for $($item.VIP_FQDN) not working" -ForegroundColor Red
$_.exception.Message
$resultsProperty.Add("Username",$sshUsername)
$resultsProperty.Add("Password","Incorrect ssh Password")
$resultsProperty.Add("RootUser",$rootUser)
$resultsProperty.Add("RootPass","Unable to SSH so cannot check Privileged Password")
}


$resultsArray += New-Object -TypeName psobject -Property $resultsProperty
$i++
}
$resultsArray | Out-GridView

$downloadsDir = "$HOME\Downloads"
if (Test-Path "$downloadsDir\Credential_Check.xlsx") {Remove-Item "$downloadsDir\Credential_Check.xlsx"}
$resultsArray | Export-Excel -Path "$downloadsDir\Credential_Check.xlsx"
Invoke-Item "$downloadsDir\Credential_Check.xlsx"
}

 

Output from the above is

Connecting to https://server1.acme.com
SSh session to https://server1.acme.com is connected, checking root credentials now
VERBOSE: Executing command st en.
VERBOSE: Waiting for match.
VERBOSE: Matching by String.
VERBOSE: Executing action.
VERBOSE: Action has been executed.
True

pwd
su: Authentication failure
PC1RNNSXTNPROD02> pwd
% Command not found: pwd
server1>
Disconnecting ssh session to https://server1.acme.com

 

With the result of "su: Authentication failure", I was expecting to drop out of the Try statement and for the Catch to be used.

What am I missing (not understanding) ?

Labels (2)
Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Can't you redirect the stream output to a variable?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

8 Replies
LucD
Leadership
Leadership
Jump to solution

Have you tried adding -ErrorAction Stop on the Invoke-SSHStreamExpectSecureAction cmdlet?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
piercj2
Enthusiast
Enthusiast
Jump to solution

Hi Luc, i had tried -erroraction stop as follows, it didn't help

try {
$sshStream = New-SSHShellStream -index $sshSession.SessionId
Invoke-SSHStreamExpectSecureAction -ShellStream $SSHStream -Command 'st en' -ExpectString "Password:" -SecureAction ($sshRootPass) -Verbose -ErrorAction Stop
$sshStream.read()
$sshStream.WriteLine("pwd")
Start-Sleep -Seconds 3
$sshStream.Read()
Start-Sleep -Seconds 3

$resultsProperty.Add("RootUser",$rootUser)
$resultsProperty.Add("RootPass",$rootPass)
}

 

It looks like there is no error passing the Invoke-SSHStreamExpectSecureAction command. The output from this is

VERBOSE: Executing command st en.
VERBOSE: Waiting for match.
VERBOSE: Matching by String.
VERBOSE: Executing action.
VERBOSE: Action has been executed.
True

su: Authentication failure

I believe Invoke-SSHStreamExpectSecureAction executes without error, hence "true" in the output.

I think the error happens when the $sshStream.read() takes an incorrect password from SecureAction ($sshRootPass), that is when su: Authentication failure happens.

I don't know how to manage this

 

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You might be right, but I suspect the error happens inside shell where you launch the 'su' command.
And that obviously doesn't trigger an exception.

Is this by any chance against an Ubuntu box?

Shouldn't that be 'sudo su' instead of just 'su'?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
piercj2
Enthusiast
Enthusiast
Jump to solution

you could be right, the error is probably happening inside the shell, not in PowerCLI, i hadn't thought of that.

If that is the case, is there any way of managing the messages that are displayed from -verbose ?

One of the outputs from -verbose is "su: Authentication failure", is there any way to manage/use this ?

The boxes in question are NSX Managers, entering privileged mode is done with "start enable", or "st en"

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You could capture the text returned by $sshStream.Read() in a variable.
And then examine the content with an If-Then-Else, or something similar.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
piercj2
Enthusiast
Enthusiast
Jump to solution

Great idea but, there's no Out-Variable option for $sshStream.Read()

 

I may have "workable" solution. 

Assuming successful authentication for privileged mode, i can run a privileged command and capture the result of that command to a variable. That variable can be written to the results array.

If authentication to privileged mode fails, the command will error. The error can be written to the results array.

Examining the errors will identify the incorrect privileged credentials.

(it's not the best solution, but the end result will be good enough)

 

if ($sshSession.Connected -like "True") {
$resultsProperty.Add("Username",$sshUsername)
$resultsProperty.Add("Password",$password)

Write-Host "SSh session to $($item.VIP_FQDN) is connected, checking $($rootUser) credentials now"
$sshStream = New-SSHShellStream -index $sshSession.SessionId
Invoke-SSHStreamExpectSecureAction -ShellStream $SSHStream -Command 'st en' -ExpectString "Password:" -SecureAction ($sshRootPass) -Verbose
$sshStream.read() 
Start-Sleep -Seconds 3
$sshStream.WriteLine("pwd")
Start-Sleep -Seconds 3
$sshStream.Read()

# Verify it's possible to run an elevated command. If error returned, password provided for 'st en' was incorrect and authentication failed 
$hwPlat = Invoke-SSHStreamShellCommand -ShellStream $sshStream -Command 'uname -i'

$resultsProperty.Add("RootUser",$rootUser)
$resultsProperty.Add("RootPass",$rootPass)
$resultsProperty.Add("HardwarePlatform",$hwPlat)

Write-Host " Disconnecting ssh session to $($item.VIP_FQDN) "
Remove-SSHSession -SessionId $sshSession.SessionId | Out-Null
Write-Host ""

} else {
Write-host "Password for $($item.VIP_FQDN) not working" -ForegroundColor Red
$_.exception.Message
$resultsProperty.Add("Username",$sshUsername)
$resultsProperty.Add("Password","Incorrect")
$resultsProperty.Add("RootUser",$rootUser)
$resultsProperty.Add("RootPass","Unable to SSH so cannot check Privileged Password")
}


$resultsArray += New-Object -TypeName psobject -Property $resultsProperty
$i++
}
$resultsArray | Sort-Object -Property {($_ | Get-Member -MemberType NoteProperty).Count } -Descending | Out-GridView

 

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Can't you redirect the stream output to a variable?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

piercj2
Enthusiast
Enthusiast
Jump to solution

I'd looked at redirecting the verbose output yesterday (about_Redirection - PowerShell | Microsoft Docs). I didn't have any success so didn't think this was the solution. With you suggesting that this was the solution, I took another look. As usual Luc, you are the man !

 

It took some trial and error, redirecting the verbose output from various locations but, eventually I struck gold 🙂

Below is the working code, i've left in the comments, write-host, etc, as it made it easier for me to see what's happening. 

# If you can ssh, check elevated privileges by entering 'st en'
if ($sshSession.Connected -like "True") {
$resultsProperty.Add("Username",$sshUsername)
$resultsProperty.Add("Password",$password)

Write-Host "SSh session to $($item.VIP_FQDN) is connected, checking $($rootUser) credentials now"
$sshStream = New-SSHShellStream -index $sshSession.SessionId
Invoke-SSHStreamExpectSecureAction -ShellStream $SSHStream -Command 'st en' -ExpectString "Password:" -SecureAction ($sshRootPass) -Verbose
$sshStream.read()
Start-Sleep -Seconds 5
$verboseOut = $sshStream.Read() 4>&1
Write-Host -ForegroundColor blue "what Luc said .... $verboseOut"
if ($verboseOut -like '*su: Authentication failure*'){
Write-Host -ForegroundColor DarkGreen "got the error :)"
$resultsProperty.Add("RootUser",$rootUser)
$resultsProperty.Add("RootPass","Incorrect privileged password")
}else{
Write-Host -ForegroundColor DarkGreen "su Authentication successful"
$resultsProperty.Add("RootUser",$rootUser)
$resultsProperty.Add("RootPass",$rootPass)
}
# Verify it's possible to run an elevated command. If error returned, password provided for 'st en' was incorrect and authentication failed inside the remote shell
$hwPlat = Invoke-SSHStreamShellCommand -ShellStream $sshStream -Command 'uname -i'
$resultsProperty.Add("HardwarePlatform",$hwPlat)

Write-Host " Disconnecting ssh session to $($item.VIP_FQDN) "
Remove-SSHSession -SessionId $sshSession.SessionId | Out-Null
Write-Host -ForegroundColor DarkGray "------------------------------------------------------------------"

} else {
Write-Warning "Password for $($item.VIP_FQDN) not working"
Write-Host -ForegroundColor DarkGray "------------------------------------------------------------------"
$_.exception.Message
$resultsProperty.Add("Username",$sshUsername)
$resultsProperty.Add("Password","Incorrect")
$resultsProperty.Add("RootUser",$rootUser)
$resultsProperty.Add("RootPass","Unable to SSH so cannot check Privileged Password")
$resultsProperty.Add("HardwarePlatform","Unable to SSH so cannot check Privileged commands")
}

 

Output is as below

Connecting to https://server1.acme.com
SSH session to https://server1.acme.com is connected, checking root credentials now
VERBOSE: Executing command st en.
VERBOSE: Waiting for match.
VERBOSE: Matching by String.
VERBOSE: Executing action.
VERBOSE: Action has been executed.
True

what Luc said ....
su: Authentication failure
server1>
got the error 🙂
Disconnecting ssh session to https://server1.acme.com
--------------------------------------------------------
Connecting to https://server2.acme.com
SSh session to https://server2.acme.com is connected, checking root credentials now
VERBOSE: Executing command st en.
VERBOSE: Waiting for match.
VERBOSE: Matching by String.
VERBOSE: Executing action.
VERBOSE: Action has been executed.
True

what Luc said ....
***************************************************************************
NOTICE TO USERS

WARNING! Changes made while logged in as the root user
can cause system failure and potentially impact your network. Please be
advised that changes made to the system as the root user must only be made
under the guidance of xxxxxxxxxxx.
***************************************************************************
root@server2:~#
su Authentication successful
Disconnecting ssh session to https://server2.acme.com

 

As always Luc, thank you !

Reply
0 Kudos