Gestión de claves ZFS: La parte que todos olvidan hasta el día del desastre

¿Te fue útil?

La encriptación es la parte fácil. La gestión de claves es la parte que solo notas cuando falta—por lo general a las 02:13, durante una interrupción, con un gerente senior preguntando si “los datos siguen ahí” como si fuera una cuestión filosófica.

La encriptación nativa de ZFS es robusta, rápida y engañosamente sencilla de activar. El problema es que “encryption=on” no es un plan. Un plan es: cómo se crean, almacenan, cargan, rotan, auditan, respaldan y recuperan las claves cuando la máquina está muerta, el pool se importa en solo lectura y tu gestor de contraseñas también está en ese pool. Esta es una guía para quienes realmente operan sistemas en producción—y quieren seguir haciéndolo.

Qué estás gestionando realmente (y por qué es más difícil de lo que parece)

La encriptación de ZFS no es un único interruptor. Es un conjunto de propiedades adjuntas a los datasets, además de una serie de comportamientos que aparecen en los peores momentos posibles: arranque, importación, failover, restauración, replicación y auditorías.

A alto nivel, la encriptación nativa de ZFS funciona así:

  • Creas un dataset encriptado con encryption=on.
  • ZFS usa una clave envolvente derivada de una frase de contraseña o material de clave almacenado (keyformat) para proteger una clave del dataset.
  • Los bloques de datos se encriptan; los metadatos quedan parcialmente protegidos dependiendo de la configuración y de la realidad en disco.
  • Para montar un dataset encriptado, por lo general necesitas cargar la clave (desbloquear) y luego montar.

La gestión de claves es todo lo que rodea ese momento de desbloqueo: de dónde viene la clave, quién puede acceder a ella, cómo la rotas y cómo demuestras que puedes recuperar sin improvisar.

Un chiste, porque lo necesitaremos: la encriptación sin un proceso de recuperación de claves probado es como un paracaídas que compraste en línea pero nunca probaste—técnicamente presente, emocionalmente inútil.

Los tres “planos de realidad” que debes alinear

La mayoría de los desastres con claves ZFS ocurren cuando estos tres planos no están alineados:

  • El plano del dataset: propiedades como encryption, keyformat, keylocation, keystatus, límites de herencia y si los datasets hijos heredan la clave.
  • El plano del host: proceso de arranque, initramfs, orden de servicios, disponibilidad de archivos de clave, solicitudes de frase de contraseña, consolas que no existen (hola, consolas serial en la nube) y la realidad de que “la tecleamos en el arranque” deja de funcionar cuando tienes 50 nodos.
  • El plano de las personas: quién conoce la frase de contraseña, cómo se almacena, cómo rotarla sin downtime, cómo revocar el acceso y cómo demostrar que esto no es “teatro de seguridad” con una contraseña compartida en un tema de chat.

Terminología de claves ZFS que deberías usar con precisión

En conversaciones de operaciones, las palabras “clave” y “contraseña” se mezclan. Para la encriptación ZFS, sé explícito:

  • Clave de encriptación del dataset (DEK): la clave interna que encripta los datos. No la tecleas; ZFS la gestiona.
  • Clave envolvente / material de clave: lo que protege la DEK. Esto se deriva de una frase de contraseña o proviene de un archivo de clave, según keyformat.
  • Clave cargada: material de clave presente en memoria y utilizable. Esto es lo que consigue zfs load-key.
  • Rotación de claves: generalmente significa cambiar la clave envolvente (re-envolver la DEK) en lugar de volver a encriptar todos los bloques de datos.

Hechos interesantes y contexto: cómo llegamos hasta aquí

Los errores en la gestión de claves no son un fallo personal. Son una tradición de la industria. Algunos puntos de contexto útiles:

  1. ZFS nació en Sun Microsystems a mediados de los 2000 con una filosofía de “todo tiene checksum” que aún se siente futurista comparado con muchas pilas heredadas.
  2. La encriptación nativa de ZFS llegó más tarde de lo que muchos asumen; durante años la gente usó GELI (FreeBSD), LUKS/dm-crypt (Linux) o encriptación hardware bajo ZFS.
  3. Los enfoques tempranos de “encriptar todo el disco” simplificaron algunos flujos de recuperación y arranque (un solo desbloqueo), pero complicaron la replicación y el control de acceso fino.
  4. Operativamente, la encriptación pasó de nicho a defecto cuando los regímenes de cumplimiento (y los titulares de brechas) convirtieron la encriptación “en reposo” en un requisito incluso para sistemas internos.
  5. El modelo de datasets de ZFS es una espada de doble filo: ofrece límites de encriptación granulares, pero también te da 400 maneras de crear herencias inconsistentes que no notarás hasta el día de la restauración.
  6. Los fallos en la gestión de claves suelen ser “fallos por éxito”: los equipos automatizan el desbloqueo para conveniencia y accidentalmente eliminan cualquier control de acceso significativo.
  7. Los sistemas de respaldo históricamente lucharon con datasets encriptados porque los administradores confundieron “encriptado en disco” con “seguro en tránsito” o “seguro en las copias de respaldo”, que son problemas distintos.
  8. La industria aprendió (repetidamente) que almacenar la única copia de la clave en el almacenamiento encriptado es una forma de arte performativo, no de ingeniería.

