
Cómo monitorear eventos de seguridad de Google Workspace con n8n y Slack
¿Quieres saber quién modificó cuentas, contraseñas, reglas de Gmail o privilegios administrativos en Google Workspace? Puedes integrar Google Admin SDK Reports API con n8n, identificar eventos sensibles y enviar alertas selectivas a un canal privado de Slack, sin desarrollar una aplicación desde cero.
nextPageToken, clasifica los registros, deduplica por event_id y notifica solo los nuevos de severidad crítica. Añade un Error Trigger para detectar fallas.1. Diferencias entre registros administrativos y Alert Center
La auditoría administrativa registra acciones que ocurren en la consola de administración de Google Workspace. Su interfaz suele encontrarse en Informes → Auditoría e investigación → Eventos de registro de administrador. No debe confundirse con el Centro de alertas, que presenta detecciones emitidas por los servicios de seguridad de Google.
| Fuente | Contenido principal | ¿Se incluye? |
|---|---|---|
| Admin log events | Cambios de usuarios, permisos y configuraciones administrativas. | Sí |
| Alert Center | Alertas generadas por los sistemas de seguridad de Google. | No; requiere Alert Center API. |
| User log events | Eventos de acceso y autenticación de usuarios. | No; se integra por otra fuente. |
El objetivo no es reenviar todo: una búsqueda de investigación es una acción administrativa registrable, pero no necesariamente un incidente. La severidad depende de la política de riesgos de la organización.
2. Arquitectura de monitoreo con n8n

