- Introduction and Ansible playbook download
- Script flow charts
- Introduction of REST API and Cisco FMC API Explorer
- Script prerequisites
- Request Access Token
- Get policy content, modify content and "PUT' in FMC - Part 1
- Get policy content, modify content and "PUT' in FMC - Part 2
- Get deployable devices and deploy policy
In the previous post, we have successfully upload the modified policy rule to FMC. Now we need to deploy the new policy to the edge device(s). The following are the steps:
a. get the array of the devices which do not have updated configuration (deployable devices)
b. obtain the "version" of the configuartion
c. obtain the "Device ID" of the deployable devices
d. lookup the deployment JSON template and modify its "version" and "device ID" keys
e. make a "POST" call to FMC to deploy the update configuration to the edge device(s)
First, we make a "GET" call to fetch the deployable device information from FMC.
- name: Get_Deployment_Device_Info
The return of this "GET" call is information about the devices which have not applied the updated configuration. The same as other "GET" returns, it contains a "items" array in a key which named "json".
Please be noted that all of the following tasks will only be executed when the "config_has_been_changed" is equal to "true".
location: /etc/ansible/roles/FMC-enable-policyrule/tasks/main.ymla. get the array of the devices which do not have updated configuration (deployable devices)
b. obtain the "version" of the configuartion
c. obtain the "Device ID" of the deployable devices
d. lookup the deployment JSON template and modify its "version" and "device ID" keys
e. make a "POST" call to FMC to deploy the update configuration to the edge device(s)
First, we make a "GET" call to fetch the deployable device information from FMC.
- name: Get_Deployment_Device_Info
The return of this "GET" call is information about the devices which have not applied the updated configuration. The same as other "GET" returns, it contains a "items" array in a key which named "json".
Please be noted that all of the following tasks will only be executed when the "config_has_been_changed" is equal to "true".
- name: Get_Deployment_Device_Info
uri:
url: "https://{{FMC_IP}}/api/fmc_config/v1/domain/{{domain}}/deployment/deployabledevices?expanded=true"
method: GET
headers:
"x-auth-access-token": "{{acc_token}}"
Connection: keep-alive
validate_certs: no
status_code: 200
body_format: json
register: DeployableDevice
when: config_has_been_changed
|
- name: get device array
WE need to abstract the "items" array from the "DeployableDevice.json" key value:
location: /etc/ansible/roles/FMC-enable-policyrule/tasks/main.yml
- name: get device array
set_fact: device_array: "{{DeployableDevice.json | json_query('items[]')}}" when: config_has_been_changed |
We utilise the "json_query" here to achieve this task.
- name: get version number
In the "items" array, we will find one more multiple items. Each item contains the information for a deployable device. What we need here is the "version" key value and the "device ID" key value.
The "version" number of all the deployable devices are the same in FMC. Every time, even you just make a single change on a single device policy, the version for all the deployable devices will be updated. And this "version" number is calculated by timestamp.
Therefore, we just need to pull the "version" number from the 1st item in this array for our task.
location: /etc/ansible/roles/FMC-enable-policyrule/tasks/main.yml
- name: get version number
set_fact: deployment_version: "{{device_array[0].version}}" when: config_has_been_changed |
- name: get the deployment device list
Here, we will create a new array which contains the deployable device ID(s).Here, we are getting all the deployable device IDs. Not only the one we just modified in the previous post.
First, we create a new empty array call "deployment_device_list". Then we add every "item.device.id" to this array as new item.
Here we also add "no_log" to this task. As the output log for this task is too much. I just don't want this log to be shown in the terminal.
location: /etc/ansible/roles/FMC-enable-policyrule/tasks/main.yml
- name: get the deployment device list # here we get all the deployable devices, NOT the policy we just changed
set_fact: deployment_device_list: "{{deployment_device_list | default([])}} + ['{{item.device.id}}']" with_items: "{{device_array}}" no_log: true # don't display output for this session, since too much! when: config_has_been_changed |
- name: get JSON POST file
In order to make the "POST" call, we need the "POST" call template. We can make this template based on the example provided by FMC API explorer. The template is shown as below:
location: /etc/ansible/roles/FMC-disable-policyrule/tasks/deployment_POST.json
{
"type": "DeploymentRequest", "version": "", "forceDeploy": true, "ignoreWarning": true, "deviceList": [] } |
As we can see, this "POST" template is very simple. Its "type" is "DeploymentRequest". Its "version" has a empty string. And the "deviceList" has a empty array.
The following is the way to use "lookup" method to pull the JSON file template.
location: /etc/ansible/roles/FMC-enable-policyrule/tasks/main.yml
- name: get JSON POST file
set_fact: deployment_POST: "{{lookup('file','/etc/ansible/roles/FMC-disable-policyrule/tasks/deployment_POST.json')}}" when: config_has_been_changed |
- name: modify the version
Since the template has a empty string as "version" value, we will need to update it with our obtained "version".
location: /etc/ansible/roles/FMC-enable-policyrule/tasks/main.yml
- name: modify the version
set_fact: deployment_POST: "{{deployment_POST | combine({'version': deployment_version})}}" when: config_has_been_changed |
As mentioned in the previous post, if the key exists in the JSON, "combine" filter will only update the key value. So in this case, the "version" key will be updated with our new version number.
- name: modify the deployment device list
The same, we update the "deviceList" array with our deployable device ID array:
location: /etc/ansible/roles/FMC-enable-policyrule/tasks/main.yml
- name: modify the deployment device list
set_fact: deployment_POST: "{{deployment_POST | combine({'deviceList': deployment_device_list})}}" when: config_has_been_changed |
- name: Deployment POST
Finally, we have our "POST" JSON ready. Then we need to make a "POST" call to the FMC and raise a device deployment request:
location: /etc/ansible/roles/FMC-enable-policyrule/tasks/main.yml
- name: Deployment POST
uri: url: "https://{{FMC_IP}}/api/fmc_config/v1/domain/{{domain}}/deployment/deploymentrequests" method: POST headers: "x-auth-access-token": "{{acc_token}}" validate_certs: no status_code: 202 body_format: json body: "{{deployment_POST}}" when: config_has_been_changed |
Just pay attention to the "status_code". For this "POST" call, the return code is "202".
After making this "POST" call, our changes will be deployed to the edge firewalls. And our goal has been achieved.
Conclusion:
The purpose of writing this post series is not only to demonstrate the way how to work with Cisco FMC with Ansible. The most important thing is that we can learn about how to use ansible modules, filters and jinja2 templates to add or modify key/values in JSON and make different API calls. These are the basic skills for REST API interaction.
As more and more network devices have REST API support, if we fully master the way to interact with REST API, network automation will become a common task in our daily work.
Reference:
No comments:
Post a Comment