StackPractices
advanced Por Mathias Paulenko

Runbook de Rotación de Claves

Usa este runbook de rotación de claves para rotarlas sin downtime. Cubre cronogramas, migración dual, verificación y rollback.

Temas: security

Overview

Un runbook de rotación de claves de cifrado define cómo rotar las claves sin interrumpir el servicio. Cubre los tipos de claves, los cronogramas de rotación, los procedimientos de migración con doble clave, los pasos de verificación y los planes de reversión. La rotación de claves limita el alcance de una clave comprometida y es un requisito para la mayoría de los marcos de cumplimiento.

When to Use

  • Para alternativas, consulta Encryption at Rest: AES-256, KMS, Envelope Encryption.

  • Rotación programada de claves (trimestral, anual)

  • Rotación de claves tras una sospecha de compromiso

  • Configuración de procedimientos de rotación para un sistema nuevo

  • Preparación para auditorías de cumplimiento (SOC 2, PCI-DSS, HIPAA)

  • Rotación de claves tras la salida de personal con acceso a ellas

Para plantillas de seguridad relacionadas, consulta el Security Audit Checklist y la Access Control Policy Template.

flowchart diagram: Inicio Rotación

Solution

# Encryption Key Rotation Runbook — `<Organization Name>`

## Runbook Metadata

| Field | Value |
|-------|-------|
| Organization | Example Corp |
| Runbook Version | 2.0 |
| Last Updated | 2026-07-05 |
| Runbook Owner | Security Team |
| Approved By | CISO |
| Review Cycle | Quarterly |
| KMS Provider | AWS KMS |
| Key Store | HashiCorp Vault (for application keys) |

## 1. Key Inventory

### Key Types

| Key Type | Purpose | Algorithm | Rotation Frequency | Storage | Access |
|----------|---------|-----------|-------------------|---------|--------|
| Data Encryption Key (DEK) | Cifra datos en reposo | AES-256-GCM | 90 días | AWS KMS | Rol IAM de la aplicación |
| Key Encryption Key (KEK) | Cifra los DEK | AES-256-GCM | 12 meses | AWS KMS | Rol de administrador KMS |
| TLS Certificate | Terminación HTTPS | RSA-2048 / ECDSA P-256 | 12 meses | ACM | Balanceador de carga |
| JWT Signing Key | Firma de tokens API | RS256 (RSA-2048) | 6 meses | Vault | Servicio de autenticación |
| API Signing Key | Firma de solicitudes API | HMAC-SHA256 | 90 días | Vault | API gateway |
| Database TDEK | Cifrado transparente de base de datos | AES-256 | 12 meses | AWS KMS | Rol IAM de base de datos |
| S3 Bucket Key | Cifrado de objetos | AES-256 | 12 meses | AWS KMS | Rol de servicio S3 |
| Secrets Encryption Key | Auto-unseal de Vault | AES-256-GCM | 12 meses | AWS KMS | Rol IAM de Vault |
| SSH CA Key | Firma de certificados SSH | Ed25519 | 12 meses | Vault | Administrador SSH CA |
| Code Signing Key | Firma de binarios/artefactos | RSA-4096 | 24 meses | HSM | Ingeniería de releases |

### Key Registry

| Key ID | Type | Environment | Created | Last Rotated | Next Rotation | Owner |
|--------|------|-------------|---------|--------------|---------------|-------|
| KMS-DEK-001 | DEK | production | 2025-10-01 | 2026-04-01 | 2026-07-01 | DevOps |
| KMS-KEK-001 | KEK | production | 2024-01-15 | 2025-01-15 | 2026-01-15 | Security |
| TLS-WEB-001 | TLS | production | 2025-06-01 | 2025-06-01 | 2026-06-01 | DevOps |
| JWT-SIGN-001 | JWT | production | 2025-11-01 | 2026-02-01 | 2026-08-01 | Auth Team |
| API-SIGN-001 | API | production | 2026-01-15 | 2026-04-15 | 2026-07-15 | API Team |
| DB-TDEK-001 | Database | production | 2024-06-01 | 2025-06-01 | 2026-06-01 | Database Team |
| S3-KEY-001 | S3 | production | 2024-03-01 | 2025-03-01 | 2026-03-01 | DevOps |

