Saturday, June 30, 2018

Ansible REST API - Interacting with Cisco FirePower Management Center (FMC) - 02 - Flow Charts of the scripts

This post belongs to my "Ansible REST API - Interacting with Cisco FMC" series. The following is the table of content of this series: 

  1. Introduction and Ansible playbook download
  2. Script flow charts
  3. Introduction of REST API and Cisco FMC API Explorer
  4. Script prerequisites
  5. Request Access Token 
  6. Get policy content, modify content and "PUT' in FMC - Part 1
  7. Get policy content, modify content and "PUT' in FMC - Part 2 
  8. Get deployable devices and deploy policy
First, let me show you how the work flows look like with the scripts:

Here is the flow chart which shows how to disable the specified policy rule:

click the image to expand
And the following is the flow chart which shows how to enable the specified policy rule. You can see they are pretty much the same as the above script:
click the image to expand
In the next post, I will talk about the "REST API basic and the Cisco FMC API Explorer". 

Sunday, June 17, 2018

LInux 101 - Enable SSH key based authentication

SSH Key based authentication allows a user to login to the remote Linux server without providing the username/password. Key based authentication works with a pair of public/private keys. The public key of the client is stored in ~/.ssh/authorized_keys on the server. The private key is kept in the client machine.

The following are the steps of authentication process:

a. User starts the SSH process by specifying key pair to be used. Then the client machine sends the SSH connection request to the server with the Key ID.

b. The server checks its ~/.ssh/authorized_keys and try to find the public key with the Key ID. Once the Key is found, the server will generate a random number and encrypts this number with the found public key.

c. The client machine decrypts the message sent by the server with its private key and obtain the random number.

d. The client machine will calculate a MD5 hash value with the "obtained random number + the session key" and send this MD5 value back to server.

(Noted: this "obtained random number + the session key" value will also be used to encrypt the communication messages between client and server later on.)

e. The server will calculate the MD5 value of "obtained random number + the session key" and compare it with the one received from the client. If they are matching, the SSH request is granted.

The follow will describe the steps of configuring the SSH key based authentication:

Step 1: Create SSH keys on the client machine


#mkdir -p $HOME/.ssh
#chmod 0700 $HOME/.ssh
#cd ~/.ssh

# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
b3:7b:be:1a:7f:66:c9:01:ea:28:f4:36:09:ec:6e:3e root@localhost.localdomain
The key's randomart image is:
+--[ RSA 2048]----+
|                 |
|                 |
|                 |
|          .      |
|   .    S. .     |
|    +   .o  .    |
|   o o +o  . o   |
|    E * .+. *    |
|   +o+ .o++=     |
+-----------------+



After this step, we will have the private key and public key:

$HOME/.ssh/id_rsa– private key.

$HOME/.ssh/id_rsa.pub – public key.

Step 2: Copy the public key to your remote SSH server


[root@localhost ~]# ssh-copy-id root@192.168.1.216
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.1.216's password: (here is the remote SSH server login password)

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@192.168.1.216'"
and check to make sure that only the key(s) you wanted were added.


Step 3: Initial the SSH session from the client machine by specifying the key to be used


specifc the prviate key (~/.ssh/id_rsa) to be used:

ssh -i ~/.ssh/id_rsa root@192.168.1.216 


SSH key based authentication is widely used. In my previous post "
Network Automation 02 - Ansible Play book for FTP server file synchronisation
", we use key based authentication for the "rsync".




Linux 101 - Setup FTP/SFTP server in Centos


1. Install vsftpd and enable the service, open the firewall port    


# yum install vsftpd

# systemctl start vsftpd
# systemctl enable vsftpd


# firewall-cmd --zone=public --permanent --add-port=21/tcp
# firewall-cmd --zone=public --permanent --add-service=ftp
# firewall-cmd --reload


2. Configure the FTP server:


# cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.orig

vi vsftpd.conf

anonymous_enable=NO            
userlist_enable=YES
userlist_deny=NO                     
userlist_file=/etc/vsftpd.userlist   

chroot_local_user=YES
allow_writeable_chroot=YES
local_root=/etc/ansible/backup
# the above folder needs to be existed
or:
local_root=/var/ftp/ansible/backup


3. Fix the SELinux for vsftpd


# setsebool -P allow_ftpd_full_access 1


4. Create user for FTP access


# useradd -m -c “dennis” -s /bin/bash dennis
# passwd dennis

Changing password for user dennis.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.


# echo "dennis" | tee -a /etc/vsftpd.userlist
# cat /etc/vsftpd.userlist

5. Create Secure FTP



# mkdir /etc/ssl/private


# openssl req -x509 -nodes -keyout /etc/ssl/private/vsftpd.pem -out /etc/ssl/private/vsftpd.pem -days 365 -newkey rsa:2048

