Use Cases (Actualizado: 1/6/2026)

Claude Code × AWS S3: sync, subida de imágenes, backups y URLs firmadas con mínimo privilegio

Guía Claude Code y AWS S3: IAM mínimo, aws s3 sync, sitio estático, imágenes, backups y URLs firmadas.

Claude Code × AWS S3: sync, subida de imágenes, backups y URLs firmadas con mínimo privilegio

S3 parece solo un lugar para guardar archivos, pero en una aplicación real aparecen permisos, exposición pública, sync, caché, borrado y coste. Claude Code acelera scripts y helpers, aunque con un prompt ambiguo puede generar una policy demasiado amplia.

Esta guía es para quien quiere usar S3 cerca de producción sin abrir un agujero de seguridad. Vamos a cubrir sitio estático, subida de imágenes, backups y URLs firmadas. La regla central es least privilege: cada script recibe solo el action y el prefix que necesita.

Los comandos siguen la documentación oficial: AWS CLI S3 reference, aws s3 sync reference, Boto3 presigned URL guide, Claude Code common workflows.

Para ampliar contexto, revisa también: IAM, security, context.

Separar los casos de uso antes del código

use case 1: sitio estático. dist se sincroniza a site/ y CloudFront sirve el contenido. use case 2: imágenes. El panel sube a uploads/ o assets/images/. use case 3: backups. Dumps y PDFs se guardan con prefix de fecha y sin —delete. use case 4: descargas privadas. El bucket queda privado y la app emite una URL firmada de corta duración.

Si mezclas todo, s3:* parece cómodo. Mejor define prefixes como site/, assets/images/, uploads/, backups/ y assets/private-reports/. Al darle esos límites a Claude Code, la policy y el script salen más revisables.

Identidad e IAM de mínimo privilegio

Primero deja bucket y región en variables para que tú y Claude Code revisen el mismo destino.

export AWS_REGION=ap-northeast-1
export S3_BUCKET=claudecode-lab-assets-prod
aws sts get-caller-identity
aws s3 ls "s3://${S3_BUCKET}/" --region "${AWS_REGION}"

Esta policy lee solo assets, escribe solo uploads y evita permisos amplios de borrado.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadPublicAssetsOnly",
      "Effect": "Allow",
      "Action": ["s3:GetObject"],
      "Resource": "arn:aws:s3:::claudecode-lab-assets-prod/assets/*"
    },
    {
      "Sid": "WriteUploadsOnly",
      "Effect": "Allow",
      "Action": ["s3:PutObject", "s3:AbortMultipartUpload"],
      "Resource": "arn:aws:s3:::claudecode-lab-assets-prod/uploads/*"
    },
    {
      "Sid": "ListLimitedPrefixes",
      "Effect": "Allow",
      "Action": ["s3:ListBucket"],
      "Resource": "arn:aws:s3:::claudecode-lab-assets-prod",
      "Condition": {
        "StringLike": {
          "s3:prefix": ["assets/*", "uploads/*", "backups/*"]
        }
      }
    }
  ]
}

Esta es la forma básica para sitios estáticos o carpetas de imágenes. Empieza siempre con dryrun.

# 1. Preview changes first. This should become a habit.
aws s3 sync ./dist "s3://${S3_BUCKET}/site/" \
  --region "${AWS_REGION}" \
  --delete \
  --cache-control "public,max-age=300" \
  --dryrun

# 2. Deploy only after the preview looks right.
aws s3 sync ./dist "s3://${S3_BUCKET}/site/" \
  --region "${AWS_REGION}" \
  --delete \
  --cache-control "public,max-age=300"

# 3. Upload long-lived images with a different cache policy.
aws s3 sync ./public/images "s3://${S3_BUCKET}/assets/images/" \
  --region "${AWS_REGION}" \
  --exclude "*.psd" \
  --cache-control "public,max-age=31536000,immutable"

Una URL firmada mantiene el bucket privado y permite descarga temporal.

import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";

const s3 = new S3Client({ region: process.env.AWS_REGION ?? "ap-northeast-1" });

export async function createDownloadUrl(key: string, filename: string) {
  if (!key.startsWith("assets/private-reports/")) {
    throw new Error(`Unexpected S3 key prefix: ${key}`);
  }

  const command = new GetObjectCommand({
    Bucket: process.env.S3_BUCKET_NAME,
    Key: key,
    ResponseContentDisposition: `attachment; filename="${filename}"`,
  });

  return getSignedUrl(s3, command, { expiresIn: 900 });
}

