Trabajar con la API de REST

Trabajar con MDR a través de la API de REST incluye obtener, crear y actualizar activos, incidentes, respuestas y usuarios.

ABRIR LA REFERENCIA DE LA API DE REST

Los métodos de la API de REST requieren un valor client_id. Puede obtener su valor client_id abriendo el bloque de Información del token de cualquier token de actualización en MDR Web Console.

He aquí ejemplos de secuencias de comandos para Python y Shell que muestran las capacidades básicas de la API de REST:

Ejemplo (Python):

###################################################

# Parte general

###################################################

 

import time

import datetime

import requests

import jwt

 

# El certificado es necesario para la autenticación de un recurso externo

#Puede descargar el certificado desde https://mdr.kaspersky.com,

#guárdelo en su disco y agregue la ruta en la variable:

VERIFY_CERT_PATH = "C:\\tools\\DigiCert Global Root G2.crt"

 

#URL de la API de REST de MDR:

API_URL = "https://mdr.kaspersky.com/api/v1"

 

# El id. de su cliente y sus tókenes de usted

#Para obtener más información sobre cómo obtener su ID y los tokens, consulte la ayuda https://support.kaspersky.com/MDR/en-US/258285.htm

CLIENT_ID = "9ed43ed54sAmpleIdf349323951f" # (Pegue su valor)

REFRESH_TOKEN = "ReFrEsHToKeN" # (Pegue su valor)

ACCESS_TOKEN = "AcCeSsToKeN" # (Pegue su valor)

 

 

###################################################

#Obtenga un token de acceso y un token de actualización para la próxima actualización del token de acceso

###################################################

 

if REFRESH_TOKEN:

refresh_token_exp = jwt.decode(REFRESH_TOKEN, options={"verify_signature": False}).get("exp")

print(f"REFRESH_TOKEN fecha y hora de caducidad: {datetime.datetime.fromtimestamp(refresh_token_exp)}")

if refresh_token_exp > time.time():

print("REFRESH_TOKEN es válido")

else:

print(

"Debe actualizar REFRESH_TOKEN; tómelo de la consola MDR (https://support.kaspersky.com/MDR/es-ES/258285.htm)"

)

exit()

else:

print(

"Debe rellenar el valor REFRESH_TOKEN; tómelo de la Consola MDR (https://support.kaspersky.com/MDR/es-ES/258285.htm)"

)

exit()

 

#Verificar la presencia y validez del token de acceso

need_update_access_token = False

if ACCESS_TOKEN:

access_token_exp = jwt.decode(ACCESS_TOKEN, options={"verify_signature": False}).get("exp")

print(f"ACCESS_TOKEN fecha y hora de caducidad: {datetime.datetime.fromtimestamp(access_token_exp)}")

if access_token_exp > time.time():

print("ACCESS_TOKEN es válido")

else:

need_update_access_token = True

else:

need_update_access_token = True

 

#Si es necesario, actualice el token de acceso y actualice el token para la próxima actualización del token de acceso

access_token = ACCESS_TOKEN

if need_update_access_token:

request_body = {"refresh_token": REFRESH_TOKEN}

result = requests.post(url=f"{API_URL}/{CLIENT_ID}/session/confirm", json=request_body, verify=VERIFY_CERT_PATH)

result_json = result.json()

 

if "error" in result_json:

print(result_json)

exit()

 

#Es necesario guardar el token de actualización para obtener el siguiente token de acceso cuando caduque el token de acceso actual

refresh_token = result_json["refresh_token"]

print(

f'Su nuevo REFRESH_TOKEN para la próxima vez que solicite ACCESS_TOKEN (reemplace el valor de REFRESH_TOKEN con este valor):: "{refresh_token}"'

)

 

# Se requiere un nuevo token de acceso para recuperar los datos

access_token = result_json["access_token"]

print(f'Su nuevo ACCESS_TOKEN (reemplace el valor de ACCESS_TOKEN con este valor): "{access_token}"')

 

#El token de acceso se añade al encabezado de la solicitud

headers = {"Authorization": f"Bearer {access_token}"}

 

 

###################################################

#Obtener el número de activos

###################################################

 

#La fecha y la hora están en milisegundos a partir de 1970-01-01T00:00:00Z

