Use Cases (Actualizado: 3/6/2026)

Claude Code y AWS IAM: guía práctica de políticas de mínimo privilegio

Diseña y valida políticas AWS IAM de mínimo privilegio con Claude Code, Access Analyzer y CDK.

Claude Code y AWS IAM: guía práctica de políticas de mínimo privilegio

AWS IAM decide quién puede hacer qué sobre cada recurso de AWS. Una política parece solo un documento JSON, pero un Action: "*" o Resource: "*" puede dar a una Lambda, a un job de CI o a una cuenta humana mucho más poder del necesario. Claude Code ayuda a redactar y revisar políticas, pero no debe convertirse en un generador de permisos sin control.

La forma segura es trabajar en pasos: describir el caso de uso, pedir un borrador a Claude Code, validar con IAM Access Analyzer, revisar los ARN y límites de negocio, fijar la política con CDK y probar tanto las acciones permitidas como las denegadas. Para empezar: una política es la regla de permisos, un rol es una identidad temporal que asume una carga de trabajo y un principal es el usuario o servicio que usa el permiso.

Masa cambió su proceso después de descubrir que una política S3 amplia, añadida como parche temporal a una Lambda de producción, seguía activa semanas después. No hubo fuga, pero la lección fue clara: Claude Code reduce el tiempo de redacción, no la responsabilidad de revisión.

Usa la documentación oficial como base

Esta guía sigue las recomendaciones actuales de AWS:

El resumen práctico: usa credenciales temporales y roles, aplica mínimo privilegio, valida con Access Analyzer, usa condiciones con cuidado y elimina permisos que ya no se usan.

flowchart LR
  A["Escribir caso de uso"] --> B["Borrador con Claude Code"]
  B --> C["Revisión humana de ARN"]
  C --> D["IAM Access Analyzer"]
  D --> E["Implementación con CDK"]
  E --> F["Pruebas permitidas y denegadas"]

Empieza por casos de uso concretos

No pidas solo “crea una política IAM”. Incluye actor, recursos, operaciones permitidas y operaciones que deben quedar prohibidas.

Caso de usoPrincipalPermisos necesariosEvitar explícitamente
Lambda de miniaturasRol de ejecución LambdaLeer un prefijo S3, escribir un prefijo S3, escribir una tabla DynamoDB, publicar un tema SNS, escribir logsBorrar S3, leer todos los buckets, operar IAM
Ayuda de carga en panel internoRol Lambda de APIPutObject en un prefijo S3, GetItem en una tabla DynamoDBList de todo el bucket, gestión de claves KMS
Despliegue desde GitHub ActionsRol CI con OIDCActualizar un stack CloudFormation y una Lambda concretaAdministratorAccess, operaciones en todas las regiones
Rol de investigación de incidentesUsuario federadoBuscar en CloudWatch Logs, leer X-Ray, GetItem en la tabla relevanteActualizar, borrar, leer secretos

La columna de prohibiciones evita que Claude Code rellene información faltante con permisos demasiado amplios.

Política Lambda lista para copiar

Esta política es para una Lambda que lee imágenes desde S3, guarda miniaturas en otro prefijo, escribe metadatos en DynamoDB, publica alertas en SNS y escribe logs. El grupo de logs se crea antes con infraestructura como código, por eso el rol no necesita 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:*"
    }
  ]
}

Guárdala como policy-lambda-image-worker.json y ejecuta:

aws accessanalyzer validate-policy \
  --policy-document file://policy-lambda-image-worker.json \
  --policy-type IDENTITY_POLICY \
  --query "findings[?findingType!='SUGGESTION']"

Después pide una revisión estructurada:

claude -p "Revisa policy-lambda-image-worker.json como política AWS IAM de mínimo privilegio.
Contexto: Lambda lee S3 incoming/, escribe thumbnails/, escribe DynamoDB image-metadata, publica SNS alert-topic y escribe CloudWatch Logs.
Comprueba: comodines, permisos de borrado, Resource demasiado amplio, Condition correcta y alcance de logs.
Devuelve una tabla con Sid, riesgo, motivo y corrección más segura."

Access Analyzer valida gramática, ARN, acciones, claves de condición y hallazgos de seguridad. No sabe si tu producto necesita realmente esa acción; esa decisión sigue siendo humana.

Implementa el rol con CDK

No dejes permisos revisados solo en la consola. Con TypeScript CDK, el rol, el grupo de logs y las políticas quedan en la misma solicitud de cambios.

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 con OIDC, no con claves largas

Para CI/CD, evita guardar claves AWS de largo plazo en secretos del repositorio. GitHub Actions puede asumir un rol IAM mediante OIDC y recibir credenciales temporales.

{
  "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"
        }
      }
    }
  ]
}

Esto es una política de confianza: decide quién puede asumir el rol. La política de permisos decide qué puede hacer después. Revísalas por separado.

Errores habituales

El primero es dejar permisos de administrador temporales. Si una emergencia exige ampliar permisos, registra responsable, fecha de caducidad, revisión de CloudTrail y nueva ejecución de Access Analyzer.

El segundo es mezclar ARN de bucket y de objeto en S3. s3:ListBucket usa arn:aws:s3:::bucket-name; s3:GetObject y s3:PutObject usan arn:aws:s3:::bucket-name/prefix/*.

El tercero es añadir condiciones IP a roles de Lambda sin entender llamadas entre servicios. aws:SourceIp puede tener sentido para humanos o APIs públicas, pero puede romper flujos internos de AWS.

El cuarto es probar solo el éxito. También confirma que s3:DeleteObject, buckets no relacionados, tablas no relacionadas y acciones IAM quedan denegadas.

Lecturas relacionadas y siguiente paso

Para profundizar, lee la guía AWS Lambda, la guía AWS S3, la guía AWS CloudWatch y las buenas prácticas de seguridad con Claude Code.

Si tu equipo quiere estandarizar Claude Code, AWS IAM, CDK y revisión de permisos CI, empieza por la página de formación y consultoría. Para trabajo individual, usa la hoja gratuita y los materiales de la página de productos.

Probé este flujo generando la política con Claude Code, validando el JSON y revisando el CDK contra la misma tabla de casos de uso. La mejora principal fue escribir primero las operaciones prohibidas: los permisos S3 amplios y los comodines de logs innecesarios aparecieron antes del despliegue.

#claude-code #aws #iam #security #typescript #infrastructure
Gratis

PDF gratis: cheatsheet de Claude Code

Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.

Cuidamos tus datos y no enviamos spam.

Masa

Sobre el autor

Masa

Ingeniero enfocado en workflows prácticos con Claude Code.