Volver al blog

Stack de Cumplimiento SOC 2: Fleet, Wazuh y Keycloak para Equipos Pequeños

28 de febrero de 202610 min
Dispositivos y datos

Ingeniería de Seguridad · Análisis Técnico en Profundidad

Los marcos de cumplimiento de seguridad existen para responder una pregunta incómoda: ¿Puedes demostrar que tus sistemas son seguros? No afirmarlo — demostrarlo con logs, alertas y rastros de auditoría que resistan el escrutinio de terceros.

ToolRoleLicense
Keycloak
Keycloak
Identity Layer (0) — SSO, SAML, OIDC, MFA, and a full audit log of every auth eventOpen Source · Apache 2.0
Wazuh
Wazuh
SIEM & Compliance Engine — log ingestion, threat correlation, SOC 2 / HIPAA / PCI dashboardsOpen Source · GPL
Fleet
Fleet
Query & Inventory Layer — osquery across all endpoints, queryable compliance recordOpen Source · MIT
🔬
OpenEDR
Behavioral Detection Layer — process trees, credential access, lateral movement via MITRE ATT&CKOpen Source · Apache 2.0
🚫
Fail2ban
Active Response Layer — bans offending IPs via firewall rules, immutable response audit trailOpen Source · GPL
📧
MXToolbox
Email & Domain Security — continuous SPF, DKIM, DMARC, and blacklist monitoringFree monitoring tier
Falco
Falco
Runtime Detection Layer — eBPF syscall interception on Linux servers and containersOpen Source · Apache 2.0
Shuffle
Shuffle
SOAR & Automation Layer — connects Wazuh, Fleet, Keycloak, Fail2ban, and Rocket.Chat into response workflowsOpen Source · Apache 2.0

El Stack de Aplicaciones

Keycloak — Capa de Identidad (Capa 0)

  • Centraliza la autenticación en todos los dispositivos y servidores mediante SSO, SAML y OIDC
  • Produce un registro de auditoría completo de cada inicio de sesión, emisión de token y acción administrativa

Para un despliegue de Keycloak totalmente gestionado en PikaPods, consulta Hosting sin dolores de cabeza: ejecuta WordPress, Ghost y Keycloak en PikaPods.

▶ show code
# Setup Steps
1. Deploy via Docker or dedicated 2 vCPU / 4 GB host
2. Create a dedicated realm — never use master for app logins
3. Create OIDC clients for Wazuh, Shuffle, Fleet, and Rocket.Chat
4. Enforce TOTP MFA via Required Actions
5. Set password policy: 12+ chars, special char, digit, history 5
6. Enable full event logging with 90+ day expiration
7. Wire Wazuh Dashboard SAML/OIDC via roles_mapping.yml
▶ show code
// Enable full event logging (realm settings)
// Keycloak realm settings — enable full event logging
{
  "eventsEnabled": true,
  "eventsExpiration": 7776000,
  "adminEventsEnabled": true,
  "adminEventsDetailsEnabled": true,
  "enabledEventTypes": [
    "LOGIN", "LOGIN_ERROR", "LOGOUT",
    "REGISTER", "REGISTER_ERROR",
    "UPDATE_PASSWORD", "UPDATE_PASSWORD_ERROR",
    "CLIENT_LOGIN", "CLIENT_LOGIN_ERROR"
  ]
}

<!-- Wazuh agent — read Keycloak log output -->
<!-- ossec.conf — on Keycloak host -->
<ossec_config>
  <localfile>
    <log_format>json</log_format>
    <location>/opt/keycloak/data/log/keycloak.log</location>
    <label key="source">keycloak</label>
  </localfile>
</ossec_config>

<!-- Wazuh rules — login failures and admin privilege changes -->
<!-- keycloak_rules.xml -->
<group name="keycloak,authentication,">
  <rule id="92001" level="8">
    <decoded_as>json</decoded_as>
    <field name="source">keycloak</field>
    <field name="type">LOGIN_ERROR</field>
    <description>Keycloak: Authentication failure</description>
    <group>pci_dss_10.2.4,hipaa_164.312.b,soc2_cc6.1,</group>
  </rule>
  <rule id="92002" level="12" frequency="5" timeframe="60">
    <if_matched_sid>92001</if_matched_sid>
    <description>Keycloak: Brute force attack — 5+ failures in 60 seconds</description>
    <group>pci_dss_10.6.1,hipaa_164.312.b,</group>
  </rule>
  <rule id="92003" level="10">
    <decoded_as>json</decoded_as>
    <field name="source">keycloak</field>
    <field name="operationType">CREATE|UPDATE|DELETE</field>
    <field name="resourceType">USER|ROLE_MAPPING|CLIENT_ROLE_MAPPING</field>
    <description>Keycloak: Admin privilege change detected</description>
    <group>pci_dss_8.5,soc2_cc6.1,</group>
  </rule>
