Claude Code e AWS IAM: guia prático de políticas de menor privilégio
Projete e valide políticas AWS IAM de menor privilégio com Claude Code, Access Analyzer e CDK.
AWS IAM define quem pode fazer o quê em cada recurso da AWS. Uma política parece apenas um JSON, mas um Action: "*" ou Resource: "*" pode dar a uma Lambda, a um job de CI ou a uma conta humana muito mais acesso do que o necessário. Claude Code ajuda a escrever e revisar políticas, mas não deve virar um aprovador automático de permissões.
O fluxo seguro é simples: descrever o caso de uso, pedir um rascunho ao Claude Code, validar com IAM Access Analyzer, revisar ARN e limites de negócio, implementar com CDK e testar tanto as ações permitidas quanto as negadas. Para iniciantes: política é a regra de permissão, role é a identidade temporária assumida por um workload, e principal é o usuário ou serviço que usa a permissão.
Masa mudou esse processo depois de encontrar uma permissão S3 ampla ainda presa a uma Lambda de produção semanas após um hotfix. Não houve vazamento, mas a conclusão ficou clara: Claude Code reduz o tempo de escrita, não a responsabilidade de revisão.
Use a documentação oficial como base
Esta orientação segue as referências oficiais da AWS:
- Security best practices in IAM
- IAM JSON policy element reference
- Validate policies with IAM Access Analyzer
- Temporary security credentials in IAM
- Permissions boundaries for IAM entities
Na prática: prefira credenciais temporárias e roles, aplique menor privilégio, valide com Access Analyzer, use condições com cuidado e remova permissões que não são mais usadas.
flowchart LR
A["Escrever o caso de uso"] --> B["Rascunho do Claude Code"]
B --> C["Revisão humana de ARN"]
C --> D["IAM Access Analyzer"]
D --> E["Implementação CDK"]
E --> F["Testes permitidos e negados"]
Comece por casos de uso concretos
Não peça apenas “crie uma política IAM”. Informe ator, recursos, ações permitidas e ações que devem continuar proibidas.
| Caso de uso | Principal | Permissões necessárias | Evitar explicitamente |
|---|---|---|---|
| Lambda de miniaturas | Role de execução Lambda | Ler um prefixo S3, escrever um prefixo S3, escrever uma tabela DynamoDB, publicar um tópico SNS, escrever logs | Apagar S3, ler todos os buckets, ações IAM |
| Upload no painel administrativo | Role Lambda de API | PutObject em um prefixo S3, GetItem em uma tabela DynamoDB | List no bucket inteiro, gestão de chaves KMS |
| Deploy pelo GitHub Actions | Role CI com OIDC | Atualizar um stack CloudFormation e a Lambda alvo | AdministratorAccess, ações em todas as regiões |
| Investigação de incidente | Usuário federado | Buscar CloudWatch Logs, ler X-Ray, GetItem na tabela relevante | Atualizar, apagar, ler secrets |
A coluna de proibições é essencial. Ferramentas generativas tendem a preencher lacunas com permissões amplas quando o limite negativo não está escrito.
Política Lambda pronta para copiar
Esta política é para uma Lambda que lê imagens do S3, grava miniaturas em outro prefixo, escreve metadados no DynamoDB, publica alerta no SNS e grava logs. O grupo de logs é criado antes por infraestrutura como código, então a role não precisa de logs:CreateLogGroup.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadSourceImages",
"Effect": "Allow",
"Action": ["s3:GetObject"],
"Resource": "arn:aws:s3:::user-uploads-prod/incoming/*"
},
{
"Sid": "WriteThumbnails",
"Effect": "Allow",
"Action": ["s3:PutObject"],
"Resource": "arn:aws:s3:::user-thumbnails-prod/thumbnails/*",
"Condition": {
"StringEquals": {
"s3:x-amz-server-side-encryption": "AES256"
}
}
},
{
"Sid": "WriteMetadata",
"Effect": "Allow",
"Action": ["dynamodb:PutItem", "dynamodb:UpdateItem"],
"Resource": "arn:aws:dynamodb:ap-northeast-1:123456789012:table/image-metadata"
},
{
"Sid": "PublishAlerts",
"Effect": "Allow",
"Action": ["sns:Publish"],
"Resource": "arn:aws:sns:ap-northeast-1:123456789012:alert-topic"
},
{
"Sid": "WriteLambdaLogs",
"Effect": "Allow",
"Action": ["logs:CreateLogStream", "logs:PutLogEvents"],
"Resource": "arn:aws:logs:ap-northeast-1:123456789012:log-group:/aws/lambda/image-worker-prod:*"
}
]
}
Salve como policy-lambda-image-worker.json e execute:
aws accessanalyzer validate-policy \
--policy-document file://policy-lambda-image-worker.json \
--policy-type IDENTITY_POLICY \
--query "findings[?findingType!='SUGGESTION']"
Depois peça uma revisão estruturada:
claude -p "Revise policy-lambda-image-worker.json como política AWS IAM de menor privilégio.
Contexto: Lambda lê S3 incoming/, escreve thumbnails/, escreve DynamoDB image-metadata, publica SNS alert-topic e escreve CloudWatch Logs.
Verifique: curingas, permissões de exclusão, Resource amplo demais, Condition correta e escopo de logs.
Retorne uma tabela com Sid, risco, motivo e correção mais segura."
Access Analyzer valida gramática, ARN, nomes de ações, chaves de condição e achados de segurança. Ele não sabe se o produto realmente precisa da permissão. Essa decisão continua sendo humana.
Implemente a role com CDK
Não deixe permissões revisadas apenas no console. Com TypeScript CDK, role, grupo de logs e política ficam na mesma revisão de código.
import * as cdk from "aws-cdk-lib";
import { Stack, StackProps, aws_iam as iam, aws_logs as logs } from "aws-cdk-lib";
import { Construct } from "constructs";
export class ImageWorkerIamStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const account = Stack.of(this).account;
const region = Stack.of(this).region;
new logs.LogGroup(this, "ImageWorkerLogGroup", {
logGroupName: "/aws/lambda/image-worker-prod",
retention: logs.RetentionDays.ONE_MONTH,
removalPolicy: cdk.RemovalPolicy.RETAIN,
});
const role = new iam.Role(this, "ImageWorkerRole", {
assumedBy: new iam.ServicePrincipal("lambda.amazonaws.com"),
description: "Execution role for image-worker-prod Lambda",
});
role.addToPolicy(new iam.PolicyStatement({
sid: "ReadSourceImages",
actions: ["s3:GetObject"],
resources: ["arn:aws:s3:::user-uploads-prod/incoming/*"],
}));
role.addToPolicy(new iam.PolicyStatement({
sid: "WriteThumbnails",
actions: ["s3:PutObject"],
resources: ["arn:aws:s3:::user-thumbnails-prod/thumbnails/*"],
conditions: {
StringEquals: {
"s3:x-amz-server-side-encryption": "AES256",
},
},
}));
role.addToPolicy(new iam.PolicyStatement({
sid: "WriteMetadataAndAlerts",
actions: ["dynamodb:PutItem", "dynamodb:UpdateItem", "sns:Publish"],
resources: [
`arn:aws:dynamodb:${region}:${account}:table/image-metadata`,
`arn:aws:sns:${region}:${account}:alert-topic`,
],
}));
role.addToPolicy(new iam.PolicyStatement({
sid: "WriteLambdaLogs",
actions: ["logs:CreateLogStream", "logs:PutLogEvents"],
resources: [
`arn:aws:logs:${region}:${account}:log-group:/aws/lambda/image-worker-prod:*`,
],
}));
}
}
CI com OIDC, não com chaves longas
Para CI/CD, evite guardar chaves AWS de longo prazo nos secrets do repositório. GitHub Actions pode assumir uma role IAM via OIDC e receber credenciais temporárias.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:example-org/example-repo:ref:refs/heads/main"
}
}
}
]
}
Essa é uma política de confiança: decide quem pode assumir a role. A política de permissões decide o que a role pode fazer depois. Revise as duas separadamente.
Falhas comuns
A primeira é deixar acesso administrador temporário para sempre. Se uma emergência exigir permissão ampla, registre responsável, data de expiração, checagem no CloudTrail e nova validação com Access Analyzer.
A segunda é misturar ARN de bucket e objeto S3. s3:ListBucket usa arn:aws:s3:::bucket-name; s3:GetObject e s3:PutObject usam arn:aws:s3:::bucket-name/prefix/*.
A terceira é colocar condição de IP em role Lambda sem entender chamadas entre serviços. aws:SourceIp pode fazer sentido para humanos ou APIs públicas, mas pode quebrar fluxos internos da AWS.
A quarta é testar só o sucesso. Confirme também que s3:DeleteObject, buckets não relacionados, tabelas não relacionadas e ações IAM são negados.
Leituras relacionadas e próximo passo
Para continuar, veja o guia AWS Lambda, o guia AWS S3, o guia AWS CloudWatch e as boas práticas de segurança com Claude Code.
Se sua equipe quer padronizar Claude Code, AWS IAM, CDK e revisão de permissões CI, comece pela página de treinamento e consultoria. Para estudo individual, use a folha gratuita e os modelos da página de produtos.
Testei este fluxo gerando a política com Claude Code, validando o JSON e revisando o CDK contra a mesma tabela de casos de uso. O maior ganho veio de escrever antes as ações proibidas: permissões S3 amplas e curingas de logs desnecessários apareceram antes do deploy.
Artigos relacionados
Claude Code e AWS API Gateway: HTTP API com SAM, CORS, logs, autenticação e limites
Implemente AWS API Gateway com Claude Code, SAM, CORS, logs, auth e throttling com exemplos práticos.
Claude Code com AWS CloudFormation e CDK: guia prático de revisão IaC
Revise AWS CDK e CloudFormation com Claude Code: IAM mínimo, diffs, drift, rollback e guardrails práticos.
Claude Code e AWS DynamoDB: design de tabela, escritas seguras e custos
Guia prático de Claude Code com DynamoDB: chaves, testes locais, TTL, IAM, custos e hot partitions.
PDF grátis: cheatsheet do Claude Code
Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.
Cuidamos dos seus dados e não enviamos spam.
Sobre o autor
Masa
Engenheiro focado em workflows práticos com Claude Code.