## 2. Rotation Schedule

### Rotation Calendar

| Month | Keys to Rotate | Owner | Estimated Duration |
|-------|---------------|-------|-------------------|
| January | KEK-001, S3-KEY-001 | Security, DevOps | 4 hours |
| February | JWT-SIGN-001 | Auth Team | 2 hours |
| March | S3-KEY-001 (if due) | DevOps | 1 hour |
| April | DEK-001, API-SIGN-001 | DevOps, API Team | 3 hours |
| May | — | — | — |
| June | TLS-WEB-001, DB-TDEK-001 | DevOps, Database Team | 4 hours |
| July | DEK-001 | DevOps | 2 hours |
| August | JWT-SIGN-001 | Auth Team | 2 hours |
| September | — | — | — |
| October | DEK-001 | DevOps | 2 hours |
| November | JWT-SIGN-001 | Auth Team | 2 hours |
| December | — | — | — |

### Rotation Triggers

| Trigger | Action | Timeline |
|---------|--------|----------|
| Scheduled rotation | Sigue este runbook | Según cronograma |
| Key compromise | Rotación de emergencia | En menos de 4 horas |
| Personnel departure | Rota las claves a las que tenían acceso | En menos de 24 horas |
| Compliance audit finding | Rota las claves marcadas | Según plazo de auditoría |
| Security incident | Rota las claves potencialmente expuestas | Según plan de respuesta a incidentes |
| Algorithm deprecation | Migra al nuevo algoritmo | Antes de la fecha de deprecación |

## 3. Pre-Rotation Checklist

| Check | Action | Responsible | Status |
|-------|--------|-------------|--------|
| Key identified | Confirma el ID y tipo de clave | Security | ✅/❌ |
| Backup current key | Exporta el material de la clave cifrada | Security | ✅/❌ |
| Notify stakeholders | Envía correo a los equipos afectados 48h antes | Security | ✅/❌ |
| Schedule maintenance window | Si es necesario (claves sin zero-downtime) | DevOps | ✅/❌ |
| Verify new key creation | Nueva clave creada en KMS/Vault | Security | ✅/❌ |
| Test in staging | Rota la clave en staging primero | Engineering | ✅/❌ |
| Prepare rollback plan | Documenta los pasos de reversión | Security | ✅/❌ |
| Verify monitoring | Alertas de rotación de claves configuradas | DevOps | ✅/❌ |

## 4. Zero-Downtime Rotation: Dual-Key Strategy

### Dual-Key Migration Process

| Step | Action | Duration | Verification | Rollback |
|------|--------|----------|--------------|----------|
| 1 | Crea la nueva clave en KMS | 5 min | La clave existe, ARN confirmado | Elimina la nueva clave |
| 2 | Despliega código que soporta ambas claves | 30 min | Despliegue exitoso | Revierte el despliegue |
| 3 | Activa el modo dual-key (lee ambas, escribe nueva) | 5 min | Config actualizada, servicio sano | Revierte la config |
| 4 | Monitorea durante 1 hora | 1 hora | Sin errores, sin fallos de descifrado | Revierte la config |
| 5 | Migra los datos existentes a la nueva clave | Variable | Migración de datos completa | Re-ejecuta con la clave vieja |
| 6 | Cambia a escritura solo con la nueva clave | 5 min | Config actualizada, servicio sano | Reactiva el modo dual |
| 7 | Monitorea durante 24 horas | 24 horas | Sin errores, sin fallos de descifrado | Reactiva el modo dual |
| 8 | Elimina el acceso a la clave vieja | 5 min | Clave vieja deshabilitada | Reactiva la clave vieja |
| 9 | Programa la eliminación de la clave vieja | 5 min | Eliminación programada (espera de 30 días) | Cancela la eliminación |
| 10 | Documenta la rotación | 15 min | Runbook actualizado | N/A |

### Dual-Key Configuration

```yaml
encryption:
  mode: dual-key
  current_key:
    kms_key_id: "arn:aws:kms:us-east-1:123:key/old-key-id"
    status: "read-only"
  new_key:
    kms_key_id: "arn:aws:kms:us-east-1:123:key/new-key-id"
    status: "read-write"
  migration:
    batch_size: 1000
    parallelism: 4
    rate_limit: 100  # records per second
```

