Recoger registros de Akamai EAA (Enterprise Application Access)
En este documento se explica cómo ingerir registros de Akamai Enterprise Application Access (EAA) en Google Security Operations mediante Unified Log Streamer (ULS) de Akamai y Bindplane. Akamai EAA genera datos operativos en forma de registros de acceso, registros de auditoría de administrador, detalles de autenticación y métricas de estado de los conectores. El analizador extrae campos de los registros JSON, realiza transformaciones de datos, como conversiones de cadenas y extracción de direcciones IP, y asigna estos campos al modelo de datos unificado. Además, gestiona varios tipos de eventos, como NETWORK_HTTP y USER_UNCATEGORIZED, en función de la presencia de campos específicos. También añade metadatos, como los nombres del proveedor y del producto, al evento de UDM.
Antes de empezar
Asegúrate de que cumples los siguientes requisitos previos:
- Una instancia de Google SecOps
- Un host con Windows 2016 o una versión posterior, o Linux con
systemdpara ejecutar el agente de Bindplane - Linux, macOS o un entorno en contenedores (Docker o Kubernetes) para ejecutar Unified Log Streamer
- Si se ejecuta a través de un proxy, asegúrese de que los puertos del cortafuegos estén abiertos según los requisitos del agente Bindplane.
- Tenant de Akamai EAA con acceso de administrador
- Credenciales de la API de Akamai (autenticación EdgeGrid):
- Token de acceso
- Token de cliente
- Secreto de cliente
- Nombre de host base de la API (por ejemplo,
akab-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net)
Obtener el archivo de autenticación de ingestión de Google SecOps
- Inicia sesión en la consola de Google SecOps.
- Ve a Configuración de SIEM > Agentes de recogida.
- Descarga el archivo de autenticación de ingestión. Guarda el archivo de forma segura en el sistema en el que se instalará Bindplane.
Obtener el ID de cliente de Google SecOps
- Inicia sesión en la consola de Google SecOps.
- Ve a Configuración de SIEM > Perfil.
- Copia y guarda el ID de cliente de la sección Detalles de la organización.
Instalar el agente de Bindplane
Instala el agente Bindplane en tu sistema operativo Windows o Linux siguiendo las instrucciones que se indican a continuación.
Instalación de ventanas
- Abre la petición de comando o PowerShell como administrador.
Ejecuta el siguiente comando:
msiexec /i "https://github.com/observIQ/bindplane-agent/releases/latest/download/observiq-otel-collector.msi" /quiet
Instalación de Linux
- Abre un terminal con privilegios de root o sudo.
Ejecuta el siguiente comando:
sudo sh -c "$(curl -fsSlL https://github.com/observiq/bindplane-agent/releases/latest/download/install_unix.sh)" install_unix.sh
Recursos de instalación adicionales
- Para ver otras opciones de instalación, consulta esta guía de instalación.
Configurar el agente de Bindplane para ingerir Syslog y enviarlo a Google SecOps
Accede al archivo de configuración:
- Busca el archivo
config.yaml. Normalmente, se encuentra en el directorio/etc/bindplane-agent/en Linux o en el directorio de instalación en Windows. - Abre el archivo con un editor de texto (por ejemplo,
nano,vio Bloc de notas).
- Busca el archivo
Edita el archivo
config.yamlde la siguiente manera:receivers: tcplog: listen_address: "0.0.0.0:5140" exporters: chronicle/chronicle_w_labels: compression: gzip creds_file_path: '/path/to/ingestion-authentication-file.json' customer_id: <CUSTOMER_ID> endpoint: malachiteingestion-pa.googleapis.com log_type: 'AKAMAI_EAA' raw_log_field: body ingestion_labels: source: akamai_eaa service: pipelines: logs/akamai_eaa: receivers: - tcplog exporters: - chronicle/chronicle_w_labels- Sustituye lo siguiente:
- Sustituye
<CUSTOMER_ID>por el ID de cliente real. - Actualiza
/path/to/ingestion-authentication-file.jsona la ruta donde se guardó el archivo de autenticación en la sección Obtener el archivo de autenticación de ingestión de Google SecOps. 0.0.0.0:5140: la dirección IP y el puerto en los que Bindplane debe escuchar. Ajusta los valores según tu entorno.
- Sustituye
- Sustituye lo siguiente:
Reinicia el agente de Bindplane para aplicar los cambios
Para reiniciar el agente de Bindplane en Linux, ejecuta el siguiente comando:
sudo systemctl restart bindplane-agentPara reiniciar el agente de Bindplane en Windows, puedes usar la consola Servicios o introducir el siguiente comando:
net stop BindPlaneAgent && net start BindPlaneAgent
Instalar Akamai Unified Log Streamer
Unified Log Streamer (ULS) extrae registros de Akamai EAA a través de la API Enterprise Application Access y los transmite a Bindplane mediante TCP o UDP.
Instalación de Linux
Descarga la última versión de ULS:
curl -LO https://github.com/akamai/uls/releases/latest/download/uls-linux-amd64Haz que el archivo binario sea ejecutable:
chmod +x uls-linux-amd64Moverlo a una ubicación estándar:
sudo mv uls-linux-amd64 /usr/local/bin/uls
Instalación en macOS
Descarga la última versión de ULS:
curl -LO https://github.com/akamai/uls/releases/latest/download/uls-darwin-amd64Haz que el archivo binario sea ejecutable:
chmod +x uls-darwin-amd64Moverlo a una ubicación estándar:
sudo mv uls-darwin-amd64 /usr/local/bin/uls
Instalación de Docker
Extrae la imagen Docker oficial de ULS:
docker pull akamai/uls:latest
Configurar las credenciales de Akamai EdgeGrid
Crea el archivo de credenciales de EdgeGrid:
mkdir -p ~/.edgerc nano ~/.edgercAñada sus credenciales de la API de Akamai con el siguiente formato:
[default] client_secret = your-client-secret host = akab-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net access_token = your-access-token client_token = your-client-tokenProtege el archivo de credenciales:
chmod 600 ~/.edgerc
Haz los cambios siguientes:
your-client-secret: tu secreto de cliente de Akamai.your-access-token: tu token de acceso de Akamai.your-client-token: tu token de cliente de Akamai.akab-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net: el nombre de host base de la API de Akamai.
Configurar ULS para transmitir registros de EAA a BindPlane
Ejecución desde la línea de comandos (pruebas)
Ejecuta ULS con salida TCP para enviar registros al agente de Bindplane:
uls --input eaa \
--feed access \
--output tcp \
--host <BINDPLANE_HOST> \
--port 5140 \
--edgerc ~/.edgerc \
--section default
- Sustituye lo siguiente:
<BINDPLANE_HOST>: la dirección IP o el nombre de host del servidor que ejecuta Bindplane5140: el puerto configurado en el receptortcplogde Bindplane.
Para transmitir varios tipos de feeds, ejecute instancias de ULS independientes:
```bash
# Access logs
uls --input eaa --feed access --output tcp --host <BINDPLANE_HOST> --port 5140 --edgerc ~/.edgerc --section default
# Admin audit logs
uls --input eaa --feed admin --output tcp --host <BINDPLANE_HOST> --port 5140 --edgerc ~/.edgerc --section default
# Connector health
uls --input eaa --feed conhealth --output tcp --host <BINDPLANE_HOST> --port 5140 --edgerc ~/.edgerc --section default
```
Servicio Systemd (producción)
En las implementaciones de producción, configura ULS como un servicio de systemd:
Crea un archivo de configuración de ULS:
sudo mkdir -p /etc/uls sudo nano /etc/uls/eaa-access-tcp.confAñade la siguiente configuración:
ULS_INPUT=eaa ULS_FEED=access ULS_OUTPUT=tcp ULS_HOST=<BINDPLANE_HOST> ULS_PORT=5140 ULS_EDGERC=/root/.edgerc ULS_SECTION=defaultCrea un archivo de servicio systemd:
sudo nano /etc/systemd/system/uls-eaa-access.serviceAñade el siguiente contenido:
[Unit] Description=Unified Log Streamer - EAA Access Logs to BindPlane After=network.target [Service] Type=simple EnvironmentFile=/etc/uls/eaa-access-tcp.conf ExecStart=/usr/local/bin/uls --input ${ULS_INPUT} --feed ${ULS_FEED} --output ${ULS_OUTPUT} --host ${ULS_HOST} --port ${ULS_PORT} --edgerc ${ULS_EDGERC} --section ${ULS_SECTION} Restart=always RestartSec=10 User=root [Install] WantedBy=multi-user.targetHabilita e inicia el servicio:
sudo systemctl daemon-reload sudo systemctl enable uls-eaa-access.service sudo systemctl start uls-eaa-access.serviceComprueba que el servicio se está ejecutando:
sudo systemctl status uls-eaa-access.serviceVer registros:
sudo journalctl -u uls-eaa-access.service -f
Repite los pasos del 1 al 7 para cada tipo de feed adicional (admin, conhealth) creando archivos de configuración y de servicio independientes con nombres diferentes (por ejemplo, uls-eaa-admin.service y uls-eaa-conhealth.service).
Despliegue de Docker
Crea un archivo de Docker Compose:
nano docker-compose.ymlAñade la siguiente configuración:
version: '3.8' services: uls-eaa-access: image: akamai/uls:latest container_name: uls-eaa-access restart: unless-stopped environment: - ULS_INPUT=eaa - ULS_FEED=access - ULS_OUTPUT=tcp - ULS_HOST=<BINDPLANE_HOST> - ULS_PORT=5140 volumes: - ~/.edgerc:/root/.edgerc:ro command: > --input eaa --feed access --output tcp --host "$${ULS_HOST}" --port "$${ULS_PORT}" --edgerc /root/.edgerc --section default uls-eaa-admin: image: akamai/uls:latest container_name: uls-eaa-admin restart: unless-stopped environment: - ULS_INPUT=eaa - ULS_FEED=admin - ULS_OUTPUT=tcp - ULS_HOST=<BINDPLANE_HOST> - ULS_PORT=5140 volumes: - ~/.edgerc:/root/.edgerc:ro command: > --input eaa --feed admin --output tcp --host "$${ULS_HOST}" --port "$${ULS_PORT}" --edgerc /root/.edgerc --section default uls-eaa-conhealth: image: akamai/uls:latest container_name: uls-eaa-conhealth restart: unless-stopped environment: - ULS_INPUT=eaa - ULS_FEED=conhealth - ULS_OUTPUT=tcp - ULS_HOST=<BINDPLANE_HOST> - ULS_PORT=5140 volumes: - ~/.edgerc:/root/.edgerc:ro command: > --input eaa --feed conhealth --output tcp --host "$${ULS_HOST}" --port "$${ULS_PORT}" --edgerc /root/.edgerc --section default- Sustituye
<BINDPLANE_HOST>por la dirección IP o el nombre de host de tu servidor Bindplane.
- Sustituye
Inicia los contenedores:
docker-compose up -dVer registros:
docker-compose logs -f
Tabla de asignación de UDM
| Campo de registro | Asignación de UDM | Lógica |
|---|---|---|
app |
target.application |
El valor que aparece después de los dos puntos en el campo app. |
apphost |
target.hostname |
Asignación directa. |
browser |
network.http.user_agent |
Asignación directa. |
bytes_in |
network.received_bytes |
Asignación directa. |
bytes_out |
network.sent_bytes |
Asignación directa. |
cc |
principal.location.country_or_region |
Asignación directa. |
client_id |
additional.fields.key: "Client Id", additional.fields.value.string_value: client_id |
Se asigna condicionalmente si se incluye client_id. |
clientip |
principal.ip |
Asignación directa. |
cloud_zone |
principal.cloud.availability_zone |
Asignación directa. |
connector_resp_time |
security_result.detection_fields.key: "Tiempo de respuesta del conector", security_result.detection_fields.value: connector_resp_time |
Se asigna de forma condicional si connector_resp_time no está vacío o no es "-". |
content_type |
additional.fields.key: "Tipo de contenido", additional.fields.value.string_value: content_type |
Se asigna condicionalmente si se incluye content_type. |
datetime |
metadata.event_timestamp |
Se analiza a partir del campo datetime con el formato RFC3339. |
deny_reason |
security_result.summary |
Asignación directa. |
device_type |
principal.platform, principal.platform_version |
Se asigna a WINDOWS, LINUX o MAC en función de la coincidencia con la expresión regular. El valor sin formato se asigna a principal.platform_version. |
di |
metadata.ingestion_labels.key: "di", metadata.ingestion_labels.value: di |
Se ha asignado directamente como etiqueta de ingestión. |
error_code |
additional.fields.key: "Código de error", additional.fields.value.string_value: error_code |
Se asigna condicionalmente si se incluye error_code. |
event |
metadata.description |
Asignación directa. |
geo_city |
principal.location.city |
Asignación directa. |
geo_country |
principal.location.country_or_region |
Asignación directa. |
geo_state |
principal.location.state |
Asignación directa. |
groups |
principal.user.group_identifiers |
Asignación directa. |
http_method |
network.http.method |
Asignación directa. |
http_ver |
network.application_protocol, network.application_protocol_version |
Analizado con grok para extraer el protocolo y la versión. |
idpinfo |
additional.fields.key: "IDP Info", additional.fields.value.string_value: idpinfo |
Se asigna condicionalmente si se incluye idpinfo. |
internal_host |
additional.fields.key: "Anfitrión interno", additional.fields.value.string_value: internal_host |
Se asigna condicionalmente si se incluye internal_host. |
metadata.log_type |
metadata.log_type |
Codificado como "AKAMAI_EAA". |
metadata.product_name |
metadata.product_name |
Codificado como "AKAMAI_EAA". |
metadata.vendor_name |
metadata.vendor_name |
Codificado como "AKAMAI_EAA". |
metadata.event_type |
metadata.event_type |
Determinado por la lógica: USER_UNCATEGORIZED si uid está presente, NETWORK_HTTP si se han definido principal.ip y target, o GENERIC_EVENT en caso contrario. |
origin_host |
additional.fields.key: "Host de origen", additional.fields.value.string_value: origin_host |
Se asigna condicionalmente si se incluye origin_host. |
origin_resp_time |
security_result.detection_fields.key: "Tiempo de respuesta del origen", security_result.detection_fields.value: origin_resp_time |
Se asigna de forma condicional si origin_resp_time no está vacío o no es "-". |
os |
principal.platform |
Se asigna a WINDOWS, MAC o LINUX en función de la coincidencia con la expresión regular. |
port |
target.port |
El valor que aparece después de los dos puntos en el campo app. |
ral |
metadata.description |
Valores concatenados de la matriz ral, separados por comas. |
referer |
network.http.referral_url |
Asignación directa. |
resource |
principal.resource.attribute.labels.key: "Resource", principal.resource.attribute.labels.value: resource |
Se asigna condicionalmente si se incluye resource. |
resource_type |
principal.resource.attribute.labels.key: "Resource Type", principal.resource.attribute.labels.value: resource_type |
Se asigna condicionalmente si se incluye resource_type. |
rscd |
metadata.ingestion_labels.key: "rscd", metadata.ingestion_labels.value: rscd |
Se ha asignado directamente como etiqueta de ingestión. |
session_id |
network.session_id |
Asignación directa. |
session_info |
additional.fields.key: "Información de la sesión", additional.fields.value.string_value: session_info |
Se asigna condicionalmente si se incluye session_info. |
state |
principal.location.state |
Asignación directa. |
status_code |
network.http.response_code |
Asignación directa. |
total_resp_time |
security_result.detection_fields.key: "Tiempo de respuesta total", security_result.detection_fields.value: total_resp_time |
Se asigna de forma condicional si total_resp_time no está vacío o no es "-". |
ts |
metadata.event_timestamp |
Se analiza a partir del campo ts como milisegundos o segundos de UNIX si está presente. De lo contrario, se analiza a partir del campo datetime. |
uid |
principal.user.userid |
Asignación directa. |
uip |
principal.ip |
Asignación directa. |
url_path |
target.url |
Asignación directa. |
user_agent |
network.http.user_agent, network.http.parsed_user_agent |
Se asignan directamente y se analizan en un campo parsed_user_agent estructurado. |
username |
principal.user.email_addresses o principal.user.userid |
Se asigna a email_addresses si parece un correo electrónico; de lo contrario, se asigna a userid. |
¿Necesitas más ayuda? Recibe respuestas de los miembros de la comunidad y de los profesionales de Google SecOps.