Recoger registros de Fastly WAF
Información general
Este analizador extrae campos de los registros JSON de Fastly WAF, los transforma y les cambia el nombre, y los asigna a UDM. Gestiona varios tipos de datos, convierte los niveles de gravedad y clasifica los eventos en función de la información disponible sobre la IP y el nombre de host. También gestiona posibles errores de análisis y elimina las entradas de registro mal formadas.
Antes de empezar
Asegúrate de que cumples los siguientes requisitos previos:
- Instancia de Google SecOps.
- Cuenta de Fastly con acceso para configurar los ajustes de WAF.
Configurar feeds
Para configurar un feed, sigue estos pasos:
- Ve a Configuración de SIEM > Feeds.
- Haz clic en Añadir feed.
- En la página siguiente, haga clic en Configurar un solo feed.
- En el campo Nombre del feed, introduce un nombre para el feed (por ejemplo, Registros de WAF de Fastly).
- Selecciona Webhook como Tipo de fuente.
- Seleccione Fastly WAF como Tipo de registro.
- Haz clic en Siguiente.
- Opcional: Especifica los valores de los siguientes parámetros de entrada:
- Delimitador de división: el delimitador que se usa para separar las líneas de registro, como
\n.
- Delimitador de división: el delimitador que se usa para separar las líneas de registro, como
- Haz clic en Siguiente.
- Revise la configuración del feed en la pantalla Finalizar y, a continuación, haga clic en Enviar.
- Haz clic en Generar clave secreta para generar una clave secreta que autentique este feed.
- Copia y guarda la clave secreta. No podrás volver a ver esta clave secreta. Si es necesario, puedes volver a generar una clave secreta, pero esta acción hará que la clave secreta anterior quede obsoleta.
- En la pestaña Detalles, copie la URL del endpoint del feed del campo Información del endpoint. Debes especificar esta URL de endpoint en tu aplicación cliente.
- Haz clic en Listo.
Crear una clave de API para la feed de webhook
Ve a la consolaGoogle Cloud > Credenciales.
Haz clic en Crear credenciales y, a continuación, selecciona Clave de API.
Restringe el acceso de la clave de API a la API Google Security Operations.
Especificar la URL del endpoint
- En tu aplicación cliente, especifica la URL del endpoint HTTPS proporcionada en el feed de webhook.
Para habilitar la autenticación, especifica la clave de API y la clave secreta como parte del encabezado personalizado con el siguiente formato:
X-goog-api-key = API_KEY X-Webhook-Access-Key = SECRETRecomendación: Especifica la clave de API como encabezado en lugar de hacerlo en la URL.
Si tu cliente de webhook no admite encabezados personalizados, puedes especificar la clave de API y la clave secreta mediante parámetros de consulta con el siguiente formato:
ENDPOINT_URL?key=API_KEY&secret=SECRETHaz los cambios siguientes:
ENDPOINT_URL: URL del endpoint del feed.API_KEY: la clave de API para autenticarte en Google Security Operations.SECRET: la clave secreta que has generado para autenticar el feed.
Configurar webhook en Fastly
- Inicia sesión en Fastly.
- Opcional: Seleccione un sitio en el menú Sitios (si tiene más de un sitio).
- Selecciona Gestionar > Integraciones de sitios.
- Haz clic en Añadir integración de sitio.
- Selecciona Webhook genérico.
- URL de webhook: introduce ENDPOINT_URL de Google SecOps, seguido de API_KEY y SECRET.
- Ubicación de las alertas: selecciona Toda la actividad o Actividad específica.
- Opcional: Si has seleccionado Actividad específica, ve al menú Actividad y selecciona los tipos de actividad que quieras que envíe el webhook.
- Haga clic en Crear integración de sitio.
Tabla de asignación de UDM
| Campo de registro | Asignación de UDM | Lógica |
|---|---|---|
anomaly_score |
security_result.detection_fields[].key: "anomaly"security_result.detection_fields[].value: anomaly_score |
Si waf.score.anomaly es 0 o está vacío y anomaly_score no está vacío o no es 0, el valor de anomaly_score se usa para rellenar la matriz security_result.detection_fields con la clave "anomaly" y el valor del campo anomaly_score. |
cache_status |
additional.fields[].key: "cache_status"additional.fields[].value.string_value: cache_status |
El valor cache_status se usa para rellenar la matriz additional.fields con la clave "cache_status" y el valor del campo cache_status. |
client_ip |
principal.ip: client_ip |
El campo client_ip está asignado a principal.ip. |
connection.fastly_is_edge |
additional.fields[].key: "fastly_is_edge"additional.fields[].value.bool_value: connection.fastly_is_edge |
El valor connection.fastly_is_edge se usa para rellenar el array additional.fields con la clave "fastly_is_edge" y el valor del campo connection.fastly_is_edge. |
connection.fastly_is_shield |
additional.fields[].key: "fastly_is_shield"additional.fields[].value.bool_value: connection.fastly_is_shield |
El valor connection.fastly_is_shield se usa para rellenar la matriz additional.fields con la clave "fastly_is_shield" y el valor del campo connection.fastly_is_shield. |
connection.request_tls_version |
network.tls.version: connection.request_tls_version |
El campo connection.request_tls_version está asignado a network.tls.version. |
fastly.server |
target.hostname: fastly.server |
El campo fastly.server está asignado a target.hostname. |
fastly.service_id |
additional.fields[].key: "service_id"additional.fields[].value.string_value: fastly.service_id |
El valor fastly.service_id se usa para rellenar el array additional.fields con la clave "service_id" y el valor del campo fastly.service_id. |
geo.city |
principal.location.city: geo.city |
El campo geo.city está asignado a principal.location.city. |
geo.country |
principal.location.country_or_region: geo.country |
El campo geo.country está asignado a principal.location.country_or_region. |
geo.location |
principal.location.region_latitude: extraído de geo.locationprincipal.location.region_longitude: extraído de geo.location |
La latitud y la longitud se extraen del campo geo.location mediante una expresión regular y se asignan a principal.location.region_latitude y principal.location.region_longitude, respectivamente. |
geo.region |
principal.location.state: geo.region |
El campo geo.region está asignado a principal.location.state. |
host |
principal.hostname: host |
El campo host está asignado a principal.hostname. |
request_headers.accept_charset |
additional.fields[].key: "accept_charset"additional.fields[].value.string_value: request_headers.accept_charset |
El valor request_headers.accept_charset se usa para rellenar la matriz additional.fields con la clave "accept_charset" y el valor del campo request_headers.accept_charset. |
request_headers.accept_language |
additional.fields[].key: "accept_language"additional.fields[].value.string_value: request_headers.accept_language |
El valor de request_headers.accept_language se usa para rellenar la matriz additional.fields con la clave "accept_language" y el valor del campo request_headers.accept_language. |
request_headers.referer |
network.http.referral_url: request_headers.referer |
El campo request_headers.referer está asignado a network.http.referral_url. |
request_headers.user_agent |
network.http.user_agent: request_headers.user_agent |
El campo request_headers.user_agent está asignado a network.http.user_agent. |
request_id |
metadata.product_log_id: request_id |
El campo request_id está asignado a metadata.product_log_id. |
request_method |
network.http.method: request_method |
El campo request_method está asignado a network.http.method. |
response_headers.cache_control |
additional.fields[].key: "cache_control"additional.fields[].value.string_value: response_headers.cache_control |
El valor response_headers.cache_control se usa para rellenar la matriz additional.fields con la clave "cache_control" y el valor del campo response_headers.cache_control. |
response_headers.content_type |
additional.fields[].key: "content_type"additional.fields[].value.string_value: response_headers.content_type |
El valor response_headers.content_type se usa para rellenar la matriz additional.fields con la clave "content_type" y el valor del campo response_headers.content_type. |
response_state |
additional.fields[].key: "response_state"additional.fields[].value.string_value: response_state |
El valor response_state se usa para rellenar la matriz additional.fields con la clave "response_state" y el valor del campo response_state. |
response_status |
network.http.response_code: response_status |
El campo response_status se asigna a network.http.response_code si el campo status está vacío. |
rule_id |
security_result.rule_id: rule_id |
Si waf.rule_id está vacío, se usa el valor rule_id para rellenar security_result.rule_id. |
severity |
waf.severity: severity |
El valor del campo severity se copia en waf.severity. |
size_bytes.request_header |
network.sent_bytes: size_bytes.request_header |
El campo size_bytes.request_header está asignado a network.sent_bytes. |
size_bytes.response_header |
network.received_bytes: size_bytes.response_header |
El campo size_bytes.response_header está asignado a network.received_bytes. |
status |
network.http.response_code: status |
El campo status está asignado a network.http.response_code. |
timestamp |
metadata.event_timestamp: timestamp |
El campo timestamp se analiza y se asigna a metadata.event_timestamp. |
url |
target.url: url |
El campo url está asignado a target.url. |
waf.blocked |
security_result.action: derivada |
Si waf.blocked es false, security_result.action tiene el valor "ALLOW". Si waf.blocked es true, security_result.action se define como "BLOCK". |
waf.executed |
security_result.detection_fields[].key: "executed"security_result.detection_fields[].value: waf.executed |
El valor de waf.executed se usa para rellenar la matriz security_result.detection_fields con la clave "executed" y el valor del campo waf.executed. |
waf.failures |
security_result.detection_fields[].key: "failures"security_result.detection_fields[].value: waf.failures |
El valor waf.failures se usa para rellenar la matriz security_result.detection_fields con la clave "failures" y el valor del campo waf.failures. |
waf.logged |
security_result.detection_fields[].key: "logged"security_result.detection_fields[].value: waf.logged |
El valor waf.logged se usa para rellenar la matriz security_result.detection_fields con la clave "logged" y el valor del campo waf.logged. |
waf.message |
metadata.description: waf.message |
Si waf.message no está vacío, se asigna a metadata.description. |
waf.rule_id |
security_result.rule_id: waf.rule_id |
Si waf.rule_id no está vacío, se asigna a security_result.rule_id. |
waf.score.anomaly |
security_result.detection_fields[].key: "anomaly"security_result.detection_fields[].value: waf.score.anomaly |
Si waf.score.anomaly no es 0 ni está vacío, el valor se usa para rellenar la matriz security_result.detection_fields con la clave "anomaly" y el valor del campo waf.score.anomaly. |
waf.score.http_violation |
security_result.detection_fields[].key: "http_violation"security_result.detection_fields[].value: waf.score.http_violation |
Si waf.score.http_violation no es 0 ni está vacío, el valor se usa para rellenar la matriz security_result.detection_fields. |
waf.score.lfi |
security_result.detection_fields[].key: "lfi"security_result.detection_fields[].value: waf.score.lfi |
Lógica similar a la de waf.score.http_violation. |
waf.score.php_injection |
security_result.detection_fields[].key: "php_injection"security_result.detection_fields[].value: waf.score.php_injection |
Lógica similar a la de waf.score.http_violation. |
waf.score.rce |
security_result.detection_fields[].key: "rce"security_result.detection_fields[].value: waf.score.rce |
Lógica similar a la de waf.score.http_violation. |
waf.score.rfi |
security_result.detection_fields[].key: "rfi"security_result.detection_fields[].value: waf.score.rfi |
Lógica similar a la de waf.score.http_violation. |
waf.score.session_fixation |
security_result.detection_fields[].key: "session_fixation"security_result.detection_fields[].value: waf.score.session_fixation |
Lógica similar a la de waf.score.http_violation. |
waf.score.sql_injection |
security_result.detection_fields[].key: "sql_injection"security_result.detection_fields[].value: waf.score.sql_injection |
Lógica similar a la de waf.score.http_violation. |
waf.score.xss |
security_result.detection_fields[].key: "xss"security_result.detection_fields[].value: waf.score.xss |
Lógica similar a la de waf.score.http_violation. |
waf.severity |
security_result.severity: derivadosecurity_result.severity_details: waf.severity |
Si waf.severity no está vacío, determina el valor de security_result.severity en función de los intervalos (<=3: ALTA, >3 y <=6: MEDIA, >6 y <=8: BAJA; en caso contrario, UNKNOWN_SEVERITY). El valor original waf.severity también se asigna a security_result.severity_details. |
waf_message |
metadata.description: waf_message |
Si waf.message está vacío y waf_message no lo está, se asigna a metadata.description. Si client_ip o host y fastly.server no están vacíos, metadata.event_type se define como "NETWORK_HTTP". De lo contrario, si client_ip o host no están vacíos, metadata.event_type se asigna a "STATUS_UPDATE". De lo contrario, se le asigna el valor "GENERIC_EVENT". Valor codificado. Valor codificado. Valor codificado. |
¿Necesitas más ayuda? Recibe respuestas de los miembros de la comunidad y de los profesionales de Google SecOps.