### Data Migration Script

```python
import boto3
from concurrent.futures import ThreadPoolExecutor

kms = boto3.client('kms')
old_key_id = "arn:aws:kms:us-east-1:123:key/old-key-id"
new_key_id = "arn:aws:kms:us-east-1:123:key/new-key-id"

def migrate_record(record_id):
    # 1. Decrypt with old key
    encrypted_data = db.get_encrypted_field(record_id)
    plaintext = kms.decrypt(
        CiphertextBlob=encrypted_data,
        KeyId=old_key_id
    )['Plaintext']

    # 2. Re-encrypt with new key
    new_ciphertext = kms.encrypt(
        Plaintext=plaintext,
        KeyId=new_key_id
    )['CiphertextBlob']

    # 3. Update record
    db.update_encrypted_field(record_id, new_ciphertext)
    return record_id

# Migrate in batches
batch_size = 1000
record_ids = db.get_all_record_ids()

for i in range(0, len(record_ids), batch_size):
    batch = record_ids[i:i + batch_size]
    with ThreadPoolExecutor(max_workers=4) as executor:
        results = list(executor.map(migrate_record, batch))
    print(f"Migrated {len(results)} records ({i + len(batch)}/{len(record_ids)})")
```

## 5. Key-Specific Rotation Procedures

### AWS KMS Key Rotation

| Step | Command | Duration |
|------|---------|----------|
| 1 | `aws kms create-key --description "DEK-v2" --key-spec SYMMETRIC_DEFAULT` | 5 min |
| 2 | Actualiza la config de la aplicación con el nuevo ARN de la clave | 5 min |
| 3 | Despliega la config actualizada | 10 min |
| 4 | Verifica el cifrado con la nueva clave | 5 min |
| 5 | `aws kms disable-key --key-id <old-key-id>` | 5 min |
| 6 | `aws kms schedule-key-deletion --key-id <old-key-id> --pending-window-in-days 30` | 5 min |

### TLS Certificate Rotation (ACM)

| Step | Command | Duration |
|------|---------|----------|
| 1 | `aws acm request-certificate --domain-name "*.example.com" --validation-method DNS` | 5 min |
| 2 | Añade el registro de validación DNS | 10 min |
| 3 | Espera la validación (automática) | 5-30 min |
| 4 | Actualiza el listener del balanceador para usar el nuevo certificado | 5 min |
| 5 | Verifica HTTPS con el nuevo certificado | 5 min |
| 6 | Elimina el certificado viejo después de 7 días | 5 min |

### JWT Signing Key Rotation

| Step | Action | Duration |
|------|--------|----------|
| 1 | Genera un nuevo par de claves en Vault | 5 min |
| 2 | Añade la nueva clave pública al endpoint JWKS | 5 min |
| 3 | Despliega código que firma con la nueva clave | 10 min |
| 4 | Espera a que los tokens viejos expiren (tiempo de vida máximo del token) | Según TTL del token |
| 5 | Elimina la clave pública vieja del JWKS | 5 min |
| 6 | Revoca la clave vieja en Vault | 5 min |

```javascript
// JWKS endpoint supporting dual keys during rotation
const jwks = {
  keys: [
    {
      kty: "RSA",
      kid: "jwt-key-v1",
      use: "sig",
      alg: "RS256",
      n: "...",
      e: "AQAB"
    },
    {
      kty: "RSA",
      kid: "jwt-key-v2",
      use: "sig",
      alg: "RS256",
      n: "...",
      e: "AQAB"
    }
  ]
};
```

### Database TDEK Rotation

| Step | Action | Duration | Downtime |
|------|--------|----------|----------|
| 1 | Crea una nueva clave KMS para la base de datos | 5 min | Ninguno |
| 2 | Actualiza la config de la base de datos con el nuevo ARN | 5 min | Ninguno |
| 3 | Dispara el re-cifrado de la base de datos | Variable | Ninguno (online) |
| 4 | Monitorea el progreso del re-cifrado | Variable | Ninguno |
| 5 | Verifica que todos los datos están cifrados con la nueva clave | 5 min | Ninguno |
| 6 | Deshabilita la clave vieja | 5 min | Ninguno |

