AWS KMS: ¿Clave Administrada por AWS o CMK para Cifrar tu Bucket S3?

Cuando configuras cifrado en un bucket S3 por primera vez, la pantalla de la consola te presenta opciones que parecen equivalentes pero tienen implicaciones operativas y de costos muy distintas. Elegir entre una clave administrada por AWS y una clave administrada por el cliente (CMK) no es solo una decisión de seguridad — define quién controla el acceso, quién paga por cada operación criptográfica, y qué tan rápido puedes revocar acceso en una emergencia.

TL;DR: AWS Managed Key vs. CMK para S3

Dimensión AWS Managed Key (aws/s3) Customer Managed Key (CMK)
Creación y rotación Automática, gestionada por AWS Manual o programada, controlada por ti
Política de clave No editable Totalmente configurable
Costo por API call Sin cargo directo para S3 SSE-KMS Cargo por cada llamada a la API de KMS
Auditoría granular CloudTrail básico CloudTrail con contexto de cifrado completo
Revocación de acceso Solo vía IAM/bucket policy Deshabilitar clave o modificar key policy
Cross-account access No soportado directamente Soportado vía key policy
Caso de uso típico Cumplimiento básico, datos internos Datos regulados, multi-cuenta, auditoría estricta

Cómo Funciona el Cifrado en S3 con AWS KMS

S3 con SSE-KMS no cifra los objetos directamente con la clave KMS. Usa un modelo de cifrado en dos capas: KMS genera una data key única por objeto, cifra el objeto con esa data key (usando AES-256), y luego cifra la data key con tu clave KMS. Solo la data key cifrada se almacena junto al objeto. La clave KMS nunca sale del servicio KMS.

Esto significa que cada operación PutObject y GetObject sobre un objeto cifrado con SSE-KMS genera una llamada a la API de KMS (GenerateDataKey al escribir, Decrypt al leer). Ese detalle es el origen del costo variable que muchos equipos no anticipan.

sequenceDiagram participant Cliente participant S3 participant KMS Cliente->>S3: PutObject (datos en texto plano) S3->>KMS: GenerateDataKey (usando CMK o aws/s3) KMS-->>S3: Data key en texto plano + Data key cifrada S3->>S3: Cifra objeto con data key en texto plano S3->>S3: Descarta data key en texto plano de memoria S3-->>Cliente: 200 OK (objeto cifrado almacenado) Note over S3: Almacena objeto cifrado + data key cifrada Cliente->>S3: GetObject S3->>KMS: Decrypt (data key cifrada) KMS-->>S3: Data key en texto plano S3->>S3: Descifra objeto S3-->>Cliente: Objeto en texto plano
  1. PutObject: S3 llama a KMS GenerateDataKey para obtener una data key en texto plano y su versión cifrada.
  2. Cifrado del objeto: S3 cifra el contenido del objeto con la data key en texto plano, luego descarta esa copia en memoria.
  3. Almacenamiento: S3 guarda el objeto cifrado junto con la data key cifrada (envelope encryption).
  4. GetObject: S3 llama a KMS Decrypt para recuperar la data key en texto plano y descifrar el objeto antes de entregarlo al cliente.

Tipos de Claves KMS: Qué Controlas y Qué No

AWS KMS ofrece tres categorías de claves. Para el caso S3, las relevantes son las dos primeras.

AWS Managed Keys son creadas automáticamente la primera vez que usas SSE-KMS en S3 sin especificar una clave. Se identifican con el alias aws/s3. AWS gestiona su rotación anual automáticamente. No puedes modificar su política de clave, no puedes deshabilitarlas, y no puedes usarlas para acceso cross-account. Son gratuitas en términos de costo de clave mensual, pero las llamadas a la API de KMS que S3 genera internamente no se cobran al usuario para este caso específico — AWS absorbe ese costo para sus servicios administrados.

Customer Managed Keys (CMK) las creas tú explícitamente. Tienes control total sobre la key policy, puedes habilitar rotación anual automática, puedes deshabilitarlas o programar su eliminación, y puedes conceder acceso cross-account. Cada llamada a la API de KMS generada por operaciones S3 se cobra a tu cuenta.

Pensar en las AWS Managed Keys como el cerrojo estándar que viene con el apartamento: funciona, cumple su propósito, pero el edificio tiene una copia de la llave maestra y tú no puedes cambiar la cerradura. Una CMK es traer tu propia cerradura — tú decides quién tiene copia.

