Getting Started

This Ansible collection automates configuration management and execution of operational tasks on Cisco Secure Firewall Threat Defence (FTD) being managed by Firewall Management Center (FMC) using Ansible.

fmc_configuration module – This module will be used to configure and manage FTD devices that are being managed by an FMC. FMC REST API will be used to communicate with the device by sending HTTPS calls formatted according to the REST API specification.

This module allows the execution of all operations available in REST API in the form of Ansible tasks. Each REST API endpoint can be wrapped into an Ansible play and be a part of a playbook.

A detailed list of supported API calls can be found on the API-Explorer page of the FMC.

Steps to access the API-Explorer page on the FMC:

  1. Open https://<FMC_IP_ADDRESS>/api/api-explorer

  2. Enter the credentials on prompt

  API-Explorer Prompt

  1. Access the page

  API-Explorer

Installing the collection

You can install the Cisco FMCAnsible collection with the Ansible Galaxy CLI:

ansible-galaxy collection install cisco.fmcansible

Creating Inventory

Ansible inventory contains information about systems where the playbooks should be run. You should create an inventory file with information about the FMC that will be used for configuration.

The default location for inventory is /etc/ansible/hosts, but you can specify a different path by adding the -i <path> argument to the ansible-playbook command.

The inventory file requires:

  • Hostname or IP Address of the FMC

  • Username for FMC

  • Password for the given user

[all:vars]
ansible_network_os=cisco.fmcansible.fmc

[vfmc]
192.168.1.1 ansible_user=user ansible_password=password ansible_httpapi_port=443 ansible_httpapi_use_ssl=True ansible_httpapi_validate_certs=False

[vfmc:vars]
network_type=HOST

Task Operations

Most operations are similar to CRUD functions and can be divided into the following groups:

Get - fetches an object by its ID

getAll - fetches a list of objects matching given criteria

create - creates a new object

createMultiple - creates multiple new objects

update - updates an existing object

delete - deletes an existing object by its ID

upsert - creates a new object if it does not exist, or updates it when the object already exists


Task Parameters

Parameter Required Type Description
operation True string The name of the operation to execute. Commonly, the operation starts with 'create', 'update', 'get', 'upsert' or 'delete' verbs, but can have an arbitrary name too.
data False dict Corresponds to the body part in HTTP request and is mandatory for create, update and upsert operations.
query_params False dict Corresponds to the query string in HTTP request
path_params False dict Corresponds to URL parameters in HTTP request
register_as False string A name for the fact that is registered with the response from the server.
filters False dict A map with filter criteria for upsert and getAll operations.

Return Value

Value Returned Type Description
response Success dict HTTP response returned from the API call.

Server Response

The module registers server response as ansible_facts to be used in the playbook as regular variables.

By default, fact names are constructed as {OBJECT_TYPE} _{LOWERCASE_OBJECT_NAME}

If you want to change the default naming convention, add a register_as parameter with the desired fact name to the play.

For a network object created by the Ansible module named test_network, the ansible_facts name will be Network_test_network


Upsert Operation

Upsert is an idempotent "Insert or Update" operation. It allows defining the desired state of the record instead of checking whether the record exists (and should be updated) or not (and should be created).

Upsert operation uses filters to look for a record on the device and define if the object already exists or not. Default filtering is done by name, and the object has a name as in the data parameter is sought.

In this example, if the network object ansible-test-network does not exist, it will be created with the mentioned value and if the object with this name exists then it will be updated with the mentioned values.

- hosts: all
  connection: httpapi
  tasks:
    - name: Get Domain
      cisco.fmcansible.fmc_configuration:
        operation: getAllDomain
        register_as: domain

    - name: upsertNetworkObject should create a new network
      cisco.fmcansible.fmc_configuration:
        operation: upsertNetworkObject
        path_params:
          domainUUID: '{{ getAllDomain[0].uuid }}'
        data:
          name: "ansible-test-network"
          description: "Upserted network object"
          value: "192.23.23.0/24"
          type: "networkobject"
        register_as: "upsertedTestObj"

Registering objects as Ansible facts

In order to reuse objects in subsequent plays during an ansible-playbook run, they should be registered as variables. FMC module automatically registers server responses as Ansible facts. Then, these facts can be used in the playbook as regular variables.

By default, fact names are constructed as {OBJECT_TYPE}_{LOWERCASE_OBJECT_NAME}. For example, a createMultipleNetworkObject play creating a NetworkObject named LocalhostNetwork registers the newly created object in a Network_localhostnetwork fact.

If you want to change the default naming convention, add a register_as parameter with the desired fact name to the play.

Task idempotency

A task is idempotent if the result of running it once is exactly the same as the result of running it multiple times. As Ansible requires modules to be idempotent, fmc_configuration complies with this requirement.

Before executing the operation, fmc_configuration` checks whether the desired final state is already achieved. If yes, no actions are executed, and the operation finishes showing that the state is not changed. A comparison of objects is described below.

For example, when running the createMultipleNetworkObject operation multiple times without changing the play configuration, only the first run results in changed status. Subsequent runs are finished with ok status.

Known issues/limitations

  • Some endpoints use 'name' vs others use 'nameOrValue'. For example: /object/networks?filter=nameOrValue:ansible-test
  • If the description parameter is specified for the security zone object Ansible will return "changed" on each run even if values are not changed.
  • Inconsistent error message and HTTP status for duplicate object error in some cases