Country Name (2 letter code) [XX]:IN
State or Province Name (full name) []:Lower Parel
Locality Name (eg, city) [Default City]:Mumbai
Organization Name (eg, company) [Default Company Ltd]:TecMint.com
Organizational Unit Name (eg, section) []:Linux and Open Source
Common Name (eg, your name or your server's hostname) []:tecmint
Email Address []:admin@tecmint.com



# firewall-cmd --zone=public --permanent --add-port=990/tcp
# firewall-cmd --zone=public --permanent --add-port=40000-50000/tcp
# firewall-cmd --reload



# vi /etc/vsftpd/vsftpd.conf


ssl_enable=YES
ssl_tlsv1_2=YES
ssl_sslv2=NO
ssl_sslv3=NO

rsa_cert_file=/etc/ssl/private/vsftpd.pem
rsa_private_key_file=/etc/ssl/private/vsftpd.pem

allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES


require_ssl_reuse=NO

ssl_ciphers=HIGH

pasv_min_port=40000
pasv_max_port=50000

debug_ssl=YES




# systemctl restart vsftpd


Saturday, June 16, 2018

Network Automation 02 - Ansible Play book for FTP server file synchronisation

In the last post, I introduced a Ansible playbook which can collect the updated router/ switch configuration files at regular intervals. However, saving the configuration files in the Ansible server is not a particular way to store those files. Because, in this way, you will have to allow the other users to login into this Ansible server and fetch the required configuration files. This may cause performance and security issues of this Ansible server. So, in our design, we build a central FTP/Web server. And the remote Ansible Servers collect the configuration files and synchronise those files with the central server.

The topology is shown as the follow diagram:

 Prerequisite:

There are a couple of prerequisite steps we need to completed before writing our Ansible Run book.

1. Install rsync on the every server including the remote Ansible Servers and the Central Server.


yum install rsync


2. Generate the Vault File

If the Vault file has been build in the previous config collection post, then ignore this step.


3. Install the FTP server in the central server

Please check my post to describe about how to setup FTP/SFTP server.


Step 1: Configure the host file

/etc/ansible/hosts

[ftp]
192.168.1.216


Step 2: Configure the host var login file

/etc/ansible/group_vars/

ansible-vault create ftp

---
  ansible_ssh_pass: 123456
  ansible_ssh_user: root


Step 3: Create the Site YML file

/etc/ansible/ftp.yml

---
  - hosts: ftp
    gather_facts: no
    become: no
    roles:
      - ftp-sync


Step 4: Initial the Ansible role "ftp-sync"


cd/etc/ansible/roles/

ansible-galaxy init ftp-sync


Step 5: Configure the tasks in "ftp-sync" role

This task will login to the central FTP server and synchronise the files from the local folder "/etc/ansible/backup" to the central server.


cd /etc/ansible/roles/ftp-sync/tasks/
vi main.yml

---
  - name: syn files
    synchronize:
      src: /etc/ansible/backup
      dest: /var/ftp/ansible/backup set_remote_user=no


Step 6: Enable SSH key based authentication on the Ansible server to bypass the password prompt in "rsync"

Ansible will utilize "rsync" to synchronise the files between the source and destination folders.

Although Ansible has the username/password to login to the Central server, the "rsync" doesn't have those details. So in order to avoid the "password prompt" pop up, we can enable SSH key based authentication for the Ansible Server on the Central server.

Please check my other post which describe how to enable SSH key based authentication for Linux.

Step 7: Setup CRON



# crontab /etc/crontab

# vi /etc/crontab

*/5 * * * * ansible-playbook /etc/ansible/ftp.yml
# every 5 minutes



Conclusion

This Ansible playbook achieve our gold to synchronise the configuration files collected by the remote Ansible server to the central storage server. The the users can fetch the configuration files from the central server via FTP, SFTP or HTTP.

Wednesday, June 13, 2018

Network Automation 01 - Ansible Play book for Cisco configuration backup

In this blog, I would like to introduce one of my Ansible playbooks. The function of this playbook is to collect the updated Cisco IOS device configurations in a defined interval. Only the updated configuration file will be kept.
Prerequisite:


1. Create a vault password file


echo "myvault" > ~/.vault_pass.txt
chomd 0600 ~/.vault_pass.txt


So this "vault_pass.txt" file has the "0600" privilege for the current user. And the "myvault" is the encryption key to encrypt other device login details which we will use later on.

2. Put the file path in the “ansible.cfg”




[defaults]
vault_password_file = ~/vault_pass.txt

Step 1: Configure the hosts file:


[customerArouter]
A-RTR01 ansible_host=192.168.199.249 ansible_hostname=A-RTR01

[customerAswitch]
A-SWT01 ansible_host=192.168.199.245 ansible_hostname=A-SWT01

[customerA:children]
customerArouter
customerAswitch

[customerBswitch]
B-SWT01 ansible_host=192.168.199.246 ansible_hostname=B-SWT01
B-SWT02 ansible_host=192.168.199.247 ansible_hostname=B-SWT02
B-SWT03 ansible_host=192.168.199.248 ansible_hostname=B-SWT03

[customerB:children]
customerBswitch

Step 2: Create the login detail file which encryption


cd /etc/ansible/group_vars/all/
ansible-vault create vault

******* the following is the content of the vault file *******

---
  customerA_ssh_username: cisco
  customerA_ssh_pass: ciscoA
  customerA_enable_pass: ciscoA

  customerB_ssh_username: cisco
  customerB_ssh_pass: cisco
  customerB_enable_pass: cisco

Step 3: Create the Group Var files

Ansible will try to find the Group Vars for the groups in the Inventory file under the “/group_vars” folder. In this example, we have “customerA” & “customerB” groups in the hosts file. So we can setup two vars files with the same name under the “/etc/ansible/group_vars/”.


cd /etc/ansible/group_vars/
vi customerA

---
  provider:
    host: "{{ ansible_host }}"
    username: "{{ customerA_ssh_username }}"
    password: "{{ customerA_ssh_pass }}"
    auth_pass: "{{ customerA_enable_pass }}"
    transport: cli




cd /etc/ansible/group_vars/
vi customerB

---
  provider:
    host: "{{ ansible_host }}"
    username: "{{ customerB_ssh_username }}"
    password: "{{ customerB_ssh_pass }}"
    auth_pass: "{{ customerB_enable_pass }}"
    transport: cli


Step 4: Create a site yml file
You can execute the role by:

ansible-playbook sc.yml


cd/etc/ansible/
vi sc.yml

---
  - hosts: customerA
    gather_facts: no
    connection: local
    roles:
      - saveconfig

  - hosts: customerB
    gather_facts: no
    connection: local
    roles:
      - saveconfig

Step 5: Initial the Ansible Role


cd/etc/ansible/roles/
ansible-galaxy init saveconfig

Step 6: Setup the default variable in the "saveconfig" role

The default variable we would like to setup is the backup folder on the local server.


cd/etc/ansible/roles/saveconfig/default/
vi main.yml

---
  backupdir: /etc/ansible/backup

Step 7: Tasks in the roles (save configuration on the local Ansible server)


cd/etc/ansible/roles/saveconfig/tasks/
vi main.yml

---
# tasks file for saveconfig

# get the time for the current save file
  - name: get time
    local_action: command date +%Y%m%d%H%M%S
    register: time

# get the current running config form the destination device
  - name: run 'show run'
    ios_command:
      provider: "{{provider}}"
      authorize: yes
      commands:
        - show run
    register: config

# if there is not an existing folder for the destination device, create one
  - name: ensure the directory exists
    file:
      path: "{{backupdir}}/{{inventory_hostname}}"
      recurse: yes
      state: directory

# get the file list from the destination device folder
  - name: Get files in a folder
    find:
      paths: "{{backupdir}}/{{inventory_hostname}}"
    register: found_files

# get the latest file attributes if the folder is not empty
  - name: get the latest old file
    set_fact:
      latest_file: "{{ found_files.files | sort(attribute='mtime',reverse=true) | first }}"
    when: found_files.matched != 0

# get the stat of the latest old config
  - name: get the stat of the old config
    stat:
      path: "{{latest_file.path}}"
    register: oldconfig_stat
    when: found_files.matched != 0

# save the new config file to folder
  - name: save output to {{backupdir}}
    copy:
      content: "{{config.stdout[0]}}"
      dest: "{{backupdir}}/{{inventory_hostname}}/config_{{inventory_hostname}}_{{time.stdout}}.txt"

# get the stat of the new config
  - name: get the stat of the new config
    stat:
      path: "{{backupdir}}/{{inventory_hostname}}/config_{{inventory_hostname}}_{{time.stdout}}.txt"
    register: newconfig_stat
    when: found_files.matched != 0

# if the new config is the same as the latest old config, delete the new config file, delete the new file if it's the same
  - name: compare the new config and the latest old config
    file:
      state: absent
      path: "{{backupdir}}/{{inventory_hostname}}/config_{{inventory_hostname}}_{{time.stdout}}.txt"
    when:
      - found_files.matched != 0
      - newconfig_stat.stat.checksum == oldconfig_stat.stat.checksum

# if the new config is different than the latest old config, do nothing

Step 8: Setup the CRON


crontab /etc/crontab

 vi /etc/crontab


*/15 * * * * ansible-playbook /etc/ansible/sc.yml
# every 15 minutes


Conclusion

In this playbook, we achieve the gold to save the updated configuration in every 15 mins. But this playbook is not perfect as users have to login to the local Ansible server to get the configuration files. In the next post, I will introduce another play book to synchronise the configuration files to the central file server. So users only have to access the central file server.

NSX Load Balancer "Application Rules" Examples:

Load Balancing is one of the features provided by the NSX Edge Services Gateway (ESG). It can provide L7 Load Balancing by utilizing the HA...