Proteger objetos S3 con una clave KMS

AWSBeginner
Practicar Ahora

Introducción

Una aplicación necesita leer una exportación privada almacenada en S3. Cifrarás las cargas nuevas con una clave del cliente, concederás acceso al lector y probarás cómo los permisos de objeto y clave afectan a las descargas reales.

Completa primero Almacenar y recuperar archivos en S3, Cifrar y descifrar una exportación privada con KMS y sus requisitos de IAM. Esta VM nueva proporciona una exportación sintética, una sesión del rol lector y recursos de referencia independientes.

Relación con las certificaciones

Este laboratorio ofrece práctica para los siguientes temas de examen.

Preparar el almacenamiento cifrado de objetos

En este paso, crearás una clave KMS del cliente y configurarás un bucket nuevo para usarla de forma predeterminada. Un bucket contiene objetos; cada objeto tiene una clave como exports/private-export.json. El cifrado del lado del servidor con KMS (SSE-KMS) permite que S3 cifre los objetos almacenados con la clave elegida. El cifrado predeterminado se aplica a cargas nuevas sin exigir que cada cliente repita las opciones de cifrado.

Usa el archivo sintético suministrado private-export.json; la sesión del rol export-reader comienza sin acceso a objetos ni claves. Conserva el bucket, el objeto y la clave de referencia. Abre AWS View, junto a Terminal, para comparar el estado de claves y buckets, las concesiones lectoras y comparaciones seguras de bytes.

Comienza en el directorio del proyecto y confirma la identidad del operador suministrado. cd cambia el directorio; la consulta del llamante devuelve un ARN de identidad sin exponer credenciales.

cd /home/labex/project
aws sts get-caller-identity --query Arn --output text

Espera el usuario labex-sec02-operator. Crea una clave simétrica del cliente y un alias legible. --query selecciona el ARN, --output text elimina las comillas JSON y $(...) guarda el resultado en una variable del shell.

KEY_ARN=$(aws kms create-key \
  --description labex-sec02-owned-export \
  --query KeyMetadata.Arn \
  --output text)
aws kms create-alias \
  --alias-name alias/labex-sec02-private-export \
  --target-key-id "$KEY_ARN"

Usa un nombre de bucket desechable con un sufijo de marca de tiempo para evitar colisiones de nombres. El prefijo labex-sec02-owned- distingue tu bucket de la referencia suministrada. Esta unidad usa us-east-1, por lo que crear el bucket no necesita una restricción de ubicación.

BUCKET="labex-sec02-owned-$(date +%s)"
aws s3api create-bucket \
  --bucket "$BUCKET" \
  --region us-east-1 \
  --query Location \
  --output text

Configura SSE-KMS con el ARN exacto de clave. Una S3 Bucket Key, o clave de bucket de S3, puede reducir solicitudes repetidas a KMS; aquí permanece desactivada para que cada objeto use su propio contexto de cifrado KMS. Escribe la regla predeterminada como un archivo JSON ordinario. El here-document expande $KEY_ARN; file:// carga la configuración guardada.

cat > bucket-encryption.json <<EOF
{
  "Rules": [
    {
      "ApplyServerSideEncryptionByDefault": {
        "SSEAlgorithm": "aws:kms",
        "KMSMasterKeyID": "$KEY_ARN"
      },
      "BucketKeyEnabled": false
    }
  ]
}
EOF

aws s3api put-bucket-encryption --bucket "$BUCKET" \
  --server-side-encryption-configuration file://bucket-encryption.json
aws s3api get-bucket-encryption \
  --bucket "$BUCKET" \
  --query ServerSideEncryptionConfiguration

Espera aws:kms, el ARN de tu clave y BucketKeyEnabled: false. Conserva KEY_ARN y BUCKET en este Terminal para los comandos posteriores. En AWS View, la clave del laboratorio está habilitada y el bucket todavía no tiene objetos.

Dar al lector ambos permisos necesarios

En este paso, cargarás la exportación y permitirás que un rol recupere sus bytes originales. La carga requiere kms:GenerateDataKey en la clave elegida. SSE-KMS usa una clave de datos para cifrar los bytes del objeto. KMS protege esa clave de datos; S3 almacena el objeto cifrado y la clave de datos cifrada y después solicita descifrado cuando un lector autorizado descarga el objeto. El material de clave no necesita aparecer en la salida de la CLI.