Modelo de amenazas: lo que la encriptación ZFS protege (y lo que no)

Si no lo documentas, tu organización lo inventará más tarde durante una revisión por brecha.

Para qué es buena la encriptación nativa de ZFS

  • Discos robados / unidades desechadas: si alguien se lleva discos o un chasis entero, los datasets encriptados protegen los datos en reposo (suponiendo que las claves no estén guardadas con los discos).
  • “Ups, mandamos el RMA equivocado”: la encriptación reduce el impacto cuando el hardware sale de tu custodia.
  • Límites multi-inquilino en almacenamiento compartido: las claves de dataset pueden separar accesos, dentro de los límites del entorno host.

Para qué no es buena

  • Malware en el host: si el dataset está montado y la clave cargada, el ransomware lee/escribe con normalidad.
  • Root en el host: root suele poder leer memoria, interceptar carga de claves o acceder a archivos de clave según tu configuración.
  • Exfiltración desde aplicaciones: la encriptación ZFS está debajo de la API del sistema de archivos; las aplicaciones ven texto plano.

Decisiones de modelo de amenazas que debes tomar explícitamente

  • ¿Se requiere arranque sin intervención? Si sí, tu clave está o bien almacenada localmente (menos segura) o bien recuperada desde un servicio de red (más piezas móviles). Ambas son válidas; fingir que puedes evitar la compensación no ayuda.
  • ¿Necesitas claves por dataset? Excelente para mínimo privilegio; doloroso para operaciones si no estandarizas nombres y herencias.
  • ¿Cuál es tu vía “romper el cristal”? ¿Quién puede desbloquear durante un incidente y cómo lo hace sin arqueología de Slack?

Patrones de diseño de claves que sobreviven la vida real

Patrón 1: Un root encriptado con claves heredadas (aburrido, efectivo)

Este es el patrón “quiero dormir”. Encriptas un dataset de nivel superior (a menudo el dataset raíz del pool o un padre designado), configuras hijos para heredar y mantienes bajo el número de claves distintas.

Pros: menos claves, procedimiento de desbloqueo más simple, recuperación de desastres más fácil. Contras: menos separación granular entre datasets.

Patrón 2: Varias claves por dominio (amigable para seguridad, costoso para ops)

Agrupas datasets por sensibilidad: por ejemplo, pool/app, pool/db, pool/secrets, cada uno con claves envolventes separadas. Aceptas que el desbloqueo y la recuperación requieren coreografías cuidadosas.

Pros: mejor aislamiento. Contras: más trabajo de rotación de claves, más dependencias en tiempo de arranque, más oportunidades de olvidar un dataset hasta que una restauración falle.

Patrón 3: Frase de contraseña vs archivo de clave (elige según tu realidad de arranque)

Frase de contraseña: los humanos pueden teclearla, pero los humanos son infraestructura poco fiable. Excelente para portátiles, menos para servidores sin cabeza a menos que tengas consola remota robusta y procedimientos.

Archivo de clave: amigable para la automatización, pero debes proteger el archivo. Si el archivo de clave vive en la misma máquina, mayormente has movido el problema. Si se recupera desde una fuente segura en el arranque, has construido un sistema de distribución de claves—felicidades por tu nuevo subsistema.

Patrón 4: keylocation es una interfaz, no una estrategia de almacenamiento

ZFS permite fijar keylocation a prompt o una ruta de archivo. Eso no es una solución de gestión de claves; es un puntero. Tu estrategia real es: de dónde viene ese archivo de clave, cómo se permissiona, cómo se rota y cómo se recupera si la máquina está frita.

Patrón 5: La regla “dos controles” para datasets de producción

En la práctica: no permitas que el gestor de contraseñas del portátil de un administrador sea la única vía para desbloquear datos de producción. Usa depósito compartido (con auditoría) o un proceso de control dual. A los auditores les gustará. Al comandante del incidente le encantará.

