Welcome to the “Quick Start Cisco ACI Scripting—Ansible” tutorial, a comprehensive guide tailored for network professionals seeking to streamline and automate Cisco Application Centric Infrastructure (ACI) using Ansible. In today’s rapidly evolving tech landscape, automation has become a cornerstone for efficient network management and provisioning. This tutorial aims to equip you with the essential skills and knowledge to leverage Ansible, a powerful automation tool, specifically customized for the Cisco ACI platform. We’ll embark on a journey to demystify the process of automating configurations, orchestrating tasks, and enhancing overall network agility, ultimately enabling you to elevate your network operations to a whole new level of efficiency and effectiveness.

What You’ll Learn

What You’ll Need

Software and Tools

Some Tips to Remember

Quick Ansible Installation on Ubuntu Linux

To install Ansible on a Linux system quickly, follow these steps:

  1. Update the package list:
    • Open a terminal.
    • Update the package list for the most up-to-date information about available packages:
sudo apt update
  1. Install software-properties-common:
    • Install the necessary packages:
sudo apt install software-properties-common
  1. Add the Ansible repository:
    • Add the Ansible repository using the following command:
sudo add-apt-repository --yes --update ppa:ansible/ansible
  1. Install Ansible:
    • Use the package manager to install Ansible.
      • On Debian/Ubuntu-based systems:
sudo apt install ansible
  1. Verify the installation:
    • Confirm that the installation was successful by checking the Ansible version:
ansible --version

Now you have Ansible installed on your Linux system and can start using it for automation tasks.

Quick Ansible Installation on macOS

To install Ansible on macOS quickly, follow these steps:

  1. Install Homebrew (if not already installed):
    • Homebrew is a package manager for macOS that makes it easy to install and manage software. If you don’t have Homebrew installed, open a terminal and run:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  1. Update Homebrew:
    • Make sure that Homebrew is up to date by running:
brew update
  1. Install Ansible:
    • Use Homebrew to install Ansible:
brew install ansible
  1. Verify the installation:
    • Confirm that the installation was successful by checking the Ansible version:
ansible --version

Now you have Ansible installed on your macOS system and can start using it for automation tasks.

Hats off to Thomas Renzy, the wizard behind the code curtain! We deeply appreciate your generosity in sharing your GitHub prowess. Thomas crafted this remarkable playbook for a Cisco Live presentation, and it serves as a solid foundation for all your automation needs. Within this repository, you’ll find playbook files that guide you on rapidly integrating automation into your Cisco ACI environment.

The playbook covers essential steps including:

Cloning the GitHub Repository

To clone the GitHub repository:

  1. Open your terminal:

    • Open your terminal on your local machine.
  2. Clone the repository:

    • Use the git clone command to clone the repository to your local machine:
git clone https://github.com/trenzy/BRKACI-1619.git
  1. Navigate to the cloned repository:
    • Change your directory to the cloned repository:
cd BRKACI-1619

Now you have successfully cloned the GitHub repository BRKACI-1619 to your local machine.

Creating a Cisco ACI Ansible YAML Inventory File

To manage Cisco ACI devices using Ansible, you can create a YAML inventory file that organizes devices and their connection details in a structured format. Follow these steps to create a YAML inventory file:

  1. Open a text editor:

    • Open your preferred text editor (for example, VS Code or Sublime Text) to create the YAML inventory file.
  2. Define hosts and connection details:

    • Define the ACI devices and their connection details in YAML format. Specify hosts, IP addresses or hostnames, and connection variables:
all:
  hosts:
    Fabric1:
      ansible_host: 10.0.103.50
      ansible_user: my_username
      ansible_password: my_password
  1. Save the inventory file:
    • Save the file with a .yml extension (for example, aci_inventory.yml). You could also use .yaml, but try to standardize on one format to prevent confusion.

Now you have a YAML-formatted Ansible inventory file for managing Cisco ACI devices. Customize the entries and configurations to match your specific setup and requirements.

  1. Generate the certificate and key:
    • Use the following openssl command to generate a self-signed certificate and a private key:
openssl req -new -newkey rsa:1024 -days 36500 -nodes -x509 -keyout ansible.key -out ansible.crt -subj '/CN=Admin/O=Your Company/C=US'
  1. Secure the certificate and key:
    • Ensure that only the appropriate users have access to the certificate and key:
chmod 400 admin.key admin.crt

YAML Writing Guidelines

YAML (YAML Ain’t Markup Language) is widely used for its simplicity and readability. Here are guidelines to write YAML for enhanced clarity and maintainability.

Indentation and Formatting

Key-Value Pairs

Comments

Arrays (Lists)

Objects (Dictionaries)

Strings

Boolean Values

Null Value

Anchors and Aliases

Multiline Strings

Be Consistent

Example:

key1: value1
key2: "value with spaces"
key3: 42
key4: true
key5: null

fruits:
  - apple
  - banana
  - orange

person:
  name: John Doe
  age: 30

description: |
  This is a multiline
  string with proper indentation.  

defaults: &defaults
  timeout: 30
  max_retries: 3

production:
  <<: *defaults
  timeout: 10

The file push-cert.yml represents an Ansible playbook, which is written in YAML format. An Ansible playbook serves as a declarative configuration file that describes the desired state of a system.

Playbook Tasks

This playbook consists of three main tasks:

  1. Task 1: Add a user

  2. Task 2: Add a certificate to user ansible

  3. Task 3: Add admin privileges for user ansible

Execution

Note that I have added use_ssl:true to this playbook so that the configuration is sent to https:// instead of http://. You could use http://, but you would need to enable it within the APIC configuration.

# Signature-based Cert Playbook
# Playbook creates a local user (Ansible) and associates a
# locally created cert with the account and also
# uses the ACI Rest module to set the domain privileges to all
#
---
# User certificate
- name: Push x509 cert and create user Ansible for signature based authentication
  hosts: Fabric1
  connection: local
  gather_facts: no

  tasks:
  - name: Add a user
    aci_aaa_user:
      hostname: "{{ inventory_hostname }}"
      username: "{{ username }}"
      password: "{{ password }}"
      aaa_user: ansible
      aaa_password: C1sc0123!
      expiration: never
      expires: no
      email: aleccham@cisco.com
      first_name: Alec
      last_name: Chamberlain
      validate_certs: no
      state: present
      use_ssl: true
  - name: Add a certificate to user ansible
    aci_aaa_user_certificate:
      use_proxy: no
      hostname: "{{ inventory_hostname }}"
      username: "{{ username }}"
      password: "{{ password }}"
      aaa_user: ansible
      certificate_name: ansible
      certificate_data: "{{ lookup('file', 'ansible.crt') }}"
      validate_certs: no
      state: present
      use_ssl: true

  - name: Add admin privileges to allow Ansible user to make changes
    aci_rest:
      hostname: "{{ inventory_hostname }}"
      username: "{{ username }}"
      password: "{{ password }}"
      use_ssl: true
      validate_certs: no
      path: /api/node/mo/uni/userext/user-ansible/userdomain-all.json
      method: post
      content:
        {"aaaUserDomain":
          {"attributes":{
            "name":"all",
            "rn":"userdomain-all",
            },
            "children":[
              {"aaaUserRole":
                {"attributes":{
                  "name":"admin","privType":"writePriv",
                  "rn":"role-admin",
                  },
                  "children":[]
                }
              }
              ]
          }
        }

To run this playbook, you would execute the ansible-playbook command followed by the filename push-cert.yml. Ansible will read the playbook, connect to the specified hosts, and execute the defined tasks.

ansible-playbook -i inventory.yml push-cert.yml -vvvv

This playbook automates the configuration of signature-based certificate authentication, enhancing security and simplifying user management within a Cisco ACI environment. Understanding and customizing this playbook allows for efficient and automated management of certificate-based authentication in Cisco ACI setups.

Explanation of Three-Tier Application Playbook

The YAML file represents an Ansible playbook designed to configure a new three-tier application in a Cisco ACI environment. Let’s break down its structure and tasks.

Playbook Structure

---
# The variables for the three tier playbook
   tenant: Ansible
   vrf: ansible-VRF
   bd:
     name: ansible-BD
     ip: 10.255.255.1
     mask: 24
   app_profile: ansible-AP
   http_filter: http_ans
   http_filter_entry: http_ans_entry
   web_to_app_contract: web_to_app
   web_to_app_contract_subject: web_to_app_subject
   db_filter: db_ans_entry
   db_filter_entry: db_ans_entry
   app_to_db_contract: app_to_db
   app_to_db_contract_subject: app_to_db_subject
   epg1: web
   epg2: app
   epg3: db
