Automated ASA, IOS and NX-OS backups using SSH, EXPECT and SCP


In the previous post I covered how to perform automated backups of Cisco IOS using EEM (Embedded Event Manager). It's a good script, but not all Cisco devices support EEM. Today we will look at how to backup an ASA, a Catalyst switch and a Nexus switch using an EXPECT script and SCP the backups to a linux server.

You will need a linux host that has SSH installed and EXPECT.

For an Ubuntu box the commands are:
sudo apt-get install ssh
sudo apt-get install expect
On Centos the commands are:
yum install expect
yum install openssh-server
With those installed and a suitable location in mind to store your backups (I am using "/data/site/") we'll crack on.

An expect script performs like a question and answer scenario, so given a few parameters (the answers) we can run a script that calls another process and when prompted, provide the answers it needs.

We will have four scripts in all. One will be the master script, which in turn will call three different scripts.

Assuming you have one ASA, two Nexus switches and two Catalyst switches you'll have one master script that calls the ASA script once, and then makes one call to each of the Nexus, and one to each of the Catalysts. This script will also work well if you have multiple sites.

In this script the naming format of the devices, and the linux machine that they are running from follow the the same format of 802-<SITE-ID>-<DEVICE>.

Naming formats:

Device UK Name UK IP US Name US IP
Backup Server 802-UK-BCKP01 1.1.1.100 802-UK-BCKP01 2.2.2.100
ASA 802-UK-FW01 1.1.1.254 802-US-FW01 2.2.2.254
Switch 1 802-UK-SW01 1.1.1.2 802-US-SW01 2.2.2.2
Switch 2 802-UK-SW02 1.1.1.3 802-US-SW02 2.2.2.3
Nexus 1 802-UK-NX01 1.1.1.4 802-US-NX01 2.2.2.4
Nexus 2 802-UK-NX02 1.1.1.5 802-US-NX02 2.2.2.5

We have a number of parameters to send with our script, such as the login name and password to connect to the devices, which will be the same across all of the sites, and on the hardware:

admin / Passw0rd

The account used to connect to the Linux box via SCP:

root / Passw0rd

The master script

The general "master" script starts with the standard "#!/bin/bash".
#!/bin/bash
We then have a number of functions, one is called getPassword and here we will specify the account details to log into the devices (loginn and loginp) and the details to perform the SCP copy (SCPUser and SCPPass).
getPassword ()
{
        loginn=admin
        loginp=Passw0rd
        SCPUser=root
        SCPPass=Passw0rd
}
The next function in the script will pass the parameters we set to an expect script to perform the Nexus backup. We then have similar functions to pass the parameters to the scripts that perform the ASA and Catalyst backups.
doNexusBackup ()
{
        echo "Doing Nexus Backup"
        ./NX-expect.sh $loginn $loginp $NX01 $SCPUser $SCPPass $SCPDir $Site $NX01Output
        ./NX-expect.sh $loginn $loginp $NX02 $SCPUser $SCPPass $SCPDir $Site $NX02Output
}

doFirewallBackup ()
{
        echo "Starting Firewall Backup"
        ./FW-expect.sh $loginn $loginp $FW $SCPUser $SCPPass $SCPDir $Site $FWOutput
}

doCatalystBackup ()
{
        echo "Starting Catalyst Backup"
        ./SW-expect.sh $loginn $loginp $CORE01 $SCPUser $SCPPass $SCPDir $Site $Core01Output
        ./SW-expect.sh $loginn $loginp $CORE02 $SCPUser $SCPPass $SCPDir $Site $Core02Output
}
To each script we are passing the login name (admin) and it's password (Passw0rd), then the IP address of the device we are connecting to, as well as the scp details (root, Passw0rd and the IP address of the SCP server). The last three variables we are passing are the directory we want to save our file to, the site (UK or US) and the filename we want to store our backup as.