Tareas prácticas con comandos (y qué significa la salida)

Los comandos abajo asumen OpenZFS en Linux, ejecutados como root a menos que se indique lo contrario. La salida es representativa; tus campos exactos pueden variar.

Tarea 1: Inventario del estado de encriptación en un pool

cr0x@server:~$ zfs list -r -o name,encryption,keyformat,keylocation,keystatus,mounted pool
NAME                 ENCRYPTION  KEYFORMAT  KEYLOCATION     KEYSTATUS  MOUNTED
pool                 off         -          -               -          yes
pool/system           aes-256-gcm  passphrase prompt          available  yes
pool/system/var       aes-256-gcm  passphrase prompt          available  yes
pool/data             aes-256-gcm  raw        file:///etc/zfs/keys/pool.data.key  available  yes
pool/data/backups     aes-256-gcm  raw        file:///etc/zfs/keys/pool.data.key  available  yes
pool/archive          aes-256-gcm  passphrase prompt          unavailable no

Interpretación: keystatus=unavailable significa que el dataset está bloqueado (clave no cargada). Si mounted=no y keystatus=available, tienes un problema de montaje, no de clave.

Tarea 2: Confirmar qué datasets heredan una clave frente a los que tienen la suya

cr0x@server:~$ zfs get -r -o name,property,value,source keylocation pool/system
NAME             PROPERTY     VALUE    SOURCE
pool/system      keylocation  prompt   local
pool/system/var  keylocation  prompt   inherited from pool/system

Interpretación: Los límites de herencia son donde empieza la proliferación de claves. La columna source te dice dónde te fuiste “local” accidentalmente y escindiste tu gestión de claves.

Tarea 3: Crear un dataset encriptado con solicitud de frase de contraseña

cr0x@server:~$ zfs create -o encryption=on -o keyformat=passphrase -o keylocation=prompt pool/secure
Enter passphrase:
Re-enter passphrase:

Interpretación: Esto crea el dataset y lo configura para requerir una frase de contraseña al cargar claves. Bueno para flujos interactivos de desbloqueo; arriesgado para arranque sin intervención.

Tarea 4: Crear un dataset encriptado usando un archivo de clave

cr0x@server:~$ install -d -m 0700 /etc/zfs/keys
cr0x@server:~$ head -c 32 /dev/urandom > /etc/zfs/keys/pool.app.key
cr0x@server:~$ chmod 0400 /etc/zfs/keys/pool.app.key
cr0x@server:~$ zfs create -o encryption=on -o keyformat=raw -o keylocation=file:///etc/zfs/keys/pool.app.key pool/app

Interpretación: keyformat=raw espera bytes de material de clave. Los permisos importan; el archivo ahora es una joya de la corona. Si es legible por usuarios casuales, tu encriptación es mayormente decoración.

Tarea 5: Bloquear y desbloquear un dataset (y verificar)

cr0x@server:~$ zfs unmount pool/app
cr0x@server:~$ zfs unload-key pool/app
cr0x@server:~$ zfs get -o name,property,value keystatus pool/app
NAME      PROPERTY  VALUE
pool/app  keystatus unavailable

cr0x@server:~$ zfs load-key pool/app
cr0x@server:~$ zfs mount pool/app
cr0x@server:~$ zfs get -o name,property,value keystatus pool/app
NAME      PROPERTY  VALUE
pool/app  keystatus available

Interpretación: Desmonta primero, luego descarga la clave. Si descargas mientras está montado, ZFS generalmente se negará porque la clave está en uso.

Tarea 6: Importar un pool sin montar y luego desbloquear deliberadamente

cr0x@server:~$ zpool import -N pool
cr0x@server:~$ zfs load-key -a
cr0x@server:~$ zfs mount -a

Interpretación: -N importa sin montar, que es lo que quieres en una recuperación controlada: importa primero, desbloquea claves después, monta al final. Hace que las fallas sean obvias y más seguras.

Tarea 7: Identificar por qué un dataset no monta (clave vs punto de montaje vs ocupado)

cr0x@server:~$ zfs mount pool/archive
cannot mount 'pool/archive': encryption key not loaded
cr0x@server:~$ zfs load-key pool/archive
Enter passphrase for 'pool/archive':

Interpretación: ZFS te está diciendo cortésmente la causa raíz real. Cuando dice “key not loaded”, no empieces a afinar ARC y escribir postmortems de rendimiento.

Tarea 8: Rotar una clave envolvente (cambio de frase) sin re-encriptar datos

