Skip to content

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

RolResponsabilidad durante la ceremonia
Ceremony Master (CTO o Security Lead)Dirige, ejecuta comandos, verifica outputs
Custodios A, B, CReciben físicamente su Shamir share, la anotan, la guardan
Testigo independienteFirma acta que valida que la ceremonia se realizó según runbook (típicamente Legal o auditor interno)
Backup OperatorVerifica 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-01 a SHARE-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 vault en 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 8201 desde 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)

  1. 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)
  2. 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."

  3. Cada custodio firma acta de asistencia
  4. 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: true

Si 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 -a

Testigo 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: true

Verificar:

bash
vault status
# Expected:
#   Initialized: true
#   Sealed: false
#   HA Mode: active

Repetir 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 shares

Verificar 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 followers

Paso 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.sh

Ver 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):

  1. 3 custodios físicamente presentes (o vía tunnel VPN + video call con Testigo)
  2. Cada custodio ejecuta vault operator unseal con su share en el/los nodos afectados
  3. Verificar vault statusSealed: false
  4. Registrar en docs/pci-dss/unseal-log/YYYY-MM-DD-unseal.md con 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 inicial

Las 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:

  1. Notificación al Security Lead en <1 hora
  2. Ceremonia de emergency re-key en <24 h con quórum de 3 custodios NO comprometidos
  3. Todas las shares viejas quedan invalidadas
  4. Custodio comprometido puede o no ser reemplazado según investigación
  5. Post-mortem obligatorio en <72h
  6. Ver INCIDENT-KEY-COMPROMISE.md

Evidencia auditable

EvidenciaUbicaciónRetención
Acta de ceremonia firmadaDrive legal + notaríaVida del sistema
Video grabado (GPG encrypted)Drive legal5 años
Vault audit log de operator init/rekeys3://fintrix-vault-audit-nyc3/audit/ (WORM)3 años
Recibos escrow físico + notarialDrive legalVida del sistema
Custodian agreements firmadosDrive legal + copia notarialVida del sistema
Unseal logsdocs/pci-dss/unseal-log/ en repo gitVida del sistema

Aprobaciones

RolNombreFirmaFecha
CTO[TO_FILL]
Security Lead[TO_FILL]
Legal[TO_FILL]

Documentación Confidencial — Solo para uso interno y auditoría PCI DSS