Back to Home

Cooking Juniper Network with Ansible

Ansible · Juniper

Cooking Juniper Network with Ansible



    One fine day, I decided to switch from the usual rsyslog collecting logs from all devices to something else, the selection and other have little relevance to this topic (they chose Graylog2), but as a result, the task appeared to replace the syslog host settings with all Juniper devices.

    In principle, running through the handles (or throwing a script on perl) over a hundred devices and clicking on a command is not a problem, but a good pack of tasks on automating the management of both network devices and a couple of hundred servers was already hanging in my head. If there are no problems with Windows in my environment (we use SCCM), then with a Linux environment mass operations are surrounded by either manual operations or bash scripts (you can also manage SCCM, but this option is mildly inconvenient).

    And since I have long wanted to start using Ansible, then it was chosen as the start for this task (for Chef and Puppet, however, the tasks are not so large, and the entry threshold is already larger).

    Install Ansible


    Installing Ansible is simple, since everything is out of the box (for this task we used ubuntu server 04.16.03):

    sudo apt-add-repository ppa:ansible/ansible
    sudo apt-get update
    sudo apt-get install ansible

    Change the settings in /etc/ansible/ansible.cfg
    #Каталог для ролей по умолчанию
    roles_path = /etc/ansible/roles
    #Проверка при подключении, можно и оставить, но предварительно к хостам придется подключится по SSH и подтвердить отпечаток.
    host_key_checking = False
    #Журнал
    log_path = /var/log/ansible.log
    Данные настройки сугубо личные для меня, у себя вы можете использовать свои.


    Module for Juniper


    Juniper in the subject and great guys, they developed their module. Information about him can be found on the off site: Ansible for JunOS . Starting with version Ansible 2.1, it is natively included in core modules Ansible .

    Install this module and check it in the list:

    sudo ansible-galaxy install Juniper.junos
    ansible-galaxy list

    Also to use the module we need nccclient

    sudo apt-get install python-pip
    pip install ncclient

    Connect to devices


    Ansible can connect to Juniper devices in several ways, the default protocol is Netconf and port 830. You can also use telnet and serial console connection, but telnet is relatively unsafe, and serial is a little for specific tasks, although the initial configuration of bare metal in the presence of a connection can be automated with its help.

    Netconf can also be used in the usual 22 ssh port, and just use cli as a transport.

    about Netconf
    What is Netconf not bad disclosed in one of the old publications on Habré .

    For authorization on devices, I would like to immediately configure authorization by key. For convenience, we generate the RSA key as root (why not DSA will be understood further). After copying it to the previously created /etc/ansible/.ssh for ease of use.

    ssh-keygen -t rsa
    cp /root/.ssh/id_rsa.pub /etc/ansible/.ssh/ansible.pub
    cp /root/.ssh/id_rsa /etc/ansible/.ssh/ansible

    As a result, on target devices, it would be necessary to manually create a user with a public key:

    set system login user ansible class super-user authentication ssh-rsa ""

    But we will also automate this further.

    Hosts


    To whom we connect, we describe in the file / etc / ansible / hosts.
    It is possible to describe device groups and variables in it, since I use different Juniper devices, so I will immediately create several groups:

    / etc / ansible / hosts
    [junex2200]
    192.168.111.101
    [junex3300]
    192.168.111.51
    [junexcore]
    192.168.111.4
    [junexdc]
    192.168.111.11
    [alljuniper:children]
    junex2200
    junex3300
    junexcore
    junexdc
    [alljuniper:vars]
    ansible_jun_username=ansible
    ansible_jun_port=22
    ansible_jun_timeout=60
    ansible_ssh_private_key_file=/etc/ansible/.ssh/ansible


    In this file, I defined 4 groups, added 1 device to each group. Then he made a general group and added variables for authorization, which will be used in the playbook. The user we have will be “ansible” , we will use the port 22, since 830 is not enabled by default, and also increase the timeout to 60, since with commit the time can easily be longer than the standard 10 seconds.

    if netconf you want to enable on juniper
    set system services netconf ssh

    Playbook initial setup


    I made the initial setup in a separate playbook . Since I have a user for connection on all devices, I will use the login / password in the playbook to create the user “ansible” with our key. Also, if you wish, you can enable Netconf on port 830, but I did not notice the difference, so I consider this unnecessary.

    Let's create the directory / etc / ansible / playbooks / juniper and in it our first playbook init.yml

    Let's analyze the contents:

    ---
    - name: juniper initialization playbook #название PB
      hosts: alljuniper #на какие hosts будем его применять
    #подключаем модуль juniper
      roles:
      - Juniper.junos 
      connection: local
      gather_facts: no
    #далее объявим переменные логин/пароль для ввода, пароль скрытый
      vars_prompt:
        - name: "DEVICE_USERNAME"
          promt: "Device username"
          private: no
        - name: "DEVICE_PASSWORD"
          promt: "Device password"
          private: yes
    #объявим переменную для определения настроек подключения
      vars:
        provider_info:
          host: "{{ inventory_hostname }}"
          username: "{{ DEVICE_USERNAME }}" 
          password: "{{ DEVICE_PASSWORD }}"
          port: "{{ ansible_jun_port }}"
          timeout: "{{ ansible_jun_timeout }}"
    #дальше блок самих задач
      tasks:
    #проверка доступности нашего порта
      - name: junos check connection 
        wait_for:
          host: "{{ inventory_hostname }}"
          port: "{{ ansible_jun_port }}"
          timeout: 10
    #создание пользователя
      - name: junos create ansible user with key-auth
        junos_user:
          provider: "{{ provider_info }}"
          name: "{{ ansible_jun_username }}"
          role: super-user
          sshkey: "{{lookup('file', '/etc/ansible/.ssh/ansible.pub') }}"
          state: present
    

    To create a user, we use the junos_user module . The module can only create a user with the rsa key, and therefore we generated it. In principle, you can use junos_config and write our line directly with the dsa key.

    set system login user ansible class super-user authentication ssh-dsa ""

    Launch playbook


    We launch the playbook init.yml created by us:

    sudo ansible-playbook init.yml

    Execution result
    DEVICE_USERNAME: megaswitchuser
    DEVICE_PASSWORD:
    PLAY [juniper initialization playbook] ********************************************************************************
    TASK [junos check connection] ********************************************************************************
    ok: [192.168.111.101]
    ok: [192.168.111.51]
    ok: [192.168.111.4]
    ok: [192.168.111.11]
    TASK [junos create ansible user with key-auth] ********************************************************************************
    changed: [192.168.111.101]
    changed: [192.168.111.51]
    changed: [192.168.111.4]
    changed: [192.168.111.11]
    PLAY RECAP ********************************************************************************
    192.168.111.101               : ok=2    changed=1    unreachable=0    failed=0
    192.168.111.51              : ok=2    changed=1    unreachable=0    failed=0
    192.168.111.4               : ok=2    changed=1    unreachable=0    failed=0
    192.168.111.11               : ok=2    changed=1    unreachable=0    failed=0
    


    changed = 1
    means a successful change, you can go to any device and yes the user will already be created there.

    When you restart the playbook, the changes will not be made again, and he will write
    changed = 0

    Syslog setup


    We have a junos_logging module . In principle, in most cases you can use it, but I need to enter advanced parameters for the host, and they are not supported in this module. Therefore, we will use the universal tool, the junos_config module to add a new host, and the junos_logging module to delete the old one.

    We create a playbook syslog.yml, in it we will already use key authorization for our user ansible.

    ---
    - name: juniper set syslog to graylog2 #название PB
      hosts: alljuniper #на какие hosts будем его применять
    #подключаем модуль juniper
      roles:
      - Juniper.junos
      connection: local
      gather_facts: no
    #объявим переменную для определения настроек подключения, уже используем параметр пользователя определенный в hosts, keyfile подтянется оттуда же сам
      vars:
        provider_info:
          host: "{{ inventory_hostname }}"
          username: "{{ ansible_jun_username }}"
          port: "{{ ansible_jun_port }}"
          timeout: "{{ ansible_jun_timeout }}"
    #дальше блок самих задач
      tasks:
    #проверка доступности нашего порта
      - name: junos check connection
        wait_for:
          host: "{{ inventory_hostname }}"
          port: "{{ ansible_jun_port }}"
          timeout: "{{ ansible_jun_timeout }}"
    #настройка конфигурации
      - name: set juniper syslog host
        junos_config:
          provider: "{{ provider_info }}"
    #дальше идет блок строк конфигурации
          lines:
            - set system syslog host 192.168.111.210 any any
            - set system syslog host 192.168.111.210 port 2514
            - set system syslog host 192.168.111.210 structured-data brief
    #добавляем комментарий к коммиту
          comment: update config add syslog graylog2
    #удаляем старый сислог с помощью модуля junos_logging
     - name: delete old syslog host
        junos_logging:
          provider: "{{ provider_info }}"
          dest: host
          name: 192.168.111.208
          facility: any
          level: any
          state: absent
    

    We launch:

    sudo ansible-playbook syslog.yml

    Execution result
    
    PLAY [juniper set syslog to graylog2] ********************************************************************************
    TASK [junos check connection] ********************************************************************************
    ok: [192.168.111.101]
    ok: [192.168.111.51]
    ok: [192.168.111.4]
    ok: [192.168.111.11]
    TASK [set juniper syslog host] ********************************************************************************
    changed: [192.168.111.101]
    changed: [192.168.111.51]
    changed: [192.168.111.4]
    changed: [192.168.111.11]
    TASK [delete old syslog host] ********************************************************************************
    changed: [192.168.111.101]
    changed: [192.168.111.51]
    changed: [192.168.111.4]
    changed: [192.168.111.11]
    PLAY RECAP ********************************************************************************
    192.168.111.4               : ok=3    changed=1    unreachable=0    failed=0
    192.168.111.11               : ok=3    changed=1    unreachable=0    failed=0
    192.168.111.51               : ok=3   changed=1    unreachable=0    failed=0
    192.168.111.101               : ok=3    changed=1    unreachable=0    failed=0
    



    Having visited any of the Junipers, it is obvious that our new syslog server was registered in the settings, and the old one was deleted.

    Optionally, you can see the commit history with a comment from the playbook:

    show system commit

    0   2018-03-07 15:12:49 KRAT by ansible via netconf
        update config add syslog graylog2
    

    Recalling the playbook will also not change the configuration, but will report that everything is OK and there are no changes.

    Summary


    We set up the environment to automate the settings in our network, now you can easily manage our network. The tasks that can be solved using the Juniper module for Ansible are not limited only to a configuration change, we can also update the software version, reboot devices, make backup configurations and much more.

    Plans


    The following plans I have identified for myself on this topic with Ansible in the near future.

    • Bring the settings of other Juniper parameters into a single view.
    • Bring the software version on all Juniper devices to one view.
    • Add a Linux server to Ansible with key authorization.
    • Prescribe rsyslog settings on a Linux server to a new collector.
    • Update / Install fresh Zabbix agents on Linux servers.

    The tool is really excellent and I really regret only that I did not start using it earlier. Whether you have one Linux machine or 100 different switches, it is never too late or too early to start automating your actions.

    Tested Equipment List


    Juniper: EX3300, EX2200, EX4550
    JunOS: 12.2R6.4, 12.3R3.4, 12.3R4.6, 12.3R6.6, 12.3R6.6, 12.2R9.4, 12.2R12.4

    PS: already in the process of writing the article I came across an article on the same topic on Habré, so I tried to more fully disclose the topic.

    Read Next