sql >> Base de Datos >  >> RDS >> MariaDB

Cifrado completo de MariaDB en reposo y en tránsito para una máxima protección de datos:segunda parte

En la primera parte de esta serie, hemos cubierto la configuración de cifrado en tránsito para servidores de replicación MariaDB, donde configuramos cifrados cliente-servidor y de replicación. Tomado de la primera publicación, donde habíamos configurado parcialmente nuestro cifrado completo (como lo indican las flechas verdes a la izquierda en el diagrama) y en esta publicación de blog, vamos a completar la configuración de cifrado con cifrado en reposo para crear un configuración de replicación de MariaDB totalmente encriptada.

El siguiente diagrama ilustra nuestra configuración actual y la configuración final que vamos a lograr:

Cifrado en reposo

El cifrado en reposo significa que los datos en reposo, como los archivos de datos y los registros, están cifrados en el disco, lo que hace que sea casi imposible que alguien acceda o robe un disco duro y obtenga acceso a los datos originales. (siempre que la clave esté protegida y no almacenada localmente). El cifrado de datos en reposo, también conocido como cifrado de datos transparente (TDE), es compatible con MariaDB 10.1 y versiones posteriores. Tenga en cuenta que el uso del cifrado tiene una sobrecarga de aproximadamente el 5-10 %, según la carga de trabajo y el tipo de clúster.

Para MariaDB, los siguientes componentes de MariaDB se pueden cifrar en reposo:

  • Archivo de datos InnoDB (tablespace compartido o tablespace individual, p. ej., *.ibd e ibdata1)
  • Archivos de datos e índices de Aria.
  • Registros de deshacer/rehacer (archivos de registro de InnoDB, por ejemplo, ib_logfile0 e ib_logfile1).
  • Registros binarios/de retransmisión.
  • Archivos y tablas temporales.

Los siguientes archivos no se pueden cifrar en este momento:

  • Archivo de metadatos (por ejemplo, archivos .frm).
  • Registro general basado en archivos/registro de consultas lentas. El registro general basado en tablas/el registro de consultas lentas se puede cifrar.
  • Registro de errores.

El cifrado de datos en reposo de MariaDB requiere el uso de complementos de cifrado y administración de claves. En esta publicación de blog, vamos a utilizar el complemento de cifrado de gestión de claves de archivo, que se proporciona de forma predeterminada desde MariaDB 10.1.3. Tenga en cuenta que hay una serie de inconvenientes al usar este complemento, por ejemplo, la clave aún puede ser leída por el usuario root y MySQL, como se explica en la página Cifrado de datos en reposo de MariaDB.

Generando Archivo Clave

Vamos a crear un directorio dedicado para almacenar nuestro material de cifrado en reposo:

$ mkdir -p /etc/mysql/rest
$ cd /etc/mysql/rest

Cree un archivo de claves. Este es el núcleo del cifrado:

$ openssl rand -hex 32 > /etc/mysql/rest/keyfile

Agregue una cadena "1;" como identificador de clave en el archivo de claves:

$ echo '1;' 
sed -i '1s/^/1;/' /etc/mysql/rest/keyfile

Por lo tanto, al leer el archivo de claves, debería verse así:

$ cat /etc/mysql/rest/keyfile
1;4eb5770dcfa691bc634cbcd3c6bed9ed4ccd0111f3d3b1dae2c51a90fbf16ed7

Lo anterior simplemente significa que para el identificador de clave 1, la clave es 4eb... El archivo de clave debe contener dos piezas de información para cada clave de cifrado. En primer lugar, cada clave de cifrado debe identificarse con un número entero de 32 bits como identificador de clave. En segundo lugar, la clave de cifrado en sí debe proporcionarse en formato hexadecimal. Estas dos piezas de información deben estar separadas por un punto y coma.

Cree una contraseña para cifrar la clave anterior. Aquí vamos a almacenar la contraseña dentro de un archivo llamado "keyfile.passwd":

$ echo -n 'mySuperStrongPassword' > /etc/mysql/rest/keyfile.passwd

Puede omitir el paso anterior si desea especificar la contraseña directamente en el archivo de configuración usando la opción file_key_management_filekey. Por ejemplo:file_key_management_filekey=mySuperStrongPassword

Pero en este ejemplo, vamos a leer la contraseña que está almacenada en un archivo, por lo que tenemos que definir la siguiente línea en el archivo de configuración más adelante: 

file_key_management_filekey=FILE:/etc/mysql/encryption/keyfile.passwd

Vamos a cifrar el archivo de claves de texto claro en otro archivo llamado keyfile.enc, usando la contraseña dentro del archivo de contraseñas:

$  openssl enc -aes-256-cbc -md sha1 -pass file:/etc/mysql/rest/keyfile.passwd -in /etc/mysql/rest/keyfile -out /etc/mysql/rest/keyfile.enc

Al enumerar el directorio, deberíamos ver estos 3 archivos:

$ ls -1 /etc/mysql/rest/
keyfile
keyfile.enc
keyfile.passwd

El contenido de keyfile.enc es simplemente una versión encriptada de keyfile:

Para probar, podemos descifrar el archivo cifrado usando OpenSSL proporcionando el archivo de contraseña (keyfile.passwd):

$ openssl aes-256-cbc -d -md sha1 -pass file:/etc/mysql/rest/keyfile.passwd -in /etc/mysql/rest/keyfile.enc
1;4eb5770dcfa691bc634cbcd3c6bed9ed4ccd0111f3d3b1dae2c51a90fbf16ed7

Entonces podemos eliminar la clave simple porque vamos a usar la cifrada (.enc) junto con el archivo de contraseña:

$ rm -f /etc/mysql/encryption/keyfile

Ahora podemos proceder a configurar el cifrado en reposo de MariaDB.

Configuración del cifrado en reposo

Tenemos que mover el archivo de clave cifrada y la contraseña a los esclavos para que MariaDB los utilice para cifrar/descifrar los datos. De lo contrario, los esclavos tendrían problemas para leer una tabla cifrada que se está respaldando desde el maestro usando una copia de seguridad física como MariaDB Backup (debido a la combinación diferente de clave/contraseña). La copia de seguridad lógica como mysqldump debería funcionar con diferentes claves y contraseñas.

En los esclavos, cree un directorio para almacenar cosas de cifrado en reposo:

(slave1)$ mkdir -p /etc/mysql/rest
(slave2)$ mkdir -p /etc/mysql/rest

En el maestro, copie el archivo de clave y el archivo de contraseña encriptados a los otros esclavos:

(master)$ cd /etc/mysql/rest
(master)$ scp keyfile.enc keyfile.passwd [email protected]:/etc/mysql/rest/
(master)$ scp keyfile.enc keyfile.passwd [email protected]:/etc/mysql/rest/

Proteja los archivos del acceso global y asigne el usuario "mysql" como propietario:

$ chown mysql:mysql /etc/mysql/rest/*
$ chmod 600 /etc/mysql/rest/*

Agregue lo siguiente en el archivo de configuración de MariaDB en la sección [mysqld] o [mariadb]:

# at-rest encryption
plugin_load_add              = file_key_management
file_key_management_filename = /etc/mysql/rest/keyfile.enc
file_key_management_filekey  = FILE:/etc/mysql/rest/keyfile.passwd
file_key_management_encryption_algorithm = AES_CBC

innodb_encrypt_tables            = ON
innodb_encrypt_temporary_tables  = ON
innodb_encrypt_log               = ON
innodb_encryption_threads        = 4
innodb_encryption_rotate_key_age = 1
encrypt-tmp-disk-tables          = 1
encrypt-tmp-files                = 1
encrypt-binlog                   = 1
aria_encrypt_tables              = ON

Tome nota de la variable file_key_management_filekey, si la contraseña está en un archivo, debe prefijar la ruta con "ARCHIVO:". Como alternativa, también puede especificar la cadena de la contraseña directamente (no se recomienda debido a su verbosidad): 

file_key_management_filekey=mySuperStrongPassword

Reinicie el servidor MariaDB un nodo a la vez, comenzando con los esclavos:

(slave1)$ systemctl restart mariadb
(slave2)$ systemctl restart mariadb
(master)$ systemctl restart mariadb

Observe el registro de errores y asegúrese de que el cifrado de MariaDB esté activado durante el inicio:

$ tail -f /var/log/mysql/mysqld.log
...
2019-12-17  6:44:47 0 [Note] InnoDB: Encrypting redo log: 2*67108864 bytes; LSN=143311
2019-12-17  6:44:48 0 [Note] InnoDB: Starting to delete and rewrite log files.
2019-12-17  6:44:48 0 [Note] InnoDB: Setting log file ./ib_logfile101 size to 67108864 bytes
2019-12-17  6:44:48 0 [Note] InnoDB: Setting log file ./ib_logfile1 size to 67108864 bytes
2019-12-17  6:44:48 0 [Note] InnoDB: Renaming log file ./ib_logfile101 to ./ib_logfile0
2019-12-17  6:44:48 0 [Note] InnoDB: New log files created, LSN=143311
2019-12-17  6:44:48 0 [Note] InnoDB: 128 out of 128 rollback segments are active.
2019-12-17  6:44:48 0 [Note] InnoDB: Creating shared tablespace for temporary tables
2019-12-17  6:44:48 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
2019-12-17  6:44:48 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
2019-12-17  6:44:48 0 [Note] InnoDB: Waiting for purge to start
2019-12-17  6:44:48 0 [Note] InnoDB: 10.4.11 started; log sequence number 143311; transaction id 222
2019-12-17  6:44:48 0 [Note] InnoDB: Creating #1 encryption thread id 139790011840256 total threads 4.
2019-12-17  6:44:48 0 [Note] InnoDB: Creating #2 encryption thread id 139790003447552 total threads 4.
2019-12-17  6:44:48 0 [Note] InnoDB: Creating #3 encryption thread id 139789995054848 total threads 4.
2019-12-17  6:44:48 0 [Note] InnoDB: Creating #4 encryption thread id 139789709866752 total threads 4.
2019-12-17  6:44:48 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
2019-12-17  6:44:48 0 [Note] Plugin 'FEEDBACK' is disabled.
2019-12-17  6:44:48 0 [Note] Using encryption key id 1 for temporary files
...

Debería ver líneas que indican la inicialización del cifrado en el registro de errores. En este punto, la mayor parte de la configuración de cifrado ya está completa.

Prueba de su cifrado

Cree una base de datos de prueba para probar en el maestro:

(master)MariaDB> CREATE SCHEMA sbtest;
(master)MariaDB> USE sbtest;

Cree una tabla estándar sin encriptación e inserte una fila:

MariaDB> CREATE TABLE tbl_plain (id INT AUTO_INCREMENT PRIMARY KEY, data VARCHAR(255));
MariaDB> INSERT INTO tbl_plain SET data = 'test data';

Podemos ver los datos almacenados en texto claro cuando navegamos por el archivo de datos de InnoDB usando una herramienta de volcado hexadecimal:

$ xxd /var/lib/mysql/sbtest/tbl_plain.ibd | less
000c060: 0200 1c69 6e66 696d 756d 0002 000b 0000  ...infimum......
000c070: 7375 7072 656d 756d 0900 0000 10ff f180  supremum........
000c080: 0000 0100 0000 0000 0080 0000 0000 0000  ................
000c090: 7465 7374 2064 6174 6100 0000 0000 0000  test data.......
000c0a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................

Cree una tabla cifrada e inserte una fila:

MariaDB> CREATE TABLE tbl_enc (id INT AUTO_INCREMENT PRIMARY KEY, data VARCHAR(255)) ENCRYPTED=YES;
MariaDB> INSERT INTO tbl_enc SET data = 'test data';

No podemos saber qué está almacenado en el archivo de datos InnoDB para tablas cifradas:

$ xxd /var/lib/mysql/sbtest/tbl_enc.ibd | less
000c060: 0c2c 93e4 652e 9736 e68a 8b69 39cb 6157  .,..e..6...i9.aW
000c070: 3cd1 581c 7eb9 84ca d792 7338 521f 0639  <.X.~.....s8R..9
000c080: d279 9eb3 d3f5 f9b0 eccb ed05 de16 f3ac  .y..............
000c090: 6d58 5519 f776 8577 03a4 fa88 c507 1b31  mXU..v.w.......1
000c0a0: a06f 086f 28d9 ac17 8923 9412 d8a5 1215  .o.o(....#......

Tenga en cuenta que el archivo de metadatos tbl_enc.frm no está cifrado en reposo. Solo se cifra el archivo de datos de InnoDB (.ibd).

Al comparar los registros binarios o de retransmisión "simples", podemos ver claramente su contenido usando la herramienta hexdump:

$ xxd binlog.000002 | less
0000560: 0800 0800 0800 0b04 726f 6f74 096c 6f63  ........root.loc
0000570: 616c 686f 7374 0047 5241 4e54 2052 454c  alhost.GRANT REL
0000580: 4f41 442c 4c4f 434b 2054 4142 4c45 532c  OAD,LOCK TABLES,
0000590: 5245 504c 4943 4154 494f 4e20 434c 4945  REPLICATION CLIE
00005a0: 4e54 2c45 5645 4e54 2c43 5245 4154 4520  NT,EVENT,CREATE
00005b0: 5441 424c 4553 5041 4345 2c50 524f 4345  TABLESPACE,PROCE
00005c0: 5353 2c43 5245 4154 452c 494e 5345 5254  SS,CREATE,INSERT
00005d0: 2c53 454c 4543 542c 5355 5045 522c 5348  ,SELECT,SUPER,SH
00005e0: 4f57 2056 4945 5720 4f4e 202a 2e2a 2054  OW VIEW ON *.* T

Mientras que para un registro binario encriptado, el contenido parece un galimatías:

$ xxd binlog.000004 | less
0000280: 4a1d 1ced 2f1b db50 016a e1e9 1351 84ba  J.../..P.j...Q..
0000290: 38b6 72e7 8743 7713 afc3 eecb c36c 1b19  8.r..Cw......l..
00002a0: 7b3f 6176 208f 0000 00dc 85bf 6768 e7c6  {?av .......gh..
00002b0: 6107 5bea 241c db12 d50c 3573 48e5 3c3d  a.[.$.....5sH.<=
00002c0: 3179 1653 2449 d408 1113 3e25 d165 c95b  1y.S$I....>%.e.[
00002d0: afb0 6778 4b26 f672 1bc7 567e da96 13f5  ..gxK&.r..V~....
00002e0: 2ac5 b026 3fb9 4b7a 3ef4 ab47 6c9f a686  *..&?.Kz>..Gl...

Cifrado de tablas Aria

Para el motor de almacenamiento Aria, no es compatible con la opción ENCRYPTED en la declaración CREATE/ALTER ya que sigue a la opción global aria_encrypt_tables. Por lo tanto, al crear una tabla Aria, simplemente cree la tabla con la opción ENGINE=Aria:

MariaDB> CREATE TABLE tbl_aria_enc (id INT AUTO_INCREMENT PRIMARY KEY, data VARCHAR(255)) ENGINE=Aria;
MariaDB> INSERT INTO tbl_aria_enc(data) VALUES ('test data');
MariaDB> FLUSH TABLE tbl_aria_enc;

Luego podemos verificar el contenido del archivo de datos de la tabla (tbl_aria_enc.MAD) o el archivo de índice (tbl_aria_enc.MAI) con la herramienta hexdump. Para cifrar una tabla Aria existente, la tabla debe reconstruirse:

MariaDB> ALTER TABLE db.aria_table ENGINE=Aria ROW_FORMAT=PAGE;

Esta declaración hace que Aria reconstruya la tabla usando la opción de tabla ROW_FORMAT. En el proceso, con la nueva configuración predeterminada, cifra la tabla cuando escribe en el disco.

Registro general de cifrado/Registro de consultas lentas

Para cifrar los registros de consultas generales y lentos, podemos configurar la opción log_output de MariaDB en 'TABLA' en lugar del 'ARCHIVO' predeterminado:

MariaDB> SET GLOBAL log_ouput = 'TABLE';

Sin embargo, MariaDB creará de forma predeterminada las tablas necesarias utilizando el motor de almacenamiento CSV, que MariaDB no cifra. Ningún motor que no sea CSV, MyISAM o Aria es legal para las tablas de registro. El truco consiste en reconstruir la tabla CSV predeterminada con el motor de almacenamiento Aria, siempre que la opción aria_encrypt_tables esté activada. Sin embargo, la opción de registro correspondiente debe estar desactivada para que la modificación de la tabla tenga éxito.

Por lo tanto, los pasos para cifrar la tabla de registro general son:

MariaDB> SET GLOBAL general_log = OFF;
MariaDB> ALTER TABLE mysql.general_log ENGINE=Aria;
MariaDB> SET GLOBAL general_log = ON;

Del mismo modo, para el registro de consultas lentas:

MariaDB> SET GLOBAL slow_query_log = OFF;
MariaDB> ALTER TABLE mysql.slow_log ENGINE=Aria;
MariaDB> SET GLOBAL slow_query_log = ON;

Verifique la salida de registros generales dentro del servidor:

MariaDB> SELECT * FROM mysql.general_log;
+----------------------------+---------------------------+-----------+-----------+--------------+------------------------------+
| event_time                 | user_host                 | thread_id | server_id | command_type | argument                     |
+----------------------------+---------------------------+-----------+-----------+--------------+------------------------------+
| 2019-12-17 07:45:53.109558 | root[root] @ localhost [] |        19 |     28001 |        Query | select * from sbtest.tbl_enc |
| 2019-12-17 07:45:55.504710 | root[root] @ localhost [] |        20 |     28001 |        Query | select * from general_log    |
+----------------------------+---------------------------+-----------+-----------+--------------+------------------------------+

Además del contenido encriptado del archivo de datos de Aria dentro del directorio de datos usando la herramienta hexdump:

$ xxd /var/lib/mysql/mysql/general_log.MAD | less
0002040: 1d45 820d 7c53 216c 3fc6 98a6 356e 1b9e  .E..|S!l?...5n..
0002050: 6bfc e193 7509 1fa7 31e2 e22a 8f06 3c6f  k...u...1..*..<o
0002060: ae71 bb63 e81b 0b08 7120 0c99 9f82 7c33  .q.c....q ....|3
0002070: 1117 bc02 30c1 d9a7 c732 c75f 32a6 e238  ....0....2._2..8
0002080: d1c8 5d6f 9a08 455a 8363 b4f4 5176 f8a1  ..]o..EZ.c..Qv..
0002090: 1bf8 113c 9762 3504 737e 917b f260 f88c  ...<.b5.s~.{.`..
00020a0: 368e 336f 9055 f645 b636 c5c1 debe fbe7  6.3o.U.E.6......
00020b0: d01e 028f 8b75 b368 0ef0 8889 bb63 e032  .....u.h.....c.2

El cifrado en reposo de MariaDB ahora está completo. Combine esto con el cifrado en tránsito que hicimos en la primera publicación, nuestra arquitectura final ahora se ve así:

Conclusión

Ahora es posible proteger totalmente sus bases de datos MariaDB a través del cifrado para protegerlas contra violaciones o robos físicos y virtuales. ClusterControl también puede ayudarlo a mantener este tipo de seguridad y puede descargarlo gratis aquí.