request_body = {

"max_last_seen": int(time.time())

* 1000, # Limitar el tiempo máximo de la última aparición del activo a la hora actual

"min_last_seen": 1639311132000, # Limitar el tiempo mínimo de la última aparición del activo a la constante: Domingo 12 de diciembre, 2021 12:12:12 PM (GMT)

}

result = requests.post(

url=f"{API_URL}/{CLIENT_ID}/assets/count", json=request_body, headers=headers, verify=VERIFY_CERT_PATH

)

print(result.json())

 

 

###################################################

#Obtener la lista de activos

###################################################

 

request_body = {

# Parámetros de búsqueda:

"max_last_seen": int(time.time())

* 1000, # Limitar el tiempo máximo de la última aparición del activo a la hora actual

"min_last_seen": 1639311132000, # Limitar el tiempo mínimo de la última aparición del activo a la constante: Domingo 12 de diciembre, 2021 12:12:12 PM (GMT)

"domain": "",

"host_names": ["MA-MDR-KES-S", "SIN-MDR-KSC"], # (Pegue su valor) Lista de hosts

"is_isolated": False,

"network_interface": "10.70.104.1",

"os_version": "Windows", # El activo debe contener la línea especificada en el nombre del SO

"product": "",

"search_phrase": "mdr", # Frase para buscar en el contenido de los campos: "host_name", "domain", "installed_product_info", "network_interfaces", "os_version"

"statuses": ["OK", "ABSENT"], # Buscar activos que tengan los estados actuales enumerados aquí

# Opciones para mostrar los resultados de la búsqueda:

"sort": "first_seen:asc", # Ordenar los resultados por la hora de la primera aparición; en el caso de la recuperación de resultados página por página, es necesario especificar un campo de ordenación que no cambie de una consulta a otra, por ejemplo, "first_seen" (no especifique campos cuyos valores cambian constantemente, por ejemplo, el campo "last_seen"; esto puede llevar a resultados incorrectos)

"page_size": 100, # Activos por página: 100

"page": 1, # Obtener la primera página de resultados de búsqueda

"version": 2, # Versión de la solución

}

result = requests.post(

url=f"{API_URL}/{CLIENT_ID}/assets/list", json=request_body, headers=headers, verify=VERIFY_CERT_PATH

)

print(result.json())

 

 

###################################################

# Obtener detalles de los activos

###################################################

 

request_body = {

"asset_id": "0xFA6A68CC9A9415963DE841048A3BE929", # (Pegue su valor) Id. del activo

"version": 2, # Versión de la solución

}

result = requests.post(

url=f"{API_URL}/{CLIENT_ID}/assets/details", json=request_body, headers=headers, verify=VERIFY_CERT_PATH

).json()

print(result)

 

 

###################################################

# Obtener el número de incidentes

###################################################

 

request_body = {

"max_update_time": int(time.time())

* 1000, # Limitar el tiempo máximo de la última actualización del incidente a la hora actual

"min_update_time": 1639311132000, # Limitar el tiempo mínimo de la última actualización del incidente a la constante: Domingo 12 de diciembre, 2021 12:12:12 PM (GMT)

"affected_hosts": [

"MA-MDR-KES-S:0xFA6A68CC9A94145456E841048A3BE929"

], # (Pegue su valor) Lista de hots en formato "host_name:asset_id"

}

result = requests.post(

url=f"{API_URL}/{CLIENT_ID}/incidents/count", json=request_body, headers=headers, verify=VERIFY_CERT_PATH

)

print(result.json())

 

 

###################################################

# Obtener la lista de incidentes

###################################################

 

request_body = {

# Parámetros de búsqueda:

"max_creation_time": int(time.time())

* 1000, # Limitar el tiempo máximo de creación del incidente a la hora actual

"min_creation_time": 1639311132000, # Limitar el tiempo mínimo de la creación del incidente a la constante: Domingo, 12 de diciembre de 2021 12:12:12 PM (GMT)

"asset_ids": [

"0xFA6A68CC9A9415963DE841048A3BE929"

], # (Pegue su valor) Lista de activos cuyos incidentes recopilamos

"priorities": ["HIGH"],

"resolutions": ["True positive"],

"response_statuses": ["Confirmed"],

"response_types": ["hash"],

"statuses": ["Closed"],

# Parámetros para entregar los resultados

"markdown_to_html": True, # Resultados en formato HTML; si el valor es "False", los resultados tendrán el formato Markdown

"sort": "creation_time:asc", # Ordena los resultados por la fecha y hora en que se creó el incidente. Si recupera los resultados página por página, asegúrese de especificar un campo de ordenación que se mantenga constante entre consultas, como por ejemplo,"creation_time" (no use campos cuyos valores cambien constantemente, por ejemplo, el campo "update_time", ya que esto puede dar lugar a resultados incorrectos)

"page_size": 100, # Incidentes por página: 100

"page": 1, # Obtener la primera página de resultados de búsqueda

}

