O problema: como proteger agentes de IA em produção com AWS WAF
Quando você expõe um agente de IA generativa construído com o Amazon Bedrock AgentCore como endpoint de API em produção, surgem requisitos legítimos de segurança: limitação de taxa, proteção contra ameaças web comuns, controles de auditoria e políticas de firewall de aplicação web. O serviço responsável por isso na AWS é o AWS WAF — Firewall de Aplicação Web (WAF).
O AWS WAF se integra com três serviços: Application Load Balancers (ALBs), distribuições do Amazon CloudFront e APIs REST do Amazon API Gateway. O CloudFront é voltado para cache e entrega de conteúdo estático — invocações de agentes são dinâmicas e em tempo real, então cache não se aplica. O API Gateway introduz sua própria camada de autenticação e transformação de requisições, o que cria um problema de dupla autenticação com o SigV4 e OAuth já embutidos no AgentCore.
Sobra o ALB voltado para a internet como ponto de integração: ele repassa cabeçalhos de forma transparente, suporta roteamento interno à VPC e se conecta diretamente a uma WebACL do AWS WAF. A partir do ALB, o tráfego é roteado para o AgentCore por meio de um VPC Interface Endpoint — Endpoint de Interface de Nuvem Privada Virtual (VPC) — para o serviço de plano de dados do AgentCore.
É aqui que aparece o desafio técnico central. ALBs exigem health checks para verificar se os backends estão respondendo. Mas o AgentCore Runtime exige autenticação — SigV4 ou OAuth — em todas as chamadas de API, inclusive nas de health check. Os health checks padrão do ALB enviam requisições sem credenciais, e por isso falham por padrão. É preciso uma forma de fazer os health checks funcionarem sem credenciais, enquanto o tráfego de produção autenticado passa normalmente para o AgentCore.
Dois padrões de arquitetura para resolver o problema
A AWS documentou dois padrões que resolvem esse problema. Ambos usam um ALB voltado para a internet com AWS WAF e roteiam o tráfego por um VPC Interface Endpoint até o AgentCore Runtime. O Padrão 1 coloca um proxy AWS Lambda entre o ALB e o VPC Endpoint, dando controle total sobre a transformação de requisições. O Padrão 2 aponta o ALB diretamente para os endereços IP das Interfaces de Rede Elástica (ENIs) do VPC Endpoint, eliminando o salto pelo Lambda. Os dois padrões foram testados de ponta a ponta com autenticação SigV4 e OAuth (JWT do Amazon Cognito).
A base comum entre os dois: o cliente envia uma requisição autenticada (assinatura SigV4 ou Bearer token OAuth) para o ALB voltado para a internet. O AWS WAF inspeciona a requisição antes de o ALB encaminhá-la para as ENIs do VPC Endpoint na porta HTTPS 443. O AgentCore valida a autenticação e roteia a requisição para o container de runtime na porta interna 8080.
Os quatro componentes compartilhados são: o AWS WAF acoplado ao ALB (com limitação de taxa, proteção contra injeção de SQL, filtragem de XSS e controle de bots via grupos de regras gerenciadas como AWSManagedRulesCommonRuleSet); o ALB voltado para a internet com listener HTTPS na porta 443; o VPC Interface Endpoint (com.amazonaws.<region>.bedrock-agentcore) para conectividade privada via PrivateLink; e o AgentCore Runtime como container gerenciado que executa o código do agente.
Atenção: use o endpoint com.amazonaws.<region>.bedrock-agentcore (plano de dados) para invocações de Runtime. Existem três endpoints distintos: bedrock-agentcore (plano de dados para Runtime, Memory e Tools), bedrock-agentcore-control (plano de controle) e bedrock-agentcore.gateway (exclusivo para o Gateway). Usar o endpoint errado não roteará para o seu Runtime.
Padrão 1: ALB com proxy Lambda
Neste padrão, uma função Lambda fica atrás do ALB e encaminha as requisições — incluindo o cabeçalho de autenticação — para o AgentCore pelo VPC Endpoint. A função Lambda oferece uma camada de computação onde é possível transformar requisições, traduzir entre métodos de autenticação ou adicionar logging personalizado antes de a requisição chegar ao AgentCore.