cr0x@server:~$ zfs change-key pool/secure
Enter new passphrase:
Re-enter new passphrase:

Interpretación: Esto cambia la clave envolvente para la raíz de encriptación de ese dataset. Es rápido porque reenvuelve material de clave, no reescribe todos los bloques.

Tarea 9: Rotar material de clave para un dataset gestionado por archivo de clave

cr0x@server:~$ head -c 32 /dev/urandom > /etc/zfs/keys/pool.app.key.new
cr0x@server:~$ chmod 0400 /etc/zfs/keys/pool.app.key.new
cr0x@server:~$ zfs set keylocation=file:///etc/zfs/keys/pool.app.key.new pool/app
cr0x@server:~$ zfs change-key pool/app
cr0x@server:~$ mv /etc/zfs/keys/pool.app.key.new /etc/zfs/keys/pool.app.key

Interpretación: Actualiza keylocation, luego change-key. Mantén la clave vieja hasta verificar el desbloqueo tras reboot/import. Sí, es un pie de arma si la borras demasiado pronto.

Tarea 10: Encontrar la raíz de encriptación y confirmar la jerarquía

cr0x@server:~$ zfs get -o name,property,value -r encryptionroot pool/data
NAME             PROPERTY        VALUE
pool/data        encryptionroot  pool/data
pool/data/backups encryptionroot pool/data

Interpretación: Los datasets hijos heredan claves desde la raíz de encriptación. Si ves hijos con raíces de encriptación diferentes, tu procedimiento de desbloqueo debe contemplarlo.

Tarea 11: Validar que las claves no estén accidentalmente almacenadas en el pool encriptado

cr0x@server:~$ zfs get -o name,property,value keylocation pool/data
NAME      PROPERTY     VALUE
pool/data keylocation  file:///etc/zfs/keys/pool.data.key

cr0x@server:~$ findmnt /etc/zfs/keys
TARGET        SOURCE    FSTYPE OPTIONS
/etc/zfs/keys /dev/sda1 ext4   rw,relatime

Interpretación: El archivo de clave vive en /dev/sda1 (probablemente el disco OS), no en pool. Si /etc está en el pool encriptado que intentas desbloquear, has construido una puerta cerrada con la llave pegada al otro lado.

Tarea 12: Comprobar fallos de desbloqueo en el arranque via journal de systemd

cr0x@server:~$ journalctl -b -u zfs-import-cache -u zfs-mount -u zfs-load-key --no-pager
-- Journal begins at ...
systemd[1]: Starting Load ZFS keys...
zfs-load-key[1023]: cannot open 'file:///etc/zfs/keys/pool.data.key': No such file or directory
systemd[1]: zfs-load-key.service: Main process exited, code=exited, status=1/FAILURE
systemd[1]: Failed to start Load ZFS keys.
systemd[1]: Dependency failed for ZFS mount.

Interpretación: Esto no es un bug de ZFS; es un problema de orden o disponibilidad de archivos. Tu ruta de clave no existía cuando se ejecutó el servicio.

Tarea 13: Listar claves cargadas rápidamente (a escala)

cr0x@server:~$ zfs list -H -o name,keystatus -r pool | awk '$2=="unavailable"{print $1}'
pool/archive
pool/secrets/hr

Interpretación: Esta es la vista “¿qué sigue bloqueado?”. Útil durante la recuperación o cuando un reboot dejó datasets indisponibles.

Tarea 14: Verificar que un dataset encriptado realmente está encriptado en disco

cr0x@server:~$ zfs get -o name,property,value encryption,keyformat pool/secure
NAME        PROPERTY   VALUE
pool/secure encryption aes-256-gcm
pool/secure keyformat  passphrase

Interpretación: encryption muestra el modo de cifrado. Si está off, no tienes encriptación; tienes optimismo.

Tarea 15: Ciclo export/import de prueba (lo más parecido a un simulacro)

cr0x@server:~$ zfs unmount -a
cr0x@server:~$ zfs unload-key -a
cr0x@server:~$ zpool export pool

cr0x@server:~$ zpool import -N pool
cr0x@server:~$ zfs load-key -a
cr0x@server:~$ zfs mount -a
cr0x@server:~$ zfs list -o name,mounted,keystatus -r pool | head
NAME         MOUNTED  KEYSTATUS
pool         yes      -
pool/system  yes      available
pool/data    yes      available

Interpretación: Esta es la prueba operativa que deberías ejecutar antes de confiar en cualquier estrategia de claves. Es dolor controlado que evita dolor no controlado después.

Replicación con datasets encriptados: send/receive sin desamor

