Ansible ASA Playbook (asa_config and asa_acl): Cisco ASA access-list

Like in my previous post in the new development version 2.2. from Ansible are new IOS and ASA core modules.

Here an example of the asa_config and asa_acl module to create and object-group in the first step and create the inside create access-list:

- name: Cisco ASA access-list config
  connection: local
  hosts: firewall
  gather_facts: false
  vars:
    cli:
      username: "{{ username }}"
      password: "{{ password }}"
      host: "{{ device_ip }}"
      authorize: yes
      auth_pass: cisco
  tasks:
    - name: create object group
      asa_config:
        lines:
          - network-object host 10.1.0.1
          - network-object host 10.1.0.2
          - network-object host 10.1.0.3
        parents: ['object-group network dummy-group']
        provider: "{{ cli }}"
#      register: result

    - name: configure access-list
      asa_acl:
        lines:
          - access-list acl_inside extended permit tcp object-group dummy-group any eq www
          - access-list acl_inside extended permit udp object-group dummy-group any eq domain
          - access-list acl_inside extended deny ip any any
        before: clear configure access-list acl_inside
        match: strict
        replace: block
        provider: "{{ cli }}" 
#      register: result

    - debug: var=result

Here output when you run the playbook the first time:

ansible-playbook cisco/asa_access-list_config.yml -i cisco/hosts

PLAY [Cisco ASA access-list config] ********************************************

TASK [create object group] *****************************************************
changed: [fw1]

TASK [configure access-list] ***************************************************
changed: [fw1]

TASK [debug] *******************************************************************
ok: [fw1] => {
    "result": "VARIABLE IS NOT DEFINED!"
}

PLAY RECAP *********************************************************************
fw1                        : ok=3    changed=2    unreachable=0    failed=0

Here the output then you run the playbook a second time, you see nothing is changed:

ansible-playbook cisco/asa_access-list_config.yml -i cisco/hosts

PLAY [Cisco ASA access-list config] ********************************************

TASK [create object group] *****************************************************
ok: [fw1]

TASK [configure access-list] ***************************************************
ok: [fw1]

TASK [debug] *******************************************************************
ok: [fw1] => {
    "result": "VARIABLE IS NOT DEFINED!"
}

PLAY RECAP *********************************************************************
fw1                        : ok=3    changed=0    unreachable=0    failed=0

Read my new post about an Ansible Playbook for Cisco ASAv Firewall Topology

Ansible Interface Playbook (ios_config): Cisco interface config

Here an Ansible Playbook with three different examples how to configure Cisco router interfaces:

1. Static IP address configuration in playbook
2. Configuration comes out of Jinja2 template, can be run dynamic with variables
3. Loop in playbook configures multiple interfaces

There are some disadvantages to work with templates, if you use commands like “no shutdown” to enable the interface. They are not shown in the running-configuration which means Ansible will assume that the configuration is not matching and execute the template again.
Another disadvantage with templates is that you cannot run “before” or “after” commands to remove existing configuration all this needs to be implemented in your Jinja2 template.

Here the Ansible Playbook:

- name: Cisco interface config
  connection: local
  hosts: all
  gather_facts: false
  vars:
    cli:
      username: "{{ username }}"
      password: "{{ password }}"
      host: "{{ device_ip }}"
  tasks:
    - name: configure IP address
      ios_config:
        before: 
          - default interface FastEthernet1/0
        lines: 
          - ip address 10.1.1.1 255.255.255.0
        after: 
          - no shutdown
        match: strict
        parents: interface FastEthernet1/0
        provider: "{{ cli }}"

    - name: configure IP out of template
      ios_config:
        src: "interfaces.j2"
        provider: "{{ cli }}"

    - name: configure IP with loop
      ios_config:
        provider: "{{ cli }}"
        before:
          - "default interface {{ item.interface }}"
        lines:
          - "ip address {{ item.address }} 255.255.255.0"
        after:
          - no shutdown
        parents: "interface {{ item.interface }}"
      with_items:
        - { interface : FastEthernet2/0, address : 10.3.3.3 }
        - { interface : FastEthernet2/1, address : 10.4.4.4 }

Read my new posts about Ansible Playbook for Cisco ASAv Firewall Topology or Ansible Playbook for Cisco BGP Routing Topology.

