To install Ansible on a Linux system quickly, follow these steps:
sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible
ansible --version
Now you have Ansible installed on your Linux system and can start using it for automation tasks.
To install Ansible on macOS quickly, follow these steps:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew update
brew install ansible
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:
To clone the GitHub repository:
Open your terminal:
Clone the repository:
git clone
command to clone the repository to your local machine:git clone https://github.com/trenzy/BRKACI-1619.git
cd BRKACI-1619
Now you have successfully cloned the GitHub repository BRKACI-1619 to your local machine.
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:
Open a text editor:
Define hosts and connection details:
all:
hosts:
Fabric1:
ansible_host: 10.0.103.50
ansible_user: my_username
ansible_password: my_password
.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.
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'
-new
: Generate a new certificate request.-newkey rsa:1024
: Generate a new Rivest, Shamir, and Adleman (RSA) key of 1024 bits.-days 36500
: Set the certificate to be valid for 36500 days (approximately 100 years).-nodes
: Do not encrypt the private key.-x509
: Output a self-signed certificate.-keyout admin.key
: Save the private key to a file named admin.key
.-out admin.crt
: Save the certificate to a file named admin.crt
.-subj '/CN=Admin/O=Your Company/C=US'
: Specify the subject information for the certificate. In this case, it sets the Common Name (CN) to Admin, Organization (O) to Your Company, and Country (C) to US.chmod 400 admin.key admin.crt
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.
key: value
to define key-value pairs.#
for single-line comments.-
(hyphen), followed by a space, followed by the value.[]
(square brackets) for inline arrays.true
or false
(lowercase).null
(lowercase).&
to create an anchor and *
to create an alias to the anchor.|
(pipe symbol) to preserve line breaks and indentation. For folded style, use >
.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.
This playbook consists of three main tasks:
Task 1: Add a user
aci_aaa_user
Ansible module to create a user named ansible in the Cisco ACI environment. Parameters such as username
, password
, email
, and other user attributes are provided.Task 2: Add a certificate to user ansible
aci_aaa_user_certificate
Ansible module to associate a certificate with the ansible user. The certificate’s name and data are provided, and the certificate file is read using Ansible’s lookup
function.Task 3: Add admin privileges for user ansible
aci_rest
Ansible module sends a Representational State Transfer (REST) application programming interface (API) request to the ACI controller. The request sets the ansible user’s domain privileges to admin, granting them the authority to make configuration changes.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.
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.
Play name and configuration:
Fabric1
group in the inventory file.Variable files:
vars_files
to include additional variables.---
# 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
use_ssl: true
, so that Ansible will use https://
to push the configuration. If you do not add that, then you would need to allow http://
in the APIC configuration.---
# 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 }}"
The tasks include the following operations:
Creating ACI tenant, VRF, bridge domain, bridge domain subnet, application profile, EPGs, contracts, filters, and subject bindings:
Loops for multiple items:
Using variables:
inventory_hostname
, tenant
, vrf
, bd
, epg1
, epg2
, epg3
, and more to dynamically configure the components.To run this playbook, execute the ansible-playbook
command followed by the filename of this YAML file (for example, three-tier.yml
).
Ensure that Ansible is properly installed, configured, and has access to the necessary ACI devices and credentials.
This playbook streamlines the process of configuring a three-tier application in a Cisco ACI environment, enhancing automation and management capabilities.
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.
Tenant:
tenant: Ansible
VRF:
vrf: ansible-VRF
Bridge domain:
name: ansible-BD
ip: 10.255.255.1
mask: 24
Application profile:
app_profile: ansible-AP
HTTP filter and filter entry:
http_filter: http_ans
http_filter_entry: http_ans_entry
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
EPGs:
epg1: web
epg2: app
epg3: db
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.
After running the playbooks, we can observe the configurations that have been pushed into the ACI fabric.
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.