La replicación es donde las buenas intenciones van a morir. La gente encripta datasets y luego asume que la replicación “simplemente funciona” como antes. Puede hacerlo—pero debes elegir qué estás replicando: texto plano, cifrado o algo intermedio.

Los tres modos de replicación que deberías entender

  • Enviar en texto plano (el receptor re-encripta): los datos se desencriptan en el lado de envío y se reciben como flujo en texto plano; el receptor puede encriptar con su propia clave. Esto es aceptable dentro de una red de confianza, pero es otra historia de seguridad.
  • Enviar raw (cifrado): el receptor obtiene bloques encriptados y (a menudo) la misma estructura de claves del dataset. Esto preserva la encriptación de extremo a extremo pero cambia cómo se comportan las claves y propiedades.
  • Flujos híbridos: enviar raw para archivos, texto plano para datasets operativos, según cumplimiento y necesidades de restauración.

Tarea 16: Enviar un dataset encriptado como flujo raw

cr0x@server:~$ zfs snapshot -r pool/data@replica-001
cr0x@server:~$ zfs send -w -R pool/data@replica-001 | zfs receive -uF backup/data

Interpretación: -w envía un stream raw (mantiene la encriptación). -u recibe sin montar. Así evitas caos de auto-montado en un destino de respaldo. Tras recibir, aún necesitas claves para montar si quieres leerlo.

Tarea 17: Recibir y fijar una clave diferente en el destino (cuando no se envía raw)

cr0x@server:~$ zfs snapshot pool/app@replica-001
cr0x@server:~$ zfs send pool/app@replica-001 | zfs receive -o encryption=on -o keyformat=passphrase -o keylocation=prompt backup/app

Interpretación: Esto re-encripta en el destino con keying controlado por el destino. Útil cuando el entorno de respaldo tiene requisitos de control de acceso diferentes.

Trampa de replicación: “send raw” puede replicar tus errores

Si usaste la misma jerarquía de claves en todas partes, send raw la preserva felizmente. Eso puede ser exactamente lo que quieres—o exactamente lo que hace que tu “entorno de respaldo” no esté separadamente protegido de producción.

Tres mini-historias del mundo corporativo desde las trincheras

Mini-historia 1: El incidente causado por una suposición errónea (“Nos pedirá la frase en el arranque”)

Tenían una flota ordenada: una docena de nodos de base de datos y un puñado de servidores de aplicaciones con almacenamiento pesado. Alguien activó la encriptación ZFS por “cumplimiento”, eligió solicitudes de frase de contraseña y lo dio por concluido. Funcionó en el laboratorio porque siempre había una persona en la consola.

Luego llegó el desencadenante mundano: una actualización del kernel y un reinicio coordinado. La mitad de los hosts estaban en una instalación de colocation con manos remotas; la otra mitad eran instancias en la nube con una consola serial técnicamente disponible pero prácticamente inutilizable bajo presión. El proceso de arranque esperó la entrada de la frase que nadie podía proporcionar a escala.

El on-call hizo lo que hacen los on-call: improvisaron. Intentaron montar datasets manualmente y luego se dieron cuenta de que los datasets ni siquiera estaban desbloqueados. Intentaron cargar claves, pero las frases “correctas” estaban dispersas entre algunas personas y un gestor de contraseñas—guardado en un dataset encriptado que, por supuesto, estaba bloqueado en uno de los hosts caídos.

La interrupción duró lo suficiente para convertirse en un incidente inter-equipos. Nadie había hecho un simulacro de reinicio con la encriptación activada. La suposición equivocada no fue técnica; fue organizativa: asumieron que un prompt humano era una dependencia aceptable en producción.

Después, pasaron a un enfoque dividido: frases para los datasets de mayor sensibilidad que podían tolerar desbloqueo manual, y archivos de clave recuperados por red para el resto con controles de acceso estrictos. La lección no fue “nunca uses prompts.” Fue: no construyas una ruta crítica que dependa de un humano calmado en una consola.

Mini-historia 2: La optimización que salió mal (“Hagamos el desbloqueo totalmente automático”)

Otra organización fue por el camino contrario. Odiaban los prompts de arranque, así que automatizaron por completo el desbloqueo almacenando archivos de clave en el filesystem raíz de cada servidor. Pusieron permisos estrictos, usaron gestión de configuración e incluso rotaron claves trimestralmente. Parecía maduro.

Entonces se comprometió una cuenta de contratista. El atacante no necesitó exploits de kernel ni magia criptográfica. Obtuvo suficiente privilegio para leer el archivo de clave en un subconjunto de hosts. A partir de ahí, los datasets encriptados de ZFS fueron un pequeño obstáculo, no una barrera.

