Friday, August 10, 2018

Ansible REST API - Interacting with Cisco FirePower Management Center (FMC) - 07 - Get policy content, modify content and "PUT' in FMC - Part 2

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 
In the previous post, we have successfully managed to pull the content of the "URL filter" policy rule. Now we will need modify this rule and there are three steps for doing it:

a. remove the "link" and "metadata" keys from the obtain rule in JSON format
b. change the "enabled" key value to "false"
c. initial a "PUT" call to apply the policy rule update to FMC

FMC REST API can only support "PUT" calls. "PATCH" is not supported. So we need to apply the whole JSON data for the policy rule even we just need to modify a single key value of it. If you are not familiar with difference between "PUT" and "PATCH", please refer to my POST "REST API 101".

The format of this "policy rule PUT" can be checked via the FMC API Explorer. From the API Explorer examples, we find that in the PUT call, we should remove the "link" and "metadata" key from the obtained JSON of policy rule. However, there is not a filter which can remove keys from a JSON directly. So we have to build a new dictionary and add the required keys in. 

Before writing any scripts, we need to understand know about the way to modify JSON data. JSON data is actually the Dictionary in Python. And in Ansible, we will use the "combine" filter to add or modify the key values of a dictionary. You can go to this link to get more details about the "combine filter". The "combine" filter is very smart. It will check the original dictionary to see if the "key" already exists. If not, it will add a new key and new value. If yes, then it will modify the existing key value with the new one.

- name: modify the put json

location: /etc/ansible/roles/FMC-enable-policyrule/tasks/main.yml

  - name: modify the put json
    set_fact:
      policy_rule_put: "{{policy_rule_put|default({}) | combine({item.key: item.value})}}"
    with_dict: "{{policy_rule_content}}"
    when: (item.key != "links") and (item.key != "metadata")


A couple of tasks are achieved in the above code:

  1. We set a new variable "poicy_rule_put" which is a dictionary. And make its initial value as empty.
  2. Then we call a "with_dict" loop to go through every key in the obtained policy rule ("policy_rule_content"). If the key name is not equal to "links" and "metadata", we will add the key and its value to the new dictionary "policy_rule_put".
After that, we should have the right format to make the "PUT" call. However, we have not modify the "enabled" key value yet. 

- name: modify the "enable"

location: /etc/ansible/roles/FMC-enable-policyrule/tasks/main.yml


  - name: modify the "enable"
    set_fact:
      policy_rule_put: "{{policy_rule_put | combine({'enabled': false})}}"
      config_has_been_changed: true
    when: policy_rule_put.enabled


In here, we use the "combine" filter again to update the "enabled" key with a new value "false" as the key "enabled" is already exist in the dictionary. 

You can also notice that I change the value of "config_has_been_changed" variable to "true" here. This "This "config_has_been_changed" was set to "false" in the var file (/etc/ansible/roles/FMC-enable-policyrule/vars/main.yml). The system will decide whether it should apply the config change to FMC based on this value.

- name: PUT_Access_Policy_roles

location: /etc/ansible/roles/FMC-enable-policyrule/tasks/main.yml


  - name: PUT_Access_Policy_roles
    uri:
      url: "https://{{FMC_IP}}/api/fmc_config/v1/domain/{{domain}}/policy/accesspolicies/{{policy_id}}/accessrules/{{policy_rule_put.id}}"
      method: PUT
      headers:
        "x-auth-access-token": "{{acc_token}}"
      validate_certs: no
      status_code: 200
      body_format: json
      body: "{{policy_rule_put}}"
    when: config_has_been_changed


This is the "PUT" call which modifies the "URL Filter" policy rule in FMC. Again, we put the "acc_token" in the "headers" field. And the "policy_rule_put" in the body field. The success return code is "200". And this task will only be executed when "config_has_been_changed" is "true".

Conclusion:

Now, we have successfully modified the FMC policy rule. But if you are familiar with Cisco FMC, you will know the actual firewall (SFR or FTD) configuration has not yet been updated at this stage. We will need to deploy the updated configuration to the edge devices. I am going to talk about how to deploy the config to the particular edge device with Ansible in the next POST which is also the last one in this series. 

Reference:

No comments:

Post a Comment

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...