Costos Asociados a KMS: El Detalle que Importa en Producción

El modelo de costos de KMS tiene dos componentes: el costo mensual por clave almacenada y el costo por llamadas a la API. Los precios exactos varían por región y cambian con el tiempo — siempre verifica la página oficial de precios de AWS KMS.

Lo que sí puedes razonar estructuralmente:

  • AWS Managed Keys: Sin costo mensual por la clave. Las llamadas a la API generadas por servicios AWS integrados (como S3 SSE-KMS con aws/s3) no se cobran directamente al usuario.
  • CMK — costo mensual: Se cobra por cada clave activa almacenada en KMS, independientemente de si se usa o no.
  • CMK — costo por API call: Cada GenerateDataKey, Decrypt, o GenerateDataKeyWithoutPlaintext cuenta. En un bucket con millones de objetos y acceso frecuente, esto escala rápido.
  • Capa gratuita: AWS ofrece un número de llamadas gratuitas por mes. Superar ese umbral activa el cargo por llamada.
graph TD A["Operación S3
PutObject / GetObject"] --> B{"Tipo de clave configurada"} B -->|"AWS Managed Key
(aws/s3)"| C["Llamada KMS interna
sin cargo al usuario"] B -->|"Customer Managed Key
(CMK)"| D["Llamada KMS facturable
GenerateDataKey / Decrypt"] D --> E{"Bucket Key
habilitado?"} E -->|"Sí"| F["Llamadas KMS reducidas
S3 agrupa operaciones"] E -->|"No"| G["Una llamada KMS
por objeto accedido"] C --> H["Costo KMS: $0
para el usuario"] F --> I["Costo KMS: reducido
verificar pricing oficial"] G --> J["Costo KMS: escala
con volumen de acceso"]
  1. Con AWS Managed Key, el costo de API calls para SSE-KMS en S3 no se traslada al usuario — AWS lo absorbe internamente.
  2. Con CMK, cada lectura y escritura de objeto cifrado genera una llamada facturable a KMS.
  3. Un bucket con alta frecuencia de acceso puede generar millones de llamadas KMS al mes — estima el volumen antes de elegir CMK.

Cuándo Usar AWS Managed Key

Si tu requisito es cumplimiento básico — datos en reposo cifrados, auditoría en CloudTrail, sin necesidad de control granular sobre la clave — la AWS Managed Key es la opción correcta. Cero overhead operativo, cero costo adicional por la clave, y S3 la gestiona transparentemente.

También es la opción correcta cuando el volumen de operaciones es alto y el presupuesto de KMS no está justificado por un requisito regulatorio específico que exija CMK.

Cuándo Necesitas una CMK

Hay escenarios donde la AWS Managed Key simplemente no alcanza:

  • Acceso cross-account: Si una cuenta B necesita leer objetos cifrados en un bucket de la cuenta A, necesitas una CMK en la cuenta A con una key policy que permita acceso a la cuenta B. Las AWS Managed Keys no soportan este patrón.
  • Revocación de emergencia: Si necesitas cortar acceso a todos los datos cifrados de forma inmediata — por ejemplo, ante una brecha — deshabilitar una CMK bloquea el descifrado de todos los objetos que la usan, independientemente de las políticas IAM. Con una AWS Managed Key no tienes esa palanca.
  • Contexto de cifrado (encryption context): Las CMK permiten usar encryption context para vincular operaciones criptográficas a metadatos específicos, lo que aparece en CloudTrail y permite auditoría más granular.
  • Requisitos regulatorios: Algunos marcos como PCI-DSS o FedRAMP en ciertos perfiles requieren que el cliente mantenga control sobre las claves de cifrado.
  • Rotación controlada: Aunque AWS Managed Keys rotan automáticamente, no puedes forzar una rotación manual ni controlar el calendario. Con CMK puedes habilitar rotación automática anual o rotar manualmente cuando lo necesites.

Configurar SSE-KMS en S3: AWS Managed Key vs. CMK

Antes de ejecutar estos comandos, verifica que tu rol o usuario tiene los permisos necesarios. Para CMK, necesitas permisos KMS además de S3.

Opción 1: Cifrado con AWS Managed Key (aws/s3)

# Habilitar cifrado por defecto en el bucket usando la AWS Managed Key de S3
aws s3api put-bucket-encryption \
  --bucket nombre-de-tu-bucket \
  --server-side-encryption-configuration '{
    "Rules": [
      {
        "ApplyServerSideEncryptionByDefault": {
          "SSEAlgorithm": "aws:kms"
        },
        "BucketKeyEnabled": true
      }
    ]
  }'