We then get to the main part of our program. Firstly it's always nice to give our backed up file a date in the filename, this puts it in the format ddmmyy:
DATE=`date +%d%m%y`
Next we get the UK or US out of the hostname on the linux server, which will also form part of the filename for the backup:
Site=`hostname | cut -d- -f 2 | awk '{print tolower($0)}'`
Next we set the file names we want to use in our backup, so the Nexus output would be 802-UK-NX01.110614.bak for the first Nexus in the UK:
NX01Output=802-$Site-NX01.$DATE.bak
NX02Output=802-$Site-NX02.$DATE.bak
Core01Output=802-$Site-Core01.$DATE.bak
Core02Output=802-$Site-Core02.$DATE.bak
FWOutput=802-$Site-FW01.$DATE.bak
Next we call our getPassword function so we have the passwords ready to use, and then we look to see what site we are in, and set our IP addresses accordingly. We then go and call each of the different functions above in turn:
case $Site in
 uk|UK)
        SCPLocation=1.1.1.100
        NX01=1.1.1.4
        NX02=1.1.1.5
        FW=1.1.1.254
        CORE01=1.1.1.2
        CORE02=1.1.1.3
        doNexusBackup
        doFirewallBackup
        doCatalystBackup

 ;;
 us|US)
        SCPLocation=2.2.2.100
        NX01=2.2.2.4
        NX02=2.2.2.5
        FW=2.2.2.254
        CORE01=2.2.2.2
        CORE02=2.2.2.3
        doNexusBackup
        doFirewallBackup
        doCatalystBackup

 ;;
esac
The finished script looks like this:
#!/bin/bash
getPassword ()
{
        loginn=admin
        loginp=Passw0rd
        SCPUser=root
        SCPPass=Passw0rd
}

doNexusBackup ()
{
        echo "Doing Nexus Backup"
        ./NX-expect.sh $loginn $loginp $NX01 $SCPUser $SCPPass $SCPDir $Site $NX01Output
        ./NX-expect.sh $loginn $loginp $NX02 $SCPUser $SCPPass $SCPDir $Site $NX02Output
}

doFirewallBackup ()
{
        echo "Starting Firewall Backup"
        ./FW-expect.sh $loginn $loginp $FW $SCPUser $SCPPass $SCPDir $Site $FWOutput
}

doCatalystBackup ()
{
        echo "Starting Catalyst Backup"
        ./SW-expect.sh $loginn $loginp $CORE01 $SCPUser $SCPPass $SCPDir $Site $Core01Output
        ./SW-expect.sh $loginn $loginp $CORE02 $SCPUser $SCPPass $SCPDir $Site $Core02Output
}


#### Starts here ####
DATE=`date +%d%m%y`
Site=`hostname | cut -d- -f 2 | awk '{print tolower($0)}'`
NX01Output=802-$Site-NX01.$DATE.bak
NX02Output=802-$Site-NX02.$DATE.bak
Core01Output=802-$Site-Core01.$DATE.bak
Core02Output=802-$Site-Core02.$DATE.bak
FWOutput=802-$Site-FW01.$DATE.bak

getPassword
case $Site in
 uk|UK)
        SCPDir=1.1.1.100
        NX01=1.1.1.4
        NX02=1.1.1.5
        FW=1.1.1.254
        CORE01=1.1.1.2
        CORE02=1.1.1.3
        doNexusBackup
        doFirewallBackup
        doCatalystBackup

 ;;
 us|US)
        SCPDir=2.2.2.100
        NX01=2.2.2.4
        NX02=2.2.2.5
        FW=2.2.2.254
        CORE01=2.2.2.2
        CORE02=2.2.2.3
        doNexusBackup
        doFirewallBackup
        doCatalystBackup

 ;;
esac
Our first expect script is for the ASA and it is called "FW-expect.sh". We tell the script that we are going to use expect and to use the variables we are passing to it, and these start at 0:
#!/usr/bin/expect -f

set loginname [lindex $argv 0]
set loginpassword [lindex $argv 1]
set FWIP [lindex $argv 2]
set SCPLogin [lindex $argv 3]
set SCPPassword [lindex $argv 4]
set SCPLocation [lindex $argv 5]
set Site [lindex $argv 6]
set FWOutput [lindex $argv 7]
We then set a time out and spawn an ssh connection using the login name and firewall IP, and get it to the enable prompt. We use \n to signify that we are pressing enter:
set timeout 30
spawn ssh $loginname@$FWIP
expect "password:"
send "$loginpassword\n"
expect ">"
send "en\n"
expect "Password:"
send "$loginpassword\n"
expect "#"
The last part of the script performs the backup, using the command "copy run scp:" and passes the login details. For the most part we can send a carriage return to accept the default values. Where we have "expect "?"" we are being prompted for the source filename and the default is the running-config, so we just want to hit enter. Similarly where the script says "expect "Address"" we have already passed this and the firewall will be prompting us to accept the default value of the SCP servers IP address that was passed in the variable SCPLocation. We then pass the login name and password for the root account on the SCP server, and then pass the directory and filename that we want to save the file to, which would be translated to /backup/UK/802-UK-FW01.110614.bak. Lastly we exit from our SSH session.
send "copy run scp://$SCPLogin@$SCPLocation\n"
expect "?"
send "\n"
expect "Address"
send "\r"
expect "username"
send "$SCPLogin:$SCPPassword\n"
expect "filename"
send "/backup/$Site/$FWOutput\n"
expect "#"
send "exit\n"
The finished script looks like this:
#!/usr/bin/expect -f

