273 lines
9.7 KiB
Markdown
273 lines
9.7 KiB
Markdown
# SPEC / BACKLOG — Validação Mail TLS no Wizard (IMAP :993 + Cert Multi-SAN)
|
|
|
|
**Versão:** 1.0
|
|
**Data:** 2026-06-12
|
|
**Autor:** Roger / Cursor DevOps
|
|
**Estado:** 📋 **BACKLOG** (correcção manual VM112 ✅ concluída)
|
|
**Depende de:** `010-admin-domain-validation/spec.md`, `SPEC-CORRECAO-ADMIN-DOMINIOS-VIRTUAIS.md`
|
|
|
|
---
|
|
|
|
## 1. Resposta directa
|
|
|
|
**Sim** — os passos executados manualmente em Jun/2026 (cert multi-SAN 10 domínios, deploy `nginx.crt`, validação IMAP `:993`, renovação via CT114 HTTP-01) **devem fazer parte da sequência de validação e provisionamento do wizard**.
|
|
|
|
Hoje o wizard valida **presença do hostname no certbot** (`cert_san`), mas **não valida o certificado efectivamente servido** em IMAP/SMTP — exactamente o cenário que causou **"Wrong Site" no Thunderbird**.
|
|
|
|
---
|
|
|
|
## 2. Lacuna actual
|
|
|
|
| O que o wizard faz hoje | O que falta |
|
|
|-------------------------|-------------|
|
|
| `cert_san` → `certbot certificates` lista SANs | Runtime TLS em `:993` / `:465` |
|
|
| `webmail_https` → GET `:443` | Cert `:6071` admin (spec 010, não implementada) |
|
|
| `haproxy_sni` → ficheiro SNI CT114 | Deploy pós-expand (`carbonio-cert-deploy.sh`) |
|
|
| — | Renovação automatizada (`certbot-renew-mail-vm112-multi.sh`) |
|
|
| — | Alerta quando SAN falta após onboarding novo domínio |
|
|
|
|
---
|
|
|
|
## 3. Sequência alvo — 14 checks infra (P1 bloqueiam `ready`)
|
|
|
|
### 3.1 Já existem (6) — `infrastructure.py`
|
|
|
|
```
|
|
carbonio_domain → dns_mail → haproxy_sni → traefik_router → cert_san → webmail_https
|
|
```
|
|
|
|
### 3.2 Admin — spec 010 (4) — **pendente implementação**
|
|
|
|
```
|
|
→ admin_block_nginx → admin_redirect_443 → admin_cert_6071 → admin_login_6071
|
|
```
|
|
|
|
Ver: `specs/010-admin-domain-validation/spec.md`
|
|
|
|
### 3.3 Mail TLS — **NOVO backlog (4)**
|
|
|
|
| ID | Label | O que valida | Método | P |
|
|
|----|-------|--------------|--------|---|
|
|
| `imap_cert_san_993` | IMAP TLS :993 | Cert apresentado inclui `mail.{dominio}` no SAN | `openssl s_client -connect 127.0.0.1:993 -servername {host}` | **P1** |
|
|
| `smtp_cert_san_465` | SMTP TLS :465 | Idem (cert global nginx/smtpd) | `openssl s_client -connect 127.0.0.1:465 -servername {host}` | **P2** |
|
|
| `cert_deployed_global` | Cert deploy Carbonio | `nginx.crt` == `mail-vm112-multi/fullchain.pem` (hash ou mtime) | comparação ficheiros | **P1** |
|
|
| `cert_renew_ready` | Renovação LE | Script + cron/systemd timer activo | `test -x /usr/local/bin/certbot-renew-mail-vm112-multi.sh` | **P2** |
|
|
|
|
**Regra `ready`:** todos P1 OK. P2 = warning visível no Desk, não bloqueia onboarding.
|
|
|
|
### 3.4 Diagrama completo
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
A[carbonio_domain] --> B[dns_mail]
|
|
B --> C[haproxy_sni]
|
|
C --> D[traefik_router]
|
|
D --> E[cert_san LE lista]
|
|
E --> F[webmail_https]
|
|
F --> G[admin_block_nginx]
|
|
G --> H[admin_redirect_443]
|
|
H --> I[admin_cert_6071]
|
|
I --> J[admin_login_6071]
|
|
J --> K[imap_cert_san_993]
|
|
K --> L[cert_deployed_global]
|
|
L --> M[cert_renew_ready]
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Provisionamento — steps novos / alterados
|
|
|
|
### 4.1 Melhorar step `cert_san` existente
|
|
|
|
**Problema:** expand LE com DNS multi-token falha para domínios em contas CF diferentes (bet*).
|
|
|
|
**Solução implementada manualmente (Jun/2026):**
|
|
|
|
| Componente | Path VM112 / CT114 |
|
|
|------------|-------------------|
|
|
| Hook HTTP-01 | `/usr/local/bin/cf-http-auth-all.sh` |
|
|
| Hook cleanup | `/usr/local/bin/cf-http-cleanup-all.sh` |
|
|
| Hook DNS multi (fallback) | `/usr/local/bin/cf-dns-auth-multi-zone.sh` |
|
|
| Renew wrapper | `/usr/local/bin/certbot-renew-mail-vm112-multi.sh` |
|
|
| Deploy | `/usr/local/bin/carbonio-cert-deploy.sh` |
|
|
| CT114 nginx temp :80 | `docker run acme-http-80` (durante renew) |
|
|
|
|
**Wizard `do_cert()` deve:**
|
|
|
|
1. Calcular SANs: todos `mail.*` activos + `nfe.{dominio}` se aplicável
|
|
2. Tentar expand `mail-vm112-multi` (HTTP-01 via CT114 — parar Traefik ~60s)
|
|
3. Executar `carbonio-cert-deploy.sh`
|
|
4. Re-correr checks `imap_cert_san_993` + `cert_deployed_global`
|
|
5. Emitir webhook `infra.cert.deployed` → VM122
|
|
|
|
### 4.2 Novo step `mail_tls_verify` (só validação, pós-provision)
|
|
|
|
Idempotente — não altera infra, apenas confirma runtime TLS.
|
|
|
|
---
|
|
|
|
## 5. Implementação wizard — ficheiros
|
|
|
|
| Ficheiro | Acção | Esforço |
|
|
|----------|-------|---------|
|
|
| `services/mail_tls_validation.py` | **Criar** — checks :993/:465, cert deploy | M |
|
|
| `services/admin_domain_validation.py` | **Criar** (spec 010) | M |
|
|
| `services/infrastructure.py` | Integrar 8 checks (4 admin + 4 mail TLS) | M |
|
|
| `services/infrastructure.py` `do_cert()` | HTTP-01 + CT114 orchestration | L |
|
|
| `tests/test_mail_tls_validation.py` | Unit + mock openssl | S |
|
|
| `tests/test_infrastructure_status.py` | Snapshot 14 steps | S |
|
|
|
|
### 5.1 Interface proposta — `mail_tls_validation.py`
|
|
|
|
```python
|
|
def check_imap_cert_san(mail_host: str, port: int = 993) -> StepResult
|
|
def check_smtp_cert_san(mail_host: str, port: int = 465) -> StepResult
|
|
def check_cert_deployed_global() -> StepResult
|
|
def check_cert_renew_ready() -> StepResult
|
|
def verify_mail_tls_runtime(domain: str, mail_aliases: list[str] | None) -> list[StepResult]
|
|
```
|
|
|
|
**`check_imap_cert_san` — lógica:**
|
|
|
|
```python
|
|
# openssl s_client -connect 127.0.0.1:993 -servername mail.example.com
|
|
# Parse SAN; ok se mail_host in SAN ou CN == mail_host
|
|
# ok=False → message: "Wrong Site — SAN não inclui {host} (CN={cn})"
|
|
```
|
|
|
|
---
|
|
|
|
## 6. Integração VM122 Desk
|
|
|
|
| Evento webhook | Quando | Payload mínimo |
|
|
|----------------|--------|----------------|
|
|
| `infra.mail_tls.failed` | `imap_cert_san_993` falha | domain, mail_host, cn, sans |
|
|
| `infra.cert.deployed` | pós `carbonio-cert-deploy.sh` | domains[], expiry, serial |
|
|
| `admin.validation.failed` | spec 010 | (já definido) |
|
|
|
|
**UI Desk — card domínio:**
|
|
|
|
| Coluna | Fonte |
|
|
|--------|-------|
|
|
| IMAP TLS | `imap_cert_san_993` |
|
|
| Admin :6071 | `admin_cert_6071` |
|
|
| Cert LE SAN | `cert_san` |
|
|
| Último deploy | `cert_deployed_global` |
|
|
|
|
---
|
|
|
|
## 7. Referência — estado VM112 pós-correcção manual (baseline)
|
|
|
|
| Check | 9 domínios Carbonio | Notas |
|
|
|-------|---------------------|-------|
|
|
| `cert_san` (lista LE) | ✅ 10 SANs | inclui bet* via HTTP-01 |
|
|
| `imap_cert_san_993` | ✅ 10/10 | cert global multi-SAN |
|
|
| `admin_*` (spec 010) | ✅ 9/9 | scripts offline OK |
|
|
| `cert_renew_ready` | ✅ script manual | falta cron no wizard |
|
|
|
|
**SANs actuais `mail-vm112-multi`:**
|
|
|
|
```
|
|
mail.ligbox.com.br, mail.diarissima.com, mail.dratcoin.com,
|
|
mail.ibytera.com, mail.myvexx.com, nfe.diarissima.com,
|
|
mail.betinplace.com, mail.betinsport.com, mail.eplacebets.com,
|
|
mail.iofficebooks.com
|
|
```
|
|
|
|
---
|
|
|
|
## 8. Backlog — fases de implementação
|
|
|
|
### Fase 1 — Validação runtime (sem alterar provision) — **P1**
|
|
|
|
| ID | Task | Est. |
|
|
|----|------|------|
|
|
| WZ-TLS-1 | Criar `mail_tls_validation.py` | 4h |
|
|
| WZ-TLS-2 | Adicionar `imap_cert_san_993` + `cert_deployed_global` em `get_status()` | 2h |
|
|
| WZ-TLS-3 | Testes unitários openssl mock | 2h |
|
|
| WZ-TLS-4 | CLI: `python -m app.services.mail_tls_validation --domain X` | 1h |
|
|
|
|
**Entrega:** API `GET /infrastructure/status/{domain}` devolve checks IMAP.
|
|
|
|
### Fase 2 — Admin checks (spec 010) — **P1**
|
|
|
|
| ID | Task | Est. |
|
|
|----|------|------|
|
|
| WZ-ADM-1 | `admin_domain_validation.py` (4 checks) | 6h |
|
|
| WZ-ADM-2 | Integrar em `get_status()` + `admin_ready` flag | 2h |
|
|
| WZ-ADM-3 | Reutilizar `check-admin-login-flow.mjs` via subprocess | 2h |
|
|
|
|
### Fase 3 — Provision cert + deploy automático — **P1**
|
|
|
|
| ID | Task | Est. |
|
|
|----|------|------|
|
|
| WZ-TLS-5 | Refactor `do_cert()` — HTTP-01 CT114 orchestration | 8h |
|
|
| WZ-TLS-6 | Idempotência: skip se SAN já presente | 2h |
|
|
| WZ-TLS-7 | Cron systemd `certbot-renew-mail-vm112-multi.timer` | 1h |
|
|
| WZ-TLS-8 | Webhook `infra.cert.deployed` → VM122 | 2h |
|
|
|
|
### Fase 4 — Desk + alertas — **P2**
|
|
|
|
| ID | Task | Est. |
|
|
|----|------|------|
|
|
| OPS-TLS-1 | Card domínio: colunas IMAP + Admin TLS | 4h |
|
|
| OPS-TLS-2 | Ticket auto `infra.mail_tls.failed` | 3h |
|
|
| OPS-TLS-3 | Scorecard AUD: +2 checks mail TLS | 2h |
|
|
|
|
---
|
|
|
|
## 9. Critérios de aceitação
|
|
|
|
- [ ] Novo domínio onboarded → wizard detecta SAN em falta **antes** do cliente configurar Thunderbird
|
|
- [ ] `GET infrastructure/status/{domain}` inclui `imap_cert_san_993` com mensagem acionável ("Wrong Site")
|
|
- [ ] `POST infrastructure/provision?step=cert_san` expande multi-SAN + deploy + re-valida IMAP
|
|
- [ ] Renovação LE não exige intervenção manual (timer + script CT114)
|
|
- [ ] Desk mostra estado TLS IMAP e Admin por domínio
|
|
- [ ] Falha IMAP TLS gera evento webhook VM122
|
|
|
|
---
|
|
|
|
## 10. Riscos e mitigação
|
|
|
|
| Risco | Mitigação |
|
|
|-------|-----------|
|
|
| Renew para Traefik ~60s (porta 80) | Timer 03:00 UTC; script idempotente; alerta se renew falha |
|
|
| bet* sem token CF DNS | Manter HTTP-01 via CT114 como path primário |
|
|
| nginx mail sem SNI real | Documentar: cert **global** — SAN multi obrigatório |
|
|
| Falso positivo `cert_san` (lista vs runtime) | Check `cert_deployed_global` + `imap_cert_san_993` |
|
|
|
|
---
|
|
|
|
## 11. Scripts / paths de referência (VM112)
|
|
|
|
```
|
|
/opt/ligbox-deploy/scripts/admin-login-check/
|
|
apply-admin-nginx-overrides.py
|
|
check-admin-login-flow.mjs
|
|
sync-traefik-admin-certs.sh
|
|
|
|
/usr/local/bin/
|
|
carbonio-cert-deploy.sh
|
|
certbot-renew-mail-vm112-multi.sh
|
|
cf-http-auth-all.sh
|
|
cf-http-cleanup-all.sh
|
|
cf-dns-auth-multi-zone.sh
|
|
|
|
/etc/letsencrypt/live/mail-vm112-multi/
|
|
/opt/zextras/conf/nginx.crt ← cert global IMAP/SMTP
|
|
```
|
|
|
|
---
|
|
|
|
## 12. Índice relacionado
|
|
|
|
| Documento | Conteúdo |
|
|
|-----------|----------|
|
|
| `specs/010-admin-domain-validation/spec.md` | Admin :6071 — 4 checks |
|
|
| `specs/010-admin-domain-validation/correcao-vm112.md` | Correcção manual admin |
|
|
| `SPEC-CORRECAO-ADMIN-DOMINIOS-VIRTUAIS.md` | Histórico VM112 |
|
|
| `BACKLOG.md` (VM122) | Track WZ-TLS-* |
|
|
|
|
---
|
|
|
|
*Próximo passo quando possível: **Fase 1** (WZ-TLS-1..4) — validação runtime sem risco de alterar produção.*
|