</group>

Wazuh — Motor SIEM y de Cumplimiento

  • Ingiere logs de prácticamente cualquier fuente y aplica reglas de correlación para detectar amenazas y violaciones de política
  • Los paneles de cumplimiento mapean cada evento a requisitos de control específicos — listos para auditoría sin semanas de trabajo manual
▶ show code
# Setup Steps
# Deploy Wazuh Manager + Indexer + Dashboard
1. Provision 4 vCPU, 8 GB RAM, 50+ GB SSD
2. Set hostname and configure /etc/hosts for local FQDN
3. Run the Wazuh all-in-one installer script
4. Confirm all three services are running
5. Log in and immediately change the default admin password
6. Lock firewall to ports 1514, 1515, and 443 only

# Install Wazuh Agents on all endpoints + Keycloak host
1. Linux: dpkg install with WAZUH_MANAGER env set
2. macOS: .pkg install + launchctl load
3. Windows: msiexec silent install
4. Verify each agent appears in dashboard within 60 seconds
5. Enable FIM on Keycloak config and log directories
6. Tag agents by group for policy segmentation

# Enable Wazuh Compliance Modules
1. Enable compliance dashboards in Wazuh → Modules
2. Verify ruleset includes compliance tags
3. Download and deploy NIST/CIS SCA policy files to agent groups
4. Run initial SCA scan and review compliance %
5. Document failing controls as tracked exceptions

# Configure Alert Routing
1. Email: configure SMTP in ossec.conf, set alert level >= 10
2. Phone/SMS: bridge via PagerDuty, OpsGenie, or Shuffle → Twilio
3. Rocket.Chat: configure incoming webhook in Wazuh or Shuffle
4. Test all channels with ossec-logtest

# Set ILM Retention Policies
1. Identify longest requirement (HIPAA = 6 years)
2. Create ILM policy: hot 7d → warm 30d → cold → delete at limit
3. Apply to wazuh-alerts-* and wazuh-archives-* templates
4. Size storage at ~1 GB/day per 100 agents
5. Configure S3 or NFS snapshot repo for cold storage
6. Document policy for audit evidence

Fleet — Capa de Consultas e Inventario

  • Gestiona osquery en todos los endpoints — servidores, estaciones de trabajo e instancias en la nube
  • Le da a los auditores un registro consultable del estado del sistema a lo largo del tiempo, no una instantánea de un momento puntual
  • Complemento WireGuard — combina Fleet con WireGuard para exigir la presencia de un túnel VPN como política de Fleet; osquery puede verificar que la interfaz de WireGuard esté activa en cada dispositivo inscrito antes de otorgar acceso a recursos internos
▶ show code
# Setup Steps
# Stand up Fleet + osquery
1. Deploy Fleet with MySQL + Redis backend (or Docker preview)
2. Configure TLS with Let's Encrypt or internal CA
3. Generate and distribute enroll secret via MDM
4. Confirm all hosts appear in Fleet UI within 5 minutes
5. Set agent update channel to stable with auto-update enabled

# Configure Fleet → Filebeat → Wazuh pipeline
1. Install Filebeat on the Fleet host (not the Wazuh server)
2. Point Filebeat input at Fleet's log output directory
3. Enable and configure the Wazuh Filebeat module
4. Test output: filebeat test output
5. Verify Fleet events appear in Wazuh Discover

# Schedule Fleet Compliance Queries
1. SELECT * FROM disk_encryption; — every 24h
2. SELECT username, uid, shell FROM users WHERE uid >= 1000; — every 12h
3. SELECT name, version, source FROM software; — every 24h
4. SELECT * FROM authorized_keys; — every 6h on servers
5. Create pass/fail Fleet Policies for FileVault/BitLocker status
6. Route query results through Fleet log pipeline → Filebeat → Wazuh
▶ show code
# Fleet result log configuration
# fleet.yml — result log configuration
logging:
  result:
    plugin: filesystem
    config:
      result_log_file: /var/log/fleet/osquery_results.log
  status:
    plugin: filesystem
    config:
      status_log_file: /var/log/fleet/osquery_status.log

