MariaDBのTDE Part 2

MariaDBのTDEの暗号化プラグイン

概要

資料

基本仕様

  • プラグイン動作

    • 暗号化関連の構造体に対してプラグインで実装した関数を定義し、それをプラグイン読み込み時にMariaDB本体に登録
    • MariaDB本体がTDE機能を実行する際に、登録された構造体の関数を呼び出す
  • 暗号化プラグインの作成

    • 必要となる暗号関連ヘッダの読み込み

        #include <mysql/plugin_encryption.h>
      
    • 必要となる各種機能を実装

      • 鍵管理・データ暗号化機能が呼び出される際の引数と戻り値については、前述で読み込む暗号関連ヘッダに詳細な説明が記載されているため、そちらを参考に実装する
    • 暗号化プラグインが提供する機能(関数)を暗号化プラグインディスクリプタ構造体として定義

      struct st_mariadb_encryption [ディスクリプタ名]= {
      MariaDB_ENCRYPTION_INTERFACE_VERSION,
      [引数で指定された鍵番号の最新鍵バージョンを返却する関数],
      [引数で指定された鍵番号・鍵バージョンに合致するデータ暗号化鍵を返却する関数],
      [暗号化コンテキストオブジェクトのサイズを返却する関数],
      [暗号化コンテキストオブジェクトを初期化する関数],
      [データの暗号化・復号化を行う関数],
      [暗号化コンテキストオブジェクトを破棄する関数],
      [暗号化されたデータの長さを返却する関数]
      };
      
    • プラグイン宣言を定義

      maria_declare_plugin([プラグイン名])
      {
      MariaDB_ENCRYPTION_PLUGIN,
      [暗号化プラグインディスクリプタへのポインタ],
      "[プラグイン名]",
      "[プラグイン作成者]",
      "[プラグイン概要]",
      PLUGIN_LICENSE_GPL,
      [プラグイン初期化関数],
      [プラグイン終了関数],
      [プラグインバージョン(hex)],
      [ステータス変数の構造体],
      [システム変数の構造体]
      "[プラグインバージョン(文字列)]",
      [プラグインステータス]
      }
      maria_declare_plugin_end;
      

MariaDBのTDE Part 1

MariaDBのTDEの仕様

概要

  • アプリケーションの変更なしにデータベースのデータファイル・ログファイル一時ファイル等を暗号化する機能
  • データベースサーバのOSに侵入された場合もしくはストレージデバイスの廃棄・盗難等へは効果がある
  • SQLインタフェース(例:SQLインジェクション)を介したアクセスに対しては効果がない

制限事項

  • 10.4未満はredoログのデータ暗号化鍵のローテーションに対応していない
  • 一部のファイルはデータ暗号化鍵のローテーションに対応していない
  • 一部ファイルはデータ暗号化自体に対応していない
    • 一般ログ(general_log)
    • スロークエリログ
    • エラーログ
    • mysqldumpで出力されたダンプデータ

基本仕様

  • 利用するためには対応する暗号化プラグインが必要となる

    • 同時に利用できる暗号化プラグインは1つのみ
    • 暗号化プラグインは鍵管理機能とデータ暗号化機能を提供し、データ暗号化機能の提供はオプションとなる
      • データ暗号化機能はMariaDB本体に標準で組み込まれており、そちら(AES-CBC)をそのまま利用できる
  • 対応するストレージエンジンはInnoDBAriaのみとなる

  • レプリケーション構成の場合、プライマリ・レプリカで異なるデータ暗号化鍵を利用することができる

  • mariadbbackupを利用することで、暗号化されたInnoDBバックアップに対応できる

  • データ暗号化に利用されるデータ暗号化鍵の仕様は次の通り

    • データ暗号化鍵は鍵番号と鍵バージョンで管理される
    • MariaDB全体で利用されるファイル群の暗号化には特定の鍵番号のデータ暗号化鍵が利用される
      • 鍵番号1
        • バイナリログ、リレーログ
        • システムデータ(double write buffer)
        • redoログ
      • 鍵番号2(鍵番号2が存在しない場合、鍵番号1が利用される。鍵番号2の利用は必須ではなくオプション扱いとなる)
        • 一時ファイル
        • 一時テーブル
  • データ暗号化は次の通り処理される

    • ページ単位で処理される
    • ページのヘッダ領域にデータ暗号化に利用したデータ暗号化鍵の鍵番号と鍵バージョンが格納されている
    • 鍵番号が同じ場合、鍵バージョンが大きいものが新しいものとして扱われる
    • 同じ鍵番号で新しい鍵バージョンのデータ暗号化鍵が追加されると、バックグラウンドで新しいデータ暗号化鍵での再暗号化処理が行われる
    • データ暗号化についてはテーブル単位で実施の有無を指定できる