Escolha o Padrão 1 se você precisar de: transformação de requisições (manipulação de cabeçalhos, alterações de payload ou tradução de protocolo); logs personalizados ou trilhas de auditoria na camada de proxy; tradução entre múltiplos métodos de autenticação; ou uma camada de computação explícita entre o ALB e o backend (algumas políticas de segurança exigem isso).
Para OAuth, a função Lambda repassa o cabeçalho Authorization (o Bearer token) sem alteração, junto com o caminho e o corpo da requisição original, de modo que o JWT chegue ao AgentCore intacto. Para SigV4, a assinatura está vinculada ao host original da requisição e se torna inválida após o encaminhamento para o VPC Endpoint — por isso o proxy refaz a assinatura usando as credenciais da sua própria execution role.
O trecho Python abaixo mostra a lógica central de encaminhamento. A função lê o cabeçalho Authorization do evento do ALB, constrói a URL de destino usando o nome DNS do VPC Endpoint e encaminha a requisição com os cabeçalhos e o corpo originais. Esse caminho funciona diretamente para Bearer tokens OAuth. Requisições SigV4 exigem a etapa adicional de reassinatura, disponível no repositório:
import json
import urllib3
import os
http = urllib3.PoolManager()
VPCE_DNS = os.environ["VPCE_DNS_NAME"]
def handler(event, context):
path = event.get("path", "/")
headers = event.get("headers", {})
body = event.get("body", "")
method = event.get("httpMethod", "POST")
target_url = f"https://{VPCE_DNS}{path}"
resp = http.request(
method,
target_url,
headers={
"Authorization": headers.get("authorization", ""),
"Content-Type": headers.get("content-type", "application/json"),
},
body=body,
)
return {
"statusCode": resp.status,
"headers": {"Content-Type": "application/json"},
"body": resp.data.decode("utf-8"),
}
A implementação completa e pronta para produção — incluindo assinatura SigV4, tratamento de query strings, respostas de health check do ALB e tratamento estruturado de erros — está disponível no repositório GitHub de acompanhamento.
Os grupos de destino Lambda não usam health checks baseados em caminho. O ALB verifica se a função é invocável chamando-a diretamente, então nenhuma configuração especial de health check é necessária.
Trade-offs do Padrão 1
- Latência: adiciona 50–200 ms por requisição (cold start do Lambda). Pode ser mitigado com concorrência provisionada.
- Custo: custo de invocação Lambda por requisição. Consulte os preços do AWS Lambda.
- Complexidade: componente adicional para implantar, monitorar e manter.
- Flexibilidade: controle total sobre transformação de requisição/resposta e logging personalizado.
Padrão 2: ALB direto para o VPC Endpoint
Neste padrão, o ALB aponta diretamente para os endereços IP das ENIs do VPC Endpoint na porta HTTPS 443. Não há função Lambda nem Network Load Balancer. O ALB repassa os cabeçalhos de autenticação para o AgentCore de forma transparente. Essa arquitetura tem menos componentes e elimina o salto pelo proxy Lambda.

Escolha o Padrão 2 se quiser: uma arquitetura mais simples com menos componentes; sem transformação de requisições entre o ALB e o AgentCore; latência mínima sem saltos adicionais; e que a aplicação cliente lide diretamente com a assinatura SigV4 ou OAuth.
A etapa-chave que faz o Padrão 2 funcionar é a criação de um target group do tipo IP na porta HTTPS 443 com um health check que não exige autenticação:
aws elbv2 create-target-group \
--name agentcore-vpce-tg \
--target-type ip \
--protocol HTTPS \
--port 443 \
--vpc-id vpc-xxxxxxxxx \
--health-check-protocol HTTPS \
--health-check-port 443 \
--health-check-path / \
--matcher HttpCode=200-499
O health check usa o caminho / com um matcher de 200–499. O AgentCore retorna 404 em / porque não é um caminho de API válido, mas o ALB aceita respostas nesse intervalo como saudáveis. O objetivo é verificar que o VPC Endpoint está respondendo — o código de status específico não importa. Essa abordagem não exige autenticação para os health checks.
Para SigV4 (AWS SDK), basta apontar o SDK para a URL do endpoint do ALB — o SDK cuida da assinatura automaticamente:
import boto3
client = boto3.client(
"bedrock-agentcore",
endpoint_url="https://<alb-dns>"
)
response = client.invoke_agent_runtime(
agentRuntimeArn="arn:aws:bedrock-agentcore:...",
payload='{"input": "hello"}'
)
Para OAuth (navegador ou curl), passe o JWT como Bearer token:
curl -X POST https://<alb-dns>/runtimes/<runtime-arn>/invocations \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{"input": "hello"}'
Observação importante: ao usar o grant client_credentials no Amazon Cognito, o JWT contém a claim client_id, mas não a claim aud. Configure o autorizador OAuth do AgentCore com allowedClients (que corresponde ao client_id) em vez de allowedAudience.
Trade-offs do Padrão 2
- Latência: sem overhead de Lambda, passagem direta.
- Custo: sem custo adicional de computação.
- Complexidade: mínima — apenas ALB + VPC Endpoint.
- Flexibilidade: sem capacidade de transformação de requisições.
Fechando a porta dos fundos com resource policies
Ambos os padrões exigem uma resource policy para impedir acesso direto ao AgentCore que contorne o AWS WAF. Sem essa política, usuários com credenciais válidas podem chamar o endpoint público do AgentCore diretamente, ignorando todas as proteções do WAF.