El flujo principal combina un Schedule Trigger periódico, HTTP Request, un nodo Code, Loop Over Items, dos nodos IF, una Data Table y un HTTP Request destinado al webhook de Slack. Otro workflow con Error Trigger vigila errores de ejecución.
3. Qué necesitas
- Una cuenta autorizada para consultar registros de auditoría de Google Workspace.
- Un proyecto de Google Cloud con Admin SDK API habilitada.
- Una instancia de n8n con salida HTTPS a Google y Slack.
- Una aplicación de Slack con Incoming Webhooks, vinculada a un canal privado.
- Permisos para crear workflows y Data Tables en n8n.
4. Crear una credencial OAuth 2.0 de solo lectura
- En Google Cloud, habilita Admin SDK API para tu proyecto.
- Configura el consentimiento OAuth de acuerdo con el tipo de aplicación y los usuarios autorizados.
- Crea el cliente OAuth e incorpora la URL de redirección exacta que n8n muestra al configurar su credencial.
- En HTTP Request, utiliza una credencial OAuth de Google con una cuenta que tenga permisos para consultar auditoría.
El alcance mínimo recomendado para este caso es:
https://www.googleapis.com/auth/admin.reports.audit.readonly
El scope permite leer reportes de auditoría y no autoriza operaciones generales de escritura sobre usuarios. Debes revisar también los permisos reales del usuario que concede el consentimiento.
5. Consultar Google Reports API y activar paginación
Configura un HTTP Request con método GET y este endpoint:
https://admin.googleapis.com/admin/reports/v1/activity/users/all/applications/admin
En Send Query Parameters, agrega maxResults = 1000 y startTime con una ventana superpuesta de 48 horas:
{{ $now.toUTC().minus({ hours: 48 }).toISO() }}
Google utiliza un nextPageToken para indicar que hay otra página. Activa Options → Pagination → Update a Parameter in Each Request, selecciona Type: Query y Name: pageToken. En Value utiliza:
{{ $response.body.nextPageToken }}
En Pagination Complete When: Other configura:
{{ !$response.body?.nextPageToken && $response.statusCode === 200 }}
Como control inicial puedes fijar Max Pages = 20 y Interval Between Requests = 200 ms. El límite evita bucles interminables, pero si la última página todavía incluye nextPageToken debes considerar la consulta incompleta y atender el error, no ignorar silenciosamente esos eventos.
maxResults a 10. Si tu dominio tiene más actividades, recibirás varias páginas y podrás verificar que el clasificador procesa todas. Al terminar restaura 1000.¿Por qué consultar 48 horas cada cinco minutos? Porque los datos pueden tardar en aparecer y el solapamiento ayuda a recuperar registros retrasados. No es una garantía absoluta: Google advierte que pueden existir demoras excepcionales y algunos eventos incluso podrían no informarse. Para mayor cobertura, añade una comprobación histórica independiente.
6. Clasificador de seguridad: código JavaScript completo
Añade un nodo Code en modo Run Once for All Items. El siguiente ejemplo procesa las páginas recuperadas, propone dos niveles de riesgo y conserva el identificador, actor, IP y fecha de cada evento.
Importante: las listas CRITICAL y HIGH son una política ilustrativa. Debes contrastar los nombres exactos de eventos con los que entrega tu organización y con la documentación oficial.
/**
* Ejemplo educativo — Admin SDK Reports API + n8n
* Code node: Run Once for All Items
* Reglas ilustrativas: contrastar los nombres con la API real.
*/
const CRITICAL = new Set([
'GRANT_ADMIN_PRIVILEGE',
'REVOKE_ADMIN_PRIVILEGE',
'DELETE_USER'
]);
const HIGH = new Set([
'CHANGE_PASSWORD',
'RESET_SIGNIN_COOKIES',
'CHANGE_GMAIL_SETTING',
'CREATE_GMAIL_SETTING',
'CREATE_USER'
]);
function unwrap(value) {
if (!value || typeof value !== 'object') return null;
if (Array.isArray(value.items)) return value;
if (value.kind === 'admin#reports#activities') return { ...value, items: [] };
if (value.body) return unwrap(value.body);
if (value.data) return unwrap(value.data);
return null;
}
const pages = $input.all().map((input, i) => {
const page = unwrap(input.json);
if (!page) throw new Error(`Página ${i + 1} sin formato esperado`);
return page;
});
if (pages.length === 0) throw new Error('La API no entregó páginas');
if (pages[pages.length - 1].nextPageToken) {
throw new Error('Paginación incompleta: aumentar Max Pages y reintentar');
}
const output = [];
const seen = new Set();
for (const activity of pages.flatMap(p => p.items)) {
const qualifier = activity.id?.uniqueQualifier;
if (qualifier == null) throw new Error('Actividad sin uniqueQualifier');
const app = activity.id?.applicationName || 'admin';
for (const [index, event] of (activity.events || []).entries()) {
const name = String(event.name || 'UNKNOWN').toUpperCase();
const severity = CRITICAL.has(name) ? 'CRITICAL'
: HIGH.has(name) ? 'HIGH' : 'IGNORE';
if (severity === 'IGNORE') continue;
const event_id = [app, String(qualifier), String(index), name].join(':');
if (seen.has(event_id)) continue;
seen.add(event_id);
const params = Array.isArray(event.parameters) ? event.parameters : [];
const target = [
'USER_IMPACTED_EMAIL', 'AFFECTED_USER_EMAIL',
'TARGET_USER_EMAIL', 'USER_EMAIL'
].map(key => params.find(p => String(p.name).toUpperCase() === key)?.value)
.find(Boolean) || null;
output.push({ json: {
source: 'google_workspace', event_id,
severity, event_name: name,
event_type: String(event.type || 'UNKNOWN').toUpperCase(),
timestamp: activity.id?.time || null,
actor_email: activity.actor?.email || null,
ip_address: activity.ipAddress || null,
target_email: target,
activity_id: String(qualifier), event_index: index
}});
}
}
return output;
Al formar event_id con aplicación, uniqueQualifier, índice del evento y nombre se consigue un identificador estable para la misma actividad. Mantén ese formato sin cambios una vez que comiences a registrar eventos, o la deduplicación dejará de coincidir con los registros previos.
7. Deduplicar eventos mediante Data Tables
Crea una Data Table de ejemplo llamada workspace_audit_seen con las columnas siguientes:
| Columna | Tipo | Finalidad |
|---|---|---|
event_id |
String | Identificador para buscar duplicados. |
severity |
String | CRITICAL o HIGH. |
event_name |
String | Acción registrada. |
actor_email |
String | Administrador que realizó la acción. |
ip_address |
String | IP observada, si existe. |
target_email |
String | Cuenta afectada, si existe. |
timestamp |
Date | Fecha del evento en UTC. |
status |
String | baseline, logged_high o sent_to_slack. |
processed_at |
Date | Fecha de procesamiento. |
En Loop Over Items usa tamaño de lote 1 y conecta un nodo Data Table → Row → Get con la condición event_id equals el identificador actual. Activa Always Output Data para que el nodo entregue un item vacío cuando no hay coincidencias. Un IF puede evaluar si existe el campo id.
- Si existe, no repitas la notificación y regresa al loop.
- Si no existe y el evento es HIGH, regístralo como
logged_high, sin enviar Slack. - Si no existe y es CRITICAL, envíalo a Slack y registra
sent_to_slackúnicamente después de confirmar la respuesta.
En la puesta en marcha inicial, marca los registros históricos como baseline para evitar un envío masivo de eventos anteriores a la instalación.
8. Enviar una alerta a Slack y verificar la respuesta
En la rama CRITICAL agrega Edit Fields y crea un campo text. Si el nodo que procesa los eventos se llama Loop Over Items, esta expresión recupera los datos originales:
{{
'🚨 *ALERTA | GOOGLE WORKSPACE*\n' +
'*Severidad:* ' + $('Loop Over Items').item.json.severity + '\n' +
'*Evento:* ' + $('Loop Over Items').item.json.event_name + '\n' +
'*Administrador:* ' + ($('Loop Over Items').item.json.actor_email || 'No disponible') + '\n' +
'*IP:* ' + ($('Loop Over Items').item.json.ip_address || 'No disponible') + '\n' +
'*Fecha UTC:* ' + ($('Loop Over Items').item.json.timestamp || 'No disponible') + '\n' +
'*Event ID:* ' + $('Loop Over Items').item.json.event_id
}}
Conecta un HTTP Request con POST, Body Content Type: JSON y un parámetro llamado text cuyo valor es {{ $json.text }}. Guarda la dirección del webhook como credencial o secreto del entorno, nunca en una publicación.
Slack generalmente responde con HTTP 200 y el texto ok cuando recibe correctamente un Incoming Webhook. En Options → Response activa la inclusión del estado y de la respuesta en formato Text. Valida esos dos valores antes de insertar sent_to_slack; si falla, detén el flujo y genera una alerta de error.
9. Monitorear errores y realizar pruebas controladas

