1. O problema: privilégio excessivo é a norma, não a exceção
Nos dois artigos anteriores desta série, vimos como evitar que segredos vazem em texto puro e como bloquear recursos inseguros antes do apply com Policy as Code. Fechamos a série com um problema mais silencioso, porque não gera erro nem alerta: permissões de IAM concedidas com mais alcance do que o necessário. Uma role de aplicação com s3:* quando só precisa de s3:GetObject em um bucket específico. Um usuário de CI com AdministratorAccess porque "assim resolve na hora e ninguém precisa pedir mais permissão depois". Nada disso quebra nada — até o dia em que uma credencial é comprometida, e o raio de ação do atacante é exatamente do tamanho da permissão que ninguém restringiu.
2. Erros comuns de permissão excessiva
-
Actions com wildcard:
"Action": "s3:*"ou"Action": "*"em vez de listar exatamente as operações necessárias (s3:GetObject,s3:PutObject). -
Resources com wildcard:
"Resource": "*"quando a intenção real era restringir a um bucket ou prefixo específico. - Roles compartilhadas entre serviços diferentes: uma única role "backend-role" usada por várias Lambdas/serviços com necessidades distintas, acumulando permissões de todos ao longo do tempo porque é mais fácil reaproveitar do que criar uma nova.
-
Credenciais de longa duração: access keys de usuário IAM sem rotação, em vez de roles assumidas temporariamente (via
sts:AssumeRole) ou identidades federadas (OIDC em pipelines de CI). - Permissões concedidas e nunca revisadas: um acesso liberado para resolver um incidente pontual ("dá acesso de admin no S3 pra debugar isso rápido") que nunca é removido depois.
3. Desenhando políticas mínimas: metodologia
Least privilege na prática raramente é "acertar de primeira" — é um processo iterativo:
- Comece restritivo, não permissivo. Ao criar uma role nova, liste apenas as actions que o código efetivamente chama, mesmo que isso signifique testar e ajustar algumas vezes até funcionar.
- Use os logs de acesso reais para calibrar. Ferramentas como o IAM Access Analyzer (AWS) geram recomendações de política baseadas no uso real registrado em CloudTrail — em vez de adivinhar quais actions são necessárias, você vê quais foram efetivamente chamadas em um período.
-
Restrinja por
Resource, não só porAction. Permitirs3:GetObjectem*ainda é privilégio excessivo se a aplicação só precisa de um bucket. Sempre que a API do serviço suportar, especifique o ARN exato. -
Adicione condições (
Condition) quando possível. Restringir por IP de origem, exigir MFA, ou limitar por tag do recurso são camadas adicionais que reduzem o impacto de uma credencial vazada.
4. Exemplo prático: de permissivo a mínimo
Política de partida, comum em código copiado de um tutorial genérico:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
]
}
Versão com least privilege, depois de identificar que a aplicação só lê objetos de um bucket específico, sob um prefixo específico:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::app-uploads-prod",
"arn:aws:s3:::app-uploads-prod/incoming/*"
],
"Condition": {
"StringEquals": {
"aws:PrincipalTag/environment": "production"
}
}
}
]
}
Em Terraform, o mesmo desenho, evitando reescrever o JSON manualmente:
data "aws_iam_policy_document" "app_uploads_read" {
statement {
effect = "Allow"
actions = [
"s3:GetObject",
"s3:ListBucket",
]
resources = [
aws_s3_bucket.app_uploads.arn,
"${aws_s3_bucket.app_uploads.arn}/incoming/*",
]
condition {
test = "StringEquals"
variable = "aws:PrincipalTag/environment"
values = ["production"]
}
}
}
resource "aws_iam_policy" "app_uploads_read" {
name = "app-uploads-read-only"
policy = data.aws_iam_policy_document.app_uploads_read.json
}
5. Automatizando a auditoria de acessos
Desenhar a política mínima na criação não é suficiente — permissões tendem a acumular ao longo do tempo, e é preciso um processo contínuo para detectar isso:
- IAM Access Analyzer identifica automaticamente recursos acessíveis por entidades externas à conta (buckets, roles, chaves KMS) e também gera relatórios de "permissões concedidas versus permissões usadas nos últimos 90 dias", apontando o que pode ser removido:
aws accessanalyzer list-findings \
--analyzer-arn arn:aws:access-analyzer:us-east-1:123456789012:analyzer/default \
--filter '{"status": {"eq": ["ACTIVE"]}}'
- cloudsplaining, uma ferramenta open source, escaneia políticas IAM de uma conta AWS inteira e sinaliza padrões arriscados (wildcards, privilege escalation, ausência de resource constraints) em um relatório HTML:
pip install cloudsplaining
cloudsplaining download --profile production
cloudsplaining scan --input-file default.json --output results/
-
Integrando com o pipeline de IaC: o mesmo
conftest/OPA visto no artigo anterior desta série pode avaliar documentos de política IAM gerados pelo Terraform antes do apply, bloqueando qualquer"Resource": "*"combinado com uma action de escrita, por exemplo:
package terraform.iam
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_iam_policy"
statement := resource.change.after.policy.Statement[_]
statement.Effect == "Allow"
statement.Resource == "*"
msg := sprintf(
"política '%s' usa Resource=\"*\" — restrinja ao ARN específico",
[resource.address],
)
}
6. Rotação e identidades temporárias
Além de restringir o que uma credencial pode fazer, reduzir por quanto tempo ela é válida limita ainda mais o impacto de um vazamento:
- Prefira roles assumidas via
sts:AssumeRolea usuários IAM com access key fixa sempre que possível. - Em pipelines de CI, use OIDC federation (GitHub Actions, GitLab CI já suportam nativamente) para que o pipeline assuma uma role temporária sem nenhuma credencial de longa duração armazenada como secret:
# GitHub Actions assumindo uma role via OIDC, sem access key fixa
permissions:
id-token: write
contents: read
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-deploy
aws-region: us-east-1
7. Conclusão da série
Segredos guardados corretamente, recursos validados por política antes do apply e permissões desenhadas com o mínimo privilégio necessário são três frentes independentes, mas que se reforçam: um segredo vazado importa menos se a credencial associada tem alcance limitado; uma política de IAM bem desenhada é, ela mesma, um alvo natural de checagem via Policy as Code. Nenhuma automação de infraestrutura está completa sem tratar segurança e governança como parte do pipeline, não como uma revisão manual que acontece (ou não) antes de ir para produção.
Imagem de capa: Logo oficial da HashiCorp, mantenedora do Vault — Wikimedia Commons
Referências:
Top comments (0)