Al pedirle algo a Claude Code, incluye objetivo, prohibiciones y comandos de verificación.

このリポジトリに AWS S3 連携を追加してください。
目的: public/images を S3 の assets/images/ に同期し、private-reports/ のPDFだけ署名付きURLで配布する。
制約: バケット全体公開は禁止。s3:DeleteObject は付けない。aws s3 sync は必ず --dryrun を先に出す。
成果物: scripts/s3-sync-assets.mjs、lib/s3-presigned-url.ts、READMEの手順、確認コマンド。
確認: npm test、aws s3 ls、aws s3 sync --dryrun の出力で説明してください。
参照: AWS CLI s3/sync docs と Anthropic Claude Code common workflows。

La policy de ejemplo es estrecha a propósito: GetObject solo para assets, PutObject solo para uploads y ListBucket limitado por prefix. Un error común es poner ListBucket sobre un ARN de objeto o dar s3:* al bucket completo.

Otro pitfall es DeleteObject. Muchos flujos no lo necesitan. Si hace falta borrar, separa el rol o crea un script con dryrun, conteo de borrados y confirmación humana. Claude Code escribe JSON rápido, pero el alcance final se revisa a mano.

Usar aws s3 sync con cuidado

aws s3 sync compara una ruta local con un prefix de S3. Con —delete elimina en remoto lo que no existe localmente. Es perfecto para despliegues deterministas, pero peligroso para backups y carpetas compartidas de imágenes.

# Backup use case: append-only, no --delete.
BACKUP_DATE=$(date +%Y-%m-%d)
aws s3 sync ./backups "s3://${S3_BUCKET}/backups/${BACKUP_DATE}/" \
  --region "${AWS_REGION}" \
  --storage-class STANDARD_IA \
  --exclude "*.tmp"

aws s3 ls "s3://${S3_BUCKET}/backups/${BACKUP_DATE}/" --recursive --summarize

Mi patrón es dryrun primero y ejecución después. El script debe imprimir bucket, región, prefix y diff. Si el número de deletes supera un umbral, se detiene. Es simple y evita el fallo más doloroso: carpeta equivocada más —delete.

URL firmada significa permiso temporal

Una presigned URL permite una acción S3 durante un tiempo limitado. No hace público el bucket. Sirve para facturas, PDFs privados, reportes exportados o descargas por usuario después de autenticar.

Cuida tres detalles: expiresIn está en segundos, valida el prefix del key y no uses el nombre del archivo del navegador como key final. Genera keys del lado servidor, por ejemplo uploads/yyyy/mm/dd/uuid.ext. URLs demasiado largas son una failure frecuente.

Costes, caché y exposición pública

El coste de S3 no es solo almacenamiento. También cuentan requests, transferencia, CloudFront, versioning y lifecycle. Para assets públicos usa CloudFront y cache-control claro. Para privados, no abras el bucket por comodidad.

DRYRUN_OUTPUT=$(aws s3 sync ./dist "s3://${S3_BUCKET}/site/" --delete --dryrun)
echo "$DRYRUN_OUTPUT"
DELETE_COUNT=$(echo "$DRYRUN_OUTPUT" | grep -c "delete:" || true)
if [ "$DELETE_COUNT" -gt 20 ]; then
  echo "Too many deletes: ${DELETE_COUNT}. Stop and review."
  exit 1
fi

Muchos tutoriales antiguos usan S3 static website hosting con bucket público. En producción moderna suele ser más fácil defender private S3 + CloudFront. También ayuda en revisiones de seguridad y ventas B2B.

Qué delegar a Claude Code y qué revisar

Claude Code debe generar scripts, helpers TypeScript, README, tests y mensajes de error. El humano revisa cuenta AWS, bucket, prefix, DeleteObject, public access y CloudFront. Antes de ejecutar, usa aws sts get-caller-identity y aws s3 ls.

Nota de verificación de Masa: la separación de prefixes fue lo que más redujo riesgo. Al dividir site, assets, uploads, backups y private-reports, el review de IAM se volvió mucho más claro. Pedir verification steps junto al código también ayudó bastante.

Resumen

Claude Code × AWS S3 funciona muy bien si mantienes permisos aburridos. Separa use cases, usa sync con dryrun, evita delete amplio, mantén el bucket privado y usa URLs firmadas cortas.

Para adaptar este patrón a un repositorio real, puedes usar training / consultation.

#claude-code #aws #s3 #iam #aws-cli #security
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.