Zero trust para APIs internas: quando o perímetro não basta
Um pod comprometido dentro da VPC pode chamar toda API interna que confia apenas na localização de rede. Zero trust para APIs internas significa que cada chamada service-to-service carrega identidade, autorização escopada e verificação — não só um IP privado.
A brecha começou dentro do perímetro. Um runner de CI comprometido, um token de serviço vazado, um movimento lateral a partir de um ambiente de staging com rotas de rede para produção — o atacante nunca tocou o load balancer público. Chamou APIs internas diretamente: http://billing-service.internal/api/v1/invoices, http://user-service.internal/admin/export. Sem autenticação. Sem autorização. Os serviços confiavam na VPC. Zero trust para APIs internas rejeita essa suposição: localização de rede é conveniência de transporte, não prova de identidade ou intenção.
Segurança perimetral — firewalls, sub-redes privadas, VPN — mantém estranhos fora. Não impede insiders comprometidos, serviços mal configurados ou atacantes da cadeia de suprimentos de se mover lateralmente. APIs internas são o ponto fraco da maioria das arquiteturas porque os times protegeram a porta da frente e deixaram as portas do corredor destrancadas.
O modelo castelo-e-moato falha em east-west
Modelo tradicional: APIs públicas autenticam usuários; APIs internas confiam na rede.
| Assumption | Reality |
|---|---|
| Só nossos serviços chamam APIs internas | Pods comprometidos, ferramentas de debug, tráfego mal roteado |
| Isolamento VPC equivale a segurança | Peering, clusters compartilhados, staging com rotas para prod |
| APIs internas são baixo risco | Contêm PII, billing, ações de admin |
| mTLS é complexidade opcional | É identidade criptográfica base para service-to-service |
Tráfego east-west — serviço A chamando serviço B dentro do mesmo cluster — costuma superar north-south em volume. Proteger só o ingress ignora a maior parte da superfície de ataque.
"É interno" não é um modelo de autorização. É a ausência de um.
Scopes OAuth e design de autorização valem também para serviços internos: um serviço de billing chamando user-service deve apresentar credenciais escopadas exatamente ao que precisa — não um god-token que lê todo registro de usuário porque "é tudo interno".
Princípios de zero trust para APIs internas
Zero trust não é um produto. É um conjunto de restrições aplicadas de forma consistente:
1. Nunca confiar, sempre verificar
Cada request — inclusive service-to-service — deve apresentar identidade verificável. Opções: mTLS com certificados de serviço, JWTs assinados com TTL curto, identidade de workload SPIFFE/SPIRE. O caller prova quem é; o callee verifica antes de executar.
2. Mínimo privilégio por chamada
Autorização não é binária "interno vs externo". Uma service account do worker de notificações recebe users:read:email em user-service — não users:admin. Design de scopes espelha OAuth externo: grants estreitos, auditáveis, revogáveis.
3. Assumir brecha
Projetar para que um serviço comprometido não exfiltre todo o datastore. Rate limits em endpoints sensíveis, audit logs em rotas de admin, segmentação para que billing não chame rotas arbitrárias de user-service.
4. Criptografar e autenticar em trânsito
TLS em todo lugar — inclusive dentro do cluster. HTTP plano em *.cluster.local é conveniente e legível por qualquer processo com acesso de rede no namespace.
5. Verificação contínua
Credenciais de curta duração. Rotação de certificados. Revogação quando um serviço é descomissionado ou comprometido. API keys estáticas de longa duração em variáveis de ambiente são o equivalente interno de reutilizar senhas.
Camadas de implementação, do pragmático ao abrangente
Times adotam zero trust de forma incremental. As camadas se empilham:
| Layer | Mechanism | Effort | Coverage |
|---|---|---|---|
| Network policy | Kubernetes NetworkPolicy, security groups | Low | Limita quais pods conversam; sem identidade |
| mTLS | Service mesh (Istio, Linkerd) ou cert-manager por serviço | Medium | Identidade criptográfica do caller |
| Token auth | JWT ou token opaco por request, validado em gateway/sidecar | Medium | Identidade + scopes opcionais |
| Policy engine | OPA, Cedar, RBAC custom na camada API | Medium–High | Autorização granular |
| Service mesh policy | mTLS + políticas de autorização no mesh | High | East-west ponta a ponta |
Ponto de partida para a maioria dos times: autenticar chamadas internas antes de otimizar policy engines. Um API gateway interno compartilhado que valida JWTs de serviço supera um mesh que ninguém configurou direito.
Network policy sozinha é necessária mas insuficiente — responde "o pod A pode alcançar a porta do pod B?" e não "este request específico deveria ser permitido?".
Anti-padrões comuns em APIs internas
God service tokens. Uma INTERNAL_API_KEY em doze serviços. Comprometer uma, controlar todas. Credenciais por serviço com permissões escopadas.
Rotas admin sem auth admin. /internal/admin/reindex invocável de qualquer pod no namespace. Superfície admin separada, auth mais forte, audit log.
Confiar em X-Forwarded-User de callers internos. Qualquer serviço pode forjar headers. Identidade de usuário deve vir de tokens validados, não de headers confiáveis em saltos internos.
Pular auth em clusters "dev" que espelham topologia prod. Staging com dados de produção e sem auth interna é uma brecha esperando um clique errado.
Cadeia de suprimentos como caller interno. Webhooks de terceiros e integrações SaaS costumam cair em filas internas. Tratá-los como não confiáveis até verificar — relacionado a ataques de cadeia de suprimentos que miram a confiança.
Como times devem implementar zero trust para APIs internas?
Estas perguntas delimitam o primeiro sprint versus o programa completo.
mTLS é obrigatório em toda chamada interna?
Nem sempre no dia um. Mínimo: alguma identidade criptográfica em caminhos sensíveis (billing, PII, admin). Expandir para mTLS completo conforme o mesh ou a infra de certificados amadurece. Chamadas HTTP internas planas a endpoints de health somente leitura têm prioridade menor que chamadas que mutam estado financeiro.
Como scopes funcionam em chamadas service-to-service?
Espelhar OAuth de usuário: emitir service tokens com audience (aud), issuer (iss), scopes (billing:invoice:read) e expiração curta. O callee valida todos os claims. Documentar quais serviços podem ter quais scopes — a mesma disciplina de design de scopes OAuth.
E serviços legacy que não conseguem adicionar auth rápido?
API gateway ou sidecar proxy na frente do serviço legacy: terminar mTLS, injetar header de identidade validada (assinado pelo gateway, não forjável), o serviço legacy confia só em requests originados no gateway. Padrão ponte até auth nativa existir.
Uma visão oposta
A postura contrária sustenta que zero trust em APIs internas adiciona latência, carga operacional e atrito de debugging — que isolamento VPC e network policies bastam para times sem adversários de nível estatal.
O custo operacional é real. Também é o movimento lateral após uma única credencial comprometida — algo que acontece a startups e enterprises por igual. Zero trust pragmático começa em caminhos de alto valor: APIs admin, exports de PII, mutações de pagamento. Mesh completo pode esperar; "sem auth porque é interno" não pode.
O atrito de debug é gerenciado com identidade de serviço em traces e audit logs estruturados — saber qual serviço chamou qual endpoint é mais fácil com identidade do que com tráfego interno anônimo.
O que importa lembrar
- Pertencer à VPC não é identidade — verificar cada chamada a API interna.
- Tráfego east-west precisa da mesma disciplina de auth que APIs públicas.
- Scopes de mínimo privilégio valem para service accounts, não só usuários.
- mTLS ou tokens assinados são baseline; network policy sozinha é insuficiente.
- God internal API keys são um único ponto de comprometimento.
- Implementar primeiro em caminhos sensíveis; fazer ponte para legacy com proxies de gateway.
Conclusão
O perímetro manteve atacantes fora até que um entrou. APIs internas projetadas para trust-on-network viram autoestradas de movimento lateral. Zero trust para APIs internas significa que cada chamada responde: quem está chamando, têm permissão para fazer isso, e o canal está protegido em integridade?
A auditoria começa com inventário: listar endpoints internos, marcar quais exigem auth hoje, marcar quais contêm dados sensíveis. A lacuna entre essas listas é o roadmap. Fechá-la antes do comprometimento, não depois.