Documentação — Implementação de mTLS (Imperva + AWS Private CA)

Objetivo: substituir o certificate pinning (quebrado pela rotação do auto cert da Imperva) por autenticação mútua (mTLS) — o app prova identidade com um client certificate assinado pela sua CA e validado pela Imperva na borda. O backend de negócio não muda.

1. Visão geral

Princípios:

2. Arquitetura

┌──────────────────────┐
│      Mobile App      │
│  (chave no Keystore/ │
│   Keychain; CSR;     │
│   cert no cofre)     │
└──────────┬───────────┘
           │ ① CSR / ② cert  (HTTPS autenticado)
           ▼
┌──────────────────────┐     ③ IssueCertificate(CSR)     ┌──────────────────────┐
│  Enrollment Service  │ ──────────────────────────────► │   AWS Private CA     │
│  (API Gateway +      │                                  │  • raiz OFFLINE      │
│   Lambda)            │                                  │  • subordinada       │
└──────────┬───────────┘                                  │    (clientAuth EKU)  │
           │                                              │  • chave da CA em KMS│
           │ ④ upload da CA subordinada + settings        └──────────────────────┘
           ▼
┌──────────────────────┐     mTLS handshake (client cert)   ┌─────────────┐
│       Imperva        │ ◄────────────────────────────────── │  Mobile App │
│  valida o client cert│  (servidor: auto cert rotacionado)  └─────────────┘
│  contra sua CA       │
└──────────┬───────────┘
           │ TLS (HTTP)
           ▼
┌──────────────────────┐
│   Backend (intocado) │ ← identidade do cliente chega via
└──────────────────────┘    header `clientCertificateInfo`

3. Fluxo de enrollment (obter o certificado)

[Diagram]

4. Fluxo de conexão (handshake mTLS)

[Diagram]

5. Proteção no sentido contrário: como o app confia no servidor

Até aqui o mTLS resolve a direção cliente → servidor: a Imperva valida o client cert e sabe que a chamada veio de um device com cert emitido pela sua CA. A pergunta inversa é: como o app sabe que está falando com o servidor legítimo (e não com um MITM)?

[Diagram]

1. Validação padrão do TLS (base)

2. Por que o MITM não passa

3. Como saber que a chamada vem do app legítimo (cert não roubado)

4. Reforços no app (Flutter)

6. Implementação por camada

6.1 AWS Private CA (a "autoridade emissora")

  1. Criar CA raiz (CA:TRUE, pathLenConstraint:1) → emitir subordinada → desativar a raiz (fica offline).
  2. Criar CA subordinada com EKU clientAuthesta é a âncora que você sobe na Imperva.
  3. Chave da CA assinada por KMS (nunca exportada).
  4. Template: clientAuth (ou ApiPassthrough para EKU vir do CSR).

6.2 Serviço de Enrollment (API Gateway + Lambda)

Camada Detalhe
Endpoint POST /enroll — recebe CSR (PEM) + token
Auth Autorizador valida token do seu IdP (Cognito/OIDC) ou device attestation
Lambda chama acm-pca:IssueCertificate → polling GetCertificate → devolve {cert, chain}
IAM role com acm-pca:IssueCertificate, acm-pca:GetCertificate
Validade 30–90 dias (curta, rotação natural)
Extras rate-limit, audit (CloudTrail), endpoint admin POST /revoke (RevokeCertificate)

6.3 Imperva (config — sem tocar no backend)

# 1) Sobe a CA subordinada (a que assina os client certs)
resource "incapsula_mtls_client_to_imperva_ca_certificate" "client_ca" {
  certificate_name = "mtls-client-ca"
  certificate      = filebase64("./ca_subordinada.pem")
  account_id       = data.incapsula_account_data.account_data.current_account
}

# 2) Associa a CA ao site
resource "incapsula_mtls_client_to_imperva_ca_certificate_site_association" "assoc" {
  certificate_id = incapsula_mtls_client_to_imperva_ca_certificate.client_ca.id
  site_id        = incapsula_site.example-site.id
}

# 3) Exige o client cert e repassa identidade ao origin
resource "incapsula_mtls_client_to_imperva_ca_certificate_site_settings" "cfg" {
  site_id                        = incapsula_site.example-site.id
  require_client_certificate     = true
  is_disable_session_resumption  = true   # se mTLS só em hosts/portas específicos
  forward_to_origin              = true
  header_name                    = "clientCertificateInfo"
  header_value                   = "COMMON_NAME"   # ou FULL_CERT/FINGERPRINT/SERIAL_NUMBER
  depends_on = [incapsula_mtls_client_to_imperva_ca_certificate_site_association.assoc]
}

Rotação da CA: o recurso não suporta update → criar nova CA, associar, migrar, deletar a antiga. Lockdown extra: fingerprints (SHA1) — allowlist dos certs de cliente, além da CA.

6.4 App mobile (Flutter)

Contexto técnico

Fluxo de enrollment (Flutter)

[Diagram]

Dependências sugeridas (validar no pub.dev na data da implementação)

Pinning de servidor no app

Ciclo de vida no app

[Diagram]

7. Considerações de segurança

8. Roadmap de implementação

Fase Entrega
1. PKI Private CA (raiz offline + subordinada)
2. Sanidade Validar na Imperva com openssl s_client + cert de teste
3. Enrollment API Gateway + Lambda (/enroll, /revoke)
4. Imperva Terraform (upload CA, associação, require_client_certificate) em site de staging/rota de teste
5. App Integração no app (Flutter) — enrollment + mTLS
6. Rollout Staging → canary → prod; manter soft pin (report) durante a transição; monitorar falhas de handshake

9. Pontos em aberto

  1. Front: Flutter (confirmado).
  2. Auth do enrollment: qual token usar? (Cognito, OIDC existente, ou incluir?)
  3. Nuvem: AWS Private CA é ok? Ou preferem smallstep/EJBCA self-hosted?
  4. Validade do cert: 30 ou 90 dias?
  5. Rollout: staging/canary primeiro (recomendado) ou direto em produção?
  6. Plugin de mTLS no Flutter: escolher/validar opção no pub.dev (ou implementar platform channel próprio).