Ok, so here's an update. (And I'm noting that this editor doesn't typically honor fonts or font sizes when used by some browsers.)
Some users will use the LDAP configuration for assigning users to specific profiles. When you do this, your config will include something like:
admin-passwd (changing key)
When you see this in the config that is backed up by R.A.N.C.I.D. (RANCID), it will change, causing a subversion update to happen. This was a problem for me, but I'll detail my fix.
SO, if you want to use RANCID to back up your Aruba 7005 (possibly others), do the following:
****** Step 1 ****** (Assuming you already have RANCID installed and working on Cisco or other devices)
Create an arubarancid file (vi or touch, etc.):
Copy the entire text below into a new file called, "arubarancid" which should reside in the same
directory as your rancid-run and rancid-fe executables
##### Copy the following to END OF FILE #####
#! /usr/bin/perl
##
## $Id: rancid.in,v 1.255 2009/04/20 19:56:27 heas Exp $
##
## rancid 2.3.2
## Copyright (c) 1997-2009 by Terrapin Communications, Inc.
## All rights reserved.
##
## Edited by Brian Murphree on 5-13-2015 for Aruba 7005 Controllers
##
## This code is derived from software contributed to and maintained by
## Terrapin Communications, Inc. by Henry Kilmer, John Heasley, Andrew Partan,
## Pete Whiting, Austin Schutz, and Andrew Fort.
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## 1. Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## 2. Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## 3. All advertising materials mentioning features or use of this software
## must display the following acknowledgement:
## This product includes software developed by Terrapin Communications,
## Inc. and its contributors for RANCID.
## 4. Neither the name of Terrapin Communications, Inc. nor the names of its
## contributors may be used to endorse or promote products derived from
## this software without specific prior written permission.
## 5. It is requested that non-binding fixes and modifications be contributed
## back to Terrapin Communications, Inc.
##
## THIS SOFTWARE IS PROVIDED BY Terrapin Communications, INC. AND CONTRIBUTORS
## ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
## TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COMPANY OR CONTRIBUTORS
## BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
## POSSIBILITY OF SUCH DAMAGE.
#
# RANCID - Really Awesome New Cisco confIg Differ
#
# usage: rancid [-dV] [-l] [-f filename | hostname]
#
use Getopt::Std;
getopts('dflV');
if ($opt_V) {
print "rancid 2.3.2
";
exit(0);
}
$log = $opt_l;
$debug = $opt_d;
$file = $opt_f;
$host = $ARGV[0];
$clean_run = 0;
$found_end = 0;
$found_version = 0;
$found_env = 0;
$found_diag = 0;
$timeo = 90; # clogin timeout in seconds
my(@commandtable, %commands, @commands);# command lists
my($aclsort) = ("ipsort"); # ACL sorting mode
my($config_register); # configuration register value
my($filter_commstr); # SNMP community string filtering
my($filter_pwds); # password filtering mode
# This routine is used to print out the router configuration
sub ProcessHistory {
my($new_hist_tag,$new_command,$command_string,@string) = (@_);
if ((($new_hist_tag ne $hist_tag) || ($new_command ne $command))
&& defined %history) {
print eval "$command \%history";
undef %history;
}
if (($new_hist_tag) && ($new_command) && ($command_string)) {
if ($history{$command_string}) {
$history{$command_string} = "$history{$command_string}@string";
} else {
$history{$command_string} = "@string";
}
} elsif (($new_hist_tag) && ($new_command)) {
$history{++$#history} = "@string";
} else {
print "@string";
}
$hist_tag = $new_hist_tag;
$command = $new_command;
1;
}
sub numerically { $a <=> $b; }
# This is a sort routine that will sort numerically on the
# keys of a hash as if it were a normal array.
sub keynsort {
local(%lines) = @_;
local($i) = 0;
local(@sorted_lines);
foreach $key (sort numerically keys(%lines)) {
$sorted_lines[$i] = $lines{$key};
$i++;
}
@sorted_lines;
}
# This is a sort routine that will sort on the
# keys of a hash as if it were a normal array.
sub keysort {
local(%lines) = @_;
local($i) = 0;
local(@sorted_lines);
foreach $key (sort keys(%lines)) {
$sorted_lines[$i] = $lines{$key};
$i++;
}
@sorted_lines;
}
# This is a sort routine that will sort on the
# values of a hash as if it were a normal array.
sub valsort{
local(%lines) = @_;
local($i) = 0;
local(@sorted_lines);
foreach $key (sort values %lines) {
$sorted_lines[$i] = $key;
$i++;
}
@sorted_lines;
}
# This is a numerical sort routine (ascending).
sub numsort {
local(%lines) = @_;
local($i) = 0;
local(@sorted_lines);
foreach $num (sort {$a <=> $b} keys %lines) {
$sorted_lines[$i] = $lines{$num};
$i++;
}
@sorted_lines;
}
# This is a sort routine that will sort on the
# ip address when the ip address is anywhere in
# the strings.
sub ipsort {
local(%lines) = @_;
local($i) = 0;
local(@sorted_lines);
foreach $addr (sort sortbyipaddr keys %lines) {
$sorted_lines[$i] = $lines{$addr};
$i++;
}
@sorted_lines;
}
# These two routines will sort based upon IP addresses
sub ipaddrval {
my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#);
$a[3] + 256 * ($a[2] + 256 * ($a[1] +256 * $a[0]));
}
sub sortbyipaddr {
&ipaddrval($a) <=> &ipaddrval($b);
}
# This routine processes a "write term"
sub WriteTerm {
print STDERR " In WriteTerm: $_" if ($debug);
my($lineauto,$comment,$linecnt) = (0,0,0);
while (<INPUT>) {
tr/\015//d;
last if (/^$prompt/);
return(1) if /Line has invalid autocommand /;
return(1) if (/(Invalid input detected|Type help or )/i);
return(1) if /\%Error: No such file or directory/;
return(0) if ($found_end); # Only do this routine once
return(-1) if (/command authorization failed/i);
# the pager can not be disabled per-session on the PIX
if (/^(<-+ More -+>)/) {
my($len) = length($1);
s/^$1\s{$len}//;
}
if (!$linecnt && defined($config_register)) {
ProcessHistory("","","", "!
config-register $config_register
");
}
/Non-Volatile memory is in use/ && return(-1); # NvRAM is locked
$linecnt++;
$lineauto = 0 if (/^[^ ]/);
# skip the crap
if (/^(##+|(building|current) configuration)|^System Time:|^Switch uptime is|^Internal Temperature/i) {
while (<INPUT>) {
next if (/^Current configuration\s*:/i);
next if (/^:/);
next if (/^([%!].*|\s*)$/);
next if (/^System Time:/);
next if (/^Switch uptime is/);
next if (/^Internal Temperature/);
last;
}
tr/\015//d;
}
# skip consecutive comment lines to avoid oscillating extra comment
# line on some access servers. grrr.
if (/^!/) {
next if ($comment);
ProcessHistory("","","",$_);
$comment++;
next;
}
$comment = 0;
# filter out any RCS/CVS tags to avoid confusing local CVS storage
s/\$(Revision|Id):/ $1:/;
# order access-lists
/^access-list\s+(\d\d?)\s+(\S+)\s+(\S+)/ &&
ProcessHistory("ACL $1 $2","$aclsort","$3","$_") && next;
# order extended access-lists
/^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+host\s+(\S+)/ &&
ProcessHistory("EACL $1 $2","$aclsort","$3","$_") && next;
/^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+(\d\S+)/ &&
ProcessHistory("EACL $1 $2","$aclsort","$3","$_") && next;
/^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+any/ &&
ProcessHistory("EACL $1 $2","$aclsort","0.0.0.0","$_") && next;
# order arp lists
/^arp\s+(\d+\.\d+\.\d+\.\d+)\s+/ &&
ProcessHistory("ARP","$aclsort","$1","$_") && next;
/^ip prefix-list\s+(\S+)\s+seq\s+(\d+)\s+(permit|deny)\s+(\d\S+)(\/.*)$/ &&
ProcessHistory("PACL $1 $3","$aclsort","$4","ip prefix-list $1 $3 $4$5
")
&& next;
# order logging statements
/^logging (\d+\.\d+\.\d+\.\d+)/ &&
ProcessHistory("LOGGING","ipsort","$1","$_") && next;
# order/prune snmp-server host statements
# we only prune lines of the form
# snmp-server host a.b.c.d <community>
if (/^snmp-server host (\d+\.\d+\.\d+\.\d+) /) {
if ($filter_commstr) {
my($ip) = $1;
my($line) = "snmp-server host $ip";
my(@tokens) = split(' ', $');
my($token);
while ($token = shift(@tokens)) {
if ($token eq 'version') {
$line .= " " . join(' ', ($token, shift(@tokens)));
if ($token eq '3') {
$line .= " " . join(' ', ($token, shift(@tokens)));
}
} elsif ($token eq 'vrf') {
$line .= " " . join(' ', ($token, shift(@tokens)));
} elsif ($token =~ /^(informs?|traps?|(no)?auth)$/) {
$line .= " " . $token;
} else {
$line = "!$line " . join(' ', ("<removed>",
join(' ',@tokens)));
last;
}
}
ProcessHistory("SNMPSERVERHOST","ipsort","$ip","$line
");
} else {
ProcessHistory("SNMPSERVERHOST","ipsort","$1","$_");
}
next;
}
if (/^(snmp-server community) (\S+)/) {
if ($filter_commstr) {
ProcessHistory("SNMPSERVERCOMM","keysort","$_",
"!$1 <removed>$'") && next;
} else {
ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && next;
}
}
# filter out LDAP admin-passwd keys
if (/^(.* admin-passwd).*/) {
ProcessHistory("ADMINPASSWD","keysort","$_",
"!$1 <removed>$'") && next;
}
# filter out WPA and ipsec keys
if (/^(.* wpa-hexkey).*/) {
ProcessHistory("WPAIPSEC","keysort","$_",
"!$1 <removed>$'") && next;
}
# filter out WPA and ipsec keys
if (/^(.*localip .* ipsec).*/) {
ProcessHistory("WPAIPSEC","keysort","$_",
"!$1 <removed>$'") && next;
}
# filter out WPA and ipsec keys
if (/^(.* key).*/) {
ProcessHistory("WPAIPSEC","keysort","$_",
"!$1 <removed>$'") && next;
}
# filter out WPA and ipsec keys
if (/^(.* wpa-passphrase).*/) {
ProcessHistory("WPAIPSEC","keysort","$_",
"!$1 <removed>$'") && next;
}
# filter out WPA and ipsec keys
if (/^(.* peer-ip-address .* ipsec).*/) {
ProcessHistory("WPAIPSEC","keysort","$_",
"!$1 <removed>$'") && next;
}
# order alias statements
/^netdestination / && ProcessHistory("ALIAS","keysort","$_","$_") && next;
# order ntp servers
if (/^ntp server (\d+)\.(\d+)\.(\d+)\.(\d+)/) {
$sortkey = sprintf("$1 %03d%03d%03d%03d",$2,$3,$4,$5);
ProcessHistory("NTP","keysort",$sortkey,"$_");
next;
}
# catch anything that wasnt matched above.
ProcessHistory("","","","$_");
# end of config. the ": " game is for the PIX
if (/^(: +)?end$/) {
$found_end = 1;
return(0);
}
}
return(0);
}
# dummy function
sub DoNothing {print STDOUT;}
# Main
@commandtable = (
{'no paging' => 'WriteTerm'},
# {'show switchinfo' => 'WriteTerm'},
# {'show roleinfo' => 'WriteTerm'},
# {'show image version' => 'WriteTerm'},
# {'show inventory' => 'WriteTerm'},
# {'show country' => 'WriteTerm'},
# {'show slots' => 'WriteTerm'},
# {'show keys all' => 'WriteTerm'},
# {'show license verbose' => 'WriteTerm'},
# {'show ap license-usage' => 'WriteTerm'},
# {'show datapath vlan table' => 'WriteTerm'},
# {'show database synchronize' => 'WriteTerm'},
# {'show master-redundancy' => 'WriteTerm'},
# {'show switches' => 'WriteTerm'},
# {'show ap database inactive' => 'WriteTerm'},
# {'show ap database unprovisioned' => 'WriteTerm'},
{'show run' => 'WriteTerm'},
);
# Use an array to preserve the order of the commands and a hash for mapping
# commands to the subroutine and track commands that have been completed.
@commands = map(keys(%$_), @commandtable);
%commands = map(%$_, @commandtable);
$cisco_cmds = join(";",@commands);
$cmds_regexp = join("|",@commands);
if (length($host) == 0) {
if ($file) {
print(STDERR "Too few arguments: file name required
");
exit(1);
} else {
print(STDERR "Too few arguments: host name required
");
exit(1);
}
}
open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!
";
select(OUTPUT);
# make OUTPUT unbuffered if debugging
if ($debug) { $| = 1; }
if ($file) {
print STDERR "opening file $host
" if ($debug);
print STDOUT "opening file $host
" if ($log);
open(INPUT,"<$host") || die "open failed for $host: $!
";
} else {
print STDERR "executing clogin -t $timeo -c\"$cisco_cmds\" $host
" if ($debug);
print STDOUT "executing clogin -t $timeo -c\"$cisco_cmds\" $host
" if ($log);
if (defined($ENV{NOPIPE})) {
system "clogin -t $timeo -c \"$cisco_cmds\" $host </dev/null > $host.raw 2>&1" || die "clogin failed for $host: $!
";
open(INPUT, "< $host.raw") || die "clogin failed for $host: $!
";
} else {
open(INPUT,"clogin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "clogin failed for $host: $!
";
}
}
# determine ACL sorting mode
if ($ENV{"ACLSORT"} =~ /no/i) {
$aclsort = "";
}
# determine community string filtering mode
if (defined($ENV{"NOCOMMSTR"}) &&
($ENV{"NOCOMMSTR"} =~ /yes/i || $ENV{"NOCOMMSTR"} =~ /^$/)) {
$filter_commstr = 1;
} else {
$filter_commstr = 0;
}
# determine password filtering mode
if ($ENV{"FILTER_PWDS"} =~ /no/i) {
$filter_pwds = 0;
} elsif ($ENV{"FILTER_PWDS"} =~ /all/i) {
$filter_pwds = 2;
} else {
$filter_pwds = 1;
}
ProcessHistory("","","","!RANCID-CONTENT-TYPE: aruba
!
");
ProcessHistory("COMMENTS","keysort","B0","!
");
ProcessHistory("COMMENTS","keysort","D0","!
");
ProcessHistory("COMMENTS","keysort","F0","!
");
ProcessHistory("COMMENTS","keysort","G0","!
");
TOP: while(<INPUT>) {
tr/\015//d;
if (/[>#]\s?exit$/) {
$clean_run = 1;
last;
}
if (/^Error:/) {
print STDOUT ("$host clogin error: $_");
print STDERR ("$host clogin error: $_") if ($debug);
$clean_run = 0;
last;
}
while (/#\s*($cmds_regexp)\s*$/) {
$cmd = $1;
if (!defined($prompt)) {
$prompt = ($_ =~ /^([^#]+#)/)[0];
$prompt =~ s/([][}{)(\\])/\\$1/g;
print STDERR ("PROMPT MATCH: $prompt
") if ($debug);
}
print STDERR ("HIT COMMAND:$_") if ($debug);
if (! defined($commands{$cmd})) {
print STDERR "$host: found unexpected command - \"$cmd\"
";
$clean_run = 0;
last TOP;
}
$rval = &{$commands{$cmd}};
delete($commands{$cmd});
if ($rval == -1) {
$clean_run = 0;
last TOP;
}
}
}
print STDOUT "Done $logincmd: $_
" if ($log);
# Flush History
ProcessHistory("","","","");
# Cleanup
close(INPUT);
close(OUTPUT);
if (defined($ENV{NOPIPE})) {
unlink("$host.raw") if (! $debug);
}
# check for completeness
if (scalar(%commands) || !$clean_run || !$found_end) {
if (scalar(%commands)) {
printf(STDOUT "$host: missed cmd(s): %s
", join(',', keys(%commands)));
printf(STDERR "$host: missed cmd(s): %s
", join(',', keys(%commands))) if ($debug);
}
if (!$clean_run || !$found_end) {
print STDOUT "$host: End of run not found
";
print STDERR "$host: End of run not found
" if ($debug);
system("/usr/bin/tail -1 $host.new");
}
unlink "$host.new" if (! $debug);
}
##### END OF FILE #####
****** Step 2 ******
Now, edit your rancid-fe file to add the following 'aruba' line (leaving all the other lines in there):
%vendortable = (
'aruba' => 'arubarancid',
);
****** Step 3 ******
Edit your hidden .cloginrc file (maybe in your /home/rancid directory) to set the autoenable
Add the following lines - braces are literal, while parenthesis are just for your reading pleasure:
add autoenable (hostname of 7005) 0
add user (hostname of 7005) (username)
add password (hostname of 7005) {password-here}
NOTE: In the file you created (arubarancid) from the past above, the following will cause RANCID to remove the LDAP key (relax, it's already in there):
# filter out LDAP admin-passwd keys
if (/^(.* admin-passwd).*/) {
ProcessHistory("ADMINPASSWD","keysort","$_",
"!$1 <removed>$'") && next;
}