Connecting to Juniper with Ansible

Recently I wanted to test out using Ansible to connect to Juniper vSRX routers. Unfortunately this was not as easy as I had thought/hoped it would be.

Juniper vSRX

Juniper provides a virtual machine image for the virtual SRX firewall.

The version I’m using here is:

media-vsrx-vmdisk-17.3R1.10.qcow2

I’m running it in kvm on Ubuntu 16.04…but that’s another story.

Configure vSRX

This is the easy part.

set system services netconf ssh
set system services ssh hostkey-algorithm no-ssh-ecdsa
set system services ssh hostkey-algorithm ssh-rsa

NOTE: In the future the ssh hostkey-algorithm settings might not be needed. More on this later in the post.

Also, the known_hosts file for where ever Ansible is running would need to be setup. HINT: ssh-keyscan.

Setup Playbook

Here’s an example playbook. Note the provider section. This took a little while to get right. The junos_facts module requires some connection information, and it uses a dictionary called provider that can be setup in the task. Obviously these variables could be pulled from somewhere else, like an Ansible Vault file, but I’m leaving it bare as an example here.

Ansible’s default facts gathering doesn’t understand how to gather facts from Juniper, so the juniper_facts module is required to get facts. Note I’m also gathing a subset of information in the example.

- name: test
  hosts:
    - routers
  roles:
    - Juniper.junos
  connection: local
  gather_facts: no
  tasks:

    - name: check is netconf port is listening
      wait_for:
        host: "{{ ansible_host }}"
        timeout: 5
        port: 830

    - name: collect default set of facts and configuration
      junos_facts:
        gather_subset: "config"
        provider:
            username: "root"
            password: "coolpass"
            transport: "netconf"
            timeout: 5
            host: "{{ ansible_host }}"

Issues with ECDSA keys

It seems that the ncclient code can’t handle, at this time, ECDSA keys. It just fails with an “unknown key” message.

I had to disable ECDSA keys in the Juniper routers.

I tried this super simple test code, prior to forcing ECDSA on the Junipers, and it errored out with hostkey_verify=True, and succeeded with it set to False.

$ cat test-netconf.py
from ncclient import manager

with manager.connect(host="<hostname>", port=830, username="root", password="coolpass", hostkey_verify=True) as m:
    c = m.get_config(source='running').data_xml
    print c

As far as I know at this time this is the latest ncclient code.

$ pip freeze | grep ncclient
ncclient==0.5.3

Maybe there is another issue hidden away somewhere. Worth some more digging when I have time.

Conclusion

Overall, I’m not happy with how this looks. I like Ansible, but sometimes the whole module thing, which exists with almost all configuration management tools, just seems hacky. Here I have to turn of fact gathering, and then turn on a task based Juniper fact gathering. Further, getting this to work with a recent vSRX node took like an hour due to the ECDSA issue. One simple little thing like that breaks connectivity via Ansible. Dependencies and versioning…these are hard and don’t seem to be getting any easier, this is too brittle.

I know the Ansible and networking (vendors) have done a lot of work to get many devices supported, it just doesn’t seem quite right to me. That said, Ansible is probably one of the best options for managing many individual network devices.