En este post se expone un código ejemplo para la creacion de objetos (URL) en Cisco Firepower Management Center utilizando la RestFul API que integrada en la maquina virtual del appliance.

Read more: Crea objetos en Cisco Firepower usando RestFul API y Pyhon3

Las RestFul API toman ventaja de la arquitectura de consultas REST utilizado comunmente en servicios WEB para ejecutar comando HTTP con datos normalmente cargados en formato JSON, XML, HTML.

Dentro de Firepower Management Center podemos activar esta caracteristica de la siguiente:

Navegamos a System>Configuration>REST API Preferences>Enable REST API

Activar REST API en FMC

Una vez activado podremos acceder a la pagina principal de REST API de FMC donde encontraremos los URLs, Verbos y tipos de estructuras que se pueden utilizar con la RESTFul API.

La dirección de RESTFUL API es la siguiente: https://<management-api>/api/api-explorer/

Página principal RESTFUL API

Navegando por la página lograremos observar las posibilidades de consulta que se pueden realizar a la RESTFUL API asi como las acciones. En este ejemplo la tarea será crear un objeto sencillo como un URL que puede ser aplicado luego en una Access-rule:

La siguiente imágen muestra la URL utilizada para la creación del objeto así como el verbo a utilizar:

Dirección para creación de objetos URLs

Además de la dirección de la API a utilizar, es requerido el {domainUUID} el cual es un identificador único para cada solicitud en la API

Con esto datos tendremos lo suficiente para realizar la consulta a la RESTFUL API para la creación de objetos URL. La siguiente tarea utilizar un cliente que consuma la RESTFUL API, en mi caso, estoy utilizando Python3 como cliente a través de la libreria ‘Request’ especializada en consultas CRUD para servicios WEB.

La razon por la cual usar Python en lugar de muchos otros clientes con GUI para consumir la API es debido a las extensas posibilidades que me otorga el poder manejar las consultas por un lenguaje de programación de alto y con muchas herramientas disponibles para la manipulacion de objetos. Siguiendo con el ejemplo, solo crearemos un objeto a manera de demostración pero las posibilidades de Python van mucho mas allá como las de crear rutinas para la creación de multiples objetos obtenidos por archivos .CSV por ejemplo.

Creando el script de consumo de API

Cargando script y librerias a utilizar

import json
import sys
import requests
import base64

###Aqui nos deshacemos de un warning de seguridad por el certificado
from requests.packages.urllib3.exceptions import SubjectAltNameWarning
requests.packages.urllib3.disable_warnings(SubjectAltNameWarning)

MIN_ARGS = 3
MAX_ARGS = 4

En el bloque anterior cargamos las librerias necesarias para manipular los datos y realizar las consultas a la RESTFUL API, agregamos 2 variables globales de argumentos para la validación de los datos de entrada.

A continuación, se definen las funciones necesarias para el SCRIPT

Función de Login

RESTFUL API de Cisco requiere autorización por token por lo que es necesario obtener primero un token de autorización para poder consumir la API, la autenticación se realiza por medio de las credenciales de administracion de FMC y estas deben estar codificadas en formato Base64 como es usual en las consultas HTTP:

# Esta funcion administra los temas de autorizacion
def auth_request(url, headers, cert_loc):
    # Initialize response
    resp = None
    # Hacemos el POST para obtener los tokens
    ## Usamos HTTPS porque es el unico puerto que admite el FMC
    if url.startswith("https"):
        try:
            resp = requests.post(url, headers=headers, verify=False)   ## Cambiamos el Verify a False para evitar el uso de certificado
            print(resp)   ##Este print nos devuelve el codigo de retorno de la solicitud post por HTTP
            if (resp == None):
                raise ValueError("Response is undefined")
            if (resp.status_code != 204):
                msg = "Error Status Code: %d in response" % resp.status_code
                raise ValueError(msg)            ## El Raise es un except pero tiene que ir acompañado
                                                 ## de un if para validar el error y el error puede se puede definir personalizado
        except Exception:                        ## El exception normal que prueba un bloque de codigo
            print("Error Handle auth_request")
    ## Dentro de este Else se ejecuta si un caso no usamos HTTPS (no recomendado)
    else:
        resp = requests.post(url, headers=headers)
    return resp
def login(server, username, password, cert_loc):
    # Direccion API para generar el token
    api_path = "/api/fmc_platform/v1/auth/generatetoken"

    # Se construye la URL para la consulta
    url = server + api_path

    ## Usuario y contraseña deben ir en formato base64 de la siguiente forma: 
      'username:password'
    ##string convertido a base64 en: https://www.base64encode.org/
    ##String para FMC
    authstring = "base64encodedmessage"
    print(authstring)
    headers = {'Authorization' : authstring}

    ##En esta funcion se le manda URL y el header de autorizacion con el username y password, cert_loc no es utilizado
    try:
       resp = auth_request(url, headers, cert_loc)
    except Exception:
       print("Error Handle login")
    ##En este caso retorna los headers para authorization y tokens
    return {'X-auth-access-token': resp.headers['X-auth-access-token'], 'X-auth-refresh-token': resp.headers['X-auth-refresh-token']}