result = requests.post(

url=f"{API_URL}/{CLIENT_ID}/incidents/list", json=request_body, headers=headers, verify=VERIFY_CERT_PATH

)

print(result.json())

 

 

###################################################

# Obtener detalles del incidente

###################################################

 

request_body = {

"incident_id": "60gWG4UBMUGN-LWUuv1m", # (Pegue su valor) Id. del incidente

"markdown_to_html": True, # Resultados en formato HTML; si el valor es "Falso", los resultados tendrá el formato Markdown

}

result = requests.post(

url=f"{API_URL}/{CLIENT_ID}/incidents/details", json=request_body, headers=headers, verify=VERIFY_CERT_PATH

)

print(result.json())

 

 

###################################################

# Obtener una lista de respuestas al incidente

###################################################

 

request_body = {

"incident_id": "60gWG4UBMUGN-LWUuv1m", # (Pegue su valor) Id. del incidente

"page_size": 10, # respuestas por página: 10

"page": 1, # Obtener la primera página de resultados de búsqueda

}

result = requests.post(

url=f"{API_URL}/{CLIENT_ID}/responses/list", json=request_body, headers=headers, verify=VERIFY_CERT_PATH

)

print(result.json())

 

 

###################################################

# Confirmar la respuesta

###################################################

 

request_body = {

"response_id": "CEgYG4UBMUGN-LWULP7W", # (Pegue su valor) Response ID

"comment": "comment_text", # Comentario que se añadirá a la respuesta

"status": "Confirmed", # Nuevo estado de respuesta: "Confirmed"

}

result = requests.post(

url=f"{API_URL}/{CLIENT_ID}/response/update", json=request_body, headers=headers, verify=VERIFY_CERT_PATH

)

print(result.json())

 

 

###################################################

# Rechazar la respuesta

###################################################

 

request_body = {

"response_id": "CEgYG4UBMUGN-LWULP7W", # (Pegue su valor) Response ID

"comment": "comment_text", # Comentario que se añadirá a la respuesta

"status": "Declined", # Nuevo estado de respuesta: "Declined"

}

result = requests.post(

url=f"{API_URL}/{CLIENT_ID}/response/update", json=request_body, headers=headers, verify=VERIFY_CERT_PATH

)

print(result.json())

 

 

###################################################

# Actualizar la lista de respuestas

###################################################

 

request_body = {

"responses_ids": [

"CEgYG4UBMUGN-LWULP7W",

"2ESl6IgB4cAOUyXBb5IB",

], # (Pegue sus valores) Id. de respuestas

"comment": "comment_text", # Comentario que se añadirá a las respuestas

"status": "Confirmed", # Estado de las nuevas respuestas: "Confirmed"

}

result = requests.post(

url=f"{API_URL}/{CLIENT_ID}/responses/update", json=request_body, headers=headers, verify=VERIFY_CERT_PATH

)

print(result.json())

Ejemplo (Shell):

# Obtener token de acceso y nuevo token de actualización

curl -X POST https://mdr.kaspersky.com/api/v1/{client_id}/session/confirm -H "Content-Type: application/json" -d '{"refresh_token": "{refresh_token}"}'

# Ejemplo de respuesta: A continuación, debe usar access_token para recuperar los datos y el refresh_token para recuperar el nuevo token de acceso y el token de actualización

{

"access_token": "SamPLET346yoKEnSamPLEToK25EnSamPLEToK35EnS",

"refresh_token": "tOKenSaMPlet259OKenS123aMPle926tOKenSaMPle"

}

 

# Obtener el número de activos

curl -X POST https://mdr.kaspersky.com/api/v1/{client_id}/assets/count -H "Content-Type: application/json" -H "Authorization: Bearer {access_token}" -d '{"max_last_seen": 1704103200000, "min_last_seen": 1704762000000}'

 

#Obtener la lista de activos

