Have you ever been asked for the config of a router or switch you (or someone else) put in so long ago you didn’t remember that device was there? So long ago that the layer of dust inside that switch is probably why the fan stopped spinning and melted it? Yup, me too. So when it comes time to rebuild it, you go to that customer’s CATTOOLS directory (or configuration manager, or whatever backup tool that they have), and find out that:
Yes, “stuff” happens, and backups sometimes don’t, for lots of reasons. This got me to thinking that what I really want (this week) is a PowerShell backup utility for an arbitrary list of network gear at any given client. This beats my previous method of snarfing up cattools directories (when I remember) or backing things up manually whenever I change them (and when I remember) - you see the recurring problem in that method? Why PowerShell? There’s so many other approaches with Python, Expect, Ansible and so on (all of which can do way more than just backups) – why build something new in PowerShell? Mostly because I can run that on any customer Windows machine and expect it to work, without installing anything the client might have a problem with. Plus I really wanted to play with Carlos Perez’s Posh-SSH code ( https://github.com/darkoperator/Posh-SSH ) So, first, what to back up? What most of my clients run is some subset of:
Seems like a reasonable starter list? OK, now how to back them up? Again, with the theme of “don’t install anything, don’t change the host you’re running on, and (to quote Ed Skoudis), to 'live off the land' " – this is all in SSH, and all in PowerShell. Essentially for each device: login, do a “show running-config” (or equivalent for that platform), capture the output and save it to ASCII. The credentials never get saved, but you can likely scrape them out of memory if you wanted to make a point. The input file looks like this (a fictional companyname.in is shown): NAME,IP,DEVTYPE The code reads the file as a CSV, so populates a “devices” variable with properties of: devices.name, devices.IP (which can also be a CN or FQDN, it just needs to resolve), and devices.devtype The 7 device types are covered in the example.in file above. Note that the Palo Alto is in there twice, devicetype 6 for “set” commands - the commands to rebuild the box, devicetype 7 for XML output - which you would use for a full backup, or if you wanted to manipulate that file in another app (stay tuned for that). Running the Code: If you run the script with no arguments, you of course get help text:
Running it “for real”, it uses get-credential to collect the userid/password for the devices in the input file. I could save these out, but I’d really rather not leave credentials like this laying around in a file.
The script then motors through the list, device by device. It takes a few minutes, and I could likely make it faster, but I’d rather it be reliable (and done) than a never ending project that never quite works – I really did write this to collect those backups! Error checking? Umm, not so much, or better stated "not yet". If you specify a device that doesn’t exist, or if the credentials don’t match, it’ll error out on that device and just go on to the next one in the list. That’d be a good thing for me to get around to fixing (sometime soon maybe).. The code itself is on my github -> https://github.com/robvandenbrink/rtrbk Where do I go from here? Give the code a spin,and you tell me! If you’ve got devices you’d like to see added, or other features you’d like to see, please use our comment form to let me know! =============== |
Rob VandenBrink 579 Posts ISC Handler Feb 18th 2017 |
Thread locked Subscribe |
Feb 18th 2017 5 years ago |
This is handy - thanks for sharing.
A common problem I ran into when I was a network admin in a former life was, changes made to running config but never committed to persistent storage. This script shouldn't be too hard to mmodify to check both running and saved configs, and do a diff, making note of any that have unsaved changes. This is dirty and untested but explains my suggestion: if (($dev.devtype -eq 1) -or ($dev.devtype -eq 2)) { # DEVTYPE 1 - CISCO IOS # DEVTYPE 2 - CISCO ASA $Session = New-SSHSession -ComputerName $dev.ip -Credential $devcreds -acceptkey:$true $stream = $Session.Session.CreateShellStream("dumb", 0, 0, 0, 0, 1000) sleep 2 $prmpt = $stream.Read().Trim() # check - need to get to enable mode? if ($prmpt -like "*>*") { $stream.Write("en`n") sleep 1 $stream.Write("$enapwd`n") sleep 1 } $stream.Write($nopage) sleep 1 $clearbuff = $stream.Read() $stream.Write("show startup`n") sleep 5 $cfg = $stream.Read() # $stream.Write("exit`n") sleep 1 out-file -filepath ($dev.name+".cfg") -inputobject $cfg #save running config separately sleep 5 $clearbuff = $stream.Read() $stream.Write("show running-config`n") sleep 5 $cfg = $stream.Read() # $stream.Write("exit`n") sleep 1 out-file -filepath ($dev.name+".runcfg") -inputobject $cfg #compare running and saved configs, identify devices running unsaved changes $cfgfile = $dev.name+".cfg" $runfile = $dev.name+".runcfg" if((Get-FileHash $cfgfile).hash -ne (Get-FileHash $runfile).hash) {write-host "running versus saved config mismatch: " $dev.name} Remove-SSHSession -SSHsession $session | out-null } |
David Longenecker 5 Posts |
Quote |
Feb 17th 2017 5 years ago |
Although I'm a fan of rConfig, this is a pretty simple way to do it as well. Thanks for posting!
|
JDoe 5 Posts |
Quote |
Feb 17th 2017 5 years ago |
Sorry, I'm a noob in using Powershell. I'm getting these errors. Any ideas on what i"m doing wrong?
PS C:\rtrbk-master> .\rtrbk.ps1 -i .\companyname.in cmdlet Get-Credential at command pipeline position 1 Supply values for the parameters: cmdlet Get-Credential at command pipeline position 1 Supply values for the following parameters: Credential backing up cisco_wap New-SSHSession : Could not load file or assembly 'Renci.SshNet, Version=2014.4.6.0, Culture=neutral, PublicKeyToken=1cee9f8bde3db106' or one of its dependencies. The system cannot find the file specified. At C:\rtrbk-master\rtrbk.ps1:40 char:16 + ... $Session = New-SSHSession -ComputerName $dev.ip -Credential $devcred ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [New-SSHSession], FileNotFoundException + FullyQualifiedErrorId : System.IO.FileNotFoundException,SSH.NewSshSession You cannot call a method on a null-valued expression. At C:\rtrbk-master\rtrbk.ps1:41 char:5 + $stream = $Session.Session.CreateShellStream("dumb", 0, 0, 0, 0, ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull |
Anonymous |
Quote |
Feb 18th 2017 5 years ago |
The error is on the new-sshsession command, which is part of posh-ssh.
In powershell, get the version: $PSVersionTable I've tested this script on 4.0 and newer - if you're running older ($psversiontable.psversion), you might want to update by installing the latest version of the Windows Management Framework. Also tested on Win7, Server 2008 R2, and pretty much everything newer. If you are running Powershell version 2, the PS update will likely fix things - version 2 had a bunch of manual steps to import modules like this, and really it's just easier to update than to do the manual import steps. If doing the update thing doesn't fly, try re-importing posh-ssh, hopefully that'll throw an error that'll give you more information: import-module -name posh-ssh -verbose |
Rob VandenBrink 579 Posts ISC Handler |
Quote |
Feb 18th 2017 5 years ago |
while it's nice for you to share, this wheel has been invented for ... 20 years (time flies), has a large community and will probably support many more devices.
Take a look at rancid: http://www.shrubbery.net/rancid/, it will keep your configs on version control as well so you get notified when something changes. |
Anonymous |
Quote |
Feb 18th 2017 5 years ago |
Thanks, I've used Rancid, it's a good tool - Nagios does a nice job too, as does a ton of other dedicated backup tools (I mentioned Cattools in the story) and larger vendor NMS platforms of course (Solarwinds Orion and the like, plus the 800 kg gorilla apps like Cisco Prime)
What this is meant for is for someone who doesn't have the time to install something, or doesn't have a host to install it on, or (this is where I am), is a consultant who's there to do something else, and often doesn't have permission to install a large management platform or even a backup app in a customer's environment. Or more likely, if you are there to fix a problem or deliver some other "thing", you simply might not have the time budgeted or the scope signed off on to install anything. Or, as mentioned, the client might have a backup tool, but they might have deleted that VM, or broken the backups by installing something else (folks can be creative like that). If you're a consultant who ends up cleaning up a situation that 2 years later (and you need a router backup to do the cleanup), it's handy to have your own tool that'll run for each of your clients as you engage with them over time (when things are going well) Since this uses PowerShell and pulls one module, it's a script that will run on any Windows host and do the job without any install time, and in fact no installation at all. There's a lot to be said for a cli tool that will do the job with minimal impact to that "other thing" you are there to do. |
Rob VandenBrink 579 Posts ISC Handler |
Quote |
Feb 18th 2017 5 years ago |
Juniper EX switches and Ubiquiti switches would be really handy, as that's what I mostly use.
This is wonderful work, and there's at least one other reason for this vs. Rancid and/or a commercial product running under Windows: I've run into management which is both penny-pinching and phobic about *nix. An open source solution running under Windows can save that situation. Kurt |
NotaBene 3 Posts |
Quote |
Feb 20th 2017 5 years ago |
You might have hit a bug that was introduced in v1.7.8 when fixing an issue that I had found.
I've reported it on GitHub. Hopefully it will be fixed soon. Cheers, Steve |
missgt 2 Posts |
Quote |
Feb 21st 2017 5 years ago |
Anonymous
A recompiled version of 1.7.8 was posted on GitHub overnight. This has corrected the issue for me. It should also fix it for you. |
missgt 2 Posts |
Quote |
Feb 22nd 2017 5 years ago |
I am running the following PS script and get the following error (just like anonymous). Note, the write-debug shows I am connected:
Import-Module SSH-Sessions $DebugPreference = "Continue" $networkobjects = Import-Csv "C:\tools\devices.csv" ForEach ( $networkobject in $networkobjects ) { $ipaddress = $networkobject.ipaddress $username = $networkobject.username $password = $networkobject.password New-SSHSession -ComputerName $ipaddress -username $username -password $password $session = Get-SSHSession -ComputerName $ipaddress write-debug $session.ComputerName write-debug $session.Connected $session.session.CreateShellStream("dumb", 0, 0, 0, 0, 1000) $stream.Write("en`n") $stream.Write("$password`n") $stream.Write("terminal pager 0`n") $stream.Write("show run`n") $stream.Read() | Out-File "C:\tools\$ipaddress.txt" Remove-SSHSession -RemoveAll } ERROR: You cannot call a method on a null-valued expression. At line:19 char:1 + $session.session.CreateShellStream("dumb", 0, 0, 0, 0, 1000) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull PS VERSION: PS C:\Users\walte> $PSVersionTable Name Value ---- ----- PSVersion 5.1.14393.693 PSEdition Desktop PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...} BuildVersion 10.0.14393.693 CLRVersion 4.0.30319.42000 WSManStackVersion 3.0 PSRemotingProtocolVersion 2.3 SerializationVersion 1.1.0.1 POSH-SSH VERSION: 1.7.8 |
Anonymous |
Quote |
Feb 26th 2017 5 years ago |
Sign Up for Free or Log In to start participating in the conversation!