Crea un segundo workflow con Error Trigger → Edit Fields → HTTP Request (Slack). Después, en los ajustes del workflow principal, asígnalo en Error Workflow. Incluye el nombre del workflow, nodo afectado, mensaje de error y enlace de ejecución cuando estén disponibles.
Para probar un evento real sin modificar cuentas ni permisos, identifica un registro administrativo benigno y añade una excepción temporal muy específica en el clasificador, marcada claramente como PRUEBA — NO ES INCIDENTE. Tras comprobar recepción y deduplicación, elimina esa excepción.
Los Error Trigger no se prueban ejecutando manualmente el flujo principal: se disparan por fallos en ejecuciones automáticas. Tampoco detectan necesariamente la caída completa de n8n. Si el monitoreo es crítico, configura una verificación externa de disponibilidad.
Comprobaciones antes de publicar
- Permisos OAuth mínimos, credenciales protegidas y acceso autorizado.
- Paginación completa sin tokens pendientes, o error visible si se alcanza el límite.
- Eventos históricos en baseline y nuevo evento crítico de prueba confirmado.
- Data Table con acceso restringido y política de retención.
- Workflow de errores asignado y programación cada cinco minutos verificada.
10. Preguntas frecuentes
¿Esta integración también monitorea los inicios de sesión?
No. La URL de este tutorial consulta eventos de la aplicación admin. Los eventos de acceso de usuarios requieren otra fuente o consulta específica.
¿Por qué no veo en Slack las alertas de Google Alert Center?
Porque Alert Center y Admin log events son sistemas distintos. Para monitorear directamente las alertas generadas por Google se debe integrar también la Alert Center API.
¿Las alertas llegan realmente en tiempo real?
No necesariamente. La programación cada cinco minutos no elimina la latencia con la que Google incorpora eventos a sus reportes; incluso puede haber retrasos excepcionales.
¿Puedo hacerlo sin una base de datos externa?
Sí. n8n Data Tables es suficiente para muchos escenarios de deduplicación ligera o moderada. Para grandes volúmenes o cumplimiento estricto puede ser preferible un almacén de auditoría especializado.
¿Cómo evito notificaciones repetidas?
Utiliza identificadores estables y consulta Data Table antes de notificar. Para eliminar duplicados durante fallos y concurrencia necesitarás un diseño más robusto de idempotencia o reconciliación.
Conclusión
Una integración entre Google Workspace, n8n y Slack permite convertir la auditoría administrativa en señales operativas relevantes. Consulta, paginación, clasificación, deduplicación y manejo de errores son los componentes que vuelven útil el sistema. No sustituye a un SIEM ni a una respuesta profesional a incidentes, pero constituye una base sólida para mejorar visibilidad y tiempos de reacción.
Documentación oficial y referencias técnicas
- Google: Admin SDK Reports API — activities.list
- Google: permisos OAuth de Reports API
- Google: retrasos y retención de registros
- n8n: HTTP Request y paginación
- n8n: Data Tables
- n8n: manejo de errores
- Slack: Incoming Webhooks
Nota: los ejemplos son educativos, sin datos privados. Verifica nombres de eventos y políticas antes de utilizarlos en un entorno productivo.