Permisos de objeto S3 y clave

Leer este objeto SSE-KMS requiere tanto acceso al objeto como permiso de descifrado de la clave.

Carga el archivo suministrado con s3api put-object. La configuración predeterminada del bucket proporciona los ajustes de cifrado; --body private-export.json lee el archivo local indicado como bytes del objeto. Usa esta API de una sola parte para la pequeña exportación.

aws s3api put-object \
  --bucket "$BUCKET" \
  --key exports/private-export.json \
  --body private-export.json \
  --query '{Encryption:ServerSideEncryption,Key:SSEKMSKeyId,BucketKey:BucketKeyEnabled}'
aws s3api head-object \
  --bucket "$BUCKET" \
  --key exports/private-export.json \
  --query '{Encryption:ServerSideEncryption,Key:SSEKMSKeyId,Bytes:ContentLength}'

Espera aws:kms, el ARN de la clave del laboratorio y el tamaño original del archivo. Los metadatos por sí solos no muestran si un lector puede descifrar. Primero concede únicamente acceso al objeto. Un ARN de objeto incluye el bucket y la clave de objeto; es distinto de un ARN de bucket. El siguiente here-document escribe un archivo de política y expande $BUCKET dentro de él.

cat > read-object.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::$BUCKET/exports/private-export.json"
    }
  ]
}
EOF
aws iam put-role-policy \
  --role-name labex-sec02-export-reader \
  --policy-name ReadExportObject \
  --policy-document file://read-object.json

Selecciona la sesión lectora preparada con --profile export-reader. Este intento debe fallar con AccessDenied: el rol puede leer este objeto, pero todavía no tiene una concesión de descifrado KMS.

aws \
  --profile export-reader s3api get-object \
  --bucket "$BUCKET" \
  --key exports/private-export.json reader-export.json

Concede a ese rol únicamente kms:Decrypt en la clave exacta. No necesita administración de claves ni kms:GenerateDataKey para descargar.

cat > decrypt-key.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "kms:Decrypt",
      "Resource": "$KEY_ARN"
    }
  ]
}
EOF
aws iam put-role-policy \
  --role-name labex-sec02-export-reader \
  --policy-name DecryptExportKey \
  --policy-document file://decrypt-key.json
aws \
  --profile export-reader s3api get-object \
  --bucket "$BUCKET" \
  --key exports/private-export.json reader-export.json \
  --query '{Encryption:ServerSideEncryption,Key:SSEKMSKeyId}'
chmod 600 reader-export.json
cmp private-export.json reader-export.json

cmp no imprime nada y devuelve éxito cuando los contenidos de bytes coinciden. AWS View debe mostrar ahora texto cifrado almacenado y un GetObject lector cuyos bytes devueltos coinciden con la exportación suministrada. Son observaciones separadas: el almacenamiento cifrado protege los bytes en reposo, mientras los permisos acotados gobiernan su recuperación.

Ejemplo de AWS View tras la concesión de clave exacta: texto cifrado almacenado y bytes originales recuperados por el lector.

Diagnosticar fallos de permisos y estado de clave

En este paso, distinguirás una concesión ausente de descifrado de una clave deshabilitada. Conserva el permiso de objeto para que solo cambie una condición cada vez.

Elimina la concesión de clave del lector y después repite la misma descarga de objeto. El rol todavía tiene s3:GetObject, pero la solicitud debe fallar con AccessDenied.

aws iam delete-role-policy \
  --role-name labex-sec02-export-reader \
  --policy-name DecryptExportKey
aws \
  --profile export-reader s3api get-object \
  --bucket "$BUCKET" \
  --key exports/private-export.json reader-export.json

Inspecciona la política de objeto restante. Debe seguir indicando únicamente este objeto de exportación.

aws iam get-role-policy \
  --role-name labex-sec02-export-reader \
  --policy-name ReadExportObject \
  --query PolicyDocument

Restablece la concesión de clave exacta y deshabilita tu clave. Una clave deshabilitada sigue existiendo, pero no puede realizar operaciones criptográficas. No cambies la clave de referencia ajena al laboratorio.