Ansible Semaphore

I spend lot of time working with Ansible in the last weeks to automate the deployment of Cisco router or Cumulus switches. (Waiting for Ansible 2.2 to support Cisco ASA devices..)
Ansible is a great tool but if you have multiple YAML files and various roles it can get pretty messy and would be nice to have central tool to trigger your tasks and structure your environment variables or inventories.

I exactly found this tool with Ansible Semaphore: https://github.com/ansible-semaphore/semaphore

The install is pretty easy and provides an API to trigger your tasks remotely.

You can create different projects and include your Ansible YAML files.

screen-shot-2016-10-15-at-21-59-57

The source is a Git repository where your files are stored:

screen-shot-2016-10-15-at-21-58-18

Here your environment variables:

screen-shot-2016-10-15-at-21-58-43

Inventory definition:

screen-shot-2016-10-15-at-21-59-02

Finally the you can execute your Ansible YAML files via the Web UI or API:

screen-shot-2016-10-15-at-22-00-26

screen-shot-2016-10-15-at-22-00-53

Have fun playing around with Semaphore 🙂

Cisco IOS automation with Ansible

Bin a long time since I wrote my last post, I am pretty busy with work redesigning the data centres for my employer. Implementing as well an SDN Software-defined Network from VMware NSX but more about this later.

Ansible released some weeks ago new core modules which allows you to push directly configuration to Cisco IOS devices. More information you find here: https://docs.ansible.com/ansible/list_of_network_modules.html

I created a small automation lab in GNS3 to test the deployment of configs via Ansible to the two Cisco routers you see below. I am running VMware Fusion and used the vmnet2 (192.168.100.0/24) network for management because I run there my CentOS VM from where I deploy the configuration.

Don’t forget you need to pre-configure your Cisco router that you can connect via SSH to deploy the configuration.

Here the folder and file script structure of my Ansible example, under roles you have the different tasks I would like to execute common and logging but as well dependencies writecfg which saves the running-config to startup-config:

site.yml
hosts
group_vars/all.yml
roles/common/meta/main.yml
roles/common/task/main.yml
roles/common/templates/common.j2
roles/logging/meta/main.yml
roles/logging/tasks/main.yml
roles/logging/templates/common.j2
roles/writecfg/handlers/main.yml

The site.yml is the main script which I execute with Ansible which includes different roles for common and logging configuration:

- name: Cisco baseline configuration
  connection: local
  hosts: ios 
  gather_facts: false

  roles:
    - role: common
      tags: common
    - role: logging
      tags: logging

In the hosts file, I define the hostname and IP addresses of my IOS devices

[ios]
rtr01 device_ip=192.168.100.130
rtr02 device_ip=192.168.100.132

The file group_vars/all.yml defines variables which I used when the script is executed:

---
username: "ansible"
password: "cisco"
secret: "cisco"
logserver: 192.168.100.131

Under the roles/../meta/main.yml I set a dependency on the writecfg handler to save the configuration later when I change anything on the device.

Under the roles/../tasks/main.yml I define the module which I want to execute and the template I would like to deploy

Under the roles/../templates/.. you find the Jinja2 template files which include the commands.

Under roles/writecfg/handler/main.yml is the dependencies I have with the two roles common and logging to save the configuration if something is changed on the router.

To execute the cisco-baseline Ansible script just execute the following command and see the result:

[user@desktop cisco-baseline]$ ansible-playbook site.yml -i hosts

PLAY [Ensure basic configuration of switches] **********************************

TASK [common : ensure common configuration exists] *****************************
ok: [rtr02]
ok: [rtr01]

TASK [logging : ensure logging configuration exists] ***************************
changed: [rtr02]
changed: [rtr01]

RUNNING HANDLER [writecfg : write config] **************************************
ok: [rtr01]
ok: [rtr02]

PLAY RECAP *********************************************************************
rtr01                      : ok=3    changed=1    unreachable=0    failed=0
rtr02                      : ok=3    changed=1    unreachable=0    failed=0

[user@desktop cisco-baseline]$

Read my new posts about Ansible Playbook for Cisco ASAv Firewall Topology or Ansible Playbook for Cisco BGP Routing Topology.