Función Logout

def logout(server, access_token, cert_loc):
    # Direccion para revocacion de token
    api_path = "/api/fmc_platform/v1/auth/revokeaccess"

    # Construyendo la URL
    url = server + api_path

    # Header para la revocacion:
    headers = {'X-auth-access-token' : access_token}

    try:
        auth_request(url, headers, cert_loc)
    except Exception:
        print("Error Handle logout")

    return (0)

Como pudieron notar en las ultimas 3 funciones el esquema es el mismo:

  • Creamos la direccion de URL que se consulta la API: base URL + API URL ejemplo https://192.168.1.1/api/fmc_platform/v1/auth/revokeaccess
  • Luego creamos los Headers necesarios para la consulta (ejemplo tokens, usuarios, contraseñas)
  • Finalmente utilizamos el bloque ‘try’ para realizar la consulta ‘request.post’ con toda la informacion generada previamente.

Creamos el objeto que deseamos:

def main():
##Validamos si la informacion ingresada al momento de la ejecucion es correcta:
    if len(sys.argv) < MIN_ARGS:
        sys.exit("Insufficient inputs. The inputs must have at least 3 arguments \"python auth_util.py <server_addr> <username> <password> <location of certificate>\"")
    # sacamos la URL base
    server = sys.argv[1]
    # obtenemos el usuario
    username = sys.argv[2]
    print(username)
    # obtenemos la contraseña
    password = sys.argv[3]
    print(password)
    # obtenemos el certificado
    cert_loc = False
    if len(sys.argv) > MAX_ARGS:
        cert_loc = sys.argv[MAX_ARGS]
   #Nos logeamos a la REST FUL API usando la funcion login:
    result = login(server, username, password, cert_loc)
## Del resultado anterior obtenemos los token de autorizacion:
    access_token = result.get('X-auth-access-token')
    refresh_token = result.get('X-auth-refresh-token')
    ## validamos si ya existe un token creado
    if (access_token != None and refresh_token != None):
        print("\nAccess tokens and Refresh tokens exist.")
        print("Access token: %s" % access_token)
        print("Refresh token: %s\n" % refresh_token)
    else:
        print("Access tokens and refresh tokens does not exist.")

    ##Creacion de los objetos para Post aqui tenemos el objeto que vamos a crear en el FMC, notese que es una biblioteca python
    post_data_url = {
            "type": "Url",
            "name": "UrlObject1_test1",
            "description": "url object 1",
            "url": "http://www.uni.edu.ni"
        }

    ##Obtenemos el URL API Path de la pagina de api-explorer del FMC:
    ##Domain UUID
    api_path = "/api/fmc_config/v1/domain/Domain-UUID/object/urls"
    ## Armamos el URL Completo:
    url_API = server + api_path

    ##Creamos los headers para el post de URL, notese el header 'Content-Type' que indica que pasaremos un objeto tipo json
    headers_url = {'Content-Type': 'application/json'}
    headers_url['X-auth-access-token'] = access_token
  ## Realizamos el post con la libreria request, notese la funcion json.dumps() que convierte una biblioteca python en formato json
    try:
            r = requests.post(url_API, data=json.dumps(post_data_url), headers=headers_url, verify=False);
            status_code = r.status_code
            resp = r.text
            if status_code == 201 or status_code == 202:
                print("Post was successful for " + post_data_url["name"])
                # json_resp = json.loads(resp)
                # print(json.dumps(json_resp,sort_keys=True,indent=4, separators=(',', ': ')))
            else:
                r.raise_for_status()
                print("Error occurred in POST --> " + resp)
    except requests.exceptions.HTTPError as err:
        print("Error in connection --> " + str(err))
    finally:
        if r: r.close()


# Stand Alone execution
if __name__ == "__main__":
    main()

Como pudieron observar la creacion de un Objeto usando la RESTFUL API se basa en armar la solicitud POST con los datos necesarios del objeto, en este caso se utiliza JSON como formato para enviar los datos FMC.

Con esto la ejecucion usando la linea de comandos de windows se puede lograr de la siguiente manera:

python ejemplo.py https://192.168.1.1 usuario contraseña

Para más ejemplos de API con equipos Cisco por refierase a: https://developer.cisco.com/firepower/. Todo el código mostrado acá fue obtenido de los tutoriales de Cisco Developers introductorios a la creación de objetos usando APIs.

Con esto me despido y que tengan exitos en sus Requests 😉 Saludos!!!