Recopila registros de Akamai EAA (Enterprise Application Access)
En este documento, se explica cómo transferir registros de Akamai Enterprise Application Access (EAA) a Google Security Operations con Unified Log Streamer (ULS) y Bindplane de Akamai. Akamai EAA produce datos operativos en forma de registros de acceso, registros de auditoría de administración, detalles de autenticación y métricas de estado del conector. 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 UDM, controlando varios tipos de eventos, como NETWORK_HTTP y USER_UNCATEGORIZED, según la presencia de campos específicos. También agrega metadatos, como los nombres del proveedor y del producto, al evento del UDM.
Antes de comenzar
Asegúrate de cumplir con los siguientes requisitos previos:
- Una instancia de Google SecOps
- Un host de Windows 2016 o posterior, o Linux con
systemdpara ejecutar el agente de Bindplane - Linux, macOS o entorno en contenedores (Docker/Kubernetes) para ejecutar Unified Log Streamer
- Si se ejecuta detrás de un proxy, asegúrate de que los puertos de firewall estén abiertos según los requisitos del agente de Bindplane.
- Tenant de Akamai EAA con acceso de administrador
- Credenciales de la API de Akamai (autenticación de EdgeGrid):
- Token de acceso
- Token cliente
- Secreto del cliente
- Nombre de host base de la API (por ejemplo,
akab-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net)
Obtén el archivo de autenticación de transferencia de Google SecOps
- Accede a la consola de Google SecOps.
- Ve a Configuración de SIEM > Agentes de recopilación.
- Descarga el archivo de autenticación de transferencia. Guarda el archivo de forma segura en el sistema en el que se instalará BindPlane.
Obtén el ID de cliente de Google SecOps
- Accede a 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.
Instala el agente de BindPlane
Instala el agente de Bindplane en tu sistema operativo Windows o Linux según las siguientes instrucciones.
Instalación en Windows
- Abre el símbolo del sistema o PowerShell como administrador.
Ejecuta el comando siguiente:
msiexec /i "https://github.com/observIQ/bindplane-agent/releases/latest/download/observiq-otel-collector.msi" /quiet
Instalación en Linux
- Abre una terminal con privilegios de raíz o sudo.
Ejecuta el comando siguiente:
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 obtener más opciones de instalación, consulta esta guía de instalación.
Configura el agente de BindPlane para transferir Syslog y enviarlo a Google SecOps
Accede al archivo de configuración:
- Ubica el archivo
config.yaml. Por lo general, 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).
- Ubica 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- Reemplaza lo siguiente:
- Reemplaza
<CUSTOMER_ID>por el ID de cliente real. - Actualiza
/path/to/ingestion-authentication-file.jsona la ruta de acceso en la que se guardó el archivo de autenticación en la sección Cómo obtener el archivo de autenticación de la transferencia de datos de Google SecOps. 0.0.0.0:5140: Es la dirección IP y el puerto en los que Bindplane escuchará. Realiza los ajustes necesarios para tu entorno.
- Reemplaza
- Reemplaza 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 de Servicios o ingresar el siguiente comando:
net stop BindPlaneAgent && net start BindPlaneAgent
Instala Akamai Unified Log Streamer
Unified Log Streamer (ULS) extrae registros de Akamai EAA a través de la API de Enterprise Application Access y los transmite a Bindplane con TCP o UDP.
Instalación en Linux
Descarga la versión más reciente de ULS:
curl -LO https://github.com/akamai/uls/releases/latest/download/uls-linux-amd64Haz que el objeto binario sea ejecutable:
chmod +x uls-linux-amd64Mueve el dispositivo a una ubicación estándar:
sudo mv uls-linux-amd64 /usr/local/bin/uls
Instalación en macOS
Descarga la versión más reciente de ULS:
curl -LO https://github.com/akamai/uls/releases/latest/download/uls-darwin-amd64Haz que el objeto binario sea ejecutable:
chmod +x uls-darwin-amd64Mueve el dispositivo a una ubicación estándar:
sudo mv uls-darwin-amd64 /usr/local/bin/uls
Instalación de Docker
Extrae la imagen oficial de Docker de ULS:
docker pull akamai/uls:latest
Configura las credenciales de Akamai EdgeGrid
Crea el archivo de credenciales de EdgeGrid:
mkdir -p ~/.edgerc nano ~/.edgercAgrega tus credenciales de la API de Akamai en 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
Reemplaza lo siguiente:
your-client-secret: Es tu secreto del cliente de Akamai.your-access-token: Es tu token de acceso de Akamai.your-client-token: Es tu token de cliente de Akamai.akab-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net: Es el nombre de host base de la API de Akamai.
Configura ULS para transmitir registros de EAA a BindPlane
Ejecución de línea de comandos (pruebas)
Ejecuta ULS con salida TCP para transmitir registros al agente de BindPlane:
uls --input eaa \
--feed access \
--output tcp \
--host <BINDPLANE_HOST> \
--port 5140 \
--edgerc ~/.edgerc \
--section default
- Reemplaza lo siguiente:
<BINDPLANE_HOST>: La dirección IP o el nombre de host del servidor que ejecuta Bindplane5140: Es el puerto configurado en el receptortcplogde BindPlane.
Para transmitir varios tipos de feeds, ejecuta instancias separadas de ULS:
```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)
Para 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.confAgrega 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 de systemd:
sudo nano /etc/systemd/system/uls-eaa-access.serviceAgrega 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.serviceVerifica que el servicio esté en ejecución:
sudo systemctl status uls-eaa-access.serviceConsulta los registros:
sudo journalctl -u uls-eaa-access.service -f
Repite los pasos del 1 al 7 para cada tipo de feed adicional (administrador, conhealth) creando archivos de configuración y de servicio separados con nombres diferentes (por ejemplo, uls-eaa-admin.service, uls-eaa-conhealth.service).
Implementación de Docker
Crea un archivo de Docker Compose:
nano docker-compose.ymlAgrega 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- Reemplaza
<BINDPLANE_HOST>por la dirección IP o el nombre de host de tu servidor de Bindplane.
- Reemplaza
Inicia los contenedores:
docker-compose up -dConsulta los registros:
docker-compose logs -f
Tabla de asignación de UDM
| Campo de registro | Asignación de UDM | Lógica |
|---|---|---|
app |
target.application |
Es el valor que se encuentra después de los dos puntos en el campo app. |
apphost |
target.hostname |
Se asigna directamente. |
browser |
network.http.user_agent |
Se asigna directamente. |
bytes_in |
network.received_bytes |
Se asigna directamente. |
bytes_out |
network.sent_bytes |
Se asigna directamente. |
cc |
principal.location.country_or_region |
Se asigna directamente. |
client_id |
additional.fields.key: "Client Id", additional.fields.value.string_value: client_id |
Se asigna de forma condicional si client_id está presente. |
clientip |
principal.ip |
Se asigna directamente. |
cloud_zone |
principal.cloud.availability_zone |
Se asigna directamente. |
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 de forma condicional si content_type está presente. |
datetime |
metadata.event_timestamp |
Se analizó a partir del campo datetime con el formato RFC3339. |
deny_reason |
security_result.summary |
Se asigna directamente. |
device_type |
principal.platform, principal.platform_version |
Se asigna a WINDOWS, LINUX o MAC según la coincidencia de regex. El valor sin procesar se asigna a principal.platform_version. |
di |
metadata.ingestion_labels.key: "di", metadata.ingestion_labels.value: di |
Se asigna directamente como una etiqueta de transferencia. |
error_code |
additional.fields.key: "Código de error", additional.fields.value.string_value: error_code |
Se asigna de forma condicional si error_code está presente. |
event |
metadata.description |
Se asigna directamente. |
geo_city |
principal.location.city |
Se asigna directamente. |
geo_country |
principal.location.country_or_region |
Se asigna directamente. |
geo_state |
principal.location.state |
Se asigna directamente. |
groups |
principal.user.group_identifiers |
Se asigna directamente. |
http_method |
network.http.method |
Se asigna directamente. |
http_ver |
network.application_protocol, network.application_protocol_version |
Se analiza con grok para extraer el protocolo y la versión. |
idpinfo |
additional.fields.key: "IDP Info", additional.fields.value.string_value: idpinfo |
Se asigna de forma condicional si idpinfo está presente. |
internal_host |
additional.fields.key: "Host interno", additional.fields.value.string_value: internal_host |
Se asigna de forma condicional si internal_host está presente. |
metadata.log_type |
metadata.log_type |
Se codifica de forma rígida como "AKAMAI_EAA". |
metadata.product_name |
metadata.product_name |
Se codifica de forma rígida como "AKAMAI_EAA". |
metadata.vendor_name |
metadata.vendor_name |
Se codifica de forma rígida como "AKAMAI_EAA". |
metadata.event_type |
metadata.event_type |
Se determina según la lógica: USER_UNCATEGORIZED si uid está presente, NETWORK_HTTP si se configuran principal.ip y target, o GENERIC_EVENT en cualquier otro caso. |
origin_host |
additional.fields.key: "Host de origen", additional.fields.value.string_value: origin_host |
Se asigna de forma condicional si origin_host está presente. |
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 según la coincidencia de regex. |
port |
target.port |
Es el valor que se encuentra después de los dos puntos en el campo app. |
ral |
metadata.description |
Valores concatenados del array ral, separados por comas. |
referer |
network.http.referral_url |
Se asigna directamente. |
resource |
principal.resource.attribute.labels.key: "Resource", principal.resource.attribute.labels.value: resource |
Se asigna de forma condicional si resource está presente. |
resource_type |
principal.resource.attribute.labels.key: "Resource Type", principal.resource.attribute.labels.value: resource_type |
Se asigna de forma condicional si resource_type está presente. |
rscd |
metadata.ingestion_labels.key: "rscd", metadata.ingestion_labels.value: rscd |
Se asigna directamente como una etiqueta de transferencia. |
session_id |
network.session_id |
Se asigna directamente. |
session_info |
additional.fields.key: "Información de la sesión", additional.fields.value.string_value: session_info |
Se asigna de forma condicional si session_info está presente. |
state |
principal.location.state |
Se asigna directamente. |
status_code |
network.http.response_code |
Se asigna directamente. |
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 |
Se asigna directamente. |
uip |
principal.ip |
Se asigna directamente. |
url_path |
target.url |
Se asigna directamente. |
user_agent |
network.http.user_agent, network.http.parsed_user_agent |
Se asigna y analiza directamente en un campo parsed_user_agent estructurado. |
username |
principal.user.email_addresses o principal.user.userid |
Se asigna a email_addresses si parece ser un correo electrónico; de lo contrario, se asigna a userid. |
¿Necesitas más ayuda? Obtén respuestas de miembros de la comunidad y profesionales de Google SecOps.