curl -X POST https://mdr.kaspersky.com/api/v1/{client_id}/assets/list -H "Content-Type: application/json" -H "Authorization: Bearer {access_token}" -d '{"max_last_seen": 1704103200000, "min_last_seen": 1704762000000, "domain": "", "host_names": ["MA-MDR-KES-S","SIN-MDR-KSC"], "is_isolated": false, "network_interface": "10.70.104.1", "os_version": "Windows", "product": "", "search_phrase": "mdr", "statuses": ["OK","ABSENT"], "sort": "first_seen:asc", "page_size": 100, "page": 1, "version": 2}'

 

# Obtener detalles de los activos

curl -X POST https://mdr.kaspersky.com/api/v1/{client_id}/assets/details -H "Content-Type: application/json" -H "Authorization: Bearer {access_token}" -d '{"asset_id": "0xFA6A68CC9A9415963DE841048A3BE929", "version": 2}'

 

# Obtener el número de incidentes

curl -X POST https://mdr.kaspersky.com/api/v1/{client_id}/incidents/count -H "Content-Type: application/json" -H "Authorization: Bearer {access_token}" -d '{"max_update_time": 1704103200000, "min_update_time": 1704762000000, "affected_hosts": ["MA-MDR-KES-S:0xFA6A68CC9A9415963DE841048A3BE929"]}'

 

# Obtener la lista de incidentes

curl -X POST https://mdr.kaspersky.com/api/v1/{client_id}/incidents/list -H "Content-Type: application/json" -H "Authorization: Bearer {access_token}" -d '{"max_creation_time": 1704103200000, "min_creation_time": 1704762000000, "asset_ids": ["0xFA6A68CC9A9415963DE841048A3BE929"], "priorities": ["HIGH"], "resolutions": ["True positive"], "response_statuses": ["Confirmed"], "response_types": ["hash"], "statuses": ["Closed"], "markdown_to_html": true, "sort": "creation_time:asc", "page_size": 100, "page": 1}'

 

# Obtener detalles del incidente

curl -X POST https://mdr.kaspersky.com/api/v1/{client_id}/incidents/details -H "Content-Type: application/json" -H "Authorization: Bearer {access_token}" -d '{"incident_id": "60gWG4UBMUGN-LWUuv1m", "markdown_to_html": true}'

 

# Obtener una lista de respuestas al incidente

curl -X POST https://mdr.kaspersky.com/api/v1/{client_id}/responses/list -H "Content-Type: application/json" -H "Authorization: Bearer {access_token}" -d '{"incident_id": "60gWG4UBMUGN-LWUuv1m", "page_size": 10, "page": 1}'

 

# Actualizar la respuesta

curl -X POST https://mdr.kaspersky.com/api/v1/{client_id}/response/update -H "Content-Type: application/json" -H "Authorization: Bearer {access_token}" -d '{"response_id": "CEgYG4UBMUGN-LWULP7W", "comment": "comment_text", "status": "Confirmed"}'

 

# Actualizar la lista de respuestas

curl -X POST https://mdr.kaspersky.com/api/v1/{client_id}/responses/update -H "Content-Type: application/json" -H "Authorization: Bearer {access_token}" -d '{"responses_ids": ["CEgYG4UBMUGN-LWULP7W", "2ESl6IgB4cAOUyXBb5IB"], "comment": "comment_text", "status": "Confirmed"}'

Ejemplo de respuesta de la API de REST con el token de acceso y el nuevo token de actualización:

{

"access_token": "SamPLET346yoKEnSamPLEToK25EnSamPLEToK35EnS",

"refresh_token": "tOKenSaMPlet259OKenS123aMPle926tOKenSaMPle"

}

Ejemplo de respuesta de la API de REST con la estructura y los valores de los comentarios:

[{

"comment_id": "bfu6TiNghqp",

"author_name": "John Doe",

"text": "<p>El primer comentario</p>",

"creation_time": 1601295428640

}, {

"comment_id": "bfu6TiNghqt",

"author_name": "Jane Doe",

"text": "<p>El segundo comentario</p>",

"creation_time": 1601295433441

}]

Ejemplo de respuesta de la API REST cuando la API de REST crea un nuevo comentario y envía una respuesta con los detalles del comentario:

{

"comment_id": "AXTej0Qi4bfu6TiNgmvT",

"author_name": "Nombre del token",

"text": "Este es un nuevo comentario creado a través de la API de REST",

"creation_time": 1601461748122

}

Ver también:

Escenario: realizar una autorización basada en token

Principio de la página