# Filebeat — forward Fleet logs to Wazuh
# filebeat.yml
filebeat.inputs:
  - type: log
    enabled: true
    paths:
      - /var/log/fleet/osquery_results.log
    fields:
      source: fleet-osquery
      compliance: true

output.logstash:
  hosts: ["wazuh-manager:5044"]
  ssl.certificate_authorities: ["/etc/filebeat/wazuh-ca.pem"]

OpenEDR — Capa de Detección de Comportamiento

  • Monitoreo de comportamiento continuo para árboles de procesos, patrones de acceso a credenciales, movimiento lateral y anomalías del sistema de archivos
  • Telemetría modelada según el framework MITRE ATT&CK

Despliega el agente de Wazuh junto con OpenEDR en cada endpoint. Configura el agente para leer directamente la telemetría JSON de OpenEDR, y luego mapea las categorías de MITRE ATT&CK a grupos de control de cumplimiento.

▶ show code
<!-- Wazuh agent — read OpenEDR telemetry and Windows Security Event Log -->
<!-- ossec.conf — on each endpoint -->
<ossec_config>
  <localfile>
    <log_format>json</log_format>
    <location>C:\ProgramData\OpenEDR\Logs\*.json</location>
    <label key="source">openedr</label>
  </localfile>
  <!-- Windows Security Event Log for HIPAA audit trail -->
  <localfile>
    <log_format>eventchannel</log_format>
    <location>Security</location>
  </localfile>
</ossec_config>

<!-- Wazuh rules — MITRE ATT&CK credential access detection -->
<!-- openedr_rules.xml -->
<group name="openedr,mitre,">
  <rule id="91001" level="12">
    <decoded_as>json</decoded_as>
    <field name="source">openedr</field>
    <field name="threat.type">credential_access</field>
    <description>OpenEDR: Credential access attempt detected</description>
    <mitre><id>T1003</id></mitre>
    <group>pci_dss_10.6.1,hipaa_164.312.b,</group>
  </rule>
</group>

Fail2ban — Capa de Respuesta Activa

  • Monitorea archivos de log en busca de fallos de autenticación repetidos y bloquea automáticamente las IPs infractoras mediante reglas de firewall
  • Produce el rastro de auditoría de respuesta automatizada e inmutable que exige PCI DSS Req. 10 y SOC 2 CC7
▶ show code
# Setup Steps
1. Install on all internet-facing servers
2. Copy jail.conf → jail.local; enable sshd and nginx-http-auth jails
3. Set bantime = 1h, findtime = 10m, maxretry = 5
4. Configure JSON log output for Wazuh ingestion
5. Add Wazuh FIM watch on /etc/fail2ban/
6. Add active-response block in ossec.conf on rule 30105
7. Test: 5 bad SSH attempts → confirm ban + Wazuh alert fires

Wazuh dispara Fail2ban (respuesta activa): Wazuh detecta patrones de fuerza bruta en SSH, RDP, aplicaciones web y fallos de inicio de sesión en Keycloak, y luego llama a Fail2ban para bloquear la IP de origen:

▶ show code
<!-- Wazuh active response configuration -->
<!-- ossec.conf — on Wazuh Manager -->
<ossec_config>
  <active-response>
    <command>fail2ban</command>
    <location>local</location>
    <rules_id>5763,5764,92002</rules_id>  <!-- SSH brute force + Keycloak brute force -->
    <timeout>3600</timeout>
  </active-response>
</ossec_config>

#!/bin/bash
# /var/ossec/active-response/bin/fail2ban.sh
ACTION=$1
USER=$2
IP=$3

if [ "$ACTION" = "add" ]; then
  fail2ban-client set wazuh-response banip "$IP"
elif [ "$ACTION" = "delete" ]; then
  fail2ban-client set wazuh-response unbanip "$IP"
fi

# /etc/fail2ban/jail.d/wazuh-response.conf
[wazuh-response]
enabled = true
banaction = iptables-multiport
port = all
filter =
logpath = /var/log/wazuh-response.log
maxretry = 1
bantime = 3600

Los logs de Fail2ban alimentan a Wazuh (rastro de auditoría): Cada bloqueo y desbloqueo se convierte en un evento de Wazuh — creando un registro inmutable de respuestas automatizadas para PCI DSS Req. 10.2 y SOC 2 CC7:

▶ show code
<!-- Fail2ban log ingestion and audit rules -->
<!-- ossec.conf — Fail2ban log ingestion -->
<ossec_config>
  <localfile>
    <log_format>syslog</log_format>
    <location>/var/log/fail2ban.log</location>
    <label key="source">fail2ban</label>
  </localfile>