La revisión post-incidente fue incómoda porque nadie había hecho nada “mal” en el sentido usual. El equipo optimizó para disponibilidad y operabilidad, y lo consiguieron. El fallo fue que optimizaron por encima del modelo de amenazas: la encriptación estaba pensada para proteger contra discos perdidos y fugas tras desmantelar hardware, pero la dirección creía que también protegía contra compromiso del host.

La solución no fue eliminar la automatización; la solución fue implementar una verdadera separación de deberes. Movieron claves fuera del host, requirieron recuperación autenticada en el arranque y redujeron quién podía acceder al mecanismo de recuperación. También introdujeron una señal de monitorización “claves cargadas”: si datasets se desbloqueaban fuera de ventanas normales, activaba investigación.

Segundo chiste, porque nos lo hemos ganado: lo único peor que una clave que no puedes encontrar es una clave que todo el mundo puede encontrar.

Mini-historia 3: La práctica aburrida pero correcta que salvó el día (el “ensayo de restauración” que nadie quiere)

Una compañía relacionada con finanzas tenía un ritual: una vez por trimestre hacían un ensayo de restauración encriptada. No era glamuroso. Costaba tiempo. Molestaba a la gente. También fue la razón por la que no tuvieron un incidente que les costara la carrera.

El ensayo era simple: elegir un dataset, exportarlo e importarlo en un host limpio, cargar claves usando el método documentado, montar en solo lectura, verificar integridad de datos y documentar cada desviación. El punto no era “podemos hacerlo eventualmente”; el punto era “podemos hacerlo estando cansados, bajo presión y con congelación de cambios en efecto.”

Un trimestre, el ensayo falló. No por ZFS en sí, sino porque el proceso de depósito de claves se había desviado. Se había hecho una rotación y el material de clave actualizado nunca llegó al depósito offline. Lo detectaron durante una prueba planificada, no durante un evento de ransomware.

Arreglaron el proceso y añadieron una regla: una rotación de claves no se considera completa hasta que el ensayo de restauración pase. La gente se quejó. Luego, más adelante, una estantería de almacenamiento murió de forma no planificada y tuvieron que reconstruir a partir de replicación y backups. Desbloquear y montar fueron las partes menos emocionantes de la recuperación—que es exactamente el objetivo.

Guion de diagnóstico rápido: qué comprobar primero, segundo, tercero

Esto es para el momento en que los datasets encriptados no montan y todos te miran como si tú personalmente hubieras perdido las leyes de la matemática.

Primero: determina si es un problema de pool o de clave

cr0x@server:~$ zpool status -x
all pools are healthy
cr0x@server:~$ zpool import
   pool: pool
     id: 1234567890
  state: ONLINE
 action: The pool can be imported using its name or numeric identifier.

Interpretación: Si el pool no puede importarse o está degradado, soluciona eso primero. Las claves no ayudan si el pool no está online.

Segundo: comprueba el estado de las claves y la raíz de encriptación

cr0x@server:~$ zfs list -r -o name,keystatus,encryptionroot,mounted pool | sed -n '1,25p'
NAME                 KEYSTATUS     ENCRYPTIONROOT  MOUNTED
pool                 -             -              yes
pool/system          available     pool/system     yes
pool/archive         unavailable   pool/archive    no

Interpretación: Si keystatus=unavailable, no pierdas tiempo en tuning de puntos de montaje. Tu siguiente movimiento es zfs load-key.

Tercero: valida la disponibilidad de keylocation y el orden de servicios

cr0x@server:~$ zfs get -o name,property,value keylocation pool/archive
NAME         PROPERTY     VALUE
pool/archive keylocation  file:///etc/zfs/keys/pool.archive.key
cr0x@server:~$ ls -l /etc/zfs/keys/pool.archive.key
ls: cannot access '/etc/zfs/keys/pool.archive.key': No such file or directory

Interpretación: Archivo de clave faltante es la falla más común en tiempo de arranque. Si existe, verifica permisos. Si no, comprueba si vive en un filesystem que no se montó todavía.

Cuarto: intenta importación y desbloqueo controlados

cr0x@server:~$ zpool export pool
cr0x@server:~$ zpool import -N pool
cr0x@server:~$ zfs load-key -a

Interpretación: Secuencias controladas reducen sorpresas. Si load-key falla, el mensaje de error suele ser accionable (frase equivocada, archivo ausente, URI inválida).

Quinto: si aún estás atascado, recopila evidencia antes de improvisar

