ollyg / Net-Appliance-Session

Development of Net::Appliance::Session Perl distribution
https://metacpan.org/pod/Net::Appliance::Session
12 stars 6 forks source link

in_privileged_mode should verify actual state on the device #13

Closed obilodeau closed 12 years ago

obilodeau commented 12 years ago

Hi,

We are using your module on our open source project PacketFence (www.packetfence.org).

We are often connecting on devices that require escalating to privileged mode and others that don't require it. This is all user-controlled and configured. Not something we can control.

Reading Cookbook Recipe 5 I realized that there is no way to connect to a switch using the same code if it's privileged or not.. Am I wrong about this?

I was thinking that since the yaml syntax knows what the privileged and unprivileged prompts look like that a call to in_privileged_mode would actually verify the state on the device connected to.

Right now with 1.36 I get an undef when calling in_privileged_mode after a connect. I was wondering if, instead of returning undef, you could check the prompt and return the actual mode?

Anyways, for now I'll probably tell users to forget about logging in unprivileged but in the long term I would really like to handle both gracefully with the same code.

    my $session;
    eval {
        $session = Net::Appliance::Session->new(
            Host      => $this->{_ip},
            Timeout   => 5,
            Transport => $this->{_cliTransport}
        );
        $session->connect(
            Name     => $this->{_cliUser},
            Password => $this->{_cliPwd}
        );
    };

    if ($@) {
        $logger->error("Error connecting to " . $this->{'_ip'} . " using ".$this->{_cliTransport} . ". Error: $!");
    }

    # are we in enabled mode?
    if (!$session->in_privileged_mode()) {

        # let's try to enable
        if (!$session->enable($this->{_cliEnablePwd})) {
            $logger->error("Cannot get into privileged mode on ".$this->{'ip'}.
                           ". Are you sure you provided enable password in configuration?");
            $session->close();
            return 0;
        }
    }

    eval {
        $session->cmd(String => "conf t", Timeout => '10');
        $session->cmd(String => "int $ifName", Timeout => '10');
        $session->cmd(String => "switchport port-security maximum $maxSecureMac vlan access", Timeout => '10');
        $session->cmd(String => "end", Timeout => '10');
    };

Please ignore the lack of proper error-handling and the fact that I don't use begin_configure in that code... ;) I'll get to these eventually.

Thanks for such a great module!

ollyg commented 12 years ago

Hi Olivier,

Many thanks for your email. I think PacketFence is awesome and I'm really pleased you're still using my module in your product!

There's a short answer to your question: yes I think it's possible for you to manually check whether you're in privileged mode:

if ($session->last_prompt =~ eval 'qr'. $session->pb->fetch('privileged_prompt')) {
    # I am in privileged mode!
}

In fact this code is already in Net::Appliance::Session, if you upgrade from the 1.x train to the 2.x train. You can safely call begin_privileged and the module uses this code to check and immediately return, if it looks like you logged-in straight into privileged mode:

https://metacpan.org/source/OLIVER/Net-Appliance-Session-2.111080/lib/Net/Appliance/Session/Engine.pm#L100

The upgrade should be safe - the main difference between 1.x and 2.x was on the packaging side, and I needed to bump the major version number for the change in packaging system.

Also, there is a version 3.x of the module nowadays, which is a complete rewrite and much more powerful. However the module API changed so you should not upgrade to 3.x unless happy to change and test your code as well.

I hope this helps, and please let me know how you get on. I'm very happy to help you out anytime.

regards, oliver.