A resource policy usa dois statements. O primeiro permite InvokeAgentRuntime apenas quando a requisição origina do seu VPC Endpoint específico (condição aws:SourceVpce). O segundo nega InvokeAgentRuntime para requisições que não originem desse VPC Endpoint, com aws:ViaAWSService definido como false para evitar o bloqueio de chamadas internas do próprio serviço AgentCore.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowVPCEOnly",
"Effect": "Allow",
"Principal": "*",
"Action": "bedrock-agentcore:InvokeAgentRuntime",
"Resource": "<runtime-arn>",
"Condition": {
"StringEquals": {
"aws:SourceVpce": "<vpce-id>"
}
}
},
{
"Sid": "DenyDirectAccess",
"Effect": "Deny",
"Principal": "*",
"Action": "bedrock-agentcore:InvokeAgentRuntime",
"Resource": "<runtime-arn>",
"Condition": {
"StringNotEquals": {
"aws:SourceVpce": "<vpce-id>"
},
"Bool": {
"aws:ViaAWSService": "false"
}
}
}
]
}
Após aplicar a policy, o resultado esperado é: OAuth via ALB → VPC Endpoint retorna 200 OK; OAuth direto ao endpoint público do AgentCore retorna 403 (não autorizado); SigV4 para um runtime configurado com OAuth retorna 403 (incompatibilidade de método de autenticação); sem autenticação via ALB retorna 401.
Defesa em profundidade: camadas de segurança
Ambos os padrões fornecem múltiplas camadas de segurança. Cada camada endereça um vetor de ameaça diferente e, juntas, formam uma postura de defesa em profundidade para o seu runtime de agentes. Uma requisição precisa passar por todas as camadas antes de chegar ao seu agente.

- AWS WAF: limitação de taxa, injeção de SQL, XSS, controle de bots e geo-bloqueio.
- Security Group do ALB: controle de acesso em nível de rede, HTTPS 443 apenas de fontes permitidas.
- Security Group do VPC Endpoint: entrada restrita ao security group do ALB.
- Autenticação do AgentCore: SigV4 ou OAuth obrigatório em cada invocação.
- Resource Policy: nega acesso que não origine do VPC Endpoint.
- VPC Endpoint Policy (opcional): restringe a principals IAM ou ações específicas.
Como escolher entre os padrões
- Padrão 1 (proxy Lambda): componentes WAF + ALB + Lambda + VPC Endpoint; latência adicional de 50–200 ms; custo de invocações Lambda; transformação de requisições disponível; health check gerenciado pelo Lambda. Indicado quando você precisa de lógica personalizada ou tradução entre múltiplos métodos de autenticação.
- Padrão 2 (direto ao VPC Endpoint): componentes WAF + ALB + VPC Endpoint; sem latência adicional de Lambda; sem custo extra de computação; sem transformação de requisições; health check via caminho
/com matcher 200–499. Indicado quando você quer a opção mais simples e de menor latência.
Considerações importantes para ambos os padrões
- Apenas porta 443. O VPC Endpoint expõe somente HTTPS 443. A porta 8080 (porta interna do container) não é acessível pelo VPC Endpoint — o AgentCore faz o roteamento 443 → 8080 internamente.
- DNS privado não é obrigatório. O ALB aponta para os IPs das ENIs do VPC Endpoint diretamente, então DNS privado no VPC Endpoint não é necessário em nenhum dos padrões.
- OAuth bloqueia SigV4. Quando um AgentCore Runtime está configurado com um autorizador OAuth, requisições SigV4 são rejeitadas com “Authorization method mismatch”. Escolha um método de autenticação por runtime.
- Seleção do serviço de endpoint. Use
bedrock-agentcorepara o plano de dados do Runtime. O endpointbedrock-agentcore.gatewayé exclusivo para o AgentCore Gateway e não roteará para o seu Runtime. - Estabilidade dos IPs das ENIs. Os IPs das ENIs do VPC Endpoint são estáveis, mas podem mudar se o endpoint for recriado. Monitore a saúde dos targets e atualize os IPs se necessário.
Recursos adicionais
- Repositório GitHub com os padrões
- Documentação do Amazon Bedrock AgentCore
- VPC Interface Endpoints para AgentCore
- Resource-based policies para AgentCore
- Guia do desenvolvedor do AWS WAF
- Protegendo seu gateway com AWS WAF
Fonte
Securing Amazon Bedrock AgentCore Runtime with AWS WAF (https://aws.amazon.com/blogs/machine-learning/securing-amazon-bedrock-agentcore-runtime-with-aws-waf/)
Leave a Reply