I'm working on automating the extract of a report on a cisco system (ISE in that case), to do that i'm using poweshell and the Plink component of the PuTTy suite.
I manage to automate the connection and run simple task, but when it come to generate the report you need to go throught a menu :
SERVER/#User# application configure ise
Selection configuration option
[1]Reset M&T Session Database
[2]Rebuild M&T Unusable Indexes
[3]Purge M&T Operational Data
[4]Reset M&T Database
[5]Refresh Database Statistics
[6]Display Profiler Statistics
[7]Export Internal CA Store
[8]Import Internal CA Store
[9]Create Missing Config Indexes
[10]Create Missing M&T Indexes
[11]Enable/Disable ACS Migration
[12]Generate Daily KPM Stats
[13]Generate KPM Stats for last 8 Weeks
[14]Enable/Disable Counter Attribute Collection
[15]View Admin Users
[16]Get all Endpoints
[17]Enable/Disable Wifi Setup
[18]Reset Config Wifi Setup
[19]Establish Trust with controller
[20]Reset Context Visibility
[21]Synchronize Context Visibility With Database
[22]Generate Heap Dump
[23]Generate Thread Dump
[24]Force Backup Cancellation
[25]CleanUp ESR 5921 IOS Crash Info Files
[26]Configure TCP params
[27]Recreate undotablespace
[28]Fetch SGA/PGA Memory usage
[0]Exit
All in need to do to generate the report is typing 16 but when i try to automate this process the flow of command can't pass this menu.
Here's some of the script i tried to use :
The easiest version
$plinkPath = "C:\Program Files\PuTTY\plink.exe"
Set-Alias plink $plinkPath
$t = "SERVER"
$l = "#User"
$pw = "SoMePaSSwOrD"
echo application configure ise 0 exit | plink -ssh -pw $pw -t $t -l $l
Normal version :
$plinkPath = "C:\Program Files\PuTTY\plink.exe"
Set-Alias plink $plinkPath
$t = "SERVER"
$l = "#User"
$pw = "SoMePaSSwOrD"
plink -ssh -pw $pw -t $t -l $l "application configure ise 0 exit"
Using System.Diagnostics.Process :
$ProcessStartInfo = New-Object System.Diagnostics.ProcessStartInfo
$ProcessStartInfo.UseShellExecute = $false
$ProcessStartInfo.RedirectStandardError = $true
$ProcessStartInfo.RedirectStandardInput = $true
$ProcessStartInfo.RedirectStandardOutput = $true
$ProcessStartInfo.FileName = "C:\Program Files\PuTTY\plink.exe"
$t = "SERVER"
$l = "#User"
$pw = "SoMePaSSwOrD"
$ProcessStartInfo.Arguments = "-ssh -t $t -l $l -pw $pw"
$Process = New-Object System.Diagnostics.Process
$Process.StartInfo = $ProcessStartInfo
$Process.Start() | Out-Null
$Process.StandardInput.WriteLine("application configure ise")
#Start-Sleep -m 3000
$Process.StandardInput.WriteLine("0")
$Process.StandardInput.WriteLine("exit")
$Process.WaitForExit()
$stdoutput = $Process.StandardOutput.ReadToEnd()
$erroutput = $Process.StandardError.ReadToEnd()
Write-Host "Standard Output: $stdoutput"
Write-Host "Error Output : $erroutput"
Write-Host "exit code: " + $Process.ExitCode
But all of these method result in the same way, no crash just blocked in the menu waiting for an input.
Just some clarification :
-No i don't use the Posh-SSH module it simply doesn't work (no output, no effect ...)
-The -m (path to a .txt file with the flow of command) in the line plink -ssh -pw $pw -t $t -l $l doesn't work either (it's apparently a known issue on cisco systems)
Related
Basically the title. My friend provided me a script to batch change RHEL passwords via Powershell and PuTTY, but the new password I entered doesn't work when I try to log in. I think the issue is that it doesn't escape one of the special characters that's in the new password, but I can't figure out what the new password would have been.
The "new password" I used was similar to this: a1b2c3d"4e5f6g7
I attempted to replace the secure strings for regular strings, or use telnet instead of SSH with a packet capture to determine what exactly is being sent, but none of that has worked thus far.
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
# Displays prompt
Write-Host "This will update the root password on the Linux Servers"
# Get the running directory
$rundirectory = Split-Path $MyInvocation.MyCommand.Path
#$rundirectory = Split-Path $rundirectory
# Get old root credential
$oldrootPassword = Read-Host "Enter old root password" -AsSecureString
$oldrootCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "root", $oldrootPassword
# Get new root credential
$newrootPassword = Read-Host "Enter new root password" -AsSecureString
$newrootCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "root", $newrootPassword
$newrootPassword2 = Read-Host "Retype new root password" -AsSecureString
$newrootCredential2 = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "root", $newrootPassword2
# $gc = get-content \linuxservers.txt
if ($newrootCredential.GetNetworkCredential().Password -ceq $newrootCredential2.GetNetworkCredential().Password) {
$templogfile = $rundirectory + "\Temp\log.txt"
$tempchfile = $rundirectory + "\Temp\pwd_changes.txt"
$log = $rundirectory + "\Logs\RHEL\Password_Changes_$(Get-Date -f MMddyyyy).log"
$newrootPassword = $newrootCredential.GetNetworkCredential().Password
$serverlist = $rundirectory + "\linuxservers.txt"
Get-Content $serverlist | %{
# Connects to host and stores SSH key in case it does not have one already
echo y | plink.exe -ssh -pw $oldrootCredential.GetNetworkCredential().Password root#$_ exit
# Opens a session to the server to use for disaster recovery
putty.exe -ssh -pw $oldrootCredential.GetNetworkCredential().Password root#$_
# Adds delay to complete login before password is changed
Start-Sleep -Milliseconds 900
# Command sent to host to change password that is then logged
echo y | plink.exe -ssh -v -pw $oldrootCredential.GetNetworkCredential().Password root#$_ "echo root:'$newrootPassword' | chpasswd" 2>&1 >> $templogfile
# Parses file and stores output in variable
$outpt = cat $templogfile | Select-String "Session sent command exit status"
# Adds server name and variable to changes file
echo `n $_.ToUpper() `n$outpt `n "------------------------------------" >> $tempchfile
# Removes the log file to be used again in loop
Remove-Item $templogfile
# Opens second PuTTY session to make sure password works
putty.exe -ssh -pw $newrootCredential.GetNetworkCredential().Password root#$_
}
} else {
$writehost = "ERROR: New root passwords do not match. Exiting..."
}
if ($writehost -ceq "ERROR: New root passwords do not match. Exiting...") {
Write-Host "ERROR: New root passwords do not match. Exiting..."
} else {
# Places contents of results file in variable
$pwresults = cat $tempchfile
# Adds comment at top of file and creates new results file
echo "Investigate all servers that do not have a command exit status of 0" $pwresults >> $log
# Removes the changes file
Remove-Item $tempchfile
# Opens results file for administrator to investigate
Invoke-Item $log
}
I expected the new password to be a1b2c3d"4e5f6g7; however, this does not work upon login.
Try this. Backslash the doublequote. You might have changed it to the password without the doublequote. You need some way to undo these things if they don't work.
$newrootPassword = $newrootpassword -replace '"','\"'
How do I pass a Y into a process started by a System.Diagnostic.Process in PowerShell?
function Start-NewPlinkProcess(
[string]$pfile = 'plink.exe',
[string]$arguments = 'somehost -l somelogin -pw somepasswd ping -c 12 someOtherHost > /home/homeie/mePingTestResults.txt'
){
$p = New-Object System.Diagnostics.Process;
$p.StartInfo.UseShellExecute = $false;
$p.StartInfo.RedirectStandardOutput = $true;
$p.StartInfo.RedirectStandardInput = $true;
$p.StartInfo.FileName = $pfile;
$p.StartInfo.Arguments = $arguments
$p.StandardInput.WriteLine("Y") # Pass a Y to stdin ignore that...
$pident = ($p.Start()).Id
Write-Host("pid: $($pident)");
#$p.WaitForExit();
#$p.StandardOutput.ReadToEnd();
return $p
}
When I call it I still get:
If you trust this host, enter "y" to add the key to
PuTTY's cache and carry on connecting.
If you want to carry on connecting just once, without
adding the key to the cache, enter "n".
If you do not trust this host, press Return to abandon the
connection.
Store key in cache? (y/n)
I've read elsewhere that it's possible to try something like echo y | plink ... and have it read it in piped from standard input, but I want to have more control over it then just that.
Do not!
Verifying host key fingerprint is an integral part of securing your connection. Blindly accepting any host key will make you vulnerable to the man-in-the-middle attacks.
Instead, use the -hostkey switch to provide the fingerprint of the expected/known host key.
[string]$arguments = 'somehost -l somelogin -pw somepasswd ping -hostkey xx:xx:xx:xx:... -c 12 someOtherHost > /home/homeie/mePingTestResults.txt'
Just move your StandardInput line below where the process is started.
function Start-NewPlinkProcess(
[string]$pfile = 'plink.exe',
[string]$arguments = 'somehost -l somelogin -pw somepasswd ping -c 12 someOtherHost > /home/homeie/mePingTestResults.txt'
){
$p = New-Object System.Diagnostics.Process;
$p.StartInfo.UseShellExecute = $false;
$p.StartInfo.RedirectStandardOutput = $true;
$p.StartInfo.RedirectStandardInput = $true;
$p.StartInfo.FileName = $pfile;
$p.StartInfo.Arguments = $arguments
$pident = ($p.Start()).Id
Write-Host("pid: $($pident)");
$p.StandardInput.WriteLine("Y") # Pass a Y to stdin ignore that...
#$p.WaitForExit();
#$p.StandardOutput.ReadToEnd();
return $p
}
I am trying to use the Write-Output command in Powershell to write a line to Netcat, but I cannot seem to do this without a new line being sent. So far I have tried...
Write-Output "command" | nc -w1 aa.bb.cc.dd xxxx
and
"command" | nc -w1 aa.bb.cc.dd xxxx
... however both cause new lines to be sent along with "command". Can someone help me find a solution that would be similar to Write-Host -NoNewLine or Echo -n in Linux?
Taking from Can I send some text to the STDIN of an active process under Windows?
$psi = New-Object System.Diagnostics.ProcessStartInfo;
$psi.FileName = "ncat.exe"
$psi.UseShellExecute = $false
$psi.RedirectStandardInput = $true
$psi.Arguments = 'localhost','9990' #ncat connection args
$psi.CreateNoWindow = $true
$p = [System.Diagnostics.Process]::Start($psi)
Start-Sleep -s 2
$p.StandardInput.Write("command") #StandardInput is a StreamWriter
$p.StandardInput.Write("command")
$p.Close()
I have been trying both standard PS1 using what I read about using:
ECHO y | plink .....
But the issue I have is that plink is being saved on a network drive. I can call it using:
$plink = "P:\path\plink.exe"
echo y | &$plink -ssh -l user-pw password $addrss exit
&$plink -ssh -l user -pw password -m "P:\path\SCOTDiagScript.txt" $addrss
The issue I have is that if I run plink manually via cmd, I get output, that I need to read and possibly display to the user. Piping the last line to Out-File gives me nothing and if I try to call cmd to then redirect to a txt file, I get an error because the path for plink has a space in it; and I am using quotes.
I have also given using .NET a try, but doing a .StandardOutput.ReadToEnd() causes it to hang; deadlock maybe? Even though I am placing it well before the exit and I have it sleep a bit before any type of exit takes place:
$ps = New-Object -TypeName System.Diagnostics.Process
$ps.StartInfo.UseShellExecute = $false
$ps.StartInfo.RedirectStandardInput = $true
$ps.StartInfo.RedirectStandardOutput = $true;
$ps.StartInfo.FileName = "P:\path\plink.exe"
$ps.StartInfo.Arguments = "-ssh -l user -pw password $addrss"
[void]$ps.Start()
Start-Sleep -m 500
$ps.StandardInput.Write("cd c:/scot/bin`r")
Start-Sleep -m 500
$ps.StandardInput.Write("GetDiagFiles.exe`r")
Start-Sleep -m 500
$ps.StandardInput.Write("cd c:/temp`r")
Start-Sleep -m 500
$ps.StandardInput.Write("ls *.zip`r")
Start-Sleep -m 500
$ps.StandardInput.Write("cd c:/scot/monitor`r")
$Out = $ps.StandardOutput.ReadToEnd();
Start-Sleep -s 10
$ps.StandardInput.Write("exit`r")
$PlinkStreamWriter.Close();
if (!$ps.HasExited) { $ps.Kill() }
$Out
I'm sure I'm doing something wrong, but I have scoured over everything at MSDN and nothing.
Doing what you ask should be as easy as:
plink -ssh -l user -pw password -m script.txt > output.log
Where the script.txt contains your commands:
cd c:/scot/bin
GetDiagFiles.exe
cd c:/temp
ls *.zip
cd c:/scot/monitor
exit
If this does not work (as you claim you have tried something similar), give us more details about the problem.
You have not created a System.Diagnostics.ProcessStartInfo object to feed into the System.Diagnostics.Process object.
You needed to put `n at the end of the commands not `r, or you can remove them altogether when using the .WriteLine method
I tested the code below using some cmd.exe and made the alterations you need, it should work with plink.exe
$ProcessStartInfo = New-Object System.Diagnostics.ProcessStartInfo
$ProcessStartInfo.UseShellExecute = $false
$ProcessStartInfo.RedirectStandardError = $true
$ProcessStartInfo.RedirectStandardInput = $true
$ProcessStartInfo.RedirectStandardOutput = $true
$ProcessStartInfo.FileName = "P:\path\plink.exe"
$ProcessStartInfo.Arguments = "-ssh -l user -pw password $addrss"
$Process = New-Object System.Diagnostics.Process
$Process.StartInfo = $ProcessStartInfo
$Process.Start() | Out-Null
$Process.StandardInput.WriteLine("cd c:/scot/bin")
$Process.StandardInput.WriteLine("GetDiagFiles.exe")
$Process.StandardInput.WriteLine("cd c:/temp")
$Process.StandardInput.WriteLine("ls *.zip")
$Process.StandardInput.WriteLine("cd c:/scot/monitor")
$Process.StandardInput.WriteLine("exit")
$Process.WaitForExit()
$stdoutput = $Process.StandardOutput.ReadToEnd()
$erroutput = $Process.StandardError.ReadToEnd()
Write-Host "Standard Output: $stdoutput"
Write-Host "Error Output : $erroutput"
Write-Host "exit code: " + $Process.ExitCode
I am trying to SFTP a file from powershell using psftp.exe (putty). I can run single command such as open but I need to change the default directory and then put the file. The following code takes me to psftp but ignores lines from cd .. to bye. I guess I can run a batch file which has the sftp commands but if possible I want to accomplish using powershell.
$file = "C:\Source\asdf.csv"
$user = "user"
$pass = "pass"
$hst = "host"
$path="C:\ProgramFiles\psftp.exe"
$cmd = #"
-pw $pass $user#$hst
cd ..
cd upload
put $file
bye
"#
invoke-expression "$path $cmd"
Give this a try:
$file = "C:\Source\asdf.csv"
$user = "user"
$pass = "pass"
$hst = "host"
$path="C:\ProgramFiles\psftp.exe"
$cmd = #(
"cd ..",
"cd upload",
"put $file",
"bye"
)
$cmd | & $path -pw $pass "$user#$hst"
In answer to the questions in the comment:
The first part, "$cmd |" pipes the contents of $cmd to the command that follows. Since it is an external program (as opposed to a cmdlet or function) it will send the contents of $cmd to stdin of the external program.
The "& $path" part says to treat the contents of $path as a command or program name and execute it.
The rest of the line is passed to the external program as command line arguments.