
Una plataforma SIEM, EDR y SOAR de código abierto, autoalojada y potenciada por IA, diseñada para operaciones de seguridad modernas.
Stack de seguridad autoalojado para equipos pequeños/medianos que no tienen un
SOC dedicado. Coloca un agente en cada endpoint, apúntalos al servidor, y obtienes
registros SIEM, integridad de archivos, vulnerabilidades de paquetes, un explorador
de registros basado en OpenSearch, triaje autónomo con IA y un motor de playbooks SOAR, todo en un
solo docker compose up.
La parte de "IA" es un modelo Ollama que se ejecuta localmente (por defecto llama3.2:3b).
Los registros nunca salen de la máquina; no hay clave de OpenAI, ni clave de Anthropic, ni
llamadas a casa. Si quieres un modelo más inteligente y tienes RAM, cámbialo en .env.

Recopila telemetría de agentes Windows y Linux a través de un único canal TCP. Eventos SIEM, alertas, FIM, paquetes, conexiones de red, puertos abiertos, actividad de Docker, capturas de pantalla.
Detecta con reglas Sigma, en el endpoint. 23 reglas que cubren 23 técnicas
de MITRE ATT&CK se incluyen en conf/sigma/builtin/; coloca conjuntos de reglas de la comunidad
junto a ellas. Sigma compara campos con nombre en lugar de texto, por lo que
Image|endswith: '\vssadmin.exe' no puede ser derrotado por la palabra "vssadmin"
apareciendo en un mensaje no relacionado — y
CommandLine|utf16le|base64offset|contains lee dentro de un payload
-EncodedCommand en base64, donde la línea de comandos en texto plano muestra solo el
envoltorio. Medido en el corpus de evaluación: 9 de 10 ataques detectados solo por Sigma,
0 de 9 negativos duros marcados falsamente. Esta capa es determinista y sigue
funcionando cuando el modelo no está disponible.
Correlaciona entre eventos, algo que ninguna regla por evento puede hacer. Un único
inicio de sesión fallido es rutinario; cinco cuentas fallando desde una misma fuente en cuarenta segundos es un
ataque de fuerza bruta por pulverización (password spray), y mirar cualquiera de esos cinco eventos nunca te
lo dirá. Cubre pulverización, fuerza bruta, un éxito que llega después de fallos
repetidos, y ráfagas de creación de cuentas o instalación de servicios — en ambas
plataformas, desde IDs de eventos de Windows o desde líneas de auth.log analizadas.
Se ejecuta en dos puntos de observación, porque ven ataques diferentes. Por host en el agente, donde un ataque contra una máquina es visible en su totalidad. Y entre hosts en la ruta de ingesta, donde una pulverización que recorrió un fallo a la vez sobre cincuenta máquinas aparece — ningún agente individual ve más de un evento, y ese es el ataque más competente, ya que pulverizar amplio y superficial se mantiene por debajo tanto del bloqueo por cuenta como de los umbrales por host.
Cobertura total con Sigma: 27 técnicas. Cada ventana se dispara una vez en lugar de una vez por evento, y cada contador está acotado — un contador basado en un nombre de usuario proporcionado por el atacante es una primitiva de agotamiento de memoria, no una detección.
Mapea las detecciones a MITRE ATT&CK, desde las propias reglas. Las reglas llevan
tags: attack.t1490, por lo que no hay una tabla de mapeo mantenida a mano que pueda quedar obsoleta. La
página de cobertura separa tres estados que un único "porcentaje de cobertura" ocultaría:
cubierto y visto, cubierto y silencioso, y no cubierto en absoluto — siendo el
último el único donde el silencio de la consola no significa nada.
Hace triaje de cada evento con un LLM local. Tres workers se ejecutan en paralelo:
uno observa cada evento entrante en tiempo real, uno ejecuta escaneos profundos
impulsados por el operador, y uno decide si tomar una acción defensiva
(BLOCK_IP, ISOLATE_HOST, KILL_PROCESS, etc.).
Modo sombra para el worker defensivo. Activa AI_SHADOW_MODE=1 y
cada veredicto autónomo se prepara para aprobación humana en el SOAR Hub
en lugar de ser despachado. Útil para ajustar el modelo con tráfico
real antes de dejarlo actuar por su cuenta.
Indexa todo en OpenSearch para que puedas buscar en tu flota con consultas difusas / exactas / de prefijo desde un solo lugar.
Ejecuta playbooks SOAR construidos en un pequeño editor visual con seguimiento de resultados multi-paso y por nodo, que pueden activarse manualmente o por veredicto de IA.
Escaneos de vulnerabilidades de los paquetes instalados de cada agente contra OSV (en línea o mediante un mirror interno).
Extrae fuentes de inteligencia de amenazas de abuse.ch (Feodo, ThreatFox, URLhaus) a una tabla local de indicadores, con poda por obsolescencia y un interruptor de aislamiento (air-gap).
Valida las configuraciones de los agentes antes de enviarlas. Análisis YAML, forma estructural y compilación de regex — una regex inválida es YAML válido y silenciosamente desactiva la regla que la contiene.
Escritorio remoto integrado mediante transmisión JPEG por WebSocket, sin necesidad de instalación separada de VNC en el endpoint.
La barra lateral agrupa todo en tres secciones: telemetría (panel, agentes, alertas, activos, FIM, registros, IA), respuesta de automatización (acciones defensivas, playbooks, reglas de automatización) y administración.
Cada agente registrado tiene su propia página con doce pestañas. La vista general muestra medidores de recursos en vivo, los registros SIEM más recientes, metadatos del agente y un resumen de amenazas:

