Wednesday, January 25, 2012

Securely backup a Cisco Firewall (ASA & FWSM)

I have a problem with Cisco. Let me put it simply in this list:

1. Cisco does not support SSH keys (at least not very well) across its fleet of firewalls and security devices.
2. Config backups: TFTP is convenient but NOT secure. FTP is convenient but NOT secure. HTTP can be convenient but still NOT secure. HTTPS can be secure but can be unwieldy to setup and support. SCP is pretty convenient on a *nix machine, and is definitely secure, but there is a catch.
3. SCP on Cisco security devices: While these security devices usually do support SCP, they cannot SCP their configs to a destination (from the security device itself). Also, you cannot pull the running-config directly via SCP.

Addressing point #1 - using a password in an expect script is not extremely secure, but it beats the alternatives in almost every case. There are ways to secure strings (like passwords) in expect but you can decide for yourself whether these are needed.
Addressing point #3 - SCP can be used in the following way: Using expect, SSH to the device and save the running-config to a predefined location (root of the disk) and logout. Open a second shell and SCP the saved config back (from predefined location on device to predefined location on expect host).

My script isn't the shining example of a secure backup, but I'm unimpressed with the alternatives to this.

Here is an example of my firewall_backup.exp:

#!/usr/bin/expect
#######################################################
# Written by paklids 2012 01 12 #
# Expect script to securely backup Cisco ASAs & FWSMs #
# using SSH and SCP. #
# #
# This script can be run under a wrapper shell script #
# and then used (if desired) to checkin the firewall #
# configurations to SVN or any other change managment #
# or archiving solution - I will post my wrapper once #
# properly sanitized. #
#######################################################
#
##set an overall timeout if individual commands hang
set timeout 15
#
##set the directory you'd like the script to work out of
set -- /home/user/*
#
##open a pre-built list of IPs/FQDN hostnames delimited by line returns
##Note: it may be necessary to SSH to each host manually as serviceaccountname
##to save SSH host key
set f [open "/home/user/firewall_list"]
#
##for each entry in firewall_list, SSH to host and move to enable
##Note: enable may not be required if you customize the permissions
##on the serviceaccountname
while {[gets $f line] != -1} {
set pw1 "password_1"
set pw2 "password_2"
spawn "/bin/bash"
send "ssh serviceaccountname@$line\r"
expect "\npassword:"
send "$pw1\r"
expect -re "(\[^\r]*)>" {
set name $expect_out(1,string)
}
send "enable\r"
expect "\nPassword:"
send "$pw2\r"
expect "#"
##determine whether this is an FWSM or an ASA and appropriately save
##running-config to disk
send "sho version\r"
expect {
"FWSM" {
send \x20
set devtype "FWSM"
expect "#"
send "copy /noconfirm running-config disk:/$name\r"
}
"Adaptive Security Appliance" {
send \x20
set devtype "ASA"
expect "#"
send "copy /noconfirm running-config disk0:/$name\r"
}
}
expect "#"
sleep 2
send "logout\r"
#
##open a new bash shell and SCP the config that had been saved to disk
##back to the host this script is running on
spawn "/bin/bash"
send "scp serviceaccountname@$line:$name /home/user/workdir/$name\r"
expect -re ".*password:.*"
send "$pw1\r"
expect "100%"
sleep 1
}
#