=pod

=head1 NAME

Net::Appliance::Session::Cookbook::Recipe02 - Get Running Config with SSH

=head1 NOTE

This Cookbook was contributed to the L<Net::Appliance::Session> project by
Nigel Bowden. Source code from the Cookbook is shipped in the C<examples>
folder of this module's distribution.

=head1 PROBLEM

You want to SSH to a Cisco IOS device, retrieve its running configuration and
save the configuration off in to a file

=head1 SOLUTION

This solution builds on the previous recipe to give us SSH access to our Cisco
device, but also shows how we can save off the configuration to a local file.

In addition, we assume this time that our login will only drop us in to the
level 1 (non-privileged) mode, and that we will need to provide a password to
get in to privileged (enable) mode.

 use strict;
 use warnings;
 
 use Net::Appliance::Session;
 
 my $ios_device_ip = '10.250.249.215';
 
 my $ios_username        = 'cisco';
 my $ios_password        = 'cisco';
 my $ios_enable_password = 'cisco';
 
 my $running_config_file = "$ENV{HOME}/running_config.txt";
 
 my $session_obj = Net::Appliance::Session->new(
     Host      => $ios_device_ip,
     Transport => 'SSH',
 );
 
 # give verbose output whilst we run this script
 $session_obj->input_log(*STDOUT);
 
 # try to login to the ios device, ignoring host check
 $session_obj->connect(
     Name => $ios_username,
     Password => $ios_password,
     SHKC => 0
 );
 
 # drop in to enable mode
 $session_obj->begin_privileged($ios_enable_password);
 
 # get our running config
 my @running_config =  $session_obj->cmd('show running');
 
 # chop out the extra info top and bottom of the config
 @running_config = @running_config[ 2 .. (@running_config -1)];
 
 open(FH, "> $running_config_file")
   or die("Cannot open config file : $!");
 print FH @running_config;
 close FH;
 
 # close down our session
 $session_obj->close;

=head1 DISCUSSION

This recipe is very similar to our previous recipe, but this time we use SSH
as our transport to our Cisco device.

This is likely to be far closer to a real-world requirement, as SSH access to
devices rather than Telnet is becoming the norm for access in many companies
and organizations.

Comparing this recipe with the previous one, you can see we have added only a
few additional lines to provide us with the required functionality.

The underlying assumption of using the SSH transport layer, rather than
Telnet, is that OpenSSH is installed on the system running the script.

The SSH transport is provided by the Net::Appliance::Session::Transport::SSH
module which is part of the Net::Appliance::Session bundle of modules. If
OpenSSH is not installed on your system, consult the
C<Net::Appliance::Session::Transport::SSH> documentation for details of how an
alternative SSH program may be specified.

Windows users currently face a challenge in this area, as
Net::Appliance::Session cannot currently support SSH for a native Windows Perl
distribution (e.g. Activestate). This is due to the limitations of the way
that a separate SSH process is spawned, which cannot be currently emulated in
Windows. However, if Cygwin (http://www.cygwin.com) is installed on your
Windows platform and Perl installed within Cygwin, then the
Net::Appliance::Session modules will work (including SSH support if OpenSSH is
installed as part of your Cygwin installation).

We will review the changes and additions to the previous recipe below to see
how we have achieved our new level of functionality.

Once we have captured our running configuration, we would like to save it off
to a local file. The file that we will dump the configuration into is
specified with:

 my $running_config_file = "$ENV{HOME}/running_config.txt";

Before we connect to our device, we need to specify that on this occaision
that we would like to connect using SSH:

 my $session_obj = Net::Appliance::Session->new(
     Host      => $ios_device_ip,
     Transport => 'SSH',
 );

When we attempt our connection, it is useful to suppress the host-check
message that OpenSSH will output a message to ask if we wish to add this host
to our list of trusted hosts (Strict Host Key Checking).

This can cause errors in our script if not handled correctly, so on this
occaision, we can switch off the Strict Host Key Checking with the C<< SHKC => 0 >>
parameter in our C<connect()> method:

 # try to login to the ios device, ignoring host check
 $session_obj->connect(
     Name => $ios_username,
     Password => $ios_password,
     SHKC => 0
 );

Once we have initially logged in to our device, we assume on this occaision
that we need to supply a password to drop in to enable mode on the device:

 # drop in to enable mode
 $session_obj->begin_privileged($ios_enable_password);

Finally, once we have retrieved our configuration from the device, we will
dump it out (in plain text) to the file we specified at the start of our
script:

 open(FH, "> $running_config_file") or die("Cannot open config file : $!");
 print FH @running_config;
 close FH;

As with the previous script, it we get a failure at any point (e.g. login
details are incorrect, a command syntax is incorrect) then the script will
die.

With a little more work, this script could provide the basis of a production
script that could potentially retrieve configurations for many devices across
your network and dump them to files. It could also be modified to pull back
the startup configurations devices, or perhaps capture the output from other
commands.

=head1 SEE ALSO

=over 4

=item L<Net::Appliance::Session>

=item L<Net::Appliance::Session::Transport>

=item L<http://www.cygwin.com/>

=item L<http://www.openssh.org/>

=back

=head1 AUTHOR

Nigel Bowden, with POD formatting by Oliver Gorwits.

=head1 COPYRIGHT & LICENSE

Copyright (c) Nigel Bowden 2007. All Rights Reserved.

You may distribute and/or modify this documentation under the same terms as
Perl itself.

=cut