cr0x@server:~$ zfs get -r -o name,property,value,source encryption,keyformat,keylocation,keystatus,encryptionroot pool > /root/zfs-encryption-audit.txt
cr0x@server:~$ journalctl -b --no-pager > /root/boot-journal.txt

Interpretación: Esto preserva el estado para análisis posterior y evita que el equipo “arregle” el problema hasta convertirlo en misterio.

Errores comunes: síntomas y soluciones

Error 1: Archivo de clave almacenado en el pool encriptado

Síntoma: tras reiniciar, zfs load-key falla porque la ruta del archivo de clave no existe; los datasets permanecen bloqueados; situación de gallina y huevo.

Solución: almacena material de clave en un filesystem raíz no encriptado, en medios extraíbles o en un mecanismo de recuperación por red disponible antes del montaje de ZFS. Vuelve a probar con zpool import -N y zfs load-key.

Error 2: “Usamos encriptación, así que los backups están seguros”

Síntoma: las copias son streams raw encriptados pero las claves no están en depósito; la restauración falla cuando el host original desaparece.

Solución: deposita las claves (o frases) necesarias para desbloquear réplicas y realiza ensayos de restauración. Si usas send raw, asegura que el lado receptor pueda desbloquear independientemente del remitente.

Error 3: Rotación de claves hecha sin prueba de reboot/import

Síntoma: todo funciona hasta el siguiente reinicio; entonces los datasets no se desbloquean porque keylocation apunta a una clave rotada que no se desplegó en todas partes.

Solución: después de rotar, ejecuta una prueba export/import (Tarea 15) en ventana de mantenimiento o en un host canario. Trata la rotación como incompleta hasta que pase.

Error 4: Deriva de herencia crea “claves misteriosas”

Síntoma: algunos datasets hijos requieren claves distintas; la automatización carga la mayoría, pero uno queda bloqueado y una aplicación falla de forma extraña.

Solución: audita encryptionroot y las fuentes de keylocation. Estandariza en una estrategia de raíz de encriptación y hazla cumplir mediante revisión de código o políticas.

Error 5: Arranque sin intervención habilitado con claves almacenadas localmente, luego declarado “seguro”

Síntoma: revisión de cumplimiento pregunta “¿quién puede desbloquear los datos?” y la respuesta honesta es “cualquiera con root en el host”, que no es lo que la dirección creía.

Solución: alinea el modelo de amenazas. Si necesitas protección contra compromiso del host, las claves locales no sirven. Mueve la recuperación fuera del host y reduce quién puede acceder a las rutas de recuperación.

Error 6: Confundir fallos de importación del pool con fallos de clave

Síntoma: ingenieros ejecutan repetidamente zfs load-key pero el pool no está importado o está en solo lectura debido a errores.

Solución: comienza con zpool status y zpool import. Deja el pool sano/importado primero; después desbloquea.

Error 7: Olvidar snapshots y acceso de replicación

Síntoma: el sistema de backup recibe datasets encriptados pero no puede montarlos para verificación; o montar para verificar filtra texto plano en entornos que no planeabas.

Solución: decide si el destino de respaldo puede desencriptar. Si sí, gestiona claves allí. Si no, verifica mediante checksums o metadatos y mantenlo bloqueado por defecto.

Listas de verificación / plan paso a paso

Lista 1: Decisiones de diseño (antes de teclear comandos)

  1. Documenta tu modelo de amenazas: ¿discos robados? ¿admin malicioso? ¿host comprometido? ¿casilla de cumplimiento?
  2. Decide la política de arranque sin intervención por clase de sistema (nodos DB vs archivado vs portátiles).
  3. Elige la granularidad de claves: raíz de encriptación única vs por dominio vs por dataset.
  4. Define depósito/romper-cristal: quién puede desbloquear, cómo y dónde viven los secretos cuando el sistema primario está abajo.
  5. Define la cadencia de rotación y qué significa “rotación completa” (pista: import/unlock probado).

Lista 2: Construir una jerarquía de datasets encriptados de forma segura

  1. Crea un dataset raíz de encriptación para un dominio (por ejemplo, pool/data).
  2. Configura datasets hijos para heredar claves salvo que exista una separación justificada.
  3. Documenta las raíces de encriptación y keylocations en tu repositorio de infraestructura (no en la cabeza de alguien).
  4. Realiza un simulacro export/import (Tarea 15) antes del corte a producción.