---
# Three Tier Application Playbook
- name: Configuring a new Three Tier Application
  hosts: apic1
  connection: local
  gather_facts: no

  vars_files:
    - /Users/threnzy/Ansible/2.9/BRKACI-1619/external_vars.yml

  tasks:
  - name: Create Ansible Tenant
    aci_tenant:
      hostname: "{{ inventory_hostname }}"
      username: ansible
      private_key: ansible.key
      tenant: "{{ tenant }}"
      description: "Tenant configured by Ansible"
      validate_certs: no
      state: present
      use_ssl: true

  - name: Create ansible-VRF
    aci_vrf:
      hostname: "{{ inventory_hostname }}"
      username: ansible
      private_key: ansible.key
      tenant: "{{ tenant }}"
      vrf: "{{ vrf }}"
      description: "VRF configured by Ansible"
      validate_certs: no
      state: present
      use_ssl: true

  - name: Creating ansible-BD
    aci_bd:
      hostname: "{{ inventory_hostname }}"
      username: ansible
      private_key: ansible.key
      tenant: "{{ tenant }}"
      vrf: "{{ vrf }}"
      bd: "{{ bd.name }}"
      enable_routing: yes
      arp_flooding: no
      l2_unknown_unicast: proxy
      description: "BD configured by Ansible"
      validate_certs: no
      state: present
      use_ssl: true

  - name: Creating ansible-BD Subnet
    aci_bd_subnet:
      hostname: "{{ inventory_hostname }}"
      username: ansible
      private_key: ansible.key
      tenant: "{{ tenant }}"
      bd: "{{ bd.name }}"
      gateway: "{{ bd.ip }}"
      mask: "{{ bd.mask }}"
      scope: "private"
      description: "BD subnet added by Ansible"
      validate_certs: no
      state: present
      use_ssl: true

  - name: Create ansible-AP
    aci_ap:
      hostname: "{{ inventory_hostname }}"
      username: ansible
      private_key: ansible.key
      tenant: "{{ tenant }}"
      ap: "{{ app_profile }}"
      description: "app profile configured by Ansible"
      validate_certs: no
      state: present
      use_ssl: true

  - name: Creating EPGs
    aci_epg:
      hostname: "{{ inventory_hostname }}"
      username: ansible
      private_key: ansible.key
      tenant: "{{ tenant }}"
      ap: "{{ app_profile }}"
      epg: "{{ item.epg }}"
      bd: "{{ bd.name }}"
      description: "EPG configured by Ansible"
      validate_certs: no
      state: present
      use_ssl: true

    loop:
      - epg: "{{ epg1 }}"
      - epg: "{{ epg2 }}"
      - epg: "{{ epg3 }}"

  - name: Creating Contracts
    aci_contract:
      hostname: "{{ inventory_hostname }}"
      username: ansible
      private_key: ansible.key
      #contract: "{{ web_to_app_contract }}"
      contract: "{{ item.contract }}"
      tenant: "{{ tenant }}"
      scope: "context"
      description: "Contract created by Ansible"
      validate_certs: no
      state: present
      use_ssl: true

    loop:
      - contract: "{{ web_to_app_contract }}"
      - contract: "{{ app_to_db_contract }}"

  - name: Add Filters
    aci_filter:
      hostname: "{{ inventory_hostname }}"
      username: ansible
      private_key: ansible.key
      #filter: "{{ http_filter }}"
      filter: "{{ item.filter }}"
      tenant: "{{ tenant }}"
      description: "Filter created by Ansible"
      validate_certs: no
      state: present
      use_ssl: true

    loop:
      - filter: "{{ http_filter }}"
      - filter: "{{ db_filter }}"

  - name: Add Port 80 and 1433 to Filter entries
    aci_filter_entry:
      hostname: "{{ inventory_hostname }}"
      username: ansible
      private_key: ansible.key
      entry: "{{ item.entry }}"
      tenant: "{{ tenant }}"
      ether_type: ip
      ip_protocol: tcp
      dst_port: "{{ item.dst_port }}"
      filter: "{{ item.filter }}"
      description: "Filter Entry created by Ansible"
      validate_certs: no
      state: present
      use_ssl: true

    loop:
      - entry: "{{ http_filter_entry }}"
        dst_port: 80
        filter: "{{ http_filter }}"
      - entry: "{{ db_filter_entry }}"
        dst_port: 1433
        filter: "{{ db_filter }}"

  - name: Bind subjects to contracts
    aci_contract_subject:
      hostname: "{{ inventory_hostname }}"
      username: ansible
      private_key: ansible.key
      tenant: "{{ tenant }}"
      contract: "{{ item.contract }}"
      subject: "{{ item.subject }}"
      reverse_filter: yes
      description: "Subject created by Ansible"
      validate_certs: no
      state: present
      use_ssl: true

    loop:
      - contract: "{{ web_to_app_contract }}"
        subject: "{{ web_to_app_contract_subject }}"
      - contract: "{{ app_to_db_contract }}"
        subject: "{{ app_to_db_contract_subject }}"

  - name: Bind Contract Subjects to filter
    aci_contract_subject_to_filter:
      hostname: "{{ inventory_hostname }}"
      username: ansible
      private_key: ansible.key
      tenant: "{{ tenant }}"
      contract: "{{ item.contract }}"
      #contract: "{{ web_to_app_contract }}"
      filter: "{{ item.filter }}"
      #filter: "{{ http_filter }}"
      #subject: "{{ web_to_app_contract_subject }}"
      subject: "{{ item.subject }}"
      validate_certs: no
      state: present
      use_ssl: true

    loop:
      - contract: "{{ web_to_app_contract }}"
        filter: "{{ http_filter }}"
        subject: "{{ web_to_app_contract_subject }}"
      - contract: "{{ app_to_db_contract }}"
        filter: "{{ db_filter }}"
        subject: "{{ app_to_db_contract_subject }}"

  - name: Bind EPGs to Contract
    aci_epg_to_contract:
      hostname: "{{ inventory_hostname }}"
      username: ansible
      private_key: ansible.key
      tenant: "{{ tenant }}"
      epg: "{{ item.epg }}"
      ap: "{{ app_profile }}"
      contract: "{{ item.contract }}"
      contract_type: "{{ item.type }}"
      validate_certs: no
      state: present
      use_ssl: true

    loop:
    - epg: "{{ epg1 }}"
      type: consumer
      contract: "{{ web_to_app_contract }}"
    - epg: "{{ epg2 }}"
      type: provider
      contract: "{{ web_to_app_contract }}"
    - epg: "{{ epg2 }}"
      type: consumer
      contract: "{{ app_to_db_contract }}"
    - epg: "{{ epg3 }}"
      type: provider
      contract: "{{ app_to_db_contract }}"

