Tuesday, August 7, 2018

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

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 last post in this series, I introduced the way to obtain the Access Token. Now we are ready to do some "real work" with the FMC REST APIs. In this post, we will modify the value of the JSON key of a policy rule. There are a couple of key steps to achieve this task:


a. Locate the policy ID which named "FTD-1-Access-Policy-SYD".
b. Locate the policy rule ID name "Application Filter" under the above policy.
c. Modify the value of the "enable" key in the above policy rule.


Click to Expand
As we know, every operation in FMC API is based on the object ID which is a system generated string. We cannot make changes by reference the configured name directly. So in our Ansible playbook, we need to search for the ID for Policy Name "FTD-1-Access-Policy-SYD". In the following, I will describe each name task in details:

- name: Get_Access_Policy

The first task is to obtain the whole JSON file of the "Access Policies". 

The "url" for this operation can be find in the FMC API Explorer. If you are not familiar with it, please go back to my previous post Introduction of REST API and Cisco FMC API Explorer. The {{FMC_IP}} & {{domain}} are vars in "/etc/ansible/roles/FMC-enable-policyrule/vars/main.yml".

Also, in this task, we put the obtained "acc_token" in the headers field for authentication purpose. The return code for this "GET" call is "200".

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

  - name: Get_Access_Policy
    uri:
      url: "https://{{FMC_IP}}/api/fmc_config/v1/domain/{{domain}}/policy/accesspolicies"
      method: GET
      headers:
        "x-auth-access-token": "{{acc_token}}"
        Connection: keep-alive
      validate_certs: no
      status_code: 200
      body_format: json
    register: accesspolicies


After having the whole JSON file, we need to check what's the structure of this file. Under the "json", there is a "items" array. And the "accessPolicy" details including the "id" are in this array. 

    "device_list": {
        "accept_ranges": "bytes",
        "cache_control": "no-cache, no-store, must-revalidate, max-age=0",
        "changed": false,
        "connection": "close",
        "content_type": "application/json",
        "cookies": {},
        "date": "Sun, 24 Jun 2018 00:54:34 GMT",
        "failed": false,
        "json": {
            "items": [
                {
                    "accessPolicy": {
                        "id": "000c2911-ed30-0ed3-0000-008589936316",
                        "name": "FTD-1-Access-Policy-SYD",
                        "type": "AccessPolicy"

                    },
        ...

 - name: get policy_json

In this step, we will pull the "json" key value which includes the "items" array:


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

  - name: get policy_json
    set_fact:
      policy_json: "{{accesspolicies.json}}"


- name: get policy array

Here we build a new array variable to hold the "items" array:


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

  - name: get policy array
    set_fact:
      policy_array: "{{policy_json | json_query('items[]')}}"


In the above task, we use the "json_query" method. If you want to know more about this method, please refer to the detailed description of "json_query" in Ansible documentation.

 - name: get policy_id

In the above step, we got the access policy array. In this array, we may have multiple access policy items. The following shows the data structure of this array:
Click to Expand
So we need to search the ID which belongs to the policy named "FTD-1-Access-Policy-SYD". I achieve this searching operation by using the Jinja2 template.


location: /etc/ansible/roles/FMC-enable-policyrule/tasks/get_policy_id.j2

{%- for item in policy_array -%}
  {%- if item.name == policy_name -%}
    {{ item.id }}
  {%- endif -%}
{%- endfor -%}


This jinja2 code is very straight forward. Basically it use a "for loop" to go through all the items in this array. If the "item.name" is equal to the "policy_name" variable defined in the VAR file ("/etc/ansible/roles/FMC-enable-policyrule/vars/main.yml"), it will return all the "item.id" value. 

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

  - name: get policy_id
    set_fact:
      policy_id: "{{lookup('template','/etc/ansible/roles/FMC-disable-policyrule/tasks/get_policy_id.j2') | trim}}"  #"trim" will remove the "\n" retrun from the j2 file


Here we use the Ansible "lookup template" to call the Jinja2 file. The "trim" keyword is used to get rid of the "\n" returned from Jinja2's return. 

The method mentioned above is very useful for fetching the useful information from the JSON configuration file of a network device. For example, a network device has multiple interfaces. Each interface has it's own configuration such as IP address, duplex/speed etc.  All the network interface configurations will be put in the same array. By using the jinja2 template, we can go through all the config items in this array and get the interface config based on the particular interface name or description.

 - name: Get_Access_Policy_rules

Now we have the policy ID for "FTD-1-Access-Policy-SYD". We can pull the policy rules in this policy and find out the specific rule we want to modify.


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

  - name: Get_Access_Policy_rules
    uri:
      url: "https://{{FMC_IP}}/api/fmc_config/v1/domain/{{domain}}/policy/accesspolicies/{{policy_id}}/accessrules?expanded=true"
      method: GET
      headers:
        "x-auth-access-token": "{{acc_token}}"
      validate_certs: no
      status_code: 200
      body_format: json
    register: accesspolicierules


I won't talk much about this as it's very similar to "- name: Get_Access_Policy" above.

  - name: get policy_rule_json

Similar to  "- name: get policy_json"

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

  - name: get policy_rule_json
    set_fact:
      policy__rule_json: "{{accesspolicierules.json}}"


- name: get policy rule array

Similar to "- name: get policy array"


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

  - name: get policy rule array
    set_fact:
      policy_rule_array: "{{policy__rule_json | json_query('items[]')}}"


 - name: get policy_rule_content

Similar to " - name: get policy_id". However, in the Jinja2 file, we return the whole content of the item instead of only the "id".


location: /etc/ansible/roles/FMC-enable-policyrule/tasks/get_policy_rule_id.j2

{%- for item in policy_rule_array -%}
  {%- if item.name == policy_rule_name -%}
    {{ item }}
  {%- endif -%}
{%- endfor -%}


The "policy_rule_name" we are going to search is "URL Filter"


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

  - name: get policy_rule_content
    set_fact:
      policy_rule_content: "{{lookup('template','/etc/ansible/roles/FMC-disable-policyrule/tasks/get_policy_rule_id.j2')}}"  #"trim" will remove the "\n" retrun from the j2 file


The return will be something like this:

    "policy_rule_content": {
        "action": "BLOCK_RESET",
        "enabled": true,
        "id": "000C2911-ED30-0ed3-0000-000268436480",
 ...
        },
        "name": "URL Filter",
        "sendEventsToFMC": true,
...

The "enabled": true above is the key value we want to modify. 

We have the "URL Filter" policy rule content now. In next step, I will modify this policy content to be the right format for a "PUT" call to modify the policy rule and this will be described in "Get policy content, modify content and "PUT' in FMC - Part 2".






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