### API Signing Key Rotation

| Step | Action | Duration |
|------|--------|----------|
| 1 | Genera una nueva clave HMAC en Vault | 5 min |
| 2 | Distribuye la nueva clave a los consumidores del API | Variable |
| 3 | Despliega código que acepta ambas claves | 10 min |
| 4 | Monitorea fallos de autenticación | 24 horas |
| 5 | Elimina la aceptación de la clave vieja | 5 min |
| 6 | Revoca la clave vieja en Vault | 5 min |

## 6. Verification

### Post-Rotation Verification Checklist

| Check | Method | Pass Criteria | Responsible |
|-------|--------|---------------|-------------|
| New key active | KMS API: `describe-key` | KeyState: Enabled | Security |
| Encryption works | Prueba de cifrado/descifrado | Éxito con la nueva clave | Engineering |
| Decryption works | Descifra datos existentes | Éxito con la clave vieja (modo dual) | Engineering |
| No errors in logs | Revisa los logs de la aplicación | 0 errores de cifrado durante 1 hora | DevOps |
| Monitoring alerts | Revisa los dashboards | Sin alertas de anomalías | DevOps |
| Performance normal | Compara con el baseline | Dentro del 5% del baseline | DevOps |
| Data migration complete | Verifica todos los registros | 100% cifrados con la nueva clave | Engineering |
| Old key disabled | KMS API: `describe-key` | KeyState: Disabled | Security |
| Documentation updated | Review runbook | Rotation logged | Security |

### Verification Script

```bash
#!/bin/bash
## Verify key rotation completion

NEW_KEY_ID="arn:aws:kms:us-east-1:123:key/new-key-id"
OLD_KEY_ID="arn:aws:kms:us-east-1:123:key/old-key-id"

## 1. Verify new key is enabled
NEW_KEY_STATE=$(aws kms describe-key --key-id $NEW_KEY_ID --query 'KeyMetadata.KeyState' --output text)
if [ "$NEW_KEY_STATE" != "Enabled" ]; then
    echo "FAIL: New key is not enabled (state: $NEW_KEY_STATE)"
    exit 1
fi
echo "OK: New key is enabled"

## 2. Verify old key is disabled
OLD_KEY_STATE=$(aws kms describe-key --key-id $OLD_KEY_ID --query 'KeyMetadata.KeyState' --output text)
if [ "$OLD_KEY_STATE" != "Disabled" ]; then
    echo "FAIL: Old key is not disabled (state: $OLD_KEY_STATE)"
    exit 1
fi
echo "OK: Old key is disabled"

## 3. Test encryption with new key
TEST_DATA="rotation-test-$(date +%s)"
ENCRYPTED=$(aws kms encrypt --key-id $NEW_KEY_ID --plaintext "$TEST_DATA" --output text --query CiphertextBlob)
DECRYPTED=$(aws kms decrypt --ciphertext-blob fileb://<(echo "$ENCRYPTED" | base64 --decode) --output text --query Plaintext | base64 --decode)
if [ "$DECRYPTED" != "$TEST_DATA" ]; then
    echo "FAIL: Encryption/decryption test failed"
    exit 1
fi
echo "OK: Encryption/decryption test passed"

echo "All verification checks passed."
```

## 7. Rollback Plan

### Rollback Triggers

| Trigger | Condition | Action |
|---------|-----------|--------|
| Decryption failures | > 1% de solicitudes fallan | Reactiva la clave vieja, revierte al modo dual-key |
| Service outage | Aplicación caída | Reactiva la clave vieja, revierte la config |
| Data corruption | La migración corrompe datos | Detiene la migración, restaura desde backup |
| Performance degradation | > 20% más lento | Pausa la migración, investiga |
| Monitoring alerts | Alertas críticas durante la rotación | Pausa la rotación, investiga |

### Rollback Steps

| Step | Action | Duration |
|------|--------|----------|
| 1 | Reactiva la clave vieja en KMS | 5 min |
| 2 | Revierte la config de la aplicación a la clave vieja | 5 min |
| 3 | Despliega la config revertida | 10 min |
| 4 | Verifica la salud del servicio | 5 min |
| 5 | Investiga la causa del fallo | Variable |
| 6 | Corrige el problema y reintenta la rotación | Variable |

