Testing SSH Key-based Authentication for Network Automation | zeroslash.io

Testing SSH Key-based Authentication for Network Automation

Submitted by zeroslash on Fri, 03/23/2018 - 10:05

In my last post How To Configure SSH Key-based Authentication on Linux, I gave a walkthrough on how to set up SSH keys with an SSH agent so you get the benefits of passwordless logins while still maintaining the increased security that key-based authentication is supposed to provide. The reason why I reiterate this is because using SSH keys without passphrases pretty much defeats the purpose of using keys at all. If your private keys get stolen, anybody can use them if you didn't create them with a passphrase. Your passphrase is your lock on your private key. The challenge arises with having to type the passphrase every time you use the key to log in. This is like a problem which goes around in a circle and it's funny because a big part of moving to key-based authentication at least for me is to get rid of typing passwords. If you have read the post then you'll see how an SSH agent helps to solve this.

 

Now how can we use this with Network Automation? For this type of use case, the main compelling reason to do this is to be able to leave your code unattended, running on its own doing its thing and the most important part - NO hardcoded passwords sitting around your code or any file. I'm pretty sure I don't have to explain why this is important.

 

So let's get started. If you haven't done so yet please go through my The Easiest Way to Build a Network Automation Lab post to follow along.

Current machine states:
vsrx1                     running (virtualbox)
vsrx2                     running (virtualbox)
vsrx3                     running (virtualbox)
netauto                   running (virtualbox)

 

In the following steps, I assume you already have the lab set up and have an SSH key pair with SSH agent on the client - in this case, I'm expecting you to have configured it on the netauto VM. Again you can refer to How To Configure SSH Key-based Authentication on Linux, the only difference is that we won't bother with the parts involving the SSH server in that post (steps 2 -3), we will use the VSRX in the Network Automation lab as the SSH server instead. You also should have the Python 3 development environment set up. If not then please follow the steps in this post Installing Python 3 for Development in Centos 7 Step by Step. This should be in the netauto VM as well. I hope you are following along here, if not give it another shot from the top with The Easiest Way to Build a Network Automation Lab as these blog posts are intended to be tied together in a series, albeit some of the individual posts can also stand on its own.

 

Step 1. Configure the VSRX with the public part of your SSH key pair generated with a passphrase.

In this example, we will use VSRX3 again.

vagrant ssh vsrx3

Let's remove any existing SSH public key configured for our user netauto first. Technically, this is not a required if you are sure there are no existing keys configured. I'm just assuming you have one having followed the steps in previous posts.

root@vsrx3% cli
root@vsrx3> edit 
Entering configuration mode

[edit]
root@vsrx3# delete system login user netauto authentication 

[edit]
root@vsrx3# commit 
commit complete

 

Let's verify that all keys have been cleared from the configuration.

root@vsrx3# show system login user netauto | display set 
set system login user netauto uid 2001
set system login user netauto class super-user

[edit]
root@vsrx3# 

 

Alright, if everything looks good then we can proceed to configure the public key generated with a passphrase.

Let's copy our public key from our client netauto VM.

[vagrant@netauto ~]$ cat ~/.ssh/id_rsa.pub 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGRgxz90bxJ6uksHkTKxHiH92MRM2LYrGljLLK0rYaWrGCl+TyiOI6kj<snip>G5iLDryk1IvuBW29O9 vagrant@netauto

 

Let's go ahead and configure it on VSRX3.

root@vsrx3# set system login user netauto authentication ssh-rsa "<paste your public key here>"       

[edit]
root@vsrx3# commit 
commit complete

 

If you followed everything correctly up to this point then we should be ready to test our key-based authentication (with passphrase loaded by the SSH agent) on our VSRX.


 

Step 2. Attempt to log in to the VSRX

Now just to make sure, add your key to the SSH agent. If it's already added then you don't have to do so. If you have logged out of your session on the netauto VM then you will have to perform this step again. Please note that this applies anytime you have logged out of your session while using an SSH agent.

[vagrant@netauto ~]$ ssh-add ~/.ssh/id_rsa
Enter passphrase for /home/vagrant/.ssh/id_rsa: 
Identity added: /home/vagrant/.ssh/id_rsa (/home/vagrant/.ssh/id_rsa)
[vagrant@netauto ~]$

 

Now our unlocked key should be loaded into memory and we should be able to keep using it without having to retype our passphrase. Unless, of course, we are logged out.

[vagrant@netauto ~]$ ssh netauto@192.168.56.12
--- JUNOS 12.1X47-D15.4 built 2014-11-12 02:13:59 UTC
netauto@vsrx3>

 

Alright! everything is looking good. We can go straight to running our code to test this out.


 

Step 3. Test the SSH key-based log in with PyEZ

Let's go into our junos virtualenv from The Easiest Way to Build a Network Automation Lab.

[vagrant@netauto ~]$ cd ./junos
[vagrant@netauto junos]$ source ./bin/activate
(junos) [vagrant@netauto junos]$

 

Let's create our test script.

(junos) [vagrant@netauto junos]$ cat > pyez-test.py

 

Then paste

