Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Introduction to InnoDB's encryption architecture, explaining how data is encrypted/decrypted during disk I/O, the role of the buffer pool (where data is unencrypted), and how to verify encryption stat
[mariadb]
...
# File Key Management
plugin_load_add = file_key_management
file_key_management_filename = /etc/mysql/encryption/keyfile.enc
file_key_management_filekey = FILE:/etc/mysql/encryption/keyfile.key
file_key_management_encryption_algorithm = AES_CTR
# InnoDB Encryption
innodb_encrypt_tables = ON
innodb_encrypt_temporary_tables = ON
innodb_encrypt_log = ON
innodb_encryption_threads = 4
innodb_encryption_rotate_key_age = 1CREATE TABLE t (i INT PRIMARY KEY) ENGINE=InnoDB ENCRYPTED=YES ENCRYPTION_KEY_ID=2;SELECT st.SPACE, st.NAME, te.ENCRYPTION_SCHEME, te.ROTATING_OR_FLUSHING
FROM information_schema.INNODB_TABLESPACES_ENCRYPTION te
JOIN information_schema.INNODB_SYS_TABLES st
ON te.SPACE = st.SPACE \G
*************************** 1. row ***************************
SPACE: 0
NAME: SYS_DATAFILES
ENCRYPTION_SCHEME: 1
ROTATING_OR_FLUSHING: 0
*************************** 2. row ***************************
SPACE: 0
NAME: SYS_FOREIGN
ENCRYPTION_SCHEME: 1
ROTATING_OR_FLUSHING: 0
*************************** 3. row ***************************
SPACE: 0
NAME: SYS_FOREIGN_COLS
ENCRYPTION_SCHEME: 1
ROTATING_OR_FLUSHING: 0
*************************** 4. row ***************************
SPACE: 0
NAME: SYS_TABLESPACES
ENCRYPTION_SCHEME: 1
ROTATING_OR_FLUSHING: 0
*************************** 5. row ***************************
SPACE: 0
NAME: SYS_VIRTUAL
ENCRYPTION_SCHEME: 1
ROTATING_OR_FLUSHING: 0
*************************** 6. row ***************************
SPACE: 0
NAME: db1/default_encrypted_tab1
ENCRYPTION_SCHEME: 1
ROTATING_OR_FLUSHING: 0
*************************** 7. row ***************************
SPACE: 416
NAME: db1/default_encrypted_tab2
ENCRYPTION_SCHEME: 1
ROTATING_OR_FLUSHING: 0
*************************** 8. row ***************************
SPACE: 402
NAME: db1/tab
ENCRYPTION_SCHEME: 1
ROTATING_OR_FLUSHING: 0
*************************** 9. row ***************************
SPACE: 185
NAME: db1/tab1
ENCRYPTION_SCHEME: 1
ROTATING_OR_FLUSHING: 0
*************************** 10. row ***************************
SPACE: 184
NAME: db1/tab2
ENCRYPTION_SCHEME: 1
ROTATING_OR_FLUSHING: 0
*************************** 11. row ***************************
SPACE: 414
NAME: db1/testgb2
ENCRYPTION_SCHEME: 1
ROTATING_OR_FLUSHING: 0
*************************** 12. row ***************************
SPACE: 4
NAME: mysql/gtid_slave_pos
ENCRYPTION_SCHEME: 1
ROTATING_OR_FLUSHING: 0
*************************** 13. row ***************************
SPACE: 2
NAME: mysql/innodb_index_stats
ENCRYPTION_SCHEME: 1
ROTATING_OR_FLUSHING: 0
*************************** 14. row ***************************
SPACE: 1
NAME: mysql/innodb_table_stats
ENCRYPTION_SCHEME: 1
ROTATING_OR_FLUSHING: 0
*************************** 15. row ***************************
SPACE: 3
NAME: mysql/transaction_registry
ENCRYPTION_SCHEME: 1
ROTATING_OR_FLUSHING: 0
15 rows in set (0.000 sec)Solutions for common issues such as Error 1005 (Wrong create options) when configuring encryption, and handling cases where encryption key IDs are set for unencrypted tables.
CREATE TABLE `test`.`table1` ( `id` INT(4) PRIMARY KEY , `name` VARCHAR(50));
ERROR 1005 (HY000): Can't create table `test`.`table1` (errno: 140 "Wrong create options")SHOW WARNINGS;
+---------+------+---------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------------------------+
| Warning | 140 | InnoDB: ENCRYPTED requires innodb_file_per_table |
| Error | 1005 | Can't create table `db1`.`tab3` (errno: 140 "Wrong create options") |
| Warning | 1030 | Got error 140 "Wrong create options" from storage engine InnoDB |
+---------+------+---------------------------------------------------------------------+
3 rows in set (0.00 sec)SHOW WARNINGS;
+---------+------+---------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------------------------+
| Warning | 140 | InnoDB: ENCRYPTION_KEY_ID 500 not available |
| Error | 1005 | Can't create table `db1`.`tab3` (errno: 140 "Wrong create options") |
| Warning | 1030 | Got error 140 "Wrong create options" from storage engine InnoDB |
+---------+------+---------------------------------------------------------------------+
3 rows in set (0.00 sec)SHOW WARNINGS;
+---------+------+---------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------------------------+
| Warning | 140 | InnoDB: innodb_encrypt_tables=OFF only allows ENCRYPTION_KEY_ID=1 |
| Error | 1005 | Can't create table `db1`.`tab3` (errno: 140 "Wrong create options") |
| Warning | 1030 | Got error 140 "Wrong create options" from storage engine InnoDB |
+---------+------+---------------------------------------------------------------------+
3 rows in set (0.00 sec)SET GLOBAL innodb_encrypt_tables=OFF;
CREATE TABLE tab1 (
id INT PRIMARY KEY,
str VARCHAR(50)
) ENCRYPTION_KEY_ID=100;
SET GLOBAL innodb_encrypt_tables=ON;
SELECT NAME, ENCRYPTION_SCHEME, CURRENT_KEY_ID
FROM information_schema.INNODB_TABLESPACES_ENCRYPTION
WHERE NAME='db1/tab1';
+----------+-------------------+----------------+
| NAME | ENCRYPTION_SCHEME | CURRENT_KEY_ID |
+----------+-------------------+----------------+
| db1/tab1 | 1 | 1 |
+----------+-------------------+----------------+CREATE TABLE tab1 (
id INT PRIMARY KEY,
str VARCHAR(50)
) ENCRYPTED=NO ENCRYPTION_KEY_ID=100;
Query OK, 0 rows affected, 1 warning (0.01 sec)
SHOW WARNINGS;
+---------+------+--------------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------------+
| Warning | 140 | InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 |
+---------+------+--------------------------------------------------+
1 row in set (0.00 sec)SET GLOBAL innodb_encrypt_tables=ON;
ALTER TABLE tab1 ENCRYPTED=DEFAULT;
SELECT NAME, ENCRYPTION_SCHEME, CURRENT_KEY_ID
FROM information_schema.INNODB_TABLESPACES_ENCRYPTION
WHERE NAME = 'db1/tab1';
+----------+-------------------+----------------+
| NAME | ENCRYPTION_SCHEME | CURRENT_KEY_ID |
+----------+-------------------+----------------+
| db1/tab1 | 1 | 100 |
+----------+-------------------+----------------+SHOW ENGINE INNODB STATUSSET GLOBAL innodb_encryption_rotate_key_age=0;SET GLOBAL innodb_encryption_threads=2;SET GLOBAL innodb_encryption_rotation_iops=50;Secure MariaDB Server data at rest with encryption. This section details how to protect your sensitive information stored on disk, ensuring data confidentiality and compliance.
[mariadb]
# File Key Management
plugin_load_add = file_key_management
file_key_management_filename = /etc/mysql/encryption/keyfile.enc
file_key_management_filekey = FILE:/etc/mysql/encryption/keyfile.key
file_key_management_encryption_algorithm = AES_CTR
# Aria Encryption
aria_encrypt_tables=ON
encrypt_tmp_disk_tables=ONSELECT * FROM db1.aria_tab LIMIT 1;
+----+------+
| id | str |
+----+------+
| 1 | str1 |
+----+------+
1 row IN SET (0.00 sec$ sudo strings /var/lib/mysql/db1/aria_tab.MAD | grep "str1"
str1Learn about InnoDB encryption for data at rest. This section details how to encrypt InnoDB tablespaces, ensuring strong data security and compliance for your mission-critical applications.
Learn about Aria encryption in MariaDB Server for data at rest. This section details how to encrypt Aria tablespaces, providing enhanced security for your stored data.
Final step of removing key management plugins from the configuration once all data and logs have been confirmed as unencrypted.
# Comment out or remove the following lines
plugin_load_add = file_key_management
file_key_management_filename = /etc/mysql/encryption/keyfileSHOW PLUGINS;Step-by-step guide to enabling encryption for user-created and internal temporary Aria tables, including the requirement to manually rebuild existing tables using ALTER TABLE.
SET GLOBAL aria_encrypt_tables=ONSET GLOBAL aria_encrypt_tables=ONSELECT TABLE_SCHEMA, TABLE_NAME
FROM information_schema.TABLES
WHERE ENGINE='Aria'
AND ROW_FORMAT='PAGE'
AND TABLE_SCHEMA != 'information_schema';ALTER TABLE aria_table ENGINE=Aria ROW_FORMAT=PAGE;mariadb-binlog require the --read-from-remote-server flag to read encrypted content.[mariadb]
plugin_load_add = file_key_management
file_key_management_filename = /etc/mysql/encryption/keyfile.txt
# The following line is optional but highly recommended.
# Uncomment it to enable usage of an encrypted key file.
# file_key_management_filekey = FILE:/etc/mysql/encryption/keyfile.key
file_key_management_encryption_algorithm = AES_CTRSELECT
'InnoDB Tables' AS Component, @@innodb_encrypt_tables AS Active
UNION SELECT 'InnoDB Logs', @@innodb_encrypt_log
UNION SELECT 'InnoDB Temp', @@innodb_encrypt_temporary_tables
UNION SELECT 'Aria System', @@aria_encrypt_tables
UNION SELECT 'Aria Temp', @@encrypt_tmp_disk_tables;+---------------+--------+
| Component | Active |
+---------------+--------+
| InnoDB Tables | ON |
| InnoDB Logs | 1 |
| InnoDB Temp | 1 |
| Aria System | 1 |
| Aria Temp | 1 |
+---------------+--------+SELECT NAME, ENCRYPTION_SCHEME, ROTATING_OR_FLUSHING
FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION
WHERE ENCRYPTION_SCHEME != 0;UNINSTALL SONAME 'file_key_management';[mariadb]
# Remove or comment out the following line
plugin_load_add = file_key_managementmkdir -p /etc/mysql/encryption
echo $(echo -n "1;1;" ; openssl rand -hex 32) | sudo tee -a /etc/mysql/encryption/keyfile.txtSET GLOBAL innodb_encrypt_tables = OFF; -- InnoDB tables
SET GLOBAL aria_encrypt_tables = OFF; -- Aria tables
SET GLOBAL encrypt_tmp_disk_tables = OFF; -- Aria temporary tables-- Create an InnoDB table
CREATE TABLE sensitive_accounts_innodb (
id INT PRIMARY KEY,
account_name VARCHAR(100)
) ENGINE=InnoDB;
-- Create an Aria table
-- Note that the ROW_FORMAT must be PAGE; otherwise, encryption isn't possible
CREATE TABLE sensitive_accounts_aria (
id INT PRIMARY KEY,
account_name VARCHAR(100)
) ENGINE=Aria ROW_FORMAT=PAGE;SELECT NAME, ENCRYPTION_SCHEME
FROM information_schema.INNODB_TABLESPACES_ENCRYPTION
WHERE NAME LIKE '%sensitive_accounts_innodb%';+--------------------------------+-------------------+
| NAME | ENCRYPTION_SCHEME |
+--------------------------------+-------------------+
| test/sensitive_accounts_innodb | 1 |
+--------------------------------+-------------------+sudo cat /var/lib/mysql/test/sensitive_accounts_aria.MAD | more-- Standard inserts work for both
INSERT INTO sensitive_accounts_innodb VALUES (1, 'Customer InnoDB');
INSERT INTO sensitive_accounts_aria VALUES (1, 'Customer Aria');
-- Standard selects return plain text
SELECT * FROM sensitive_accounts_innodb;
SELECT * FROM sensitive_accounts_aria;-- Disable encryption for the InnoDB table
ALTER TABLE sensitive_accounts_innodb ENCRYPTED=NO;
SELECT NAME, ENCRYPTION_SCHEME FROM information_schema.INNODB_TABLESPACES_ENCRYPTION
WHERE NAME LIKE '%sensitive_accounts_innodb%';
+--------------------------------+-------------------+
| NAME | ENCRYPTION_SCHEME |
+--------------------------------+-------------------+
| test/sensitive_accounts_innodb | 0 |
+--------------------------------+-------------------+
-- Disable encryption for the Aria table
-- This is only possible after disabling global Aria encryption
ALTER TABLE sensitive_accounts_aria ENGINE=Aria, ALGORITHM=COPY;ALTER TABLE sensitive_accounts_innodb ENCRYPTED=YES;
SELECT NAME, ENCRYPTION_SCHEME FROM information_schema.INNODB_TABLESPACES_ENCRYPTION
WHERE NAME LIKE '%sensitive_accounts_innodb%';
+--------------------------------+-------------------+
| NAME | ENCRYPTION_SCHEME |
+--------------------------------+-------------------+
| test/sensitive_accounts_innodb | 1 |
+--------------------------------+-------------------+mkdir -p /etc/mysql/encryption
echo $(echo -n "1;" ; openssl rand -hex 32) | sudo tee -a /etc/mysql/encryption/keyfile.txt[mariadb]
innodb_encrypt_tables = OFF
innodb_encrypt_log = OFF
innodb_encrypt_temporary_tables = OFF
aria_encrypt_tables = OFF
encrypt_tmp_disk_tables = OFF[mariadb]
# File Key Management
plugin_load_add = file_key_management
file_key_management_filename = /etc/mysql/encryption/keyfile.enc
file_key_management_filekey = FILE:/etc/mysql/encryption/keyfile.key
file_key_management_encryption_algorithm = AES_CTRExplore key management and encryption plugins for MariaDB Server. This section details how to manage encryption keys and leverage plugins for robust data-at-rest protection.
[mariadb]
encrypt_binlog = ONmariadb-binlog --read-from-remote-server --user=root -p binlog.000012 > decrypted.sqlmariadb-binlog /var/lib/mysql/binlog.000012 > decrypted.sql[mariadb]
encrypt_binlog = OFF[mariadb]
innodb_encrypt_tables = ON
innodb_encrypt_log = ON
encrypt_temporary_tables = ON
aria_encrypt_tables = ON
encrypt_tmp_disk_tables = ONSET GLOBAL innodb_encrypt_tables = ON; -- for InnoDB tables
SET GLOBAL aria_encrypt_tables = ON; -- for Aria tables
SET GLOBAL encrypt_tmp_disk_tables = ON; -- for Aria temporary tablesHow InnoDB manages encryption keys using 32-bit integer IDs, including the default key ID (innodb_default_encryption_key_id), assigning specific keys to tables, and the process of key rotation.
Overview of key management in MariaDB, discussing the need for plugins to manage encryption keys, support for multiple keys (ID 1 for system, ID 2 for temp), and key rotation capabilities.
CREATE TABLE tab1 (
id INT PRIMARY KEY,
str VARCHAR(50)
) ENCRYPTED=YES ENCRYPTION_KEY_ID=100;
SELECT NAME, ENCRYPTION_SCHEME, CURRENT_KEY_ID
FROM information_schema.INNODB_TABLESPACES_ENCRYPTION
WHERE NAME='db1/tab1';
+----------+-------------------+----------------+
| NAME | ENCRYPTION_SCHEME | CURRENT_KEY_ID |
+----------+-------------------+----------------+
| db1/tab1 | 1 | 100 |
+----------+-------------------+----------------+SET SESSION innodb_default_encryption_key_id=100;
CREATE TABLE tab1 (
id INT PRIMARY KEY,
str VARCHAR(50)
) ENCRYPTED=YES;
SELECT NAME, ENCRYPTION_SCHEME, CURRENT_KEY_ID
FROM information_schema.INNODB_TABLESPACES_ENCRYPTION
WHERE NAME='db1/tab1';
+----------+-------------------+----------------+
| NAME | ENCRYPTION_SCHEME | CURRENT_KEY_ID |
+----------+-------------------+----------------+
| db1/tab1 | 1 | 100 |
+----------+-------------------+----------------+SET GLOBAL innodb_encryption_threads=4;
SET GLOBAL innodb_encrypt_tables=ON;
SET SESSION innodb_default_encryption_key_id=100;
CREATE TABLE tab1 (
id INT PRIMARY KEY,
str VARCHAR(50)
);
SELECT NAME, ENCRYPTION_SCHEME, CURRENT_KEY_ID
FROM information_schema.INNODB_TABLESPACES_ENCRYPTION
WHERE NAME='db1/tab1';
+----------+-------------------+----------------+
| NAME | ENCRYPTION_SCHEME | CURRENT_KEY_ID |
+----------+-------------------+----------------+
| db1/tab1 | 1 | 100 |
+----------+-------------------+----------------+SET GLOBAL innodb_encryption_threads=4;
SET GLOBAL innodb_encrypt_tables=ON;
CREATE TABLE tab1 (
id INT PRIMARY KEY,
str VARCHAR(50)
) ENCRYPTION_KEY_ID=100;
SELECT NAME, ENCRYPTION_SCHEME, CURRENT_KEY_ID
-> FROM information_schema.INNODB_TABLESPACES_ENCRYPTION
-> WHERE NAME='db1/tab1';
+----------+-------------------+----------------+
| NAME | ENCRYPTION_SCHEME | CURRENT_KEY_ID |
+----------+-------------------+----------------+
| db1/tab1 | 1 | 100 |
+----------+-------------------+----------------+Step-by-step guide to enabling encryption for InnoDB, covering the configuration of innodb_encrypt_tables for automatic encryption and the use of ENCRYPTED=YES table options for per-table encryption.
Guide to using the HashiCorp Key Management plugin, which integrates MariaDB with HashiCorp Vault for centralized, secure key storage and lifecycle management.
hashicorp-key-management-vault-urlhashicorp-key-management-tokenhashicorp-key-management-vault-cahashicorp-key-management-timeouthashicorp-key-management-max-retrieshashicorp-key-management-caching-enabledhashicorp-key-management-use-cache-on-timeouthashicorp-key-management-cache-timeouthashicorp-key-management-cache-version-timeouthashicorp-key-management-check-kv-versionSET GLOBAL innodb_encryption_threads=4;
SET GLOBAL innodb_encrypt_tables=ON;
SET SESSION innodb_default_encryption_key_id=100;
CREATE TABLE tab1 (
id INT PRIMARY KEY,
str VARCHAR(50)
);
SELECT NAME, ENCRYPTION_SCHEME, CURRENT_KEY_ID
FROM information_schema.INNODB_TABLESPACES_ENCRYPTION
WHERE NAME='db1/tab1';
+----------+-------------------+----------------+
| NAME | ENCRYPTION_SCHEME | CURRENT_KEY_ID |
+----------+-------------------+----------------+
| db1/tab1 | 1 | 100 |
+----------+-------------------+----------------+SET GLOBAL innodb_encryption_threads=4;
SET GLOBAL innodb_encrypt_tables=ON;
SET SESSION innodb_default_encryption_key_id=100;
CREATE TABLE tab1 (
id INT PRIMARY KEY,
str VARCHAR(50)
) ENCRYPTED=NO;
SELECT NAME, ENCRYPTION_SCHEME, CURRENT_KEY_ID
FROM information_schema.INNODB_TABLESPACES_ENCRYPTION
WHERE NAME='db1/tab1';
+----------+-------------------+----------------+
| NAME | ENCRYPTION_SCHEME | CURRENT_KEY_ID |
+----------+-------------------+----------------+
| db1/tab1 | 0 | 100 |
+----------+-------------------+----------------+SET GLOBAL innodb_encryption_threads=4;
SET GLOBAL innodb_encrypt_tables='FORCE';
SET SESSION innodb_default_encryption_key_id=100;
CREATE TABLE tab1 (
id INT PRIMARY KEY,
str VARCHAR(50)
) ENCRYPTED=NO;
ERROR 1005 (HY000): Can't create table `db1`.`tab1` (errno: 140 "Wrong create options")
SHOW WARNINGS;
+---------+------+----------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+----------------------------------------------------------------------+
| Warning | 140 | InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 |
| Warning | 140 | InnoDB: ENCRYPTED=NO cannot be used with innodb_encrypt_tables=FORCE |
| Error | 1005 | Can't create table `db1`.`tab1` (errno: 140 "Wrong create options") |
| Warning | 1030 | Got error 140 "Wrong create options" from storage engine InnoDB |
+---------+------+----------------------------------------------------------------------+
4 rows in set (0.00 sec)CREATE TABLE tab1 (
id INT PRIMARY KEY,
str VARCHAR(50)
) ENCRYPTED=YES ENCRYPTION_KEY_ID=100;
SELECT NAME, ENCRYPTION_SCHEME, CURRENT_KEY_ID
FROM information_schema.INNODB_TABLESPACES_ENCRYPTION
WHERE NAME='db1/tab1';
+----------+-------------------+----------------+
| NAME | ENCRYPTION_SCHEME | CURRENT_KEY_ID |
+----------+-------------------+----------------+
| db1/tab1 | 1 | 100 |
+----------+-------------------+----------------+SET SESSION innodb_default_encryption_key_id=100;
CREATE TABLE tab1 (
id INT PRIMARY KEY,
str VARCHAR(50)
) ENCRYPTED=YES;
SELECT NAME, ENCRYPTION_SCHEME, CURRENT_KEY_ID
FROM information_schema.INNODB_TABLESPACES_ENCRYPTION
WHERE NAME='db1/tab1';
+----------+-------------------+----------------+
| NAME | ENCRYPTION_SCHEME | CURRENT_KEY_ID |
+----------+-------------------+----------------+
| db1/tab1 | 1 | 100 |
+----------+-------------------+----------------+CREATE TABLE tab1 (
id INT PRIMARY KEY,
str VARCHAR(50)
) ENCRYPTED=NO;
SELECT NAME, ENCRYPTION_SCHEME, CURRENT_KEY_ID
FROM information_schema.INNODB_TABLESPACES_ENCRYPTION
WHERE NAME='db1/tab1';
+----------+-------------------+----------------+
| NAME | ENCRYPTION_SCHEME | CURRENT_KEY_ID |
+----------+-------------------+----------------+
| db1/tab1 | 0 | 100 |
+----------+-------------------+----------------+
ALTER TABLE tab1
ENCRYPTED=YES ENCRYPTION_KEY_ID=100;
SELECT NAME, ENCRYPTION_SCHEME, CURRENT_KEY_ID
FROM information_schema.INNODB_TABLESPACES_ENCRYPTION
WHERE NAME='db1/tab1';
+----------+-------------------+----------------+
| NAME | ENCRYPTION_SCHEME | CURRENT_KEY_ID |
+----------+-------------------+----------------+
| db1/tab1 | 1 | 100 |
+----------+-------------------+----------------+[mariadb]
innodb_encrypt_temporary_tables=ON[mariadb]
innodb_encrypt_log = ON~$ vault secrets enable -path /test -version=2 kv~$ vault kv get /test/1
====== Metadata ======
Key Value
--- -----
created_time 2019-12-14T14:19:19.42432951Z
deletion_time n/a
destroyed false
version 1
==== Data ====
Key Value
--- -----
data 0123456789ABCDEF0123456789ABCDEF~$ vault kv put /test/1 data="0123456789ABCDEF0123456789ABCDEF"--plugin-load-add=hashicorp_key_management.so
--loose-hashicorp-key-management
--loose-hashicorp-key-management-vault-url="$VAULT_ADDR/v1/test"
--loose-hashicorp-key-management-token="$VAULT_TOKEN"path "my_vault/data/*" {
capabilities = ["read"]
}
path "sys/mounts/my_vault/tune" {
capabilities = ["read"]
}FLUSH HASHICORP_KEY_MANAGEMENT_CACHE;SHOW HASHICORP_KEY_MANAGEMENT_CACHE;Advanced configuration guide for the AWS KMS plugin, detailing how to secure key access using IAM policies, restrict usage by IP address, and implement Multi-Factor Authentication (MFA).
libcurl3-devuuidopensslINSTALL SONAME 'aws_key_management';[mariadb]
...
plugin_load_add = aws_key_management[default]
aws_access_key_id = AKIAIG6IZ6TKF52FVV5A
aws_secret_access_key = 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$ cat /var/lib/mysql/.aws/credentials
[default]
aws_access_key_id = AKIAIG6IZ6TKF52FVV5A
aws_secret_access_key = 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
region = us-east-1chown mysql /var/lib/mysql/.aws/credentials
chmod 600 /var/lib/mysql/.aws/credentials[mariadb]
plugin_load_add = aws_key_management
aws-key-management = FORCE_PLUS_PERMANENT
aws-key-management-master-key-id = alias/mariadb-encryption
aws-key-management-region = us-east-1
!include /etc/my.cnf.d/enable_encryption.presetsetsebool -P mysql_connect_any 1systemctl start mariadb# journalctl --no-pager -o cat -u mariadb.service
[Note] /usr/sbin/mysqld (mysqld 10.1.9-MariaDB-enterprise-log) starting as process 19831 ...
[Note] AWS KMS plugin: generated encrypted datakey for key id=1, version=1
[Note] AWS KMS plugin: loaded key 1, version 1, key length 128 bit
[Note] InnoDB: Using mutexes to ref count buffer pool pages
[Note] InnoDB: The InnoDB memory heap is disabled
[Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
[Note] InnoDB: Memory barrier is not used
[Note] InnoDB: Compressed tables use zlib 1.2.7
[Note] InnoDB: Using CPU crc32 instructions
[Note] InnoDB: Initializing buffer pool, size = 2.0G
[Note] InnoDB: Completed initialization of buffer pool
[Note] InnoDB: Highest supported file format is Barracuda.
[Note] InnoDB: 128 rollback segment(s) are active.
[Note] InnoDB: Waiting for purge to start
[Note] InnoDB: Percona XtraDB (http://www.percona.com) 5.6.26-74.0 started; log sequence number 1616819
[Note] InnoDB: Dumping buffer pool(s) not yet started
[Note] Plugin 'FEEDBACK' is disabled.
[Note] AWS KMS plugin: generated encrypted datakey for key id=2, version=1
[Note] AWS KMS plugin: loaded key 2, version 1, key length 128 bit
[Note] Using encryption key id 2 for temporary files
[Note] Server socket created on IP: '::'.
[Note] Reading of all Master_info entries succeded
[Note] Added new Master_info '' to hash table
[Note] /usr/sbin/mysqld: ready for connections.# ls -l /var/lib/mysql/aws*
-rw-rw----. 1 mysql mysql 188 Feb 25 18:55 /var/lib/mysql/aws-kms-key.1.1
-rw-rw----. 1 mysql mysql 188 Feb 25 18:55 /var/lib/mysql/aws-kms-key.2.1# sudo -u mysql mariadb-install-db
Installing MariaDB/MySQL system tables in '/var/lib/mysql' ...
2016-02-25 23:16:06 139731553998976 [Note] /usr/sbin/mysqld (mysqld 10.1.11-MariaDB-enterprise-log) starting as process 39551 ...
2016-02-25 23:16:07 139731553998976 [Note] AWS KMS plugin: generated encrypted datakey for key id=1, version=1
2016-02-25 23:16:07 139731553998976 [Note] AWS KMS plugin: loaded key 1, version 1, key length 128 bit
...MariaDB [test]> CREATE TABLE t1 (id serial, v VARCHAR(32)) ENCRYPTION_KEY_ID=3;
Query OK, 0 rows affected (0.91 sec)[Note] AWS KMS plugin: generated encrypted datakey for key id=3, version=1
[Note] AWS KMS plugin: loaded key 3, version 1, key length 128 bit# ls -l /var/lib/mysql/aws*
-rw-rw----. 1 mysql mysql 188 Feb 25 18:55 /var/lib/mysql/aws-kms-key.1.1
-rw-rw----. 1 mysql mysql 188 Feb 25 18:55 /var/lib/mysql/aws-kms-key.2.1
-rw-rw----. 1 mysql mysql 188 Feb 25 19:10 /var/lib/mysql/aws-kms-key.3.1Details the File Key Management plugin, which reads encryption keys from a plain-text (or encrypted) file, serving as a simple solution or reference implementation for data-at-rest encryption.
file_key_management_encryption_algorithmfile_key_management_digestfile_key_management_filekeyfile_key_management_filenamefile_key_management_use_pbkdf2file_key_managementStep-by-step tutorial for setting up the AWS KMS plugin, covering the creation of a Customer Master Key (CMK) in AWS, configuring IAM roles for EC2, and installing the plugin from source.
value[mariadb]
plugin_load_add = file_key_managementUNINSTALL SONAME 'file_key_management';<encryption_key_id>;<encryption_key_version>;<hex-encoded_encryption_key><encryption_key_id>;<hex-encoded_encryption_key>$ openssl rand -hex 32
a7addd9adea9978fda19f21e6be987880e68ac92632ca052e5bb42b1a506939amkdir -p /etc/mysql/encryption
echo $(echo -n "1;1;" ; openssl rand -hex 32) | sudo tee -a /etc/mysql/encryption/keyfile.txt
echo $(echo -n "2;1;" ; openssl rand -hex 32) | sudo tee -a /etc/mysql/encryption/keyfile.txt
echo $(echo -n "100;2;" ; openssl rand -hex 32) | sudo tee -a /etc/mysql/encryption/keyfile.txtmkdir -p /etc/mysql/encryption
echo $(echo -n "1;" ; openssl rand -hex 32) | sudo tee -a /etc/mysql/encryption/keyfile.txt
echo $(echo -n "2;" ; openssl rand -hex 32) | sudo tee -a /etc/mysql/encryption/keyfile.txt
echo $(echo -n "100;" ; openssl rand -hex 32) | sudo tee -a /etc/mysql/encryption/keyfile.txt1;1;a7addd9adea9978fda19f21e6be987880e68ac92632ca052e5bb42b1a506939a
2;1;49c16acc2dffe616710c9ba9a10b94944a737de1beccb52dc1560abfdd67388b
100;2;8db1ee74580e7e93ab8cf157f02656d356c2f437d548d5bf16bf2a56932954a31;a7addd9adea9978fda19f21e6be987880e68ac92632ca052e5bb42b1a506939a
2;49c16acc2dffe616710c9ba9a10b94944a737de1beccb52dc1560abfdd67388b
100;8db1ee74580e7e93ab8cf157f02656d356c2f437d548d5bf16bf2a56932954a3[mariadb]
loose_file_key_management_filename = /etc/mysql/encryption/keyfile$ sudo openssl rand -hex 128 > /etc/mysql/encryption/keyfile.key$ sudo openssl enc -aes-256-cbc -md sha256 -pbkdf2 \
-pass file:/etc/mysql/encryption/keyfile.key \
-in /etc/mysql/encryption/keyfile.txt \
-out /etc/mysql/encryption/keys.enc
$ sudo openssl enc -aes-256-cbc -md sha256 -iter 20000 \
-pass file:/etc/mysql/encryption/keyfile.key \
-in /etc/mysql/encryption/keyfile.txt \
-out /etc/mysql/encryption/keys.enc$ sudo openssl enc -aes-256-cbc -md sha1 \
-pass file:/etc/mysql/encryption/keyfile.key \
-in /etc/mysql/encryption/keyfile.txt \
-out /etc/mysql/encryption/keys.enc[mariadb]
...
loose_file_key_management_filename = /etc/mysql/encryption/keyfile.enc
loose_file_key_management_filekey = FILE:/etc/mysql/encryption/keyfile.key
loose_file_key_management_digest = sha256
loose_file_key_management_use_pbkdf2 = 20000[mariadb]
...
loose_file_key_management_filename = /etc/mysql/encryption/keyfile.enc
loose_file_key_management_filekey = FILE:/etc/mysql/encryption/keyfile.key[mariadb]
...
loose_file_key_management_encryption_algorithm = AES_CTRCREATE TABLE t (i INT) ENGINE=InnoDB ENCRYPTED=YES-- Generate a new 256-bit key
openssl rand -hex 32[Service]
Environment=AWS_CREDENTIAL_PROFILES_FILE=/etc/aws-kms-credentials# cat /etc/systemd/system/mariadb.service.d/aws-kms.conf
[Service]
Environment=AWS_ACCESS_KEY_ID=AKIAIRSG2XYZATCJLZ4A
Environment=AWS_SECRET_ACCESS_KEY=ux91LZIxCp4ZXabcdefgIViQNtTan42QAmJqJVqV# cat /etc/systemd/system/mariadb.service.d/aws-kms.env
AWS_ACCESS_KEY_ID=AKIAIRSG2XYZATCJLZ4A
AWS_SECRET_ACCESS_KEY=ux91LZIxCp4ZXabcdefgIViQNtTan42QAmJqJVqV
# chown root /etc/systemd/system/mariadb.service.d/aws-kms.env
# chmod 600 /etc/systemd/system/mariadb.service.d/aws-kms.env
# cat /etc/systemd/system/mariadb.service.d/aws-kms.conf
[Service]
EnvironmentFile=/etc/systemd/system/mariadb.service.d/aws-kms.env$ whoami
mysql
$ cat /proc/$(pgrep mysqld)/environ | tr '\0' '\n' | grep AWS
AWS_ACCESS_KEY_ID=AKIAIRSG2XYZATCJLZ4A
AWS_SECRET_ACCESS_KEY=ux91LZIxCp4ZXabcdefgIViQNtTan42QAmJqJVqV"Condition": {
"IpAddress": {
"aws:SourceIp": [
"10.1.2.3/32"
]
}
},"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "True"
}
},[Service]
EnvironmentFile=/etc/systemd/system/mariadb.service.d/aws-kms.env
ExecStart=
ExecStart=/usr/local/bin/iam-kms-wrapper --config=/etc/my.cnf.d/iam-kms-wrapper.config /usr/sbin/mysqld $MYSQLD_OPTS[kms]
kms_mfa_id = arn:aws:iam::551888187628:mfa/MDBEnc
kms_mfa_socket = /tmp/kms_mfa_socketpackage main
import (
"syscall"
"os"
"log"
"flag"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/sts"
"github.com/robfig/config"
)
func main() {
config_file_p := flag.String("config", "", "location of the config file")
flag.Parse()
if flag.NArg() < 1 {
log.Fatal("Command to wrap must be given as first command-line argument")
}
cmd := flag.Arg(0)
args := flag.Args()[0:]
conf, err := config.ReadDefault(*config_file_p)
if err != nil {
log.Fatal(err)
}
kms_mfa_id, err := conf.String("kms","kms_mfa_id")
mfa_socket_file, err := conf.String("kms","kms_mfa_socket")
sess := session.New()
svc := sts.New(sess)
syscall.Umask(0044)
log.Printf("Reading MFA token from %s\n",mfa_socket_file)
if err := syscall.Mknod(mfa_socket_file, syscall.S_IFIFO|uint32(os.FileMode(0622)), 0); err != nil {
log.Fatal(err)
}
file, err := os.Open(mfa_socket_file)
if err != nil {
log.Fatal(err)
}
token := make([]byte, 6)
if _, err := file.Read(token); err != nil {
log.Fatal(err)
}
file.Close()
if err := syscall.Unlink(mfa_socket_file); err != nil {
log.Fatal(err)
}
mfa_token := string(token)
token_params := &sts.GetSessionTokenInput{
DurationSeconds: aws.Int64(900),
SerialNumber: aws.String(kms_mfa_id),
TokenCode: aws.String(mfa_token),
}
resp, err := svc.GetSessionToken(token_params)
if err != nil {
if awsErr, ok := err.(awserr.Error); ok {
// Prints out full error message, including original error if there was one.
log.Fatal("Error:", awsErr.Error())
} else {
log.Fatal("Error:", err.Error())
}
}
creds := resp.Credentials
os.Setenv("AWS_ACCESS_KEY_ID",*creds.AccessKeyId)
os.Setenv("AWS_SECRET_ACCESS_KEY",*creds.SecretAccessKey)
os.Setenv("AWS_SESSION_TOKEN",*creds.SessionToken)
execErr := syscall.Exec(cmd, args, os.Environ())
if execErr != nil {
panic(execErr)
}
}[MDBEncAdmin]
aws_access_key_id=AKIAJMPPNO7EBKABCDEF
aws_secret_access_key=pVdGwbuK5/jG64aBK1oEJOXRlkdM0aAylgabCDef{
"Sid": "Allow Enable and Disable of the key",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::551888181234:user/MDBEncAdmin"
},
"Action": [
"kms:EnableKey",
"kms:DisableKey"
]
},{
"Version": "2012-10-17",
"Id": "key-consolepolicy-2",
"Statement": [
{
"Sid": "Allow Enable and Disable of the key",
"Effect": "Allow",
"Principal": {
...$ cat ~/.aws/credentials
[MDBEncAdmin]
aws_access_key_id=AKIAJMPPNO7EBKABCDEF
aws_secret_access_key=pVdGwbuK5/jG64aBK1oEJOXRlkdM0aAylgabCDef
$ AWS_PROFILE=MDBEncAdmin aws --region us-east-1 kms disable-key --key-id arn:aws:kms:us-east-1:551888181234:key/abcdf8f6-084b-4cff-99ca-abcdef6c7907c[ERROR] AWS KMS plugin : GenerateDataKeyWithoutPlaintext failed : DisabledException - Unable to parse ExceptionName: DisabledException Message: arn:aws:kms:us-east-1:551888181234:key/abcdf8f6-084b-4cff-99ca-abcdef6c7907c is disabled.#!/usr/bin/env python
import boto3
import sys
# Command-line argument processing should be more robust than this...
action= sys.argv[1]
mfa_token= sys.argv[2]
# These should perhaps go into a config file instead of here
mfa_serial= 'arn:aws:iam::551888181234:mfa/MDBEncAdmin'
key_id= 'arn:aws:kms:us-east-1:551888181234:key/abcdf8f6-084b-4cff-99ca-abcdef6c7907c'
# Make the connection to the Security Token Service to get temporary credentials
token_client= boto3.client('sts')
token_response= token_client.get_session_token(
DurationSeconds= 900,
SerialNumber= mfa_serial,
TokenCode= mfa_token
)
cred= token_response['Credentials']
# Start new session using temporary, MFA-authenticated credentials
kms_session= boto3.session.Session(
aws_access_key_id= cred['AccessKeyId'],
aws_secret_access_key= cred['SecretAccessKey'],
aws_session_token= cred['SessionToken'],
region_name= key_id.split(':')[3]
)
# Start KMS client and execute operation against key
kms_client= kms_session.client('kms')
if action == 'enable' or action == 'e':
action_f= kms_client.enable_key
elif action == 'disable' or action == 'd':
action_f= kms_client.disable_key
else:
raise Exception('Action must be either "disable" or "enable"')
action_f(KeyId=key_id)$ AWS_PROFILE=MDBEncAdmin python kms-manage-key disable 575290
$ AWS_PROFILE=MDBEncAdmin python kms-manage-key enable 799870{
"detail-type": [
"AWS API Call via CloudTrail"
],
"detail": {
"eventSource": [
"kms.amazonaws.com"
],
"errorCode": [
"AccessDenied",
"UnauthorizedOperation"
]
}
}Details the operation of background threads (configured via innodb_encryption_threads) which handle key rotation, and the encryption/decryption of tablespaces when global settings.
SELECT SPACE, NAME
FROM information_schema.INNODB_TABLESPACES_ENCRYPTION
WHERE ROTATING_OR_FLUSHING = 1;SELECT COUNT(*) AS 'encrypting'
FROM information_schema.INNODB_TABLESPACES_ENCRYPTION
WHERE ROTATING_OR_FLUSHING = 1;/* information_schema.INNODB_TABLESPACES_ENCRYPTION does not always have rows for all tablespaces,
so let's join it with information_schema.INNODB_SYS_TABLESPACES */
WITH tablespace_ids AS (
SELECT SPACE
FROM information_schema.INNODB_SYS_TABLESPACES ist
UNION
/* information_schema.INNODB_SYS_TABLESPACES doesn't have a row for the system tablespace (MDEV-20802) */
SELECT 0 AS SPACE
)
SELECT NOW() AS 'time',
'tablespaces', COUNT(*) AS 'tablespaces',
'encrypted', SUM(IF(ite.ENCRYPTION_SCHEME IS NOT NULL, ite.ENCRYPTION_SCHEME, 0)) AS 'encrypted',
'encrypting', SUM(IF(ite.ROTATING_OR_FLUSHING IS NOT NULL, ite.ROTATING_OR_FLUSHING, 0)) AS 'encrypting'
FROM tablespace_ids
LEFT JOIN information_schema.INNODB_TABLESPACES_ENCRYPTION ite
ON tablespace_ids.SPACE = ite.SPACE-- Disable encryption for new tables and the system tablespace
SET GLOBAL innodb_encrypt_tables = OFF;
-- Enable encryption threads to perform the decryption work
SET GLOBAL innodb_encryption_threads = 4;
-- Force rotation to unencrypted state by setting age to 1
SET GLOBAL innodb_encryption_rotate_key_age = 1;[mariadb]
innodb_encrypt_tables = OFF
innodb_encryption_threads = 4
innodb_encryption_rotate_key_age = 1SELECT TABLE_SCHEMA, TABLE_NAME
FROM information_schema.TABLES
WHERE ENGINE='InnoDB'
AND (CREATE_OPTIONS LIKE '%ENCRYPTED=YES%' OR CREATE_OPTIONS LIKE '%ENCRYPTION="Y"%');SELECT COUNT(*) AS "Encrypted_Tablespaces"
FROM information_schema.INNODB_TABLESPACES_ENCRYPTION
WHERE ENCRYPTION_SCHEME != 0 OR ROTATING_OR_FLUSHING != 0;ALTER TABLE db_name.table_name ENCRYPTED=NO;[mariadb]
# Ensure the plugin remains loaded for this restart!
innodb_encrypt_log = OFFsudo systemctl restart mariadbSHOW GLOBAL VARIABLES LIKE 'innodb_encrypt_log';SELECT TABLE_NAME, CREATE_OPTIONS
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_database_name';Introduction to the AWS Key Management plugin, which uses Amazon KMS to generate and store master keys, decrypting them at startup to enable data-at-rest encryption with key rotation support.
aws_key_management_key_specaws_key_management_log_levelaws_key_management_master_key_idaws_key_management_mockaws_key_management_regionaws_key_management_request_timeoutaws_key_management_rotate_keyaws_key_managementlibcurl3-devuuidopenssl# clone the MariaDB Server source code repository
git clone https://github.com/MariaDB/server.git
cd server
# prepare the build
mkdir _build
cd _build
cmake .. -DNOT_FOR_DISTRIBUTION=ON \
-DPLUGIN_AWS_KEY_MANAGEMENT=DYNAMIC \
-DAWS_SDK_EXTERNAL_PROJECT=1
# build the plugin only
cd plugin/aws_key_management
makeINSTALL SONAME 'aws_key_management';[mariadb]
plugin_load_add = aws_key_managementUNINSTALL SONAME 'aws_key_management';[mariadb]
...
aws_key_management_master_key_id=alias/<your key's alias>CREATE TABLE t (i INT) ENGINE=InnoDB ENCRYPTED=YESSET GLOBAL aws_key_management_rotate_key=2;SET GLOBAL aws_key_management_rotate_key=-1;aria_used_for_temp_tables is set to ON. To ensure these are no longer encrypted, set:SET GLOBAL aria_encrypt_tables = OFF;[mysqld]
aria_encrypt_tables = OFFSELECT TABLE_SCHEMA, TABLE_NAME
FROM information_schema.TABLES
WHERE ENGINE = 'Aria'
AND ROW_FORMAT = 'PAGE'
AND TABLE_SCHEMA NOT IN ('information_schema', 'performance_schema', 'sys')
AND (CREATE_OPTIONS LIKE '%`encrypted`=yes%' OR CREATE_OPTIONS LIKE '%`encrypted`=1%');ALTER TABLE db_name.table_name ENGINE=Aria, ALGORITHM=COPY;SET GLOBAL encrypt_tmp_disk_tables = OFF;SELECT CONCAT('ALTER TABLE `', table_schema, '`.`', table_name,
'` ENGINE=Aria, ALGORITHM=COPY;') AS ddl
FROM information_schema.tables
WHERE ENGINE='Aria'
AND TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema','sys')
AND (CREATE_OPTIONS LIKE '%`encrypted`=yes%' OR CREATE_OPTIONS LIKE '%`encrypted`=1%');