set loginname [lindex $argv 0]
set loginpassword [lindex $argv 1]
set FWIP [lindex $argv 2]
set SCPLogin [lindex $argv 3]
set SCPPassword [lindex $argv 4]
set SCPLocation [lindex $argv 5]
set Site [lindex $argv 6]
set FWOutput [lindex $argv 7]

set timeout 30
spawn ssh $loginname@$FWIP
expect "password:"
send "$loginpassword\n"
expect ">"
send "en\n"
expect "Password:"
send "$loginpassword\n"
expect "#"
send "copy run scp://$SCPLogin@$SCPLocation\n"
expect "?"
send "\n"
expect "Address"
send "\r"
expect "username"
send "$SCPLogin:$SCPPassword\n"
expect "filename"
send "/backup/$Site/$FWOutput\n"
expect "#"
send "exit\n"
The expect scripts for the Catalyst (or any IOS) which is called "SW-expect.sh" looks very similar. We are passing the same variables, and the challenge/responses are very similar. So I have just included the whole script:
#!/usr/bin/expect -f

set loginname [lindex $argv 0]
set loginpassword [lindex $argv 1]
set Switchnum [lindex $argv 2]
set SCPLogin [lindex $argv 3]
set SCPPassword [lindex $argv 4]
set SCPLocation [lindex $argv 5]
set Site [lindex $argv 6]
set CoreOutput [lindex $argv 7]

set timeout 30
spawn ssh $loginname@$Switchnum
expect "Password:"
send "$loginpassword\n"
expect "#"
send "copy run scp:\n"
expect "Address"
send "$SCPLocation\n"
expect "username"
send "$SCPLogin\n"
expect "filename"
send "/backup/$Site/$CoreOutput\n"
expect "Password:"
send "$SCPPassword\n"
expect "#"
send "exit\n"
The Nexus backup script (NX-expect.sh) is also very similar, the main difference being that we need to specify the vrf we are using for the backup:
#!/usr/bin/expect -f

set loginname [lindex $argv 0]
set loginpassword [lindex $argv 1]
set NXnum [lindex $argv 2]
set SCPLogin [lindex $argv 3]
set SCPPassword [lindex $argv 4]
set SCPLocation [lindex $argv 5]
set Site [lindex $argv 6]
set NXOutput [lindex $argv 7]

set timeout 30
spawn ssh $loginname@$NXnum
match_max 100000
expect "Password:"
send "$loginpassword\n"
expect "#"
send "copy run scp://$SCPLogin@$SCPLocation/backup/$Site/$NXOutput vrf management\n"
expect "password:"
send "$SCPPassword\n"
expect "#"
send "exit\n"
interact
Because this script uses SSH we need to have the SSH keys stored so that when the script is called it won't sit there expecting you to accept the SSH certificate. Before running the script you should manually SSH to the device as the user that the script will run under - so from the root account if the script is going to run as root SSH to the device, or do SSH using sudo. If you don't do this part the script won't accept the SSH key from the device and the script will not run.

Once you have all the scripts they need to be executable (so do "chmod a+x" on each of them, or "sudo chmod a+x").

You can then add an entry to the crontab to run the scripts at a time of your choosing.

Hope you find this useful, you might want to include some error checking and confirmation through email into the script. Because of the inclusion of the site in the backup file location it's then quite easy to perform an rsync to keep offsite copies on the other data center.

CCIE #49337, author of CCNA and Beyond, BGP for Cisco Networks, MPLS for Cisco Networks, VPNs and NAT for Cisco Networks.

Related Posts

Previous
Next Post »

2 comments

comments
Anonymous
13 June 2014 at 03:57 delete

Hi Stuart,
Your blog is great source of information and is in my xml feed. I haven't used but there is an app which which uses pexpect and does something similar, you may want to have a look at:
http://www.copyandwaste.com/posts/view/spur-network-configuration-manager-has-been-released/

Thanks!

Reply
avatar
13 June 2014 at 04:14 delete

That looks pretty neat. I might have a look at it, thanks for the tip!

Reply
avatar