aws iam put-role-policy \
  --role-name labex-sec02-export-reader \
  --policy-name DecryptExportKey \
  --policy-document file://decrypt-key.json
aws kms disable-key --key-id "$KEY_ARN"
aws \
  --profile export-reader s3api get-object \
  --bucket "$BUCKET" \
  --key exports/private-export.json reader-export.json

Espera un fallo por clave deshabilitada. Tener un permiso IAM no puede hacer utilizable una clave deshabilitada. Confirma su estado nativo, después habilítala y recupera de nuevo el objeto.

aws kms describe-key --key-id "$KEY_ARN" --query KeyMetadata.KeyState --output text
aws kms enable-key --key-id "$KEY_ARN"
aws \
  --profile export-reader s3api get-object \
  --bucket "$BUCKET" \
  --key exports/private-export.json reader-export.json \
  --query ServerSideEncryption \
  --output text
chmod 600 reader-export.json
cmp private-export.json reader-export.json

Espera aws:kms y una comparación correcta. AWS View mantiene juntas las solicitudes fallidas y la recuperación correcta, mientras el bucket y la clave de referencia siguen siendo utilizables. Ejemplo de AWS View con fallos por permiso revocado y clave deshabilitada seguidos de una lectura correcta.

Una descarga fallida puede dejar un archivo local anterior, así que su presencia por sí sola no demuestra que la solicitud tuvo éxito; la lectura firmada y la comparación demuestran la recuperación.

Eliminar los recursos del laboratorio y programar la eliminación de la clave

En este paso, limpiarás los recursos exactos de exportación. Termina primero las comprobaciones funcionales anteriores. Un bucket de S3 debe estar vacío antes de eliminarse; una clave KMS del cliente usa un periodo de espera de eliminación en lugar de desaparecer inmediatamente.

Elimina únicamente tu exportación indicada y después su bucket. Enumera el inventario correctamente y confirma que tu $BUCKET no aparece mientras permanece labex-sec02-reference.

aws s3api delete-object --bucket "$BUCKET" --key exports/private-export.json
aws s3api delete-bucket --bucket "$BUCKET"
aws s3api list-buckets --query 'Buckets[].Name'

Elimina los dos permisos que añadiste y el alias del laboratorio. El rol lector suministrado es un componente de sesión; no lo elimines ni elimines los recursos de referencia ajenos al laboratorio.

aws iam delete-role-policy \
  --role-name labex-sec02-export-reader \
  --policy-name ReadExportObject
aws iam delete-role-policy \
  --role-name labex-sec02-export-reader \
  --policy-name DecryptExportKey
aws iam list-role-policies --role-name labex-sec02-export-reader --query PolicyNames
aws kms delete-alias --alias-name alias/labex-sec02-private-export

Programa la eliminación de tu clave con el periodo mínimo de siete días y después lee su estado nativo. Programarla la hace inutilizable inmediatamente, pero no demuestra que ya se haya eliminado.

aws kms schedule-key-deletion \
  --key-id "$KEY_ARN" \
  --pending-window-in-days 7 \
  --query DeletionDate \
  --output text
aws kms describe-key --key-id "$KEY_ARN" --query KeyMetadata.KeyState --output text
aws kms describe-key \
  --key-id alias/labex-sec02-reference \
  --query KeyMetadata.KeyState \
  --output text

Espera PendingDeletion para tu clave y Enabled para la referencia. Elimina los archivos locales indicados; estos comandos dejan intactos los archivos ajenos del proyecto.

rm -f private-export.json reader-export.json read-object.json decrypt-key.json bucket-encryption.json

Ejecuta la verificación de este paso antes de eliminar los perfiles desechables de CLI. Las consultas correctas de inventario nativo, no los errores de autenticación, demuestran la limpieza.

rm -f /home/labex/.aws/credentials /home/labex/.aws/config
unset KEY_ARN BUCKET

Resumen

Configuraste SSE-KMS como valor predeterminado del bucket, cargaste una exportación cifrada y recuperaste los bytes originales con un rol acotado a un objeto y una clave. Revocar kms:Decrypt y deshabilitar la clave impidieron cada uno la lectura sin cambiar la concesión de objeto. Restableciste el acceso, eliminaste únicamente recursos S3 del laboratorio y programaste la eliminación de su clave KMS conservando el bucket y la clave de referencia.