Las alertas son todo lo que las propias reglas de correlación del agente ya han marcado. Con colores por severidad, filtrables, buscables:

La pestaña Análisis de IA es el lado orientado al operador del LLM local. Los escaneos manuales y automáticos aterrizan aquí. Cada insight lleva una etiqueta de veredicto, confianza, indicadores MITRE (cuando el modelo los devuelve), IOCs, siguientes pasos, y un botón Ver fuente que abre la fila de registro exacta que la IA observó:

Hardware, software y sockets de red por agente. La pestaña de hardware lista cada dispositivo PnP, el software lista los paquetes instalados, la red lista cada socket TCP/UDP con su proceso propietario:


Búsqueda entre agentes respaldada por OpenSearch. Elige un agente, elige un conjunto de datos (eventos SIEM, alertas de seguridad, eventos de procesos, red, FIM, registros de auditoría) y busca. También hay un botón para abrir OpenSearch Dashboards (fork de Kibana) para usuarios avanzados:

Cada intento de inicio de sesión contra la propia plataforma, tanto local como LDAP, con resultado, IP de origen y marca de tiempo. Útil cuando alguien está de humor "quién-inició-sesión-cuándo":

Necesitarás Docker 24+ con Compose v2 y Python 3.10+ en el host (solo para el paso único de compilación del agente). El stack completo requiere ~16 GB de RAM, consulta Requisitos del sistema a continuación.```bash git clone https://github.com/d3vhex/Sentora.git cd Sentora
cp .env.example .env
python scripts/init_secrets.py
cd Sentora ./build_agent.sh # on Linux/macOS/WSL
cd ..
docker compose up --build -d
Abra <http://localhost:8000>. El inicio de sesión predeterminado es `admin` / `admin123`.
Cámbielo inmediatamente en **Users & Roles**.
Ollama descarga automáticamente `llama3.2:3b` en el primer arranque. Verifíquelo con:```bash
docker exec sentora-ollama ollama list
Desplegar un agente: desde la página Deploy Agent, copia el comando de una línea para el sistema operativo que quieras. En la máquina de destino (shell de administrador), pégalo. El instalador descarga el binario, coloca una configuración, se registra con el servidor y se registra a sí mismo como una tarea programada / unidad systemd.
| Servicio | Puerto | Accesible desde | Propósito |
|---|---|---|---|
app | :8000 | cualquier lugar | API REST + interfaz React |
ingest | :5001 | cualquier lugar | Recopilador de registros TCP (el agente envía aquí) |
db | :3307 | localhost | MySQL 8.0 (3306 dentro de la red) |
rabbitmq | :5672 / :15672 | localhost | Cola de trabajos + interfaz de gestión |
ollama | :11434 | localhost | Entorno de ejecución LLM local |
opensearch | :9200 | localhost | Búsqueda de registros de texto completo |
opensearch-dashboards | :5601 | localhost | Explorador opcional estilo Kibana |
ai-worker-{automation,manual,defensive} | — | Trabajadores de análisis LLM |
Solo app e ingest escuchan en todas las interfaces. El resto se vincula a
BIND_ADDR (por defecto 127.0.0.1), porque ninguno de ellos se autentica en la
configuración predeterminada — OpenSearch se ejecuta con su plugin de seguridad deshabilitado y
Dashboards es una vista sin autenticación de cada registro recopilado. Expón uno
colocándolo detrás del mismo proxy inverso y autenticación que app, no ampliando
BIND_ADDR.
El botón "Open Dashboards" en Log Explorer enlaza al puerto 5601 en el nombre de host del servidor, por lo que funciona desde el propio host; los operadores remotos necesitan ese proxy inverso.
| Perfil | CPU | RAM | Disco | Notas |
|---|---|---|---|---|
| Laboratorio (≤ 5 agentes) | 4 núcleos | 12 GB | 40 GB SSD | llama3.2:3b, heap de OpenSearch a 1 GB |
| Equipo pequeño (10–50 agentes) | 8 núcleos | 16 GB | 100 GB SSD | Los valores predeterminados del compose están bien |
| Producción (50+ agentes) | 16+ núcleos | 32 GB+ | 250 GB+ NVMe | Mueve OpenSearch y Ollama a sus propios hosts |
Huella en reposo:
llama3.2:3b): ~3 GB, más durante la inferenciaSi tienes poca RAM, cambia a qwen2.5:1.5b u otro modelo pequeño de Ollama
y reduce el heap de OpenSearch. No se requiere GPU, pero Ollama
la usará automáticamente si está presente.
Cuando el veredicto del trabajador defensivo es ACT con confianza ≥
AI_AUTO_ACT_CONF (por defecto 0.75) y la acción recomendada está en la
lista segura a continuación, el trabajador pone la acción directamente en la cola de la tabla
automations del agente:```
BLOCK_IP KILL_PROCESS RESTART_SERVICE ISOLATE_HOST
DISABLE_USER QUARANTINE_FILE SUSPEND_PROCESS LOGOFF_USER
CONTAINER_ISOLATE CONTAINER_STOP CONTAINER_KILL
### Modo sombra
Establece `AI_SHADOW_MODE=1` en `.env` y el worker defensivo deja de disparar
acciones reales. Los veredictos que habrían activado una respuesta autónoma
se guardan como **propuestas** en su lugar, con `source_file = AI_DEFENSIVE_SHADOW`
y `shadow_status = pending`. El operador revisa cada una desde
**SOAR Hub > Shadow Queue** y puede:
- **Aprobar** > la acción SOAR real (`call_agent_soar`) se dispara y la
propuesta se marca como `approved` (con marca de tiempo + nombre del operador).
- **Rechazar** > la propuesta se marca como `rejected` con una nota opcional.
No se toma ninguna acción.
Las propuestas nunca caducan; nada decide por ti. Útil para dejar que el
modelo se ejecute sobre telemetría de producción mientras generas confianza
en sus veredictos antes de liberar `BLOCK_IP` / `ISOLATE_HOST` reales, etc.
---
## Notas de seguridad
### Autenticación
La interfaz se autentica con una sesión del lado del servidor: el inicio de sesión emite un token opaco
en una cookie `HttpOnly`, y `userdb.sessions` es la autoridad. Solo se
almacena el SHA-256 del token, por lo que un volcado de base de datos no produce nada utilizable.
Se aplican dos relojes, ambos configurables en `.env`:
| Configuración | Predeterminado | Significado |
| :--- | :--- | :--- |
| `SESSION_IDLE_MINUTES` | `60` | La sesión muere este tiempo después de su última solicitud |
| `SESSION_ABSOLUTE_HOURS` | `12` | Límite máximo independientemente de la actividad |
| `SESSION_COOKIE_SECURE` | `0` | Establecer en `1` una vez que TLS termine frente a la aplicación |
| `SESSION_COOKIE_SAMESITE` | `Lax` | `Lax` bloquea el POST/XHR entre sitios que CSRF necesita |
Las sesiones se revocan inmediatamente al cambiar la contraseña, restablecer la contraseña de administrador,
cambiar el rol y eliminar la cuenta: un administrador que elimina el acceso de alguien ya
no deja su pestaña abierta funcionando.
Cada ruta es **denegar por defecto**: sin una sesión válida, una solicitud se
rechaza antes de que se ejecute el handler. Las excepciones son el endpoint de inicio de sesión, el
shell SPA, los activos estáticos y los endpoints orientados a agentes, que se autentican
con `X-Agent-Key` o un token de inscripción en su lugar.
`X-User-ID` todavía lo envía el frontend, pero ya no es identidad: el
servidor lo valida contra la sesión y rechaza una discrepancia. Debido a que
los navegadores no pueden adjuntar encabezados personalizados a solicitudes entre sitios sin una
preflight CORS, exigirlo en solicitudes que cambian el estado respalda `SameSite` como
un segundo control CSRF.
La protección de rutas se declara con `@require_permission(...)` y se aplica mediante
middleware a través de un registro, por lo que se aplica independientemente de en qué lado de
`@app.route` se encuentre el decorador. El registro de arranque imprime el recuento:```
[Auth] Routes: <n> permission-gated, <n> session-only, <n> public.
Si esa línea informa 0 permission-gated, RBAC no se está aplicando — trátalo
como una interrupción del servicio.
Cada ruta debe ser una de tres cosas: con permiso restringido, listada en
_PUBLIC_HANDLERS, o nombrada en SESSION_ONLY_HANDLERS en
tests/test_auth_wiring.py con un comentario que explique por qué la sesión
sola es suficiente. Un test lo verifica, así que una ruta nueva no puede llegar
silenciosamente sin gobernanza — que es como run_playbook, delete_soar_action
y test_ldap_connection habían terminado siendo accesibles por cualquier cuenta
que pudiera iniciar sesión.
Cinco intentos fallidos para una cuenta, o veinte desde una dirección, dentro
de quince minutos, y los intentos posteriores se rechazan con 429 hasta que
pase la ventana. Se cuenta desde login_logs, que ya registraba cada fallo y
que nadie leía — bcrypt era el único freno contra la adivinación en línea.
| Configuración | Valor por defecto | Significado |
|---|---|---|
LOGIN_MAX_FAILURES_USER | 5 | Fallos por cuenta permitidos en la ventana |
LOGIN_MAX_FAILURES_IP | 20 | Fallos por dirección; más alto, porque una oficina comparte una única dirección NAT |
LOGIN_LOCKOUT_WINDOW_MIN | 15 | Cuánto hacia atrás se cuentan los fallos |
La comprobación se ejecuta antes de la comparación de contraseñas, por lo que
también elimina la diferencia de tiempo entre un nombre de usuario conocido y
uno desconocido. Falla en abierto si login_logs no es accesible: una página
de inicio de sesión que no se puede alcanzar porque la tabla de auditoría está
caída es su propia interrupción del servicio.
X-Forwarded-For solo se respeta desde un peer listado en TRUSTED_PROXIES
(direcciones o CIDRs separados por comas, vacío por defecto). Sin nada delante
de la aplicación, la cabecera la suministra el atacante, así que creerla
incondicionalmente — que es lo que esto reemplazó — permitía a un llamador
escribir cualquier dirección en el registro de auditoría y restablecer su propio
límite de tasa en la misma solicitud.```
TRUSTED_PROXIES=10.0.0.0/8,192.168.1.5
Déjalo vacío cuando se accede a la aplicación directamente.
### La API propia del agente
El agente escucha en `0.0.0.0:9099` y se ejecuta como SYSTEM o root. Cada ruta
requiere `X-Agent-Key`; `/self_destruct` requiere específicamente la clave de
inscripción de este propio agente, por lo que un secreto filtrado a nivel de
flota no puede desinstalar todos los endpoints a la vez. `/health` responde a
la comprobación de actividad sin clave y no revela nada más sin una.
No hay un respaldo permisivo. Una compilación anterior aceptaba cualquier clave
no vacía siempre que `AGENT_MASTER_SECRET` no estuviera definido en el host —
lo cual nunca se definía, por lo que era el valor predeterminado en todas
partes. Un EDR que falla en modo abierto es peor que ningún EDR, porque la
consola informa que el endpoint está protegido.
`AGENT_BIND` mueve el listener. Sigue siendo `0.0.0.0` por defecto porque el
servidor alcanza a los agentes a través de HTTP en este puerto; vincular a
loopback requiere un transporte de reemplazo, no un cambio de configuración.
### CORS
`CORS_ORIGINS` tiene un valor predeterminado vacío. En el despliegue normal,
esta aplicación sirve la SPA por sí misma, por lo que las solicitudes son del
mismo origen y no se necesita ninguna entrada. Un comodín se rechaza de plano:
los navegadores rechazan `Access-Control-Allow-Origin: *` en cualquier
solicitud que lleve cookies. Los despliegues de origen dividido deben listar
orígenes explícitos y establecer `SESSION_COOKIE_SAMESITE=None` con
`SESSION_COOKIE_SECURE=1`.
### Secretos predeterminados
`.env.example` incluye marcadores de posición. El `.env` real está ignorado por
git. Rota estos antes de exponer la plataforma a cualquier cosa más allá de
`localhost`:
- `DB_PASSWORD`
- `AGENT_SHARED_SECRET` (respaldo de autenticación del agente). Se genera
automáticamente en el primer arranque si no está definido.
El inicio de sesión `admin / admin123` ya no necesita recordarse: la cuenta
sembrada se crea con `must_change_password`, y mientras esté definido, la
sesión no puede alcanzar nada más que `/change-password`. Se aplica en el
middleware en lugar de en la interfaz, porque una bandera que se confía en que
el front end respete es una sugerencia, y la API también responde a curl.
### Certificados TLS
Nada incluye una clave privada. Un `certs/server.key` y `certs/rootCA.key`
funcionales solían estar comprometidos, lo que daba a cada despliegue la misma
identidad TLS y la publicaba: cualquiera que hubiera clonado el repositorio
tenía la clave, por lo que el certificado no demostraba nada sobre quién estaba
al otro lado.
Con `TLS_ENABLED=1` y sin certificado presente, la aplicación genera uno en el
primer arranque. Cada instalación obtiene su propia clave y la clave nunca
abandona la máquina que la creó. `certs/*.key` y `certs/*.crt` están ignorados
por git.
La CA tiene firma propia, por lo que los navegadores advierten a menos que
confíes en ella explícitamente. Esa advertencia es honesta — prefierela a un
secreto compartido que no produce ninguna advertencia. Para cualquier cosa
pública, apunta `TLS_CERT` / `TLS_KEY` a un certificado real; cuando están
definidos y faltan, la aplicación lo indica en lugar de sustituir uno con firma
propia.
Para regenerar a mano:```bash
python certs/generate_certs.py --force
Las claves antiguas siguen en el historial de git. Trata el par que se envió antes de este cambio como quemado; las nuevas instalaciones ya no lo usan.
El servidor usa dos claves Fernet, ambas generadas automáticamente en el primer arranque:
| Clave | Ubicación | Protege |
|---|---|---|
| Clave de agente | data/fernet.key (o FERNET_KEY_PATH) | Telemetría del agente; se entrega vía /api/agents/bootstrap |
| Clave de servidor | .env FERNET_KEY | Campos en reposo internos del servidor (p. ej., la columna de contraseña) |
chmod 600 en ambas. Haz copias de seguridad. Perder cualquiera de las dos hace que los
datos cifrados correspondientes sean ilegibles. Aún no hay rotación in situ.
Dos mecanismos independientes, ambos opcionales:
Enriquecimiento por veredicto (ai/intel.py). El trabajador de IA contrasta
los indicadores encontrados en un registro contra AlienVault OTX y VirusTotal. Necesita
OTX_API_KEY / VT_API_KEY; si no están definidas, no se realiza ninguna llamada externa.
Fuentes de indicadores (core/threat_feeds.py). Rellena la tabla threat_intel
cada hora desde abuse.ch — Feodo Tracker (direcciones C2 de botnets), ThreatFox
(IoCs mixtos con una puntuación de confianza) y URLhaus (URLs que distribuyen malware).
Los indicadores llevan last_seen y se podan después de THREAT_INTEL_STALE_DAYS
(por defecto 30): una dirección que alojó un C2 el último trimestre normalmente
pertenece a otra persona ahora, y mantenerla produce falsos positivos indefinidamente. Cada
fuente está limitada a THREAT_INTEL_MAX_PER_FEED filas porque la tabla se lee
en la ruta de alertas.
abuse.ch ha estado moviendo las descargas detrás de una clave de cuenta gratuita. Una fuente
que devuelve 401/403 lo indica en el registro del servidor; establece THREAT_INTEL_AUTH_KEY.
Comprueba qué llegó realmente:```bash docker logs sentora-server | grep ThreatIntel
### Modo de aislamiento (air-gap)```ini
OSV_MODE=mirror
OSV_MIRROR_URL=http://osv.internal
THREAT_INTEL_MODE=off
# or serve the feeds internally:
# THREAT_INTEL_FEODO_URL=http://mirror.internal/feodo.json
Con esos valores configurados, más OTX_API_KEY / VT_API_KEY sin definir, nada sale de la
red. Las fuentes están incluidas, Ollama es local, no se contacta con ningún CDN.
/api/exposure/report cuenta paquetes sin parchear y eventos de integridad de archivos
en toda la flota, por agente, de peor a mejor. Informa su propia cobertura:
complete: false cuando un agente no pudo leerse, porque un total sobre la mitad
de la flota no es un total de flota.
Deliberadamente no hay puntuación. El endpoint anteriormente devolvía
100 - vulns*2 - fim*5 como una "puntuación de cumplimiento" — eso no se corresponde con ningún marco,
no escala con el tamaño de la flota y se fija en cero en cualquier flota real. La clasificación
por gravedad está ausente por la misma razón: vulnerabilities_report no tiene
columna de gravedad y sus campos están cifrados en reposo, por lo que cualquier calificación tendría
que inventarse.
POST /<agent>/config/<type> valida antes de que cualquier cosa llegue a un sensor:
análisis YAML, forma estructural y — la capa que importa — compilación de
regex. Una regex inválida es YAML perfectamente válido y desactiva silenciosamente
la categoría que la contiene, por lo que una verificación solo de sintaxis la enviaría directamente al
endpoint. El editor valida contra el mismo endpoint mientras escribes y
reporta problemas con números de línea en los que se puede hacer clic.
Agent (Win / Linux) │ TCP frames + REST polling ▼ ingest (:5001) ──► RabbitMQ ──► AI worker fleet (3 modes) │ │ ▼ ▼ MySQL (per-agent _db) ai_analysis_results │ ▼ app (Sanic :8000) ──► React UI + REST + WebSocket screen proxy
La versión más profunda (diseño por módulos, esquema, pipeline de IA, autonomía SOAR, superficies de air-gap) se encuentra en
[docs/Sentora_Architecture.md](https://github.com/d3vhex/sentora/blob/HEAD/docs/Sentora_Architecture.md).
Documentación operativa:
| Documento | Cubre |
| :--- | :--- |
| [Arquitectura](https://github.com/d3vhex/sentora/blob/HEAD/docs/Sentora_Architecture.md) | Diseño de módulos, flujo de datos, modelo de autenticación, pipeline de IA |
| [Despliegue en producción](https://github.com/d3vhex/sentora/blob/HEAD/docs/production-deployment.md) | Dimensionamiento, topología de red, TLS, copias de seguridad, monitorización, air-gap |
| [Runbook de actualización](https://github.com/d3vhex/sentora/blob/HEAD/docs/update-runbook.md) | Actualizaciones, despliegue de agentes, migraciones de BD, rollback |
| [Informe de progreso](https://github.com/d3vhex/sentora/blob/HEAD/docs/PROGRESS_REPORT.md) | Qué ha cambiado y por qué |
---
## Configuración de desarrollo```bash
# 1. Database. Only init_userdb.sql — it creates and selects `userdb`.
#
# db/init.sql is NOT a server-init script. It is the per-agent schema
# template, applied by server.create_tables_if_not_exist() after
# connecting to that agent's own database, which is why it contains no
# CREATE DATABASE or USE. Running it standalone fails at line 5 with
# "No database selected" — the same way it broke every first-time
# `docker compose up` while it was mounted into the MySQL init directory.
mysql -u root -p < db/init_userdb.sql
# 2. Backend. requirements.lock pins every version the image is built
# from; requirements.txt is the loose list it was resolved from.
pip install -r requirements.lock
python app.py
# 3. Ingest (separate terminal)
python server.py
# 4. Frontend dev server
cd frontend
npm install
npm run dev
Mismo script, tres roles:```bash WORKER_TYPE=automation python ai_worker.py WORKER_TYPE=manual python ai_worker.py WORKER_TYPE=defensive python ai_worker.py
Production: deja que `docker-compose.yaml` lo haga.
---
## Contribuciones
Se aceptan PRs. Antes de abrir uno:
1. Fork → rama → PR contra `main`.
2. Ejecuta las comprobaciones:```bash
pytest -ra # no MySQL or RabbitMQ needed
python -m compileall -q app.py core security
cd frontend && npx tsc --noEmit && npm run build && cd ..
# With the stack up — enumerates every route and calls it twice
python scripts/api_smoke_test.py
@require_permission(...). El registro de arranque
imprime el recuento; si informa 0 permission-gated, algo está mal
con la conexión, no con tu ruta.Para cualquier cosa más grande que una corrección, abre un issue primero para que podamos alinearnos en el enfoque.
. ├── app.py # Sanic API + React SPA host ├── server.py # TCP ingest ├── ai_worker.py # AI worker fleet (3 modes) ├── ai/ │ ├── utils.py # LLM helpers, AI cache, SOAR queueing │ └── intel.py # OTX / VT per-verdict enrichment (opt-in) ├── core/ │ ├── mq.py # RabbitMQ publisher │ ├── opensearch.py # OpenSearch index/search │ ├── config_validation.py # Agent YAML validation (parse, shape, regex) │ └── threat_feeds.py # abuse.ch indicator feeds ├── security/ │ ├── session.py # Server-side session store │ └── ssrf.py # Proxy destination rules ├── scanners/ │ └── vuln.py # Server-side OSV scanner ├── scripts/ │ ├── init_secrets.py # Generate the secrets .env needs │ ├── rotate_db_password.py # Rotate the MySQL root password safely │ └── api_smoke_test.py # Exercise every route against a live server ├── tests/ # pytest; no MySQL or RabbitMQ required ├── frontend/ # React 18 + TS SPA │ └── src/lib/ # Shared logic (playbook action catalogue) ├── Sentora/ # Cross-platform agent ├── certs/ # Self-signed dev certs ├── docs/ # Architecture + screenshots └── docker-compose.yaml
---
## Licencia
AGPL-3.0. Consulta [LICENSE](https://github.com/d3vhex/sentora/blob/HEAD/LICENSE).
Úsalo, modifícalo, redistribúyelo. Lo que AGPL añade sobre la GPL normal:
si ejecutas una versión modificada en un servidor de red donde otros usuarios
interactúan con ella, debes publicar las modificaciones también bajo AGPL.
- Autoalojamiento para uso interno → sin obligación de divulgar el código fuente.
- SaaS de cara al público sobre un Sentora modificado → debes publicar
las modificaciones.
- ¿Quieres distribuir un derivado de código cerrado u omitir la cláusula
de copyleft de red? Hay disponible una exención de licencia comercial. Contacta con el autor.
El nombre y el logotipo de "Sentora" son marcas comerciales de los autores del proyecto y
no están cubiertos por AGPL. Haz un fork libremente, pero renómbralo si lo redistribuyes como
producto propio.
---
## Lo que no está en Community Edition
Community Edition no tiene límites artificiales: sin límite de agentes, sin
límite de retención, sin restricciones de funciones en el núcleo. Ejecútala tan ampliamente como
tu hardware lo permita.
La distribución de pago Pro / Enterprise añade funciones de integración empresarial
(SSO SAML/SCIM, multiinquilino, informes de cumplimiento, HA, auditoría WORM,
paquetes de actualización firmados para entornos aislados, aprobaciones SOAR de 4 ojos,
reemisores premium de ticketing/SIEM). La capacidad de detección principal nunca se
mueve detrás de ese muro.
Si algo de eso es relevante para tu despliegue,
[contacta](mailto:[email protected]).