How to program Cisco ACI with Ansible and Docker

Ansible guide : https://docs.ansible.com/ansible/devel/scenario_guides/guide_aci.html

I create a docker container with ansible, python and the demo from github.

git clone https://github.com/CiscoDevNet/aci-learning-labs-code-samples 
cd aci-learning-labs-code-samples 

docker image with ansible and python:

docker pull zednetwork/aci-ansible2-4

New version with ansible 2.8.2 using debian 10.

docker pull zednetwork/aci-ansible.2-8-2

Docker Compose example:

version: "3" 
services:
  ansible:
    image: zednetwork/aci-ansible2-4
    tty: true
    stdin_open: true

Start the container and connect to it:

docker-compose up -d 
Creating network "aci-ansible_default" with the default driver

Pulling ansible (zednetwork/aci-ansible2-4:)…

latest: Pulling from zednetwork/aci-ansible2-4

22dbe790f715: Downloading [>                                                  ]  465.6kB/45.34 MBf88405a685: Pulling fs layer

22dbe790f715: Downloading [=>                                                 <..>
22dbe790f715: Pull complete
3bf88405a685: Pull complete
Creating aci-ansible_ansible_1 … done

Check container

# docker images
 REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
 zednetwork/aci-ansible2-4   latest              ff17ed37f691        34 minutes ago      659MB

# docker ps
 CONTAINER ID        IMAGE                       COMMAND             CREATED              STATUS              PORTS               NAMES
 53993071ffa9        zednetwork/aci-ansible2-4   "bash"              About a minute ago   Up About a minute                       aci-ansible_ansible_1

Connect to the container. Use the Container ID above.

# docker exec -it 53993071ffa9 /bin/bash
root@53993071ffa9:/#

This container already contains an example from devnet.cisco.com ( https://developer.cisco.com/docs/aci/#ansible). This example uses a public ACI Fabric.

We can use the first playbook to create a tenant on the ACI Fabric. The fabric credential is on the inventory file.

root@53993071ffa9:~/aci_ansible_learning_labs_code_samples/intro_module# cat inventory
 [apic:vars]
 username=admin
 password=ciscopsdt
 ansible_python_interpreter="/usr/bin/env python"
 [apic]
 sandboxapicdc.cisco.com

You can connect directly to the fabric and verify if your tenant is present. https://sandboxapicdc.cisco.com/

root@53993071ffa9:~/aci_ansible_learning_labs_code_samples/intro_module# ansible-playbook -i inventory 01_aci_tenant_pb.yml
 What would you like to name your Tenant?: MyFirstTenant-tn
 PLAY [ENSURE APPLICATION CONFIGURATION EXISTS] 
 TASK [ENSURE APPLICATIONS TENANT EXISTS] 
 changed: [sandboxapicdc.cisco.com]
 PLAY RECAP 
 sandboxapicdc.cisco.com    : ok=1    changed=1    unreachable=0    failed=0

Go to ACI > Tenants

You can delete your tenant with another playbook

root@53993071ffa9:~/aci_ansible_learning_labs_code_samples/intro_module# ansible-playbook -i inventory 01-1_aci_tenant_pb.yml
 What would you like to name your Tenant?: MyFirstTenant-tn
 PLAY [ENSURE APPLICATION CONFIGURATION EXISTS] 
 TASK [ENSURE APPLICATIONS TENANT EXISTS] 
 changed: [sandboxapicdc.cisco.com]
 PLAY RECAP 
 sandboxapicdc.cisco.com    : ok=1    changed=1    unreachable=0    failed=0

Other example to list all tenants:

# cat listTenants.yml
---
- name: ENSURE APPLICATION CONFIGURATION EXISTS
  hosts: apic
  connection: local
  gather_facts: False
  
  tasks:

    - name: List all tenants
        aci_tenant:
        host: "{{ ansible_host }}"
        username: "{{ username }}"
        password: "{{ password }}"
        state: "query"
      validate_certs: False 

# ansible-playbook -i inventory listTenants.yml -vvv

How to test your network services with Docker

This container has been tested with IOS / NXOS and ACI.

Test syslog

You can verify if you receive logs with syslog-ng. This service runs on the default port udp/514.

The configuration on the file /etc/syslog-ng/syslog-ng.conf redirects the external logs to the following file: /var/log/remote-syslog.log

# Extract of syslog-ng.conf

source s_net {
tcp(ip(0.0.0.0) port(514));
udp(ip(0.0.0.0) port(514));
};

log { source(s_net); destination(d_net); };
destination d_net { file(“/var/log/remote-syslog.log”); };

Logs could be see with the following command:

root@89944db0da60:~# tailf /var/log/remote-syslog.log
Apr 15 06:50:51 10.0.100.46 2019 Apr 15 06:50:48 UTC: %ETHPORT-5-IF_DOWN_CFG_CHANGE: Interface Ethernet1/1 is down(Config change)
Apr 15 06:50:52 10.0.100.46 2019 Apr 15 06:50:49 UTC: %ETHPORT-5-IF_DOWN_ADMIN_DOWN: Interface Ethernet1/1 is down (Administratively down)
Apr 15 06:50:55 10.0.100.46 2019 Apr 15 06:50:52 UTC: last message repeated 1 time
Apr 15 11:57:59 10.255.0.2 %LOG_LOCAL7-4-SYSTEM_MSG [F1186][raised][config-failure][warning][sys/phys-[eth1/35]/fault-F1186] Port configuration failure.                                   Reason: 2                                   Failed Config: l1:PhysIfspeed_failed_flag

Test snmptrap

snmptrapd is used to receive snmptrap. The logs are redirect to the file : /var/log/snmptrapd.log.

The configuration files are the following : /etc/snmp/snmptrapd.conf and /etc/default/snmptrapd.

The community configured is “public”. You can change in the /etc/snmp/snmptrad file or disabled the authentification with ” disableAuthorization yes”

Example:


Agent Address: 0.0.0.0
Agent Hostname: nxos – UDP: [10.0.100.46]:59353->[172.21.0.2]:162
Date: 6:50:57 15-4
Enterprise OID: .
EngineID:
Trap Type: Cold Start
Trap Sub-Type: 0
Community/Infosec Context: TRAP2, SNMP v2c, community nxos
Uptime: 0
Description: Cold Start
PDU Attribute/Value Pair Array:
iso.3.6.1.2.1.1.3.0 = Timeticks: (16384794) 1 day, 21:30:47.94
iso.3.6.1.6.3.1.1.4.1.0 = OID: iso.3.6.1.2.1.17.0.2
iso.3.6.1.4.1.9.9.46.1.3.1.1.1.1.1 = INTEGER: 1
iso.3.6.1.2.1.31.1.1.1.1.436207616 = STRING: “Ethernet1/1”


Agent Address: 0.0.0.0
Agent Hostname: nxos – UDP: [10.0.100.46]:59353->[172.21.0.2]:162
Date: 6:51:6 15-4
Enterprise OID: .
EngineID:
Trap Type: Cold Start
Trap Sub-Type: 0
Community/Infosec Context: TRAP2, SNMP v2c, community nxos
Uptime: 0
Description: Cold Start
PDU Attribute/Value Pair Array:
iso.3.6.1.2.1.1.3.0 = Timeticks: (16385696) 1 day, 21:30:56.96
iso.3.6.1.6.3.1.1.4.1.0 = OID: iso.3.6.1.4.1.9.9.43.2.0.2
iso.3.6.1.4.1.9.9.43.1.1.1.0 = Timeticks: (16384764) 1 day, 21:30:47.64
iso.3.6.1.4.1.9.9.43.1.1.6.1.6.7117 = INTEGER: 3


Test tacacs+

tacacs+ is used to verify the Authentication, Authorization and Accounting. The configuration is in the file /etc/tacacs/tac_plus.conf.

We use the following package : http://www.shrubbery.net/tac_plus/

The current configuration is the following:

  • Tacacs Key : cisco1234
  • user : user1 / cisco1234
  • Right: admin

The log files are the following :

  • For accounting : /var/log/tacacs/tac_plus.acct
  • For authentication : /var/log/tac_plus.log

Test radius

We use freeradius with the following files:

  • radiusd.conf
  • clients.conf
  • users

The logs are in the following directory /var/log/freeradius/.

Example for IOS/NXOS and ACI :

user1 Cleartext-Password := “cisco1234”
Service-Type = NAS-Prompt-User,
Cisco-AVPair = “shell:priv-lvl=15”,
Cisco-AVPair += “shell:domains=all/admin/”

Synchronize ntp

This container can be use to verify if your device can synchronize with a ntp server. This container runs a ntp server as stratum 5.

server 127.127.1.0
fudge 127.127.1.0 stratum 5

SSH / scp server

You can use this container to upload some file via scp if needed. The daemon is stopped and you need to create you own user.

root@9371dba394dc:~# adduser cisco
 Adding user cisco' ... Adding new groupcisco' (1001) …
 Adding new user cisco' (1001) with groupcisco' …
 Creating home directory /home/cisco' ... Copying files from/etc/skel' …
 New password:
 Retype new password:
 passwd: password updated successfully
 Changing the user information for cisco
 Enter the new value, or press ENTER for the default
         Full Name []:
         Room Number []:
         Work Phone []:
         Home Phone []:
         Other []:
 Is the information correct? [Y/n] y

root@9371dba394dc:~# /etc/init.d/ssh start
 [ ok ] Starting OpenBSD Secure Shell server: sshd.

The port exposed for ssh is 30022 on the docker-compose.yml file. You can change this port.

Docker-compose file

docker-compose.yml

version: "3"
 services:
   network-test:
     build: .
     image: zednetwork/network-test
     ports:
      - "30022:22/tcp"
      - "123:123/udp"
      - "49:49/tcp"
      - "162:162/udp"
      - "514:514/udp"
      - "1812:1812/udp"
      - "1813:1813/udp"
     tty: true
     stdin_open: true

To download the container :
docker pull zednetwork/network-test:latest

To enter in the container :

docker exec -it <container_ID> /bin/bash

Cisco Nexus 9000 – POAP

In this article, we will discuss about POAP to provision multiple switches.

We need a DHCP, TFTP and SCP server. We can also use an HTTP server to deliver the software and the configuration.

POAP Infrastructure:

http://www.cisco.com/c/dam/en/us/td/i/300001-400000/330001-340000/331001-332000/331649.eps/_jcr_content/renditions/331649.jpg

POAP Process:

http://www.cisco.com/c/dam/en/us/td/i/300001-400000/330001-340000/332001-333000/332315.eps/_jcr_content/renditions/332315.jpg

Software used:

  • ISC-DHCP-SERVER – version 4.3.1
  • ATFTPD – version 0.7
  • OPENSSH-server 6.7p1

DHCP configuration example :

Subnet used : 192.168.255.0/24

In the following block, I reserve a baud for the Client XXXXXXXX. XXXX is the serial number of the switch.

In the option dhcp-client-identifier you need to add “\000” before the serial number.

We have to assign the following parameter:

  • IP address
  • Default Gateway
  • IP address TFTP Server
  • Filename
  • DNS server

In the file: /etc/dhcp/dhcpd.conf

option domain-name-servers 192.168.255.254;

subnet 192.168.255.0 netmask 255.255.255.0 {

host switch1 {
 option dhcp-client-identifier "\000XXXXXXXXXX";
 fixed-address 192.168.255.1;
 option routers 192.168.255.254;
 option bootfile-name "/nxos/poap.py";
 option tftp-server-name "192.168.255.200";
 }

}

TFPT server:

I kept the default configuration, in the file /etc/default/atftpd

USE_INETD=true
 OPTIONS="--tftpd-timeout 300 --retry-timeout 5 --mcast-port 1758 --mcast-addr 239.239.239.0-255 --mcast-ttl 1 --maxthread 100 --verbose=5 /srv/tftp"

In the directory /srv/tftp, I downloaded the poap.py file on github. (https://github.com/datacenter/nexus9000/blob/master/nx-os/poap/poap.py)

This script is provided by Cisco. In this file, you need to customize one part. In the following part you enter the information for:

  • The target image
  • Directory for the image and configuration
  • Method to download the image and configuration here scp
  • The credential of the SCP Server
  • The name of the configuration file (here based on the serial number)
# system and kickstart images, configuration: location on server (src) and target (dst)
 n9k_image_version       = "7.0.3.I5.2" # this must match your code version
 image_dir_src           = "/srv/tftp/nxos"  # Sample - /Users/bob/poap
 ftp_image_dir_src_root  = image_dir_src
 tftp_image_dir_src_root = image_dir_src
 n9k_system_image_src    = "nxos.%s.bin" % n9k_image_version
 config_file_src         = "/srv/tftp/nxos/conf" # Sample - /Users/bob/poap/conf
 image_dir_dst           = "bootflash:" # directory where n9k image will be stored
 system_image_dst        = n9k_system_image_src
 config_file_dst         = "volatile:poap.cfg"
 md5sum_ext_src          = "md5"
 # Required space on /bootflash (for config and system images)
 required_space          = 800000

# copy protocol to download images and config
 # options are: scp/http/tftp/ftp/sftp
 protocol                = "scp" # protocol to use to download images/config

# Host name and user credentials
 username                = "root" # server account
 ftp_username            = "anonymous" # server account
 password                = "password" # password
 hostname                = "192.168.255.200" # ip address of ftp/scp/http/sftp server
 config_file_type        = "serial_number"

After you need to generate a md5 of the poap.py script. The following line will replace the second line with the MD5. If the MD5 is not valided the POAP process will fail and restart.

f=poap.py ; cat $f | sed '/^#md5sum/d' > $f.md5 ; sed -i "s/^#md5sum=.*/#md5sum=\"$(md5sum $f.md5 | sed 's/ .*//')\"/" $f
#!/bin/env python
#md5sum="3b614973cbde2742388b5997228678cd"
# Still needs to be implemented.
# Return Values:

You also need to generate an md5 for the image:

md5sum nxos.7.0.3.I5.2.bin > nxos.7.0.3.I5.2.bin.md5

Don’t forget your configuration file name “conf.XXXXXXX” where XXXX is the serial number and to configure the credential in this file.

 

 

Cisco EEM

Utiliser EEM recevoir une notification par mail quand une personne se connecte sur un équipement.

Nom de l’applet

 event manager applet EEM-ENABLE-CONNECTION

Déclenchement du EEM sur une commande passe contenant “en”. “sync no skip no” permet de continuer a effectuer l’action de l’utilisateur. Il est possible d’empecher de passer la commande également.

 event cli pattern "en.*" sync no skip no

Envoie un message dans le syslog

 action 1.0 syslog msg "NEW-ENABLE-CONNECTION

Regarde qui est connecté

 action 2.0 cli command "show users"

Envoie du mail

 action 3.0 mail server "<IP SERVER>" to "<Mail du destinataire>" 
 from "<Mail de l'expéditeur>" cc "<Autre Mail si besoin>" 
 subject "<Sujet du mail>" body "$_cli_result"