Playbook Tasks

The tasks include the following operations:

  1. Creating ACI tenant, VRF, bridge domain, bridge domain subnet, application profile, EPGs, contracts, filters, and subject bindings:

    • These tasks use Ansible ACI modules to create and configure components like tenants, virtual routing and forwarding (VRF) instances, bridge domains, subnets, application profiles, endpoint groups (EPGs), contracts, and filters, and bind subjects to filters and EPGs to contracts.
  2. Loops for multiple items:

    • Some tasks use loops to iterate over multiple items (for example, EPGs, contracts, and filters) and perform similar actions for each item.
  3. Using variables:

    • The playbook uses variables such as inventory_hostname, tenant, vrf, bd, epg1, epg2, epg3, and more to dynamically configure the components.

Execution

This playbook streamlines the process of configuring a three-tier application in a Cisco ACI environment, enhancing automation and management capabilities.

Explanation of Variable File for the Three-Tier Playbook

The variable file contains key-value pairs that serve as input variables for the Three Tier Application Ansible playbook. These variables help customize and configure components within the Cisco ACI environment.

Variables

  1. Tenant:

    • tenant: Ansible
    • Specifies the name of the tenant in the Cisco ACI environment
  2. VRF:

    • vrf: ansible-VRF
    • Specifies the name of the VRF instance
  3. Bridge domain:

    • Defines the bridge domain with additional details:
      • name: ansible-BD
      • ip: 10.255.255.1
      • mask: 24
    • Specifies the name, IP address, and subnet mask for the bridge domain
  4. Application profile:

    • app_profile: ansible-AP
    • Specifies the name of the application profile
  5. HTTP filter and filter entry:

    • http_filter: http_ans
    • http_filter_entry: http_ans_entry
    • Defines the names for the HTTP filter and filter entry
  6. Contracts and subjects:

    • web_to_app_contract: web_to_app
    • web_to_app_contract_subject: web_to_app_subject
    • app_to_db_contract: app_to_db
    • app_to_db_contract_subject: app_to_db_subject
    • Specifies the names for contracts and their associated subjects
  7. EPGs:

    • Defines the names for EPGs:
      • epg1: web
      • epg2: app
      • epg3: db
    • Specifies EPG names for different tiers of the application

Usage

These variables serve as a critical input to the Three Tier Application Ansible playbook, allowing for efficient and configurable automation in a Cisco ACI environment.

Looking at What Is Created

After running the playbooks, we can observe the configurations that have been pushed into the ACI fabric.

  1. Admin > AAA > Users:
    • Click a user and navigate to the right-hand pane to inspect the attached certificate.

Looking at the created User

Looking at the created Certificate

  1. Tenants > Ansible:

Looking at the created Tenant

  1. Tenants > Application Profiles > ansible-AP > Application EPGs > app > Policy > General:
    • Check if the newly created bridge domain is attached to this EPG. Also, review contracts to confirm the contract application.

Looking at the created EPG

Looking at the created EPG Contracts

  1. Networking > Bridge Domains > ansible-BD > Policy > General:
    • Check the configuration of the created bridge domain.

Looking at the created BD

  1. Networking > VRF > ansible-VRF:
    • Check the configuration of the created VRF.

Looking at the created VRF

Fantastic job! You’ve successfully initiated your journey into automating Cisco ACI using Ansible. This accomplishment sets the stage for streamlining and automating various aspects of Cisco ACI, bringing efficiency and agility to network operations. By carefully following this guide, you’ve gained insights into setting up Ansible, crafting playbooks, and executing tasks crucial for managing and provisioning network resources within the Cisco ACI environment.

Learn More