MariaDBのTDEでのhashicorp plugin利用(AlmaLinux8)

目的

  • AlmaLinux8で提供されているMariaDB 10.5でTransparent Data Encryptionを利用する
  • 鍵・暗号化プラグインとしてMariaDB 10.9向けのhashicorp key management pluginを利用する

環境

  • dockerのalmalinux:8イメージのコンテナ

方法

  1. dockerコンテナを作成してコンテナ内に移動

  2. 必要パッケージをインストール

# dnf -y install rpm-build yum-utils git
# dnf config-manager --set-enable powertools
  1. MariaDBのバージョンを10.3から10.5に切り替え
# dnf module reset mariadb
# dnf module enable mariadb:10.5
  1. 作業用の一般アカウントを作成して、MariaDBのソースパッケージを取得
# adduser dummy
# su - dummy
$ dnf download --source mariadb-server
  1. MariaDBのソースパッケージをインストール
$ rpm -ivh mariadb-10.5.13-1.module_el8.6.0+2761+593e5e59.src.rpm
  1. 作業用の一般アカウントからログアウトし、パッケージ作成に必要な各種ライブラリをインストール
$ exit
# dnf -y install Judy
# rpm --nodeps -ivh https://repo.almalinux.org/almalinux/8/PowerTools/x86_64/os/Packages/Judy-devel-1.0.5-18.module_el8.6.0+2867+72759d2f.x86_64.rpm
# dnf builddep /home/dummy/rpmbuild/SPECS/mariadb.spec
  1. hashicorp key management pluginで必要となるパッケージをインストール
# dnf -y install libcurl-devel
  1. specファイルからソースコードを展開し、パッチを適用
# su - dummy
$ rpmbuild --bp ./rpmbuild/SPECS/mariadb.spec
  1. MariaDBリポジトリから10.9のブランチを取得し、hashicorp key management pluginをコピー
$ git clone -b 10.9 --single-branch --depth 1 https://github.com/MariaDB/server.git
$ cp -ar ./server/plugin/hashicorp_key_management ./rpmbuild/BUILD/mariadb-10.5.13-downstream_modified/plugin/
  1. hashicorp key management pluginをコンパイル
$ cd rpmbuild/BUILD/mariadb-10.5.13-downstream_modified/
$ cmake .
$ make hashicorp_key_management
  1. MariaDB Server 10.5をインストール
$ exit
# dnf -y install mariadb-server
  1. hashicorp key management pluginをプラグインディレクトリにコピー
# cp /home/dummy/rpmbuild/BUILD/mariadb-10.5.13-downstream_modified/plugin/hashicorp_key_management/hashicorp_key_management.so /usr/lib64/mariadb/plugin/
  1. hashicorp vaultをインストール
# dnf config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
# dnf -y install vault
# setcap -r /usr/bin/vault
  1. hashicorp vaultの初期設定
# mkdir -p /root/vault/data
# cat <<EOF > /root/vault/config.hcl
storage "file" {
  path = "/root/vault/data"
}

# for normal docker only
disable_mlock = "true"

listener "tcp" {
  address       = "127.0.0.1:8200"
  tls_cert_file = "/root/vault/server.crt"
  tls_key_file  = "/root/vault/server.key"
}
EOF

# openssl genrsa 2048 > /root/vault/ca.key
# openssl req -new -key /root/vault/ca.key -subj "/CN=ca.local" > /root/vault/ca.csr
# openssl x509 -req -in /root/vault/ca.csr -signkey /root/vault/ca.key -days 365 -out /root/vault/ca.crt

# openssl genrsa 2048 > /root/vault/server.key
# echo 'subjectAltName = DNS:localhost, IP=127.0.0.1' > /root/vault/san.ext
# openssl req -new -key /root/vault/server.key -subj "/CN=localhost" > /root/vault/server.csr
# openssl x509 -req -in /root/vault/server.csr -CA /root/vault/ca.crt -CAkey /root/vault/ca.key  -CAcreateserial -days 365 -extfile /root/vault/san.ext -out /root/vault/server.crt
  1. hashicorp vaultの初期化
# vault server -config=/root/vault/config.hcl &
# VAULT_CACERT=/root/vault/ca.crt vault operator init
  1. 出力される「Unseal Key」と「Root Token」を記録

  2. hashicorp vaultを利用できるようにunsealを実施

# VAULT_CACERT=/root/vault/ca.crt vault operator unseal
Unseal Key (will be hidden): [Unseal Keyを入力]

※標準設定で3個のUnseal Keyの入力が必要なので、上記処理を異なるUnseal Keyで3回繰り返す
  1. MariaDBのTDEで利用するKVストアを有効化
# VAULT_CACERT=/root/vault/ca.crt vault login
Token (will be hidden): [Root Tokenを入力]

