Service mesh e mTLS

1. Introdução ao Service Mesh e sua Importância para Segurança

Em arquiteturas de microserviços, a comunicação entre serviços é um dos pontos mais críticos de segurança. Sem proteção adequada, dados trafegam em texto claro, identidades de serviço podem ser falsificadas, e ataques como man-in-the-middle (MITM) tornam-se factíveis. É aqui que o service mesh entra como uma camada de infraestrutura dedicada a gerenciar a comunicação entre serviços de forma segura, observável e controlada.

Um service mesh é composto por dois elementos principais:

  • Plano de dados (data plane): implementado por proxies sidecar (como Envoy, Linkerd-proxy) que interceptam todo o tráfego de entrada e saída de cada serviço.
  • Plano de controle (control plane): gerencia configurações, distribui certificados e define políticas de segurança (ex: Istiod no Istio, Conduit no Linkerd).

O grande benefício para segurança é que o service mesh permite implementar criptografia, autenticação e autorização sem modificar uma única linha de código da aplicação. O desenvolvedor continua escrevendo HTTP simples, enquanto o sidecar cuida do TLS, da verificação de identidade e das políticas de acesso.

2. Fundamentos do mTLS (Mutual TLS)

O TLS tradicional (unidirecional) autentica apenas o servidor perante o cliente. O cliente verifica o certificado do servidor, mas o servidor não verifica quem é o cliente. Em ambientes de microserviços, isso é insuficiente — precisamos que ambas as partes provem sua identidade.

O mTLS (Mutual TLS) resolve isso:

  • O cliente apresenta seu certificado ao servidor.
  • O servidor valida o certificado do cliente contra uma Autoridade Certificadora (CA) confiável.
  • Após a autenticação bilateral, um canal criptografado é estabelecido.

O handshake mTLS segue estes passos:

1. Cliente envia "ClientHello"
2. Servidor responde com "ServerHello" + certificado do servidor
3. Cliente valida certificado do servidor
4. Servidor envia "CertificateRequest" (solicita certificado do cliente)
5. Cliente envia seu certificado
6. Servidor valida certificado do cliente
7. Troca de chaves simétricas (Diffie-Hellman)
8. Conexão criptografada estabelecida

Cada serviço no mesh recebe uma identidade única baseada em seu certificado, permitindo que políticas de segurança sejam aplicadas por identidade de workload, não por IP ou hostname.

3. Como o Service Mesh Implementa mTLS na Prática

O service mesh automatiza todo o ciclo de vida dos certificados:

  • Geração automática: ferramentas como SPIRE ou cert-manager integram-se ao plano de controle para emitir certificados X.509 para cada pod/serviço.
  • Distribuição via sidecar: o proxy Envoy recebe o certificado e a chave privada através do plano de controle (ex: via SDS - Secret Discovery Service no Istio).
  • Rotação sem downtime: certificados são renovados automaticamente antes da expiração. O sidecar carrega o novo certificado sem interromper conexões ativas (usando rotação de segredos em segundo plano).

Exemplo de configuração de mTLS no Istio usando PeerAuthentication:

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: production
spec:
  mtls:
    mode: STRICT

Este manifesto define que todo o tráfego dentro do namespace production deve usar mTLS. Se um serviço tentar se comunicar sem TLS, a conexão será rejeitada.

4. Políticas de Segurança com mTLS no Service Mesh

O mTLS no service mesh oferece três modos de operação:

  • STRICT: mTLS obrigatório. Conexões sem certificado são rejeitadas.
  • PERMISSIVE: aceita tanto mTLS quanto texto plano. Útil durante migração.
  • DISABLE: desabilita mTLS (não recomendado em produção).

Após a autenticação mTLS, podemos aplicar autorização baseada em identidade (RBAC). O Istio permite criar políticas AuthorizationPolicy que usam a identidade do cliente (obtida do certificado mTLS) para decidir se uma requisição é permitida.

Exemplo de política de autorização:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: payments-policy
  namespace: production
spec:
  selector:
    matchLabels:
      app: payments
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/production/sa/orders"]
    to:
    - operation:
        methods: ["POST"]
        paths: ["/api/v1/charge"]

Neste exemplo, apenas o serviço orders (com service account orders) pode chamar o endpoint POST /api/v1/charge do serviço payments. Qualquer outra identidade terá a requisição negada.

5. Benefícios de Segurança do mTLS em Service Mesh

