obsidian-vault/ligbox-ops-platform/specs/021-wizard-cybersecurity-telemetry/spec.md
2026-06-19 17:26:42 +00:00

413 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Feature Specification: Cibersegurança do Wizard — Telemetria em Tempo Real (021)
**Criado:** 2026-06-17
**Solicitado por:** Roger
**Status:** Spec — implementação pendente
**Prioridade:** P1
**Sistema:** Wizard VM112 (`/opt/ligbox-wizard`) + Portal onboard + Desk VM122
**Módulo Desk:** `wizard-security` (novo — Spec 015)
**Depende de:** Spec 001/014 (webhooks + funil), Spec 015 (módulos), Spec 016 (handoff + sessionStorage)
**UI principal:** **Audit Overview** → tenant VM112 + **Infra 2** + **Eventos**
---
## Resumo
Estender a observabilidade do onboarding com **vias de cibersegurança** dos processos do wizard: CSP (browser), auditoria de inputs (API VM112), integridade do handoff server-side e eventos de abuso — tudo visível **em tempo quase real** no Desk VM122, na mesma sessão (`session_id` / hash) do funil.
**Princípio:** isto é **camada extra de detecção e resposta** — complementa (não substitui) HTTPS, handoff one-time, React escaping e ausência de SQL no fluxo de credenciais.
**Regra de ouro:** **nunca** enviar senhas, tokens de handoff completos nem corpos de request com PII sensível nos webhooks de segurança.
---
## Problema
| Hoje | Necessidade |
|------|-------------|
| Desk vê **progresso** do funil (`session.started` → `completed`) | Ver também **tentativas de abuso** na mesma sessão |
| Audit Overview = saúde infra (Carbonio, DNS, cert) | Card **Segurança onboarding** por tenant VM112 |
| CSP / validação de inputs inexistentes ou invisíveis | Política activa + relatórios no Desk |
| IA/fuzzing acelera ataques | Alertas operacionais sem esperar abuse report |
---
## Modelo de ameaças (wizard VM112)
| Ameaça | Camada actual | Gap | Via Spec 021 |
|--------|---------------|-----|--------------|
| **XSS** (ler sessionStorage) | React escape + sem `dangerouslySetInnerHTML` | Sem CSP nem reporte | CSP + `security.csp_violation` |
| **SQL injection** | Handoff sem SQL (JSON encriptado) | Outras APIs futuras | Middleware `security.input_blocked` |
| **Roubo handoff token** | Token opaco, TTL 15 min, one-shot | Sem telemetria de reutilização | `security.handoff_rejected` |
| **Senha na URL** | Nunca — só `?onboard_handoff=` | — | Auditoria confirma ausência |
| **MITM** | HTTPS Let's Encrypt | — | Fora de escopo (já coberto) |
| **Fuzzing / brute** | Parcial | Sem rate limit visível | `security.rate_limited` |
| **Path traversal / SSRF** | Não auditado | — | `security.input_blocked` |
| **IA a gerar payloads** | Mesmas defesas | Sem feed SOC | Eventos no Desk em segundos |
### O que sessionStorage **não** é
- **Não** protege contra SQL injection (corre só no browser).
- **Risco real:** XSS bem-sucedido → script lê `ligbox_onboard_password`.
- **Resposta Spec 021:** CSP reduz superfície + reporta violações; inputs maliciosos bloqueados antes de chegar ao estado.
---
## Vias de processo — mapa completo
### Via 1 — Credenciais (Portal → Wizard)
```
Utilizador (onboard.ligbox.com.br)
→ Self-Service / Login (HTTPS)
→ POST /onboard-handoff [VM112 API — senha encriptada server-side]
→ redirect ?onboard_handoff=<token_opaco>
→ POST /consume [one-shot, apaga token]
→ sessionStorage.ligbox_onboard_password [temporário, mesma origem]
→ wizard /onboard
```
**Eventos de segurança:**
| Evento | Quando |
|--------|--------|
| `security.handoff_created` | Handoff emitido (sem senha no payload) |
| `security.handoff_consumed` | Consume OK |
| `security.handoff_rejected` | Token expirado, reutilizado, session mismatch |
| `security.handoff_expired` | TTL 15 min excedido |
### Via 2 — Inputs do wizard (passos 0N)
Rotas VM112 a auditar (mínimo):
| Endpoint / acção | Campos |
|------------------|--------|
| Validação domínio | `domain`, FQDN |
| Conta admin | `localPart`, `domain`, `email` |
| DNS / Cloudflare | `domain`, records |
| Portal users | `login_id`, `planned_corporate_email` |
| Company profile | `legal_name`, `tax_id`, texto livre |
| Handoff consume | `token`, `session_id` |
**Eventos:**
| Evento | Severidade | Acção API |
|--------|------------|-----------|
| `security.input_warn` | baixa | Sanitizar + log + webhook |
| `security.input_blocked` | alta | HTTP 400 + log + webhook |
| `security.rate_limited` | média | HTTP 429 + webhook |
**Padrões detectados (regex/heurística MVP):**
- SQLi: `' OR `, `UNION SELECT`, `; DROP`, `1=1--`
- XSS: `<script`, `javascript:`, `onerror=`, `onload=`
- Path: `../`, `%2e%2e`
- Command: `` ` ``, `$(`, `|`, `&&`
- Oversize: campo > limite (ex. domínio > 253, nome > 500)
**Nunca logar:** `password`, `root_password`, corpo de `/consume` com segredos.
### Via 3 — CSP (browser → Desk)
```
Browser (portal + wizard)
→ viola Content-Security-Policy
→ POST report-uri / report-to
→ VM122 /api/v1/security/csp-report
→ webhook_events (source: vm112-security)
→ Audit Overview + Infra 2 + Eventos
```
**Header CSP (Traefik / nginx — portal + wizard):**
```
Content-Security-Policy:
default-src 'self';
script-src 'self';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
connect-src 'self' https://desk.ligbox.com.br;
frame-ancestors 'none';
base-uri 'self';
report-uri https://desk.ligbox.com.br/api/v1/security/csp-report;
```
(Ajustar `connect-src` para APIs VM112/Traefik em produção.)
**Evento:** `security.csp_violation` — inclui `blocked-uri`, `violated-directive`, `document-uri` (sem dados de utilizador).
### Via 4 — Correlação com funil (VM122)
Cada evento `security.*` **deve** incluir quando disponível:
- `session_id` (hash UUID)
- `domain`
- `client_ip` (ingress)
- `endpoint` / `wizard_step`
- `severity`: `info` | `warn` | `high` | `critical`
O Desk correlaciona com timeline Spec 014 na mesma sessão.
---
## Módulo Desk (Spec 015)
| Campo | Valor |
|-------|--------|
| `id` | `wizard-security` |
| `label` | Segurança Wizard |
| `default_enabled` | `true` |
| `nav_views` | _(enrichment — Audit Overview, Infra 2, Eventos)_ |
Desactivar módulo → APIs devolvem payload sem `security_summary`; UI oculta card e filtro.
---
## RBAC
| Acção | Perfis |
|-------|--------|
| Ver card Segurança no Audit Overview | `super_admin`, `ops_lead` |
| Ver feed segurança Infra 2 | `super_admin`, `ops_lead`, `noc` |
| Ver eventos `security.*` em Eventos | `super_admin`, `ops_lead`, `noc` |
| POST `csp-report` | Público (browser) — rate limit + validação schema |
| POST webhook segurança VM112 | `X-Webhook-Secret` (mesmo ou derivado de onboard) |
Técnicos `technician` — sem card segurança (opcional: só tickets ligados).
---
## API Desk (VM122)
### Ingestão
| Método | Path | Auth | Descrição |
|--------|------|------|-----------|
| POST | `/api/v1/security/csp-report` | nenhum (browser) | Relatório CSP (JSON W3C ou legacy) |
| POST | `/api/v1/webhooks/security` | `X-Webhook-Secret` | Eventos VM112 `security.*` |
| POST | `/api/v1/webhooks/onboard` | existente | Aceitar também `security.*` no mesmo ingress (opcional) |
### Consulta
| Método | Path | Descrição |
|--------|------|-----------|
| GET | `/api/v1/security/events?window=24h&session_id=` | Lista eventos segurança |
| GET | `/api/v1/security/summary?tenant_id=1` | KPIs para Audit Overview |
| GET | `/api/v1/audit/tenants/1/details` | Enriquecido com `security_summary` + `security_events_recent` |
### Payload webhook (VM112 → VM122)
```json
{
"event": "security.input_blocked",
"session_id": "ee2239fd-dd05-444e-b79c-a5701a255ba8",
"domain": "evil.example",
"data": {
"endpoint": "POST /api/domains/validate",
"field": "domain",
"reason": "sql_injection_pattern",
"pattern_id": "sqli_union",
"client_ip": "203.0.113.42",
"wizard_step": 0,
"severity": "high"
}
}
```
**Proibido no payload:** passwords, tokens handoff completos, headers `Authorization`.
### Persistência
Tabela nova ou reutilizar `webhook_events`:
| Opção | Prós |
|-------|------|
| **A**`webhook_events` com `source=vm112-security` | Reutiliza Eventos, Infra 2, funil |
| **B** — tabela `security_events` dedicada | Queries mais rápidas, retenção própria |
**MVP:** opção A (consistente com arquitectura actual).
Índices recomendados: `(source, created_at)`, `(session_id)`, `(event_type)`.
---
## API VM112 (wizard)
### Middleware `security_audit.py` (novo)
- Executar **antes** do handler em rotas listadas na Via 2.
- Retornar 400/429 com corpo genérico (não revelar qual regex matched em produção — opcional `reason` interno no webhook only).
- Fire-and-forget POST para VM122 (não bloquear UX se Desk offline).
### Cliente webhook
Reutilizar cliente existente de onboarding (`session.started`, etc.) com fila retry (3 tentativas, backoff 2s).
### Config (.env VM112)
```
DESK_SECURITY_WEBHOOK_URL=https://desk.ligbox.com.br/api/v1/webhooks/security
DESK_WEBHOOK_SECRET=<mesmo WEBHOOK_SECRET>
SECURITY_AUDIT_ENABLED=true
SECURITY_RATE_LIMIT_PER_IP=60/min
```
---
## UI Desk
### Audit Overview → modal VM112 Ligbox Onboard
Novo bloco **«Segurança onboarding»** (acima ou abaixo do resumo domínios):
| KPI | Exemplo |
|-----|---------|
| Violações CSP (24h) | 3 |
| Inputs bloqueados | 1 |
| Handoffs rejeitados | 0 |
| Sessões com alerta | 2 |
Lista recente (clicável → detalhe):
| Hora | Sessão (hash) | Evento | IP | Domínio |
|------|---------------|--------|-----|---------|
| 21:42 | `ee2239fd…` | `security.csp_violation` | 203.0.113.1 | — |
| 21:40 | `3dfa8c6c…` | `security.input_blocked` | 198.51.100.5 | `foo';DROP--` |
Clique → modal com timeline **funil + segurança** intercalados (ou abas).
### Infra 2 (SOC)
- Painel **«Segurança wizard»** no feed (15s refresh).
- Flash visual em `security.input_blocked` e `security.csp_violation` (como eventos novos no feed VM112).
### Eventos
- Filtro toolbar: **Segurança** (`source=vm112-security` ou `event` prefix `security.`).
- Colunas: severidade, evento, sessão (hash completo), domínio, IP, hora.
### Tickets (opcional Fase C)
Auto-ticket quando:
- ≥3 `security.input_blocked` mesmo IP em 10 min, ou
- `security.csp_violation` + `security.input_blocked` mesma sessão
Subject: `[security] {domain|sem domínio} — {event}` · prioridade alta.
---
## Taxonomia de eventos `security.*`
| event | Label UI | Severidade default |
|-------|----------|-------------------|
| `security.csp_violation` | Violação CSP | warn |
| `security.input_warn` | Input suspeito (sanitizado) | info |
| `security.input_blocked` | Input bloqueado | high |
| `security.rate_limited` | Rate limit | warn |
| `security.handoff_created` | Handoff criado | info |
| `security.handoff_consumed` | Handoff consumido | info |
| `security.handoff_rejected` | Handoff rejeitado | high |
| `security.handoff_expired` | Handoff expirado | info |
| `security.auth_failed` | Autenticação portal falhou (agregado) | warn |
| `security.session_anomaly` | Sessão inconsistente (IDs mismatch) | high |
---
## Fases de implementação
### Fase A — Ingestão VM122 (Desk)
- [ ] T001 `POST /api/v1/security/csp-report` + validação schema + rate limit
- [ ] T002 `POST /api/v1/webhooks/security` (ou extensão onboard ingress)
- [ ] T003 Persistência `webhook_events` source `vm112-security`
- [ ] T004 `GET /api/v1/security/summary` e `/security/events`
- [ ] T005 Registar módulo `wizard-security` em `registry.py`
### Fase B — VM112 wizard
- [ ] T006 Middleware auditoria inputs (Via 2)
- [ ] T007 Eventos handoff (Via 1)
- [ ] T008 Cliente webhook segurança + retry
- [ ] T009 Testes unitários padrões SQLi/XSS
### Fase C — UI Desk
- [ ] T010 Card Segurança no Audit Overview modal VM112
- [ ] T011 Filtro Eventos «Segurança»
- [ ] T012 Painel Infra 2 + flash eventos novos
- [ ] T013 Hash sessão na lista (já feito — correlacionar)
### Fase D — Infra Traefik/nginx
- [ ] T014 CSP headers portal + wizard (CT114 Traefik)
- [ ] T015 Validar `report-uri` reachability desde browser público
- [ ] T016 Documentar excepções CSP se libs externas exigirem
### Fase E — Resposta operacional (opcional)
- [ ] T017 Auto-ticket regras abuso
- [ ] T018 Push ntfy em `security.input_blocked` critical
- [ ] T019 Retenção 90 dias + purge `security.*` antigos
---
## Critérios de aceitação
1. Browser com CSP activo envia violação → evento visível em Eventos em <30s.
2. POST domínio `foo<script>alert(1)</script>.com` 400 VM112 + `security.input_blocked` no Desk.
3. Reutilizar token handoff `security.handoff_rejected` correlacionado à `session_id`.
4. Audit Overview VM112 mostra KPIs segurança 24h sem regressão nos domínios existentes.
5. Módulo `wizard-security` OFF card oculto; APIs sem `security_summary`.
6. Nenhum webhook contém senha nem token handoff completo (auditoria manual + teste).
7. Mesma sessão: funil (`session.started`) + evento segurança partilham `session_id` no detalhe.
---
## Testes
```bash
# CSP report (simulado)
curl -s -X POST https://desk.ligbox.com.br/api/v1/security/csp-report \
-H 'Content-Type: application/csp-report' \
-d '{"csp-report":{"document-uri":"https://onboard.ligbox.com.br/onboard","violated-directive":"script-src","blocked-uri":"https://evil.com/x.js"}}'
# Input blocked (após Fase B)
curl -s -X POST https://onboard.ligbox.com.br/api/.../validate \
-d '{"domain":"x\"; DROP TABLE--"}'
# → 400 + evento no Desk
# Summary Desk
curl -s -H "Authorization: Bearer $TOKEN" \
"https://desk.ligbox.com.br/api/v1/security/summary?tenant_id=1"
```
---
## Fora de escopo (v1)
- WAF comercial (Cloudflare WAF rules futuro)
- SIEM externo (export syslog)
- Pentest automatizado no wizard
- Substituir sessionStorage por Web Crypto / Credential Management API
- Segurança Carbonio pós-provisionamento (Spec separada)
---
## Relação com specs existentes
| Spec | Relação |
|------|---------|
| **016** | Handoff + sessionStorage Via 1 auditada, senha nunca no webhook |
| **014** | Relógio por fase mesma sessão, timeline paralela segurança |
| **015** | Módulo `wizard-security` |
| **017** | Purge independente; não apagar `security.*` antes de retenção |
| **010** | Assist/takeover técnico alertas segurança na sessão assistida |
---
## Conclusão
A Spec 021 define as **vias de cibersegurança** dos processos do wizard (credenciais, inputs, CSP, handoff) com **telemetria em tempo real no VM122** Audit Overview, Infra 2 e Eventos sem confundir protecção (HTTPS, handoff, React) com **visibilidade operacional** (o que o Roger precisa para operar e reagir).
**Próximo passo:** Fase A (ingestão VM122) pode começar sem alterações no wizard; Fase B liga a detecção activa na VM112.