## 8. Emergency Rotation

### Emergency Rotation Procedure

| Step | Action | Duration | Notes |
|------|--------|----------|-------|
| 1 | Crea una nueva clave | 5 min | KMS create-key |
| 2 | Actualiza todos los servicios para usar la nueva clave | 30 min | Despliegue paralelo |
| 3 | Re-cifra todos los datos | Variable | Migración por lotes |
| 4 | Revoca la clave vieja | 5 min | Deshabilita + programa eliminación |
| 5 | Rota todas las credenciales que tenían acceso a la clave | 1 hora | IAM, Vault, CI/CD |
| 6 | Audita CloudTrail en busca de uso no autorizado | 2 horas | Revisa uso de la clave vieja |
| 7 | Documenta el incidente | 1 hora | Reporte de incidente |
| 8 | Notifica a los stakeholders | 30 min | Security, legal, compliance |

### Emergency Contacts

| Role | Name | Phone | Email |
|------|------|-------|-------|
| Security Lead | Jane Doe | +1-555-0101 | jane@example.com |
| DevOps Lead | John Smith | +1-555-0102 | john@example.com |
| CISO | Robert Chen | +1-555-0103 | robert@example.com |
| AWS Support | Enterprise support | +1-555-0104 | support@aws.amazon.com |

Explanation

La rotación de claves limita el impacto de una clave comprometida. Si un atacante obtiene una clave, solo puede descifrar los datos del período en que esa clave estuvo activa. Rotar las claves cada 90 días significa que una clave comprometida expone como máximo 90 días de datos. Sin rotación, una sola clave comprometida expone todos los datos cifrados con ella.

La estrategia de doble clave permite la rotación sin downtime. En lugar de cambiar de la clave vieja a la nueva instantáneamente, el sistema soporta ambas claves simultáneamente. Durante la migración, la aplicación lee con ambas claves (los datos viejos usan la clave vieja, los datos nuevos usan la nueva) y escribe con la nueva clave. Una vez que todos los datos están migrados, la clave vieja se elimina. Este enfoque maneja grandes volúmenes de datos que no se pueden re-cifrar instantáneamente. Para más información sobre la rotación en AWS KMS, consulta la documentación de rotación de claves de AWS KMS. Las guías de gestión de claves de NIST proporcionan un marco para los cronogramas de rotación. La hoja de referencia de almacenamiento criptográfico de OWASP cubre las mejores prácticas de rotación de claves.

Los distintos tipos de claves tienen procedimientos de rotación diferentes. Las claves de AWS KMS se rotan creando una nueva clave y actualizando la configuración de la aplicación. Los certificados TLS se rotan a través de ACM con validación DNS. Las claves de firma JWT requieren un endpoint JWKS que sirva tanto la clave pública vieja como la nueva hasta que los tokens viejos expiren. Las claves de cifrado de base de datos usan re-cifrado online. Las claves de firma de API requieren coordinación con los consumidores para distribuir la nueva clave.

La verificación confirma que la rotación funcionó. La nueva clave debe estar activa y funcional. La clave vieja debe estar deshabilitada. Los datos deben estar cifrados con la nueva clave. Los logs de la aplicación deben mostrar 0 errores de cifrado. El monitoreo debe mostrar un rendimiento normal. Sin verificación, una rotación puede parecer completa mientras algunos datos siguen cifrados con la clave vieja o la aplicación está fallando silenciosamente.

Los planes de reversión son esenciales. Si ocurren fallos de descifrado después de la rotación, el sistema debe poder revertir a la clave vieja rápidamente. Los disparadores de reversión definen cuándo revertir: fallos de descifrado superiores al 1%, caída del servicio, corrupción de datos o degradación de rendimiento. El procedimiento de reversión reactiva la clave vieja y revierte la configuración.

La rotación de emergencia sigue un cronograma comprimido. Cuando se sospecha que una clave está comprometida, se crea una nueva clave, se actualizan todos los servicios, se re-cifran los datos y se revoca la clave vieja, todo en cuestión de horas. La rotación de emergencia también requiere rotar todas las credenciales que tenían acceso a la clave, auditar en busca de uso no autorizado y documentar el incidente.

