Using Perl's Net::OpenSSH for automated remote CLI access

Mark StingleyRecruit
Mark Stingley Sep 21, 2011 2:14 PM

Lately, I've been using the simple Perl code to retrieve performance data from Palo Alto.  This is not only an alternative to the Palo Alto XML API, it should work on any remote device that features an SSH command shell, such as switches, routers, and other firewalls.

 

This example retrieves past 24 hour CPU stats without relying on 'expect' or other fancy tools.  It requires the Perl modules Date::Calc and Net::OpenSSH.  A read-only adminstrator must be created for the SSH access.  I run it once an hour.

 

My thanks to Salvador Fandiño for writing the fine Net::OpenSSH module and to the fine folks at PerlMonks.org for the supporting tips and examples.

 

The following code has been well tested, but your mileage may vary.   The user (you) accepts all consequences for use.  No guarantee of  suitability.

 

---------------------------------------------

 

#!/usr/bin/perl

 

#chkPAcpu.pl
#Copyright 2011-2014 Mark Stingley (www.AltSec.info)
#Licensed under http://www.gnu.org/copyleft/gpl.html

 

# This code provides for running SSH commands on a restricted shell remote host,
# such as a firewall, IPS, or other network devices. This particular version
# retrieves the hourly CPU stats for a Palo Alto firewall/IPS.

 

use strict;
use warnings;
use Date::Calc qw(:all);
use Net::OpenSSH;
use lib "/usr/local/lib/perl5/5.8.0";

 


#for debugging, uncomment the below
#$Net::OpenSSH::debug |= 16;

 

#Set up the required connection arguments and the desired command line

# <---- EDIT user, passwd, host, and outpath below ---->
my $user = "Palo Alto device Read-Only Admin username";
my $passwd = "password";
my $host = "Palo Alto device IP address";
my $outpath = "/some/path/for/the/data";

 

#The command skips the non-existent page content "ARG" simply to

#force the CLI to not page the output.

my @cmd = "show running resource-monitor hour \| except ARG";

my @quitcmd = "exit";

 

#get today's date and time to timestamp the name of the output file
my ($sec, $min, $hour, $mday, $mon, $yr, $wday, $yday, $isdst)=localtime(time);
$yr = ( $yr + 1900 );
my $da = sprintf("%02d",$mday);
my $mo = sprintf("%02d",$mon + 1);
my $hh = sprintf("%02d",$hour);
my $mm = sprintf("%02d",$min);

 

#put the data and time into a string for file naming

#such as 201109211330.cpu

my $TimeChk = "$yr$mo$da$hh$mm";

 

#initiate the ssh connection
my $ssh = Net::OpenSSH->new("$host", user => "$user", passwd => "$passwd", timeout => 90 );
$ssh->error and
   die "Couldn't establish SSH connection: ". $ssh->error;

 

#push the commands to the remote host command line with carriage returns

#stuffing both commands to the command line buffers the "quit" until the data has been retrieved.

#this method makes it possible to close the session cleanly and not leave the admin account logged in
my @output = $ssh->capture({stdin_data => "@cmd\n@quitcmd\n"});
$ssh->error and
   die "Couldn't run remote command: ". $ssh->error;

 

#open a new textfile in the data directory and write the results
open(OUTFILE, ">$outpath/$TimeChk.cpu") || die "Can't open $outpath/$TimeChk for writing!\n";
print OUTFILE "@output";
close(OUTFILE);

 

#close the ssh session
undef $ssh;