</ossec_config>

<!-- fail2ban_rules.xml -->
<group name="fail2ban,">
  <rule id="93001" level="8">
    <decoded_as>fail2ban</decoded_as>
    <match>Ban</match>
    <description>Fail2ban: IP banned after repeated failures</description>
    <group>pci_dss_10.2.4,pci_dss_10.6.1,soc2_cc7.2,</group>
  </rule>
  <rule id="93002" level="6">
    <decoded_as>fail2ban</decoded_as>
    <match>Unban</match>
    <description>Fail2ban: IP ban expired and lifted</description>
    <group>pci_dss_10.2.4,</group>
  </rule>
</group>

El resultado es un bucle cerrado: Wazuh detecta → Fail2ban bloquea → Fail2ban registra la acción → Wazuh la guarda como un evento de cumplimiento con marca de tiempo e IP completas.


MXToolbox — Seguridad de Correo y Dominio

  • Monitoreo pasivo de la salud del dominio de correo — verifica continuamente los registros SPF, DKIM y DMARC
  • Un DMARC mal configurado o una IP en lista negra pueden habilitar la suplantación de dominio o causar fallos en la notificación de brechas
▶ show code
# Setup Steps
1. Add blacklist monitors for all outbound mail server IPs
2. Add DNS monitors for SPF, DKIM, DMARC health on all sending domains
3. Add MX record monitors to detect tampering
4. Route MXToolbox webhooks into Shuffle → Wazuh for centralized logging

Falco — Capa de Detección de Comportamiento en Tiempo de Ejecución

  • Interceptación de syscalls basada en eBPF — detecta amenazas a nivel de kernel sin que los agentes modifiquen el código del endpoint
  • Cubre el vacío que deja OpenEDR en servidores y contenedores Linux, donde los agentes EDR de Windows no aplican

Despliega Falco en cada endpoint Linux para detección de comportamiento en tiempo de ejecución basada en eBPF. Falco intercepta llamadas al sistema y mapea anomalías — shells generadas desde procesos web, escrituras masivas de archivos, escalamientos de privilegios — a técnicas de MITRE ATT&CK, alimentando eventos JSON estructurados directamente a Wazuh.

▶ show code
# Setup Steps
1.  Add the Falco apt repo and install: apt install -y falco
2.  Select eBPF driver at install — do not use kernel module on production hosts
3.  Install driver: falcoctl driver install --type ebpf
4.  Enable service: systemctl enable --now falco
5.  Set json_output: true in /etc/falco/falco.yaml
6.  Configure file output to /var/log/falco/falco.json
7.  Add custom rules to falco_rules.local.yaml (mass file writes, shells from web processes)
8.  Add Wazuh <localfile> block to tail /var/log/falco/falco.json
9.  Restart Wazuh agent and confirm Falco events appear in Wazuh Discover
10. Add custom Falco decoder and rules in local_rules.xml on the Wazuh manager

Shuffle — Capa SOAR y de Automatización

  • Conecta Wazuh, Fleet, Keycloak, Fail2ban y Rocket.Chat en flujos de trabajo de respuesta automatizada
  • Cada acción automatizada se registra como una ejecución de flujo de trabajo con marca de tiempo — proporcionando el rastro de auditoría de respuesta que exigen los auditores

Despliega Shuffle SOAR para automatizar el triage, el enriquecimiento y la respuesta en todo el stack. Las alertas de Wazuh disparan flujos de trabajo de Shuffle que consultan a Fleet por contexto del host, llaman a la respuesta activa de Wazuh para bloquear IPs, y notifican a Rocket.Chat con detalles enriquecidos del incidente.

▶ show code
# Setup Steps
1.  Provision dedicated host: 2 vCPU / 4 GB RAM / 20 GB disk
2.  Install Docker + Compose: curl -fsSL https://get.docker.com | sh
3.  Clone Shuffle repo, set OUTER_HOSTNAME in docker-compose.yml, run docker compose up -d
4.  Restrict login to Keycloak OIDC immediately after first launch
5.  Install the Wazuh and HTTP apps from the Shuffle app library
6.  Configure Wazuh app with manager URL and a least-privilege API user
7.  Create a Webhook trigger in Shuffle and copy the hook URL
8.  Add the Shuffle <integration> block to Wazuh ossec.conf with the webhook URL
9.  Restart Wazuh manager and confirm test alerts arrive in Shuffle → Executions
10. Build triage playbook: parse alert level → if >= 12, call Wazuh active response → notify Rocket.Chat
11. Build Falco playbook: filter on falco rule group → enrich via Fleet/osquery → alert with host + process context
12. Build FIM rollback playbook: filter on rule 550/554 → SSH to agent → trigger restic/VSS restore → notify
13. Test each playbook end-to-end with ossec-logtest synthetic alerts
14. Set execution history retention to 30 days in Shuffle Settings