Variants

ContextApproachNotes
AWS KMSManaged key rotationAutomatic annual rotation available
Azure Key VaultManaged key rotationAzure Key Vault rotation policies
Google Cloud KMSManaged key rotationAutomatic rotation per schedule
HashiCorp VaultSelf-managed keysVault transit engine for encryption
On-premises HSMManual rotationThales/Gemalto HSM procedures
Multi-cloudCloud-specific + VaultCentralized key management
Air-gappedOffline HSMPhysical key management procedures

What Works

  1. Usa la estrategia de doble clave para zero-downtime — sin interrupción del servicio
  2. Rota primero en staging — detecta problemas antes de producción
  3. Migra los datos en lotes — evita saturar la base de datos
  4. Monitorea durante 24 horas después de la rotación — detecta problemas diferidos
  5. Mantén la clave vieja durante 30 días antes de eliminarla — margen de seguridad
  6. Documenta cada rotación — pista de auditoría para cumplimiento
  7. Automatiza donde sea posible — reduce el error humano

Common Mistakes

  1. Rotar sin soporte de doble clave — causa downtime o pérdida de datos
  2. Sin plan de reversión — atascado si la rotación falla
  3. Sin verificación — la rotación parece completa pero no lo está
  4. Eliminar la clave vieja demasiado pronto — los datos aún cifrados con la clave vieja se vuelven ilegibles
  5. Sin prueba en staging — la rotación en producción es la primera prueba
  6. No rotar las claves tras la salida de personal — el empleado que se fue sigue teniendo acceso
  7. Sin monitoreo durante la rotación — los problemas se detectan días después

Preguntas frecuentes

¿Qué es envelope encryption y cómo se relaciona con la rotación de claves?

Envelope encryption usa una Key Encryption Key (KEK) para cifrar Data Encryption Keys (DEK). El DEK cifra los datos reales. Al rotar, solo necesitas re-cifrar el DEK con la nueva KEK — los datos subyacentes no necesitan re-cifrado. Esto hace la rotación más rápida porque estás re-cifrando una clave pequeña, no todo el conjunto de datos. AWS KMS usa envelope encryption por defecto.

¿Cómo rotamos claves para datos demasiado grandes de re-cifrar?

Usa la estrategia de doble clave. Mantén la clave vieja para leer los datos existentes y usa la nueva clave para escribir datos nuevos. Re-cifra los datos viejos en lotes gradualmente durante horas de baja carga. Para conjuntos de datos muy grandes, considera un enfoque de migración perezosa: re-cifra los datos solo cuando se accedan o modifiquen. Esto distribuye la migración en un período más largo sin afectar el rendimiento.

¿Cuál es la diferencia entre rotación automática y manual?

AWS KMS ofrece rotación automática para claves gestionadas, que rota el material de la clave anualmente sin cambiar el ARN de la clave. La aplicación no necesita ningún cambio. La rotación manual crea una nueva clave con un nuevo ARN, lo que requiere actualizar la configuración de la aplicación. La rotación automática es más simple pero menos flexible — no puedes controlar el momento ni forzar una rotación de emergencia. La rotación manual da control total pero requiere más trabajo operativo.

¿Deberíamos usar la misma clave en todos los entornos?

No. Usa claves separadas para desarrollo, staging y producción. Una clave de desarrollo comprometida no debería afectar los datos de producción. Las claves separadas también permiten cronogramas de rotación diferentes — las claves de desarrollo pueden rotarse con menos frecuencia ya que los datos no son sensibles. Usa políticas de KMS o namespaces de Vault para asegurar el aislamiento entre entornos.

¿Cómo manejamos la rotación de claves para integraciones de terceros?

Coordina con el tercero antes de rotar. Comparte la nueva clave a través de un canal seguro (no por correo electrónico). Mantén un período de transición donde se acepten tanto la clave vieja como la nueva. Monitorea los fallos de autenticación durante la transición. Establece una fecha límite para que el tercero cambie a la nueva clave. Después de la fecha límite, revoca la clave vieja. Documenta el proceso de coordinación para fines de auditoría.