A adoção de mTLS via service mesh traz ganhos concretos:

  • Eliminação de ataques MITM: todo tráfego entre serviços é criptografado e autenticado bilateralmente. Um atacante que consiga interceptar o tráfego não conseguirá ler nem modificar os dados.
  • Isolamento de workload: cada serviço recebe uma identidade criptográfica única (baseada no service account do Kubernetes). Isso impede que um serviço comprometido se passe por outro.
  • Rastreabilidade e auditoria: o Envoy registra todas as conexões mTLS estabelecidas, incluindo identidade de origem e destino, permitindo auditoria forense em caso de incidente.

6. Desafios e Boas Práticas na Adoção

Apesar dos benefícios, a adoção de mTLS em service mesh apresenta desafios:

Impacto no desempenho:
- O handshake TLS adiciona latência inicial (tipicamente 1-5ms por conexão).
- A criptografia consome CPU, especialmente em cenários de alto throughput.
- Mitigação: usar conexões persistentes (HTTP/2, gRPC) para reduzir handshakes, e empregar aceleração de hardware (AES-NI) quando possível.

Gerenciamento de certificados:
- Certificados expiram — é preciso renovação automática e monitoramento.
- Revogação de certificados comprometidos exige integração com CRL ou OCSP.
- Mitigação: usar certificados de curta duração (ex: 24h) com renovação automática via SPIRE ou cert-manager.

Compatibilidade com serviços legados:
- Serviços que não suportam TLS podem exigir modo PERMISSIVE durante a migração.
- Ambientes híbridos (on-premise + cloud) podem ter CAs diferentes — é necessário estabelecer uma cadeia de confiança comum.

7. Exemplo Prático: Configuração de mTLS com Istio

Vamos configurar mTLS estrito em um namespace e testar a comunicação.

Passo 1: Habilitar mTLS STRICT no namespace secure-app:

kubectl create namespace secure-app
kubectl label namespace secure-app istio-injection=enabled

kubectl apply -n secure-app -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: strict-mtls
spec:
  mtls:
    mode: STRICT
EOF

Passo 2: Implantar dois serviços de teste:

kubectl apply -n secure-app -f samples/helloworld/helloworld.yaml
kubectl apply -n secure-app -f samples/sleep/sleep.yaml

Passo 3: Verificar conexões seguras com istioctl:

istioctl proxy-config secret -n secure-app deploy/sleep

Este comando mostra os certificados mTLS que o sidecar do sleep está usando.

Passo 4: Testar comunicação com mTLS ativo:

kubectl exec -n secure-app deploy/sleep -- curl -s http://helloworld:5000/hello

A requisição funciona porque ambos os serviços têm sidecars que negociam mTLS automaticamente.

Passo 5: Testar comunicação sem mTLS (simulando um cliente externo):

kubectl run -n secure-app test-pod --image=alpine/curl --rm -it -- sh
/ # curl -v http://helloworld:5000/hello

A conexão será rejeitada, pois o serviço helloworld exige mTLS e o pod test-pod não tem sidecar.

Verificação nos logs do Envoy:

istioctl proxy-config log -n secure-app deploy/helloworld --level debug
kubectl logs -n secure-app deploy/helloworld -c istio-proxy | grep mTLS

Os logs mostrarão eventos como "mTLS handshake completed" para conexões autorizadas e "TLS error" para tentativas sem certificado.

8. Conclusão e Próximos Passos

O service mesh combinado com mTLS representa uma das abordagens mais eficazes para garantir segurança na comunicação entre microserviços. Ele elimina a necessidade de implementar lógica de TLS em cada aplicação, oferece autenticação bilateral robusta e permite controle de acesso granular baseado em identidade.

Para uma implementação segura em produção, siga este checklist:

  • [ ] Habilitar mTLS STRICT em todos os namespaces de produção
  • [ ] Configurar rotação automática de certificados com expiração curta (≤ 48h)
  • [ ] Implementar políticas de autorização baseadas em service accounts
  • [ ] Monitorar logs de conexão mTLS para detecção de anomalias
  • [ ] Testar cenários de falha (certificado expirado, CA comprometida)
  • [ ] Usar modo PERMISSIVE apenas durante migração, com prazo definido

O mTLS é um pilar fundamental para implementar o modelo Zero Trust em arquiteturas de microserviços, onde nenhuma comunicação é confiável por padrão.

Referências