from jnpr.junos import Device

dev = Device(host='192.168.56.12', user='netauto')
for i in range(10):
    dev.open()
    print(i, dev.facts["hostname"])
    dev.close()

Press enter then CTRL+D

 

In this code we are basically just opening and closing a session 10 times to VSRX3 and extracting the hostname information. What this will prove is that we can run the script, get it to SSH to VSRX3 using key-based authentication which we know is using a passphrase we initially loaded into our SSH agent, then repeat that 10 times without being asked for a passphrase.

Let's go ahead and try it out.

(junos) [vagrant@netauto junos]$ python pyez-test.py
0 vsrx3
1 vsrx3
2 vsrx3
3 vsrx3
4 vsrx3
5 vsrx3
6 vsrx3
7 vsrx3
8 vsrx3
9 vsrx3
(junos) [vagrant@netauto junos]$ 

 

This looks awesome! But we have one problem here. What if we need to log out or got accidentally logged out? This brings us to the next step.


 

Step 4. Screen saves the day.

If you are familiar with screen then that's great this should be pretty easy for you. If not then let me show you how we can use screen to keep our programs running even if we log out or get disconnected from our session.

First, let's exit out of our junos virtualenv.

(junos) [vagrant@netauto junos]$ deactivate 
[vagrant@netauto junos]$ cd
[vagrant@netauto ~]$

 

Then let's launch screen.

[vagrant@netauto ~]$ screen

 

Once you do this it's almost like nothing happened. However, you will notice that your screen gets cleared and you're prompt is now at the very top (as if you used the command clear). Unless you launched screen while your prompt was already in this position, you may not notice any change.

Hit CTRL+A then D

 

You should now be back to your original screen. And you will get an output similar to below.

[vagrant@netauto ~]$ screen
[detached from 7696.pts-0.netauto]
[vagrant@netauto ~]$

 

If I wish to go back to the same session I just have to issue a reconnect.

[vagrant@netauto ~]$ screen -r 7696

 

This means I'm reconnecting to my screen session 7696. Now let's go ahead actually make this work for us.


 

Step 5. Run the script again from the screen session.

At this point, we are still in the screen session. Let's go back into our junos virtualenv and run our script again.

[vagrant@netauto ~]$ cd ./junos
[vagrant@netauto junos]$ source ./bin/activate
(junos) [vagrant@netauto junos]$

 

Before running the script let's have it run longer than 10 cycles, let's change it to 50. This will give us enough time to exit out of the screen session for a couple of seconds and come back to see the script still running.

Let's just do a simple find and replace.

(junos) [vagrant@netauto junos]$ sed -i 's/10/50/g' pyez-test.py

 

Then let's review our modified code just to make sure.

(junos) [vagrant@netauto junos]$ cat pyez-test.py 
from jnpr.junos import Device

dev = Device(host='192.168.56.12', user='netauto')
for i in range(50):
    dev.open()
    print(i, dev.facts["hostname"])
    dev.close()

 

As you can see the range has been set to 50. So let 's now run the script.

(junos) [vagrant@netauto junos]$ python pyez-test.py
<snip>
jnpr.junos.exception.ConnectAuthError: ConnectAuthError(192.168.56.12)

 

We just got an error. What happened? Can you guess what it is?

If you are thinking that we lost access due to we did not add our private key yet to the SSH agent then you are correct. This is because with our new screen session, technically we are in a brand new shell so it's a different shell environment from our original session before we entered our screen session. Remember that when we get logged out and we log in again we had to add and add our SSH key again with the SSH agent. This means that our use of the SSH agent is session specific, or I should say shell environment specific. In fact, if you try to run your script via cron, your use of keys with a passphrase won't work. This is because cron runs with a restricted environment compared to your normal shell.

So let's go back and add our SSH key.

(junos) [vagrant@netauto junos]$ ssh-add ~/.ssh/id_rsa
Enter passphrase for /home/vagrant/.ssh/id_rsa: 
Identity added: /home/vagrant/.ssh/id_rsa (/home/vagrant/.ssh/id_rsa)
(junos) [vagrant@netauto junos]$

 

Then go ahead and rerun the script.

(junos) [vagrant@netauto junos]$ python pyez-test.py 
0 vsrx3
1 vsrx3
2 vsrx3
3 vsrx3
4 vsrx3

Exit out from screen session.

Hit CTRL+A then D

 

Hit the up arrow so you'll get your screen reconnect command again or just type the command again.

[vagrant@netauto ~]$ screen -r 7696

 

And you should see your script still running and eventually it will reach its end.

45 vsrx3
46 vsrx3
47 vsrx3
48 vsrx3
49 vsrx3
(junos) [vagrant@netauto junos]$

 

As you have seen, screen is a useful tool for stuff like this. In fact, you may find it helpful for normal day-to-day work on Linux. You can do a bunch of things and leave it for some time like you are just pausing whatever you're doing and then you can come back to it anytime later. You don't necessarily have to be working with long-running programs to get the benefits of screen.

 

That's it for this post and I hope you were able to make it work in your lab. If you have any questions or comments let me know by getting in touch through my contacts.