Quem Deletou Meu EC2? Rastreando TerminateInstances com CloudTrail
Uma instância EC2 sumiu em produção e ninguém assume a responsabilidade. Antes de escalar o incidente, o primeiro passo é consultar o CloudTrail — ele registra cada chamada de API na sua conta, incluindo exatamente quem executou o TerminateInstances e quando.
TL;DR — Resumo Rápido
| Etapa | O que fazer |
|---|---|
| 1 | Abrir o CloudTrail Event History no console ou usar a CLI |
| 2 | Filtrar pelo nome do evento TerminateInstances |
| 3 | Identificar o campo userIdentity no evento retornado |
| 4 | Confirmar ARN, tipo de principal e hora exata da ação |
Como o CloudTrail Registra Ações de EC2
O CloudTrail captura chamadas de API feitas à AWS — via console, CLI, SDK ou serviços internos. Para o EC2, cada ação de controle (criar, parar, terminar instância) gera um evento de gerenciamento (management event) que fica disponível no Event History por 90 dias, sem necessidade de configurar uma trail separada.
O evento TerminateInstances é emitido pelo serviço ec2.amazonaws.com e contém o campo userIdentity, que identifica o principal que fez a chamada — seja um usuário IAM, uma role assumida, o próprio root, ou um serviço AWS agindo em seu nome.
(IAM User / Role / Root)"] -->|"chamada de API"| EC2API["EC2 API
TerminateInstances"] EC2API -->|"evento gerado"| CT["CloudTrail"] CT --> EH["Event History
(90 dias)"] CT -->|"se trail configurada"| S3["S3 Bucket
(retenção longa)"] CT -->|"se trail + CWL"| CWL["CloudWatch Logs
Insights"]
- Principal — quem fez a chamada: usuário IAM, role, root ou serviço AWS.
- API Call — a ação
TerminateInstancesenviada ao endpoint do EC2. - CloudTrail — intercepta e registra o evento com metadados completos.
- Event History — armazena os últimos 90 dias de eventos de gerenciamento, consultáveis via console ou CLI.
- Trail (opcional) — se configurada, persiste os eventos em S3 para retenção além de 90 dias.
Passo 1 — Buscar o Evento TerminateInstances via CLI
A CLI é mais precisa que o console quando você precisa filtrar por instância específica ou cruzar atributos. É possível filtrar por múltiplos atributos na mesma chamada para refinar a busca, como nome do evento e nome do recurso simultaneamente — basta encadear chamadas ou usar --query para pós-filtrar o resultado. O atributo mais direto para este caso é o EventName.
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=TerminateInstances \
--start-time 2024-01-15T00:00:00Z \
--end-time 2024-01-16T00:00:00Z \
--region us-east-1 \
--output json
Se você sabe o ID da instância (i-0abc123def456), filtre diretamente por ela para evitar ruído em contas com alto volume de eventos:
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=ResourceName,AttributeValue=i-0abc123def456 \
--region us-east-1 \
--output json
Pense no Event History como o CCTV do corredor — ele grava tudo que passa, mas a fita dura só 90 dias. Depois disso, sem uma trail configurada apontando para S3, a gravação some.
Passo 2 — Interpretar o Campo userIdentity
O campo mais importante do evento retornado é o userIdentity. Ele revela não apenas o nome do usuário, mas o tipo de principal — o que muda completamente a investigação dependendo do valor encontrado.
🔽 Exemplo completo do campo userIdentity (clique para expandir)
{
"userIdentity": {
"type": "AssumedRole",
"principalId": "AROAEXAMPLEID:session-name",
"arn": "arn:aws:sts::123456789012:assumed-role/DevOpsRole/session-name",
"accountId": "123456789012",
"sessionContext": {
"sessionIssuer": {
"type": "Role",
"principalId": "AROAEXAMPLEID",
"arn": "arn:aws:iam::123456789012:role/DevOpsRole",
"accountId": "123456789012",
"userName": "DevOpsRole"
},
"attributes": {
"mfaAuthenticated": "false",
"creationDate": "2024-01-15T10:23:00Z"
}
}
}
}
Os tipos mais comuns de userIdentity.type e o que cada um significa na prática:
| Tipo | Significado | Onde investigar |
|---|---|---|
IAMUser | Usuário IAM com credenciais próprias | Campo userName |
AssumedRole | Role assumida via STS | sessionContext.sessionIssuer.arn |
Root | Conta root da AWS | Acesso root direto — alerta crítico |
AWSService | Serviço AWS agindo internamente | Campo invokedBy |
No exemplo acima, a role DevOpsRole foi assumida e a sessão foi criada às 10:23 UTC. O campo mfaAuthenticated: false indica que a sessão não usou MFA — informação relevante para a análise de segurança.
Passo 3 — Verificar pelo Console (Event History)
Para quem prefere o console ou precisa mostrar o resultado para alguém sem acesso à CLI:
- Acesse CloudTrail → Event History no console da AWS.
- No filtro, selecione Event name e digite
TerminateInstances. - Ajuste o intervalo de tempo para cobrir o período suspeito.
- Clique no evento para expandir os detalhes e localizar o campo User name e o AWS access key usado.
Event History"] --> B["Filtrar por Event Name:
TerminateInstances"] B --> C["Selecionar intervalo
de tempo suspeito"] C --> D["Lista de eventos
retornada"] D --> E["Clicar no evento
para expandir"] E --> F["Ler userIdentity:
tipo, ARN, sessionContext"] F --> G{"Tipo de principal?"} G -->|"IAMUser"| H["Campo userName
identifica diretamente"] G -->|"AssumedRole"| I["Ler sessionContext
e principalId"] G -->|"Root"| J["Alerta crítico:
acesso root"]
- O filtro por Event name retorna todos os eventos
TerminateInstancesno período. - Cada evento exibe o usuário, horário e região diretamente na lista.
- Expandir o evento revela o JSON completo, incluindo o
userIdentitye os parâmetros da chamada.
Passo 4 — Cruzar com CloudWatch Logs (se Trail estiver configurada)
Se sua conta tem uma trail ativa enviando eventos para CloudWatch Logs, você consegue fazer queries mais sofisticadas com CloudWatch Logs Insights — útil quando o volume de eventos é alto demais para navegar manualmente.
fields @timestamp, userIdentity.arn, requestParameters.instancesSet.items.0.instanceId
| filter eventName = 'TerminateInstances'
| sort @timestamp desc
| limit 20
Essa query retorna os 20 eventos mais recentes de TerminateInstances, com o ARN do principal e o ID da instância afetada — tudo em uma visualização tabular dentro do console do CloudWatch.
Experiência de Campo: O Caso da Role Compartilhada
Em um incidente real, o evento apontava para uma role chamada AutomationRole — o time de infraestrutura concluiu que um script de automação havia terminado a instância por engano. Investigação encerrada. Errado.
O campo sessionContext.sessionIssuer mostrava a role, mas o campo principalId continha o sufixo da sessão: AROAEXAMPLEID:jenkins-pipeline-deploy. Esse sufixo é o RoleSessionName definido no momento do sts:AssumeRole — e revelou que foi um pipeline específico do Jenkins, não o script genérico, que fez a chamada.
A distinção importa: a role era compartilhada por vários sistemas. Sem ler o principalId completo, você identifica a role mas não quem a assumiu naquele momento. Sempre leia o sufixo da sessão.
O
RoleSessionNameé o único campo que diferencia múltiplos consumidores de uma mesma role — e ele fica noprincipalId, não no ARN da role.
Permissões IAM Necessárias para Consultar o CloudTrail
Para executar os comandos acima, o principal precisa das seguintes permissões. Note que cloudtrail:LookupEvents não suporta restrição por recurso — requer Resource: "*" conforme documentado no Service Authorization Reference da AWS.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cloudtrail:LookupEvents"
],
"Resource": "*"
}
]
}
Se a investigação incluir queries no CloudWatch Logs Insights sobre logs de trail, adicione também logs:StartQuery, logs:GetQueryResults e logs:DescribeLogGroups com o ARN do log group específico.
Próximos Passos e Prevenção
Identificar o responsável resolve o incidente imediato, mas o trabalho real começa depois. Algumas ações recomendadas:
- Configurar uma Trail permanente apontando para S3 com retenção além de 90 dias — o Event History tem janela limitada.
- Habilitar CloudTrail Insights para detectar automaticamente picos anômalos em chamadas de API como
TerminateInstances. - Aplicar SCPs via AWS Organizations para restringir
ec2:TerminateInstancesem contas de produção, exigindo condições específicas (ex: tag de ambiente). - Revisar políticas de role compartilhada — roles usadas por múltiplos sistemas dificultam a atribuição. Prefira roles dedicadas por workload.
Para aprofundar, consulte a documentação oficial do CloudTrail Event History e o guia de exemplos de log do CloudTrail.
Glossário
| Termo | Definição |
|---|---|
| Event History | Interface do CloudTrail que exibe os últimos 90 dias de eventos de gerenciamento sem configuração adicional. |
| userIdentity | Campo do evento CloudTrail que identifica o principal (usuário, role, serviço) que fez a chamada de API. |
| AssumedRole | Tipo de identidade quando uma role IAM foi assumida via STS — o principal real está no sessionContext. |
| RoleSessionName | Nome de sessão definido no momento do sts:AssumeRole, visível no sufixo do principalId. |
| Management Event | Categoria de evento CloudTrail que registra operações de controle sobre recursos AWS, como criar ou terminar instâncias. |
Comentários
Postar um comentário