NETCONF through a Firewall, Part 2.
Now that we've established SSH tunneling through the network, we can verify a NETCONF session directly. When I use the ssh command, I specify the sub-command netconf using the -s parameter, as illustrated. Note that the netconf sub-command is after the hostname:
01 [email@example.com]$ ssh -s srx3600.jumpy netconf
03 Warning: Permanently added '[localhost]:8001' (RSA) to the list of known hosts.
04 <!-- No zombies were killed during the creation of this user interface -->
05 <!-- user jeremy, class j-super-user -->
13 <capability>http://xml.juniper.net/netconf/junos/1.0</capabili<wbr/>ty> <capability>http://xml.juniper.net/dmi/system/1.0</capability> </capabilities>
What you see here is the actual NETCONF "hello" message in response to the connection. If you do not see this, then one of two things is not setup correctly:
You can close the NETCONF session using <Ctrl-C>.
I am going to demonstrate a Python script using a module called jnpr.eznc. This is an active open-source project that is relatively new. I will write a more detailed blog on this module in the near term, but for now, if you'd like to get started using it, please see the github repo and README files located here.
Let's first take a look at a script that is *NOT* in an ssh-tunneled environment. Let's say I simply want to connect to the Junos OS device, display the serial-number and version, and then close the connection. It would look like the following:
01 from jnpr.junos import Device
03 dev = Device(host='srx3600.corp.net', user='jeremy', password='logmein')
07 print dev.facts['serialnumber']
08 print dev.facts['version']
The above example illustrates making a connection providing the username and password. If you are using ssh-keys, then you simply do not provide the password.
Now to do the tunneling use-case, we know that we are connecting through a local port forward. We could do something like the following:
01 from jnpr.junos import Device
03 # srx3600-1.jumpy uses port 8001
04 dev = Device(host='localhost', port=8001, user='jeremy')
08 print dev.facts['serialnumber']
09 print dev.facts['version']
But now we've duplicated information between our script and the ssh config file. What we really want to do is use the ssh config file to extract the port associated with srx3600-1.jumpy so we can connect by the hostname directly.
I am using the Python paramiko module to illustrate the technique to load the ssh config file and extract the information based on the hostname defined in the config file, e.g., "srx3600-1.jumpy":
01 import paramiko
02 import os
04 from jnpr.junos import Device
06 # load the $HOME/.ssh/config file and do a lookup on the
07 # host name "srx3600-1.jumpy"
09 config_file = os.path.join(os.getenv('HOME'),'.ssh/config')
10 ssh_config = paramiko.SSHConfig()
12 got_lkup = ssh_config.lookup( "srx3600-1.jumpy" )
14 # now open the NETCONF connection using the information
15 # we retreived from the ssh config file
17 dev = Device(user='jeremy', host=got_lkup['hostname'], port=got_lkup['port'])
21 print dev.facts['serialnumber']
22 print dev.facts['version']
Writing Python scripts for Junos OS automation tasks can be easy (and fun!). With a little bit of practice and the right set of modules (like jnpr.junos), you can quickly create very powerful automation tools with a high degree of confidence.
Network Automatic Blog - Jeremy Schulman - Nov. 4, 2013.
Reposted with permission to TechWiki.