Lista 3: Runbook operativo para reinicio y recuperación

  1. Importa pools sin montar: zpool import -N.
  2. Carga claves: zfs load-key -a.
  3. Montar: zfs mount -a.
  4. Verifica que los datasets críticos estén montados y las claves disponibles.
  5. Comprueba la salud de las aplicaciones solo después de confirmar el almacenamiento.

Lista 4: Rotación de claves paso a paso (versión segura)

  1. Anuncia ventana de mantenimiento e identifica radio de impacto (raíces de encriptación afectadas).
  2. Genera nuevo material de clave (política de frases o bytes de archivo).
  3. Despliega material de clave a todos los nodos relevantes (o sistema de recuperación), pero no borres el material antiguo todavía.
  4. Cambia la clave: zfs change-key en las raíces de encriptación.
  5. Realiza prueba controlada export/import en un host canario.
  6. Sólo después de un reboot/import exitoso: elimina material antiguo de ubicaciones activas, conserva depósito según política.

Preguntas frecuentes

1) Si encripto un dataset padre, ¿los hijos se encriptan automáticamente?

Si los hijos se crean bajo un dataset encriptado, normalmente heredarán la encriptación. Pero la herencia puede desviarse si alguien establece propiedades localmente o crea datasets en lugares inesperados. Confirma con zfs get -r encryption,encryptionroot.

2) ¿zfs change-key re-encripta todos mis datos?

No, por lo general reenvuelve material de clave (rápido). Aun así es operacionalmente riesgoso porque puedes quedarte fuera si manejas mal keylocation o el depósito. Trata esto como un cambio que necesita pruebas.

3) ¿Cuál es la diferencia entre keyformat=passphrase y keyformat=raw?

passphrase deriva material de clave de un secreto ingresado por un humano. raw espera bytes de clave reales (a menudo almacenados en un archivo). Raw es amigable para automatización y puede tener alta entropía, pero aumenta la importancia de proteger el archivo de clave.

4) ¿Puedo desbloquear un dataset sin montarlo?

Sí. zfs load-key desbloquea (carga la clave en memoria); montar es separado. Esto es útil para recuperación controlada y para evitar montar en el entorno equivocado.

5) Si un dataset está encriptado, ¿el pool en sí está encriptado?

La encriptación ZFS es a nivel de dataset. Un pool puede contener datasets encriptados y no encriptados. Tus auditorías deben revisar la jerarquía de datasets, no asumir “el pool está encriptado”.

6) ¿Puedo replicar datasets encriptados a un sitio de respaldo y mantenerlos encriptados de extremo a extremo?

Sí, con sends raw (p. ej., zfs send -w). Pero entonces debes asegurar que el sitio de respaldo tenga una forma independiente y probada de desbloquear—o mantenerlo bloqueado intencionalmente y aceptar métodos de verificación distintos.

7) ¿Por qué mi sistema arrancó pero los servicios fallaron, aunque el pool se importó bien?

Comúnmente: el pool se importó, pero las claves no se cargaron, así que los datasets encriptados no montaron. Comprueba zfs list -o name,keystatus,mounted y los logs del sistema para fallos de zfs-load-key.

8) ¿Es seguro almacenar archivos de clave en el disco del SO?

Depende de tu modelo de amenazas. Es conveniente operativamente y protege contra discos de datos robados, pero no protege contra un atacante con root en el host. Si necesitas garantías más fuertes, usa recuperación fuera del host y controles de acceso más estrictos.

9) ¿Cómo demuestro a los auditores (y a mí mismo) que la recuperación funciona?

Realizando un simulacro de import/unlock/mount en un sistema limpio, usando solo procedimientos documentados y secretos en depósito. Guarda la salida de zfs get y los pasos que seguiste. Repite con periodicidad.

Conclusión: lo aburrido vence a lo heroico

La encriptación ZFS es buena ingeniería. Pero la jugada ganadora no es habilitarla: es operacionalizarla. Tu yo futuro no quiere una configuración ingeniosa; quiere una configuración que sobreviva reinicios, restauraciones, cambios de personal y el incómodo momento en que tu sistema “seguro” es inaccesible porque la clave estaba guardada en algún lugar… seguro.

Si te llevas solo un hábito de esto: ejecuta el simulacro export/import + load-key antes de que lo necesites. El Día del Desastre no le importa que el diseño se viera limpio en un diagrama. Le importa si la persona de guardia puede desbloquear los datos sin adivinar.

← Anterior
Ubuntu 24.04: SSH funcionaba ayer, ahora “Permiso denegado” — soluciona las 5 causas más comunes
Siguiente →
Formato de registros SPF: comillas y espacios que silenciosamente rompen el correo

Deja un comentario