# VAULT_CACERT=/root/vault/ca.crt vault secrets enable --path /data -version=2 kv
  1. データ暗号化鍵を生成
# VAULT_CACERT=/root/vault/ca.crt vault kv put /data/1 data=$(openssl rand -hex 32)
  1. TDE用のアクセストークン設定
# VAULT_CACERT=/root/vault/ca.crt vault policy write tde-policy - <<EOF
path "data/*" {
  capabilities = ["read", "list"]
}
path "sys/mounts/data/*" {
  capabilities = ["read", "list"]
}
EOF

# VAULT_CACERT=/root/vault/ca.crt vault token create -field token -policy=tde-policy

※出力されるトークンを記録する
  1. MariaDBの起動
# dnf -y install sudo
# /usr/bin/mysql_install_db --user=mysql
# sudo -u mysql /usr/libexec/mysqld --basedir=/usr &
  1. 暗号化前の動作検証
# mysql -uroot -e 'show databases'
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+

# mysql -uroot -e 'create database dummy'

# mysql -uroot -e 'show databases'
+--------------------+
| Database           |
+--------------------+
| dummy              |
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+

# mysql -uroot dummy -e 'create table example(id int, name char(40), primary key(id))'
# mysql -uroot dummy -e 'insert into example values(1, "abcd")'
# mysql -uroot dummy -e 'insert into example values(2, "efgh")'
# mysql -uroot dummy -e 'select * from example'
+----+------+
| id | name |
+----+------+
|  1 | abcd |
|  2 | efgh |
+----+------+

# cat /var/lib/mysql/ib_logfile0 | strings | egrep 'abcd|efgh'
abcd
efgh
  1. TDEおよびhashicorp key management pluginを有効化
# cp /root/vault/ca.crt /etc/my.cnf.d/
# cat <<EOF > /etc/my.cnf.d/hashicorp.cnf
[mariadb]
plugin-load-add=hashicorp_key_management.so
hashicorp-key-management-vault-url="https://127.0.0.1:8200/v1/data"
hashicorp-key-management-token="[tokenを設定]"
hashicorp-key-management-vault-ca=/etc/my.cnf.d/ca.crt
hashicorp-key-management-timeout=15
hashicorp-key-management-max-retries=3

encrypt-binlog=1
encrypt-tmp-disk-tables=1
encrypt-tmp-files=1
innodb-default-encryption-key-id=1
innodb-encrypt-log=1
innodb-encrypt-tables=1
innodb-encrypt-temporary-tables=1
innodb-encryption-rotate-key-age=1
innodb-encryption-rotation-iops=100
innodb-encryption-threads=4
EOF
  1. 設定反映のためMariaDBを再起動
# kill $(pidof mysqld)
# sudo -u mysql /usr/libexec/mysqld --basedir=/usr &
  1. MariaDBのパラメータで暗号化状態を確認
# mysql -uroot -e 'show variables like "%encrypt%"'
+----------------------------------+-------+
| Variable_name                    | Value |
+----------------------------------+-------+
| aria_encrypt_tables              | OFF   |
| encrypt_binlog                   | ON    |
| encrypt_tmp_disk_tables          | ON    |
| encrypt_tmp_files                | ON    |
| innodb_default_encryption_key_id | 1     |
| innodb_encrypt_log               | ON    |
| innodb_encrypt_tables            | ON    |
| innodb_encrypt_temporary_tables  | ON    |
| innodb_encryption_rotate_key_age | 1     |
| innodb_encryption_rotation_iops  | 100   |
| innodb_encryption_threads        | 4     |
+----------------------------------+-------+

# mysql -uroot -e 'select * from information_schema.INNODB_TABLESPACES_ENCRYPTION\G'
*************************** 1. row ***************************
                       SPACE: 0
                        NAME: innodb_system
           ENCRYPTION_SCHEME: 1
          KEYSERVER_REQUESTS: 1
             MIN_KEY_VERSION: 1
         CURRENT_KEY_VERSION: 1
    KEY_ROTATION_PAGE_NUMBER: NULL
KEY_ROTATION_MAX_PAGE_NUMBER: NULL
              CURRENT_KEY_ID: 1
        ROTATING_OR_FLUSHING: 0
*************************** 2. row ***************************
                       SPACE: 2
                        NAME: mysql/innodb_index_stats
           ENCRYPTION_SCHEME: 1
          KEYSERVER_REQUESTS: 1
             MIN_KEY_VERSION: 1
         CURRENT_KEY_VERSION: 1
    KEY_ROTATION_PAGE_NUMBER: NULL
KEY_ROTATION_MAX_PAGE_NUMBER: NULL
              CURRENT_KEY_ID: 1
        ROTATING_OR_FLUSHING: 0