Configuración de Alertas

Enruta las alertas de Wazuh por severidad para asegurar que el equipo correcto sea notificado en el momento correcto:

SeveridadDestinoCondiciones de Disparo
Nivel 12+ (crítico)Email + TeléfonoAmenazas activas, acceso a credenciales, incumplimiento de política
Nivel 8–11 (alto)Rocket.Chat #securityNuevas cuentas de administrador, ráfagas de inicios de sesión fallidos, desviación de configuración
Resumen semanalEmailTasas de cumplimiento/incumplimiento y tendencias de alertas
Exportación pre-auditoríaPDFLos paneles de cumplimiento de Wazuh se exportan directamente para paquetes de evidencia SOC 2 / PCI

Marcos de Seguridad Cubiertos por Este Stack

  • Las Cinco Funciones del NISTPrioridad: Crítica. El marco estratégico utilizado para organizar todo el ciclo de vida de defensa de red y servidores. Cada herramienta de este stack se corresponde directamente con una o más de las cinco funciones: Identificar (Fleet, Keycloak), Proteger (Fail2ban, WireGuard), Detectar (Wazuh, OpenEDR, Falco), Responder (Shuffle, Fail2ban), y Recuperar (guías de Wazuh, flujos de trabajo de Shuffle).
  • CWE — La cobertura de Common Weakness Enumeration se aborda mediante la detección de comportamiento de OpenEDR y la biblioteca de reglas de Wazuh, que marca patrones de debilidad conocidos (inyección, escalamiento de privilegios, autenticación inadecuada) a nivel de proceso y de log.
  • CIS Docker BenchmarksPrioridad: Alta. El estándar de referencia para el endurecimiento de los entornos de servidores en contenedores donde viven las apps modernas. Wazuh incluye reglas de auditoría de CIS Docker Benchmark listas para usar; las políticas de osquery de Fleet pueden verificar el cumplimiento del benchmark de forma continua en cada host que ejecute contenedores.

Respondiendo Preguntas de Auditores

"Muéstrame tu monitoreo de control de acceso." Exporta el panel de Wazuh SOC 2 CC6. El historial de consultas de Fleet muestra el estado de la cuenta de usuario de cada host durante todo el período de auditoría. Los registros de eventos de administrador de Keycloak muestran cada otorgamiento y revocación de privilegios.

"Muéstrame tu capacidad de detección de incidentes." El mapa de cobertura de MITRE ATT&CK de OpenEDR combinado con las estadísticas de reglas de Wazuh demuestra detección activa en toda la superficie de ataque. Los registros de bloqueos de Fail2ban muestran la respuesta automatizada a intentos activos de fuerza bruta.

"¿Hubo algún incidente de seguridad durante el período de auditoría?" El historial de alertas de Wazuh proporciona un registro completo, con marca de tiempo e inmutable. Que existan incidentes significa que tu proceso de detección y respuesta funcionó según lo diseñado.

"¿Cómo detectas cambios de software no autorizados?" Las consultas de inventario de software de Fleet y el File Integrity Monitoring (FIM) de Wazuh proporcionan un registro continuo de qué se instaló, cuándo y en qué host.

"¿Cómo aplicas la MFA y gestionas el acceso de usuarios?" Keycloak aplica la MFA en la capa de identidad para todos los servicios internos. Sus registros de auditoría, ingeridos por Wazuh, proporcionan un registro con marca de tiempo de cada evento de autenticación y cambio administrativo.

Esta arquitectura escala desde una startup de 50 endpoints que busca SOC 2 Type I hasta una empresa de 10,000 endpoints que mantiene la certificación PCI DSS. La base open source mantiene los costos de licenciamiento cerca de cero, y el diseño modular permite agregar feeds comerciales de EDR, logs de seguridad en la nube, o monitoreo de red sin reemplazar el pipeline central.

Ponte en contacto

¿Te interesa un tema? Déjame una nota y elige una categoría. También estoy disponible para una reunión de consultoría gratuita: escríbeme y lo organizamos.