I’ve been working for my new employer for just under 90 days now, carefully studying the network topology slowly pealing back the layers mindful not to break anything. There have been some exciting moments not including the Cisco Catalyst 6509 VSS member that decided to go into recovery mode one evening – revealing a cabling problem with a pair of Cisco ASA 5585-X running in an HA configuration.
A few weeks back I had the opportunity to show off some of my scripting skills by automating the configuration change of some 450+ Motorola RFS4000 and Symbol WS2000 Wireless LAN Switches. We were migrating from Microsoft’s Internet Authentication Service (IAS) to Microsoft’s Network Policy Service (NPS).
The first problem, nobody had an inventory of the wireless LAN switches that we needed to reconfigure. No problem – a quick dump of the logs on the IAS servers provided a nice lengthy list of IP addresses which had authenticated with IAS over the past 6 months. I wrote a quick Perl script to interrogate each IP address, first via ICMP, then via SNMP, and lastly via WGET/CURL. The result was a list of each model switch we had to contend with along with the software versions; WS2000 v1.x, RFS4000 v4.x and RFS4000 v5.x . There weren’t too many RFS4000 v5.x switches so we decided to handled those changes manually, although on retrospect it would have been far easier to also code that solution as opposed to manually logging into all those WiNG 5.x devices at 4AM in the morning.
I did have a challenge with the passwords. There were multiple administrator passwords in use across all the different models so I had to add some logic to deal with the three different possible passwords. It was good that there were only three passwords because a fourth failed password attempt would cause the wireless LAN switch to disconnect the session and would have made the task a lot harder .
I ended up writing two scripts, one for the WS2000 v1.x and one for the RFS4000 v4.x due to the time constraints. I could have combined the two scripts and detected the version of software but there were some anxious managers waiting eagerly on this change. I added a bash shell script to kick off the Expect script for each switch model and then loop through all the IP addresses or FQDNs.
This wasn’t a sexy solution by any means, it required a bit of testing to determine the commands that were needed for each model and software release but it was a much better solution than manually making the changes on some 450+ devices. We did have to-do a bit of error checking to make sure that the configurations went down to all 450+ devices. We had one or two instances where the WAN connection to that specific office just happen to go offline while the script was running. Thankfully we were able to use the logfile size (logs generated by the Expect script) as a quick determination if there had been a problem or discrepancy that required additional investigation.
If you have a similar challenge hopefully you’ll find the code below helpful.
Symbol WS2000 v1.x
#!/bin/bash # # Language: Bash Shell Script # # Filename: /usr/local/etc/run-ws2000.sh # # Purpose: This script will kickoff the Expect scripts that will re-configure # the RADIUS configuration on the Motorola (formerly Symbol) WS-2000 # Wireless LAN Switches. # # Author: Michael McNamara # Date: February 21, 2014 # Version: 1.0 # # Changes: # # Variables PATH_TO=/usr/local/etc/ EXPECT=/usr/local/etc/symbolws2000radius.exp SWITCHES='10.1.1.1 10.1.1.2 10.1.1.3 10.1.1.4' ########################################################################## # M A I N S C R I P T B O D Y ########################################################################## for SWITCH in $SWITCHES do $EXPECT $SWITCH done exit
#!/usr/bin/expect -f # # Language: Expect # # Filename: /usr/local/etc/symbolws2000radius.exp # # Purpose: This is an Expect script that will login to a Motorola (formerly # Symbol) WS2000 Wireless LAN Switch v1.x and modify the RADIUS servers # used for 802.1x EAP authentication of the corporate ESSID/WLAN. # # Author: Michael McNamara # # Date: February 21, 2014 # # Version: 1.0 # # Changes: # February 24, 2014 (M.McNamara) v1.1 - issue with enable prompt changing, # abstract prompt in a varaible to account for all possibilities. # # License: # Copyright (C) 2010 Michael McNamara (mfm@michaelfmcnamara.com) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # Variables set PATH "/usr/local/etc" set TELNET "/usr/bin/telnet" set SWITCH [lindex $argv 0] set USERNAME admin set PASSWORDS {password1 password2 password3} set PINDEX 0 # Which Wireless LAN are we going to change? set WLAN_IDX 2 # RADIUS/NPS Servers set RADIUS1 10.1.1.1 set RADIUS2 10.1.1.2 set PROMPTS "(%|#|cli\>|admin\>|\$|\-\-\-\>)" set TODAY [timestamp -format %y%m%d ] set WEEKDAY [timestamp -format %a ] set DATE [timestamp -format %c ] stty -echo log_file $PATH/logs/$SWITCH.radius.log log_user 0 # Disable logging to STDOUT #log_user 1 # Enable logging to STDOUT # Useful information out to logfile send_log "*********************************************************************\r\n" send_log "Starting logfile for $SWITCH on $DATE\r\n" send_log "*********************************************************************\r\n" set timeout 30 spawn $TELNET $SWITCH expect { "Connected to" { expect "login:" send -- "$USERNAME\r" expect -exact "assword:" send -- "[lindex $PASSWORDS $PINDEX]\r" expect { "Login incorrect" { send_user "\nDEBUG: Login failed with $USERNAME [lindex $PASSWORDS $PINDEX] on $SWITCH\n" send_log "\nDEBUG: Login failed with $USERNAME [lindex $PASSWORDS $PINDEX] on $SWITCH\n" incr PINDEX if {$PINDEX == [llength $PASSWORDS]} { send_user "ERROR: PASSWORD ISSUE WITH $SWITCH - UNABLE TO LOGIN!\n" send_log "*********************************************************************\r\n" send_log "End of logfile for $SWITCH on $DATE \r\n" send_log "*********************************************************************\r\n" exit } expect "login:" send -- "$USERNAME\r" expect -exact "assword:" send -- "[lindex $PASSWORDS $PINDEX]\r" exp_continue } "admin>" { send -- "network\r" expect -re $PROMPTS send -- "wlan\r" expect -re $PROMPTS send -- "show eap $WLAN_IDX\r" expect -re $PROMPTS #################################################################### # REMOVE THE FOLLOWING # FROM THE FILE TO ACTUALLY MAKE THE CHANGES #################################################################### # REMOVE THE FOLLOWING # FROM THE FILE TO ACTUALLY MAKE THE CHANGES #################################################################### send -- "set eap server $WLAN_IDX 1 $RADIUS1\r" expect -re $PROMPTS send -- "set eap server $WLAN_IDX 2 $RADIUS2\r" expect -re $PROMPTS send -- "show eap $WLAN_IDX\r" expect -re $PROMPTS send -- "save\r" expect -re $PROMPTS #################################################################### send -- "quit\r" expect eof } } } "No route to host" { send_log "ERROR: Unable to connect to $SWITCH via telnet!\n" send_user "ERORR: Unable to connect to $SWITCH via telnet!\n" } } send_log "*********************************************************************\r\n" send_log "End of logfile for $SWITCH on $DATE \r\n" send_log "*********************************************************************\r\n" exit 0
Motorola RFS4000 v4.x
#!/bin/bash # # Language: Bash Shell Script # # Filename: /usr/local/etc/run-rfs4000.sh # # Purpose: This script will kickoff the Expect scripts that will re-configure # the RADIUS configuration on the Motorola RFS 4000 v4.x # Wireless LAN Switches. # # Author: Michael McNamara # Date: February 21, 2014 # Version: 1.0 # # Changes: # # # Variables PATH_TO=/usr/local/etc EXPECT=/usr/local/etc/motorolarfs4000radius.exp SWITCHES='10.1.1.1 10.1.1.2 10.1.1.3 10.1.1.4' ########################################################################## # M A I N S C R I P T B O D Y ########################################################################## for SWITCH in $SWITCHES do $EXPECT $SWITCH done exit
#!/usr/bin/expect -f # # Language: Expect # # Filename: /usr/local/etc/motorolarfs4000radius.exp # # Purpose: This is an Expect script that will login to a Motorola (formerly # Symbol) RFS4000 Wireless LAN Switch v4.x and modify the RADIUS servers # used for 802.1x EAP authentication of the corporate ESSID/WLAN. # # Author: Michael McNamara (mfm@michaelfmcnamara.com) # # Date: February 21, 2014 # # Version: 1.1 # # Changes: # February 25, 2014 (M.McNamara) v1.1 - disable StrictHostKeyChecking so the # the initial SSH connection doesn't generate a yes/no dialog which # could hang up the Expect script. # # February 24, 2014 (M.McNamara) v1.0 - issue with enable prompt changing, # abstract prompt in a varaible to account for all possibilities. # # License: # Copyright (C) 2014 Michael McNamara (mfm@michaelfmcnamara.com) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # Variables set PATH "/usr/local/etc" set TELNET "/usr/bin/telnet" set SSH "/usr/bin/ssh" set SSH_OPTIONS "-o StrictHostKeyChecking=no" set SWITCH [lindex $argv 0] set USERNAME admin set PASSWORDS {password1 password2 password3} set PINDEX 0 # Which Wireless LAN are we going to change? set WLAN_IDX 2 # RADIUS/NPS Servers set RADIUS1 10.1.1.1 set RADIUS2 10.1.1.2 set PROMPTS "(%|#|cli\>|admin\>|\$|\-\-\-\>)" set TODAY [timestamp -format %y%m%d ] set WEEKDAY [timestamp -format %a ] set DATE [timestamp -format %c ] stty -echo # Setup the logging log_file $PATH/logs/$SWITCH.radius.log log_user 0 # Disable logging to STDOUT #log_user 1 # Enable logging to STDOUT # Useful information out to logfile send_log "*********************************************************************\r\n" send_log "Starting logfile for $SWITCH on $DATE\r\n" send_log "*********************************************************************\r\n" # Set the timeout to 30 seconds for the following commands set timeout 30 # Spawn an SSH connection to the switch spawn $SSH $SSH_OPTIONS $USERNAME@$SWITCH expect { "yes/no" { send "yes\r" } "User Access Verification" { expect "*?sername:" send -- "$USERNAME\r" expect -exact "assword:" send -- "[lindex $PASSWORDS $PINDEX]\r" expect { "Incorrect Login" { send_user "\nDEBUG: Login failed with $USERNAME [lindex $PASSWORDS $PINDEX] on $SWITCH\n" send_log "\nDEBUG: Login failed with $USERNAME [lindex $PASSWORDS $PINDEX] on $SWITCH\n" incr PINDEX if {$PINDEX == [llength $PASSWORDS]} { send_user "ERROR: PASSWORD ISSUE WITH $SWITCH - UNABLE TO LOGIN!\n" send_log "*********************************************************************\r\n" send_log "End of logfile for $SWITCH on $DATE \r\n" send_log "*********************************************************************\r\n" exit } expect "*?sername:" send -- "$USERNAME\r" expect -exact "assword:" send -- "[lindex $PASSWORDS $PINDEX]\r" exp_continue } ">" { send -- "terminal length 0\r" expect -re $PROMPTS send -- "enable\r" expect -re $PROMPTS send -- "show wireless mobile-unit\r" expect -re $PROMPTS send -- "show wireless wlan config $WLAN_IDX\r" expect -re $PROMPTS ##################################################################### # REMOVE THE FOLLOWING # FROM THE FILE TO ACTUALLY MAKE THE CHANGES ##################################################################### # REMOVE THE FOLLOWING # FROM THE FILE TO ACTUALLY MAKE THE CHANGES ##################################################################### send -- "config t\r" expect -re $PROMPTS send -- "wireless\r" expect -re $PROMPTS send -- "wlan $WLAN_IDX radius server primary $RADIUS1\r" expect -re $PROMPTS send -- "wlan $WLAN_IDX radius server secondary $RADIUS2\r" expect -re $PROMPTS send -- "exit\r" expect -re $PROMPTS send -- "show wireless wlan config $WLAN_IDX\r" expect -re $PROMPTS send -- "write mem\r" expect -re $PROMPTS ##################################################################### send -- "quit\r" expect eof } } } "No route to host" { send_log "ERROR: Unable to connect to $SWITCH via telnet!\n" send_user "ERORR: Unable to connect to $SWITCH via telnet!\n" } } send_log "*********************************************************************\r\n" send_log "End of logfile for $SWITCH on $DATE \r\n" send_log "*********************************************************************\r\n" exit 0
Cheers!
ches says
Thanks Michael, i’ve been meaning to work out how to do this for a while! Your example will come in very handy, i’m sure.