Tema
Runbook — Ceremonia de Claves Criptográficas (Shamir Secret Sharing)
Documento: RUN-KEY-CEREMONY-01 Versión: 1.0 Fecha: 2026-07-29 Owner: Security Lead Referencias PCI DSS: Req 3.7.1, 3.7.6, 3.7.8
Propósito
Este runbook describe el procedimiento paso a paso para:
- Ceremonia inicial: primera inicialización del Vault cluster con distribución de Shamir shares
- Ceremonia de re-key: rotación programada de la Master Key (cada 3 años o por compromiso)
- Ceremonia de unseal: desbloquear el cluster tras reinicio/failover
Toda ceremonia genera evidencia auditable para cumplimiento PCI DSS Req 3.7.
Roles participantes
| Rol | Responsabilidad durante la ceremonia |
|---|---|
| Ceremony Master (CTO o Security Lead) | Dirige, ejecuta comandos, verifica outputs |
| Custodios A, B, C | Reciben físicamente su Shamir share, la anotan, la guardan |
| Testigo independiente | Firma acta que valida que la ceremonia se realizó según runbook (típicamente Legal o auditor interno) |
| Backup Operator | Verifica que audit log queda persistido en Spaces WORM |
Preparación (48 horas antes)
Materiales físicos requeridos
- [ ] Sala segura sin ventanas ni cámaras, acceso restringido
- [ ] 5 formularios impresos pre-numerados (
SHARE-FORM-01aSHARE-FORM-05) - [ ] 5 sobres de manila con sello anti-manipulación (tamper-evident)
- [ ] 5 lapiceros indelebles distintos color negro
- [ ] Cámara de video (para grabar el acto — no las shares, ver §Grabación)
- [ ] Reloj sincronizado con NTP visible
- [ ] Impresora que no cachee documentos (o desconectada de red)
- [ ] Papel para acta de asistencia
Verificaciones técnicas
- [ ] Los 3 nodos Vault están running:
systemctl status vaulten cada uno - [ ] Cluster status:
vault operator raft list-peers(aunque no unsealed, muestra membership) - [ ] Audit path a Spaces está accesible (probar
s3cmd put test.txt s3://fintrix-vault-audit-nyc3/) - [ ] Certificados TLS válidos y no expirados
- [ ] Conectividad entre nodos:
nc -zv 10.100.0.20 8201desde cada peer
Confirmación de asistentes (24h antes)
- [ ] Custodio A confirma presencia física en la sala + hora
- [ ] Custodio B idem
- [ ] Custodio C idem
- [ ] Testigo independiente idem
- [ ] Ceremony Master idem
Si algún custodio no puede asistir, se debe reprogramar. NO se acepta remoto.
Ceremonia Inicial — Bootstrap del cluster
Paso 1: Apertura (00:00 — 00:10)
- Ceremony Master abre la sala y verifica que:
- Todos los asistentes tienen documento de identidad
- Ningún participante lleva dispositivos electrónicos personales (celulares en caja al ingresar)
- La cámara de video está grabando (ángulo que muestra la sala, NO las pantallas donde salen las shares)
- Ceremony Master lee en voz alta:
"Iniciamos ceremonia de inicialización del Vault cluster de Fintrixs Pay para el ambiente de producción. Fecha: [fecha]. Hora: [hora]. Custodios presentes: [nombres]. Testigo: [nombre]. Ceremony Master: [nombre]. Esta ceremonia genera claves criptográficas que protegen datos de portadores de tarjeta en cumplimiento de PCI DSS Req 3.7."
- Cada custodio firma acta de asistencia
- Se muestra a la cámara el reloj sincronizado
Paso 2: Verificación del cluster (00:10 — 00:20)
Ceremony Master ejecuta desde su laptop (conectada por SSH tunnel a vault-01):
bash
# En vault-01
export VAULT_ADDR=https://10.100.0.20:8200
export VAULT_CACERT=/etc/vault.d/tls/vault.crt
vault status
# Expected output:
# Initialized: false
# Sealed: trueSi el output muestra Initialized: true, ABORTAR la ceremonia — el cluster ya fue inicializado. Investigar antes de continuar.
Paso 3: Inicialización con Shamir (00:20 — 00:35)
Ceremony Master ejecuta:
bash
vault operator init \
-key-shares=5 \
-key-threshold=3 \
-stored-shares=0 \
-format=json \
> /tmp/vault-init-output.json
# Verificar
jq '. | {shares: (.unseal_keys_b64 | length), threshold: .unseal_threshold}' /tmp/vault-init-output.json
# Expected: {"shares": 5, "threshold": 3}⚠️ CRÍTICO: el archivo /tmp/vault-init-output.json contiene las 5 shares + root token en texto claro. Es la única vez que Vault las muestra.
Paso 4: Distribución de shares (00:35 — 00:55)
Ceremony Master lee la primera share:
bash
jq -r '.unseal_keys_b64[0]' /tmp/vault-init-output.json
# Output: eyJ...<base64>...==- Custodio A se acerca a la pantalla (los demás dan vuelta)
- Anota la share manualmente en
SHARE-FORM-01 - Ceremony Master repite la lectura para verificación
- Custodio A confirma que anotó correctamente
- Dobla el formulario, lo pone en sobre, sella con cinta anti-manipulación
- Firma el sobre + escribe fecha + hora
- Ceremony Master y testigo firman también el sobre
Repetir para custodios B, C, y para escrows D y E (los sobres D/E se llevan a caja fuerte y notaría respectivamente al terminar).
Paso 5: Root token (00:55 — 01:00)
bash
jq -r '.root_token' /tmp/vault-init-output.json
# Output: hvs.<token>- Ceremony Master lo anota en un sobre separado
- Sello + firma
- Se entrega al Security Lead (para configuración inicial de engines + policies)
- Este root token debe ser revocado post-configuración (Vault genera admin AppRoles que reemplazan al root)
Paso 6: Destrucción del archivo temporal (01:00 — 01:05)
bash
# Wipe multi-pass del archivo
shred -uvfz -n 7 /tmp/vault-init-output.json
# Verificar que no quedan trazas
grep -r "unseal_keys" /tmp /var/tmp /home 2>/dev/null || echo "OK: no leftover"
# Limpiar swap si tiene contenido de RAM
sync && swapoff -a && swapon -aTestigo verifica visualmente que se ejecutó y el archivo ya no existe.
Paso 7: Unseal inicial del cluster (01:05 — 01:20)
3 custodios (mínimo threshold) ejecutan vault operator unseal cada uno con su share:
bash
# Custodio A ingresa su share (nadie más ve la pantalla)
vault operator unseal
# Prompt: Unseal Key: [pega share A]
# Progress: 1/3
# Custodio B
vault operator unseal
# Progress: 2/3
# Custodio C
vault operator unseal
# Progress: 3/3
# Unsealed: trueVerificar:
bash
vault status
# Expected:
# Initialized: true
# Sealed: false
# HA Mode: activeRepetir el unseal en vault-02 y vault-03 (necesitan sus propios 3 unseals para joinsear al cluster):
bash
# En vault-02
export VAULT_ADDR=https://10.100.0.21:8200
vault operator unseal # x3 shares
# En vault-03
export VAULT_ADDR=https://10.100.0.22:8200
vault operator unseal # x3 sharesVerificar Raft cluster:
bash
export VAULT_ADDR=https://10.100.0.20:8200
export VAULT_TOKEN=<root_token_temporal>
vault operator raft list-peers
# Expected: 3 nodes, 1 leader + 2 followersPaso 8: Configuración inicial (01:20 — 01:40)
Security Lead ejecuta el script de configuración:
bash
VAULT_ADDR=https://10.100.0.20:8200 \
VAULT_TOKEN=<root_token_temporal> \
VAULT_CACERT=/etc/vault.d/tls/vault.crt \
bash backend/infra/vault/configure-engines.shVer output: enable audit, transit engine, KEKs, HMAC key, AppRoles.
Paso 9: Revocación del root token (01:40 — 01:45)
Root token se usa solo para bootstrap. Post-configuración se revoca y se usan AppRoles:
bash
# Generar admin AppRole para futura administración
vault write auth/approle/role/vault-admin \
token_policies="crypto-admin-policy" \
token_ttl=1h \
token_max_ttl=8h
# Revocar root token
vault token revoke <root_token>
# Verificar
vault token lookup <root_token>
# Expected: "token not found"Paso 10: Escrow D y E (01:45 — 02:00)
- Escrow D: Ceremony Master + 1 custodio llevan el sobre a la caja fuerte de la oficina. Requiere 2 personas para abrir. Log de acceso firmado.
- Escrow E: Ceremony Master + testigo llevan el sobre a la notaría designada. Recibo notarial archivado.
Paso 11: Cierre y acta (02:00 — 02:15)
Ceremony Master imprime el acta de ceremonia:
ACTA DE CEREMONIA DE CLAVES CRIPTOGRÁFICAS
Fintrixs Pay S.A.S.
Fecha: [YYYY-MM-DD] Hora: [HH:MM UTC]
ASISTENTES:
Ceremony Master: [nombre + cargo + firma]
Custodio A: [nombre + cargo + firma]
Custodio B: [nombre + cargo + firma]
Custodio C: [nombre + cargo + firma]
Testigo: [nombre + cargo + firma]
CLUSTER INICIALIZADO:
Nodos: vault-01 (10.100.0.20), vault-02 (10.100.0.21), vault-03 (10.100.0.22)
Shamir shares: 5
Threshold: 3
Raft leader: vault-01
SHARES DISTRIBUIDAS:
Share 1 → Custodio A (sobre firmado #001)
Share 2 → Custodio B (sobre firmado #002)
Share 3 → Custodio C (sobre firmado #003)
Share 4 → Escrow físico caja fuerte oficina (recibo firmado)
Share 5 → Escrow legal notaría [nombre] (acta notarial #____)
ENGINES HABILITADOS:
transit (encryption-as-a-service)
secret (kv-v2)
pki_int (mTLS internal CA)
KEKs CREADAS:
transit/keys/kek-card-vault (AES-256-GCM, auto-rotate 12 meses)
transit/keys/kek-tokenization (AES-256-GCM, auto-rotate 12 meses)
transit/keys/hmac-pan-fpr (HMAC-SHA-256, auto-rotate 12 meses)
TEST DE INTEGRIDAD:
Encrypt/decrypt round-trip: PASS ✓
Raft cluster health: 3/3 nodes ✓
Audit log activo: file + syslog ✓
ROOT TOKEN:
Revocado post-configuración: SI ✓
Admin AppRole creado: vault-admin ✓
Firmas:
[Ceremony Master] [Custodio A] [Custodio B] [Custodio C] [Testigo]Se archiva:
- Original firmado → drive legal de Fintrixs
- Copia notarizada → escrow notarial
- Video grabado → drive legal encriptado
Duración total: ~2:15 hs.
Ceremonia de Unseal (tras reinicio del cluster)
Ocurre cada vez que:
- Un nodo se reinicia (planificado o crash)
- Todo el cluster se reinicia (raro, mantenimiento mayor)
Procedimiento breve (30-45 min):
- 3 custodios físicamente presentes (o vía tunnel VPN + video call con Testigo)
- Cada custodio ejecuta
vault operator unsealcon su share en el/los nodos afectados - Verificar
vault status→Sealed: false - Registrar en
docs/pci-dss/unseal-log/YYYY-MM-DD-unseal.mdcon firma de los custodios que participaron
Ceremonia de Re-key (rotación de Master Key)
Cada 3 años o por sospecha de compromiso. Muy similar a la inicial pero se usa vault operator rekey en lugar de init:
bash
# Con quórum de 3 custodios actuales:
vault operator rekey -init -key-shares=5 -key-threshold=3
# Cada custodio (uno por uno) confirma con su share ACTUAL:
vault operator rekey -nonce=<nonce> <current_share_A>
vault operator rekey -nonce=<nonce> <current_share_B>
vault operator rekey -nonce=<nonce> <current_share_C>
# Al llegar a 3, Vault emite 5 NUEVAS shares → se distribuyen igual que ceremonia inicialLas shares viejas quedan invalidadas inmediatamente. Los custodios que se salen deben entregar (o destruir bajo testigo) su share vieja.
Grabación de la ceremonia — política
- SÍ se graba: la sala, los asistentes, los sobres siendo firmados y sellados
- NO se graba: ninguna pantalla que muestre shares, ni close-ups a los formularios anotados
- La cámara se posiciona atrás de los asistentes cuando cada uno anota su share
- Video se guarda encriptado con GPG (key custodiada por Legal) en drive legal, retención 5 años
Compromiso sospechado — respuesta inmediata
Si un custodio pierde/le roban/comparte su share:
- Notificación al Security Lead en <1 hora
- Ceremonia de emergency re-key en <24 h con quórum de 3 custodios NO comprometidos
- Todas las shares viejas quedan invalidadas
- Custodio comprometido puede o no ser reemplazado según investigación
- Post-mortem obligatorio en <72h
- Ver
INCIDENT-KEY-COMPROMISE.md
Evidencia auditable
| Evidencia | Ubicación | Retención |
|---|---|---|
| Acta de ceremonia firmada | Drive legal + notaría | Vida del sistema |
| Video grabado (GPG encrypted) | Drive legal | 5 años |
| Vault audit log de operator init/rekey | s3://fintrix-vault-audit-nyc3/audit/ (WORM) | 3 años |
| Recibos escrow físico + notarial | Drive legal | Vida del sistema |
| Custodian agreements firmados | Drive legal + copia notarial | Vida del sistema |
| Unseal logs | docs/pci-dss/unseal-log/ en repo git | Vida del sistema |
Aprobaciones
| Rol | Nombre | Firma | Fecha |
|---|---|---|---|
| CTO | [TO_FILL] | ||
| Security Lead | [TO_FILL] | ||
| Legal | [TO_FILL] |
