Exam Topics Covered: 3.2 Construct API requests to create and delete objects using Firepower device management (FDM)
There are two management points for Firepower Threat Defense:
FMC - Firepower Management Console. Provides centralized management of all Firepower devices.
FDM - Firepower Device Manager. Management dashboard and API for a single Firepower appliance.
This section will focus on the FDM since that is what is on the blueprint.
The API documentation is available on the device at the following URL: https://<ftd_device_ip/#/api-explorer and also offline here: https://developer.cisco.com/site/ftd-api-reference/
The Python requests module can be used to interact with the FDM API.
To authenticate to FDM, you must first post a JSON payload containing the username and password for the device. The device will then respond with a token that will need to be set as a Bearer token in an Authorization header on all subsequent requests. The token will be stored in the JSON key access_token
. Below is an example of the authentication process.
token_payload = {"grant_type": "password",
"username": "admin",
"password": "Cisco1234"}
headers = {"Content-Type":"application/json", "Accept": "application/json"}
url = f"https://{hostname}/api/fdm/latest/fdm/token"
resp = requests.post(url=url,
headers=headers,
json=token_payload,
verify=False)
pprint(resp.json(), indent=2)
{ 'access_token': 'eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTMzNzQ2OTksInN1YiI6ImFkbWluIiwianRpIjoiYTUzOTBlZTMtYjk3YS0xMWVhLWEzOTEtZTE1MzgwYzJjODUzIiwibmJmIjoxNTkzMzc0Njk5LCJleHAiOjE1OTMzNzY0OTksInJlZnJlc2hUb2tlbkV4cGlyZXNBdCI6MTU5MzM3NzA5OTczNSwidG9rZW5UeXBlIjoiSldUX0FjY2VzcyIsInVzZXJVdWlkIjoiZGQyMmU5NDMtYTY0OC0xMWVhLWJjYjktZTFiZDNkMzYyYTMyIiwidXNlclJvbGUiOiJST0xFX0FETUlOIiwib3JpZ2luIjoicGFzc3dvcmQiLCJ1c2VybmFtZSI6ImFkbWluIn0.OghgsgVogome3KUDG7EzVIQq4OP20FoxOfm_q2cvtLU',
'expires_in': 1800,
'refresh_expires_in': 2400,
'refresh_token': 'eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTMzNzQ2OTksInN1YiI6ImFkbWluIiwianRpIjoiYTUzOTBlZTMtYjk3YS0xMWVhLWEzOTEtZTE1MzgwYzJjODUzIiwibmJmIjoxNTkzMzc0Njk5LCJleHAiOjE1OTMzNzcwOTksImFjY2Vzc1Rva2VuRXhwaXJlc0F0IjoxNTkzMzc2NDk5NzM1LCJyZWZyZXNoQ291bnQiOi0xLCJ0b2tlblR5cGUiOiJKV1RfUmVmcmVzaCIsInVzZXJVdWlkIjoiZGQyMmU5NDMtYTY0OC0xMWVhLWJjYjktZTFiZDNkMzYyYTMyIiwidXNlclJvbGUiOiJST0xFX0FETUlOIiwib3JpZ2luIjoicGFzc3dvcmQiLCJ1c2VybmFtZSI6ImFkbWluIn0.lEzBnu6tBSvpnY3jL3LJVbZ8HAyfIs8jGB5cyZSzPgE',
'token_type': 'Bearer'}
token = resp.json()['access_token']
headers['Authorization'] = f"Bearer {token}"
Network objects are containers for IP subnets or host addresses which can be used within Access Control Lists and other configuration in order to provide a more easily identified and rememberable name for an IP or group of IPs. Objects can be queried simply by doing a GET request on the API endpoint. Below is an example of querying existing network objects. The returned objects are the default objects for all IPv4 and IPv6 addresses (Any).
url = f"https://{hostname}/api/fdm/latest/object/networks"
resp = requests.get(url, headers=headers, verify=False)
pprint(resp.json())
{'items': [{'description': None,
'dnsResolution': None,
'id': 'f9889d06-a647-11ea-9cb5-efb78339c869',
'isSystemDefined': True,
'links': {'self': 'https://10.10.20.65/api/fdm/latest/object/networks/f9889d06-a647-11ea-9cb5-efb78339c869'},
'name': 'any-ipv4',
'subType': 'NETWORK',
'type': 'networkobject',
'value': '0.0.0.0/0',
'version': 'm7bdadny4jua5'},
{'description': None,
'dnsResolution': None,
'id': 'f999b407-a647-11ea-9cb5-333ef5baa6ee',
'isSystemDefined': True,
'links': {'self': 'https://10.10.20.65/api/fdm/latest/object/networks/f999b407-a647-11ea-9cb5-333ef5baa6ee'},
'name': 'any-ipv6',
'subType': 'NETWORK',
'type': 'networkobject',
'value': '::/0',
'version': 'gd2eq7j4pkcws'}],
'paging': {'count': 2,
'limit': 10,
'next': [],
'offset': 0,
'pages': 0,
'prev': []}}
A network object can be created by posting the JSON payload describing the new object.
url = f"https://{hostname}/api/fdm/latest/object/networks"
object = {"name": "TEST_OBJ",
"description": "API-created Object",
"subType": "NETWORK",
"value": "1.1.1.0/24",
"type": "networkobject"}
resp = requests.post(url, headers=headers, json=object, verify=False)
If the the JSON payload is incorrect, an HTTP status of 422 'Unprocessable Entity' will be received
A network object can be deleted by issuing a DELETE request with the object_id
in the API endpoint URL. The object_id
will first need to be retrieved by querying for the object. Then the ID will be appended to the URL for the delete request. Note that the API will return an HTTP status code 204 to indicate the object has been deleted. There will be no content in the response body.
get_url = f"https://{hostname}/api/fdm/latest/object/networks"
resp = requests.get(get_url, headers=headers, verify=False)
for item in resp.json()['items']:
if item['name'] == "TEST_OBJ":
obj_id = item['id']
print(obj_id)
b91e90d7-b97d-11ea-a391-410fe0690874
delete_url = f"https://{hostname}/api/fdm/latest/object/networks/{obj_id}"
resp = requests.delete(delete_url, headers=headers, verify=False)
resp.status_code
204
resp.content
b''
The FDM API has a limit of 10 items that can be returned in a single request. The limit can be modified by setting the limit
query parameter. The JSON response will include a paging
dictionary which will indicate the next and previous URLs to retrieve the next or previous data. If previous is blank, it means the current request contained the first set of data. If next is empty, it means the current request contained the last set of data.
Below is a snippet from a JSON response after configuring > 10 objects on the device.
'paging': {'count': 11,
'limit': 10,
'next': ['https://10.10.20.65/api/fdm/latest/object/networks?limit=10&offset=10'],
'offset': 0,
'pages': 0,
'prev': []}}