Nota: BucketKeyEnabled: true reduce el número de llamadas a KMS al usar una clave de bucket intermedia, lo que disminuye costos cuando usas CMK. Con AWS Managed Key también es recomendable habilitarlo.

Opción 2: Cifrado con Customer Managed Key (CMK)

🔽 Ver comandos completos para CMK
# Paso 1: Crear una CMK simétrica en KMS
aws kms create-key \
  --description 'CMK para cifrado de bucket S3 produccion' \
  --key-usage ENCRYPT_DECRYPT \
  --origin AWS_KMS

# El comando devuelve el KeyId y el ARN de la clave.
# Guarda el ARN para el siguiente paso.

# Paso 2: Crear un alias legible para la clave
aws kms create-alias \
  --alias-name 'alias/s3-produccion-cmk' \
  --target-key-id 'arn:aws:kms:us-east-1:123456789012:key/tu-key-id'

# Paso 3: Habilitar rotación automática anual
aws kms enable-key-rotation \
  --key-id 'arn:aws:kms:us-east-1:123456789012:key/tu-key-id'

# Paso 4: Configurar cifrado por defecto en el bucket con la CMK
aws s3api put-bucket-encryption \
  --bucket nombre-de-tu-bucket \
  --server-side-encryption-configuration '{
    "Rules": [
      {
        "ApplyServerSideEncryptionByDefault": {
          "SSEAlgorithm": "aws:kms",
          "KMSMasterKeyID": "arn:aws:kms:us-east-1:123456789012:key/tu-key-id"
        },
        "BucketKeyEnabled": true
      }
    ]
  }'

Verificar la configuración de cifrado

aws s3api get-bucket-encryption \
  --bucket nombre-de-tu-bucket

IAM: Permisos Mínimos para Operar con CMK en S3

Este es el punto donde más equipos se bloquean en producción. Tener permisos S3 no es suficiente cuando el bucket usa una CMK — el principal que lee o escribe también necesita permisos KMS. El error típico es un AccessDenied que llega desde KMS, no desde S3, y que los logs de S3 no muestran claramente.

🔽 Ver política IAM mínima para leer/escribir objetos cifrados con CMK
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PermisosS3",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::nombre-de-tu-bucket/*"
    },
    {
      "Sid": "PermisosKMSParaCMK",
      "Effect": "Allow",
      "Action": [
        "kms:GenerateDataKey",
        "kms:Decrypt"
      ],
      "Resource": "arn:aws:kms:us-east-1:123456789012:key/tu-key-id"
    }
  ]
}

Además de la política IAM, la key policy de la CMK debe incluir explícitamente al principal como usuario o rol autorizado. Una política IAM que permite kms:Decrypt no es suficiente si la key policy no lo autoriza — KMS evalúa ambas, y ambas deben permitir la acción.

# Verificar la key policy actual de tu CMK
aws kms get-key-policy \
  --key-id 'arn:aws:kms:us-east-1:123456789012:key/tu-key-id' \
  --policy-name default

El Error que Nadie Anticipa: AccessDenied en Lectura con CMK

El escenario: migras un bucket a CMK, subes objetos sin problema, y al día siguiente un job de procesamiento empieza a fallar con AccessDenied. El equipo revisa las políticas S3 — todo parece correcto. Revisan CloudTrail de S3 — la solicitud ni siquiera llega a S3.

El error real está en CloudTrail de KMS: el rol del job tiene s3:GetObject pero no tiene kms:Decrypt en su política IAM, o tiene el permiso IAM pero no está en la key policy de la CMK. S3 intenta llamar a KMS para descifrar la data key, KMS rechaza la operación, y S3 devuelve AccessDenied al cliente sin contexto adicional.

La corrección siempre requiere dos pasos: agregar el permiso en la política IAM del rol y agregar el principal en la key policy de la CMK. Hacer solo uno de los dos no resuelve el problema.

# Buscar eventos KMS denegados en CloudTrail para diagnosticar
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=Decrypt \
  --start-time '2024-01-01T00:00:00Z' \
  --end-time '2024-01-02T00:00:00Z'

Bucket Key: Reducir Costos KMS sin Cambiar de Clave

Cuando habilitas S3 Bucket Key (BucketKeyEnabled: true), S3 genera una clave de bucket temporal derivada de tu CMK y la usa para cifrar las data keys de los objetos individuales durante un período corto. Esto reduce drásticamente el número de llamadas directas a KMS — en lugar de una llamada por objeto, S3 agrupa las operaciones.

El resultado observable: el número de llamadas a la API de KMS en CloudTrail y en tus métricas de costos cae significativamente para buckets con alto volumen de escritura. La seguridad no se degrada — la clave de bucket también está cifrada con tu CMK y se rota periódicamente por S3.

Bucket Key es compatible tanto con AWS Managed Keys como con CMK, y se puede habilitar en buckets existentes sin re-cifrar los objetos ya almacenados.

# Verificar si Bucket Key está habilitado
aws s3api get-bucket-encryption \
  --bucket nombre-de-tu-bucket \
  --query 'ServerSideEncryptionConfiguration.Rules[0].BucketKeyEnabled'

Árbol de Decisión: ¿Qué Tipo de Clave Usar?

graph TD Start(["¿Qué tipo de clave
necesito para S3?"]) --> Q1{"¿Requieres acceso
cross-account al bucket?"} Q1 -->|"Sí"| CMK1["Customer Managed Key
con key policy cross-account"] Q1 -->|"No"| Q2{"¿Necesitas revocar acceso
a nivel de clave en emergencias?"} Q2 -->|"Sí"| CMK2["Customer Managed Key
deshabilitar clave = acceso bloqueado"] Q2 -->|"No"| Q3{"¿Tienes requisitos regulatorios
que exigen control de clave?"} Q3 -->|"Sí"| CMK3["Customer Managed Key
con rotación y auditoría"] Q3 -->|"No"| AMK["AWS Managed Key (aws/s3)
+ Bucket Key habilitado"] CMK1 --> OPT["Habilitar Bucket Key
si el volumen es alto"] CMK2 --> OPT CMK3 --> OPT
  1. Si no necesitas control granular ni acceso cross-account, la AWS Managed Key cubre el requisito con cero overhead.
  2. Si necesitas revocar acceso de emergencia independientemente de IAM, una CMK es el único mecanismo disponible.
  3. Si el acceso cross-account es un requisito, la CMK con key policy es la única opción viable.
  4. Si el volumen de operaciones es alto y usas CMK, habilita Bucket Key para controlar el costo de API calls.

Wrap-Up: AWS KMS para S3 en Producción

La elección entre AWS Managed Key y CMK para cifrado en S3 no es una decisión de seguridad binaria — ambas cifran tus datos correctamente. Es una decisión sobre control operativo, modelo de costos y requisitos de cumplimiento. Para la mayoría de los workloads internos sin requisitos regulatorios estrictos, la AWS Managed Key con Bucket Key habilitado es la configuración más práctica. Para datos regulados, acceso cross-account, o escenarios donde necesitas la capacidad de revocar acceso a nivel de clave, una CMK justifica el overhead adicional.

Antes de escalar cualquier solución a producción, estima el volumen de llamadas KMS que generará tu patrón de acceso — ese número define si el costo de CMK es manejable o si necesitas optimizar con Bucket Key.

Recursos oficiales para profundizar:

Glosario de Términos Clave

Término Definición
SSE-KMS Server-Side Encryption con AWS KMS. S3 gestiona el cifrado usando claves KMS.
Data Key Clave simétrica generada por KMS para cifrar un objeto específico. Nunca se almacena en texto plano.
Envelope Encryption Patrón donde la data key se cifra con una clave maestra (CMK), y solo la versión cifrada se almacena.
Key Policy Política de acceso adjunta directamente a una clave KMS. Controla quién puede usar o administrar la clave.
Bucket Key Clave temporal derivada de la CMK, generada por S3 para reducir llamadas directas a la API de KMS.

Related Posts

Comentarios

Entradas populares de este blog

EC2 sin acceso a Internet en VPC personalizada: Internet Gateway y Route Table

Actualizar Contenido en CloudFront: Cómo Crear una Invalidación para Limpiar el Caché del Edge

Aumentar el Timeout de Lambda: Configuración, Límites y Diagnóstico en Producción