*************************** 3. row ***************************
                       SPACE: 5
                        NAME: dummy/example
           ENCRYPTION_SCHEME: 1
          KEYSERVER_REQUESTS: 1
             MIN_KEY_VERSION: 1
         CURRENT_KEY_VERSION: 1
    KEY_ROTATION_PAGE_NUMBER: NULL
KEY_ROTATION_MAX_PAGE_NUMBER: NULL
              CURRENT_KEY_ID: 1
        ROTATING_OR_FLUSHING: 0
*************************** 4. row ***************************
                       SPACE: 1
                        NAME: mysql/innodb_table_stats
           ENCRYPTION_SCHEME: 1
          KEYSERVER_REQUESTS: 1
             MIN_KEY_VERSION: 1
         CURRENT_KEY_VERSION: 1
    KEY_ROTATION_PAGE_NUMBER: NULL
KEY_ROTATION_MAX_PAGE_NUMBER: NULL
              CURRENT_KEY_ID: 1
        ROTATING_OR_FLUSHING: 0
*************************** 5. row ***************************
                       SPACE: 3
                        NAME: mysql/transaction_registry
           ENCRYPTION_SCHEME: 1
          KEYSERVER_REQUESTS: 1
             MIN_KEY_VERSION: 1
         CURRENT_KEY_VERSION: 1
    KEY_ROTATION_PAGE_NUMBER: NULL
KEY_ROTATION_MAX_PAGE_NUMBER: NULL
              CURRENT_KEY_ID: 1
        ROTATING_OR_FLUSHING: 0
*************************** 6. row ***************************
                       SPACE: 4
                        NAME: mysql/gtid_slave_pos
           ENCRYPTION_SCHEME: 1
          KEYSERVER_REQUESTS: 1
             MIN_KEY_VERSION: 1
         CURRENT_KEY_VERSION: 1
    KEY_ROTATION_PAGE_NUMBER: NULL
KEY_ROTATION_MAX_PAGE_NUMBER: NULL
              CURRENT_KEY_ID: 1
        ROTATING_OR_FLUSHING: 0
  1. ファイルの暗号化状態を確認
# cat /var/lib/mysql/ib_logfile0 | strings | egrep 'abcd|efgh'
#
# cat /var/lib/mysql/ib_logfile0 | strings | head -20
MariaDB 10.5.13
X`;a
B{9 K
YX0WA
mLos
w\q:
$Q{e
orGR
dX(m
,{^Ca
b)Q!
=9J<
tZeT
tu1v
}+m3
l7J     Z
]9Zx
BCI:
b57l%
}"?1

# cat /var/lib/mysql/dummy/example.ibd | strings | egrep 'abcd|efgh'
#
# cat /var/lib/mysql/dummy/example.ibd | strings | head -20
/:LS
fi?;
        k"I(
J(7O
\z?+
F8?,
5"3Z
rvP_
8?.CL
^:4+
{)}]i
P%F
)`tN
&Ywt
Wbce
2+Jjg6
l!0t
vxF6N
C.yL
v8bJ

デバッグが有効なMariaDBパッケージ作成(AlmaLinux8)

目的

  • AlmaLinux8で提供されているMariaDBのソースパッケージを用いてデバッグが有効なパッケージを作成する

環境

  • dockerのalmalinux:8イメージのコンテナ

方法

  1. dockerコンテナを作成してコンテナ内に移動

  2. 必要パッケージをインストール

# dnf -y install rpm-build epel-release yum-utils
# dnf config-manager --set-enable powertools
  1. 作業用の一般アカウントを作成して、MariaDBのソースパッケージを取得
# adduser dummy
# su - dummy
$ dnf download --source mariadb-server
  1. MariaDBのソースパッケージをインストール
rpm -ivh mariadb-10.3.32-2.module_el8.6.0+2867+72759d2f.src.rpm
  1. 作業用の一般アカウントからログアウトし、パッケージ作成に必要な各種ライブラリをインストール
$ exit
# dnf -y install Judy
# rpm -ivh https://repo.almalinux.org/almalinux/8/PowerTools/x86_64/os/Packages/Judy-devel-1.0.5-18.module_el8.6.0+2867+72759d2f.x86_64.rpm
# dnf builddep /home/dummy/rpmbuild/SPECS/mariadb.spec
  1. specファイルにデバッグオプションを設定し、パッケージ作成時のエラー対策の調整を実施
$ su - dummy
$ diff mariadb.spec_org mariadb.spec
18a19
> %global with_debug 1
776c777
< %{?with_debug: CFLAGS="$CFLAGS -O0 -g"}
---
> %{?with_debug: CFLAGS="$CFLAGS -O0 -g -Wno-error"}
1604,1606d1604
<
< * Tue May 05 2021 Michal Schorm <mschorm@redhat.com> - 3:10.3.29-1
< - Rebase to 10.3.29
  1. specファイルからパッケージを作成
$ rpmbuild --nocheck -bb mariadb.spec