---
title: "AWS KMS プラグインによる暗号鍵の管理"
publish_date: 2019-08-20
updated_date: 2023-10-12
author: "MariaDB"
tags:
  - name: "encryption"
    url: "/ja/resources/blog/tag/encryption-ja.md"
  - name: "MariaDB Server"
    url: "/ja/resources/blog/tag/mariadb-server-ja.md"
  - name: "Security"
    url: "/ja/resources/blog/tag/security-ja.md"
---

# AWS KMS プラグインによる暗号鍵の管理

MariaDB Server は バージョン 10.1 から[データ暗号化(Data-at-Rest Encryption)](https://staging-mdb.com/kb/en/library/documentation/mariadb-administration/user-server-security/securing-mariadb/securing-mariadb-encryption/securing-mariadb-data-at-rest-encryption/)をサポートしていますが，暗号化鍵の管理(ローテーション等)において [AWS KMS(Key Management Service)](https://aws.amazon.com/jp/kms/)を利用することが可能となっています。

今回は Amazon EC2 インスタンスに MariaDB Server 10.4 をインストールし，AWS KMS で生成した暗号鍵を利用してデータの暗号化を行ってみます。

### 実行環境

[AWS SDK C++](https://aws.amazon.com/jp/sdk-for-cpp/), [AWS KMS プラグイン](https://staging-mdb.com/kb/en/library/documentation/mariadb-administration/user-server-security/securing-mariadb/securing-mariadb-encryption/securing-mariadb-data-at-rest-encryption/key-management-and-encryption-plugins/aws-key-management-encryption-plugin/)をソースからビルドする必要があるため，今回は 4 vCPU / 16 GB メモリのインスタンスタイプを利用しました。

- Amazon EC2 インスタンスタイプ: t2.xlarge
- OS: CentOS 7.6.10 (SELINUX=disabled)
- MariaDB : Community Server 10.4.7

### cmake3 のインストール

AWS SDK C++ のビルドにバージョン 3.2 以降の cmake が必要となりますが，CentOS 7.6 標準の cmake は 2.8 ですので，cmake3 を事前にインストールします。

```
sudo yum -y install cmake3

```

### AWS SDK C++ KMS クライアントのビルド事前準備

[Setting Up the AWS SDK for C++](https://docs.aws.amazon.com/ja_jp/sdk-for-cpp/v1/developer-guide/setup.html) に従い AWS SDK C++ の依存パッケージをインストールします。

```
sudo yum -y install gcc gcc-c++ bison git
sudo yum -y install libcurl-devel openssl-devel libuuid-devel pulseaudio-libs-devel

```

### MariaDB Server aws\_key\_management プラグインのビルド

GitHub から MariaDB Community Server 10.4.7 を clone, AWS KMS プラグインのみビルドします。

```
sudo yum -y install ncurses-devel
git clone -b mariadb-10.4.7 https://github.com/MariaDB/server.git
mkdir build10.4
cd build10.4
cmake3 -DRPM=centos7 -DPLUGIN_AWS_KEY_MANAGEMENT=DYNAMIC -DAWS_SDK_EXTERNAL_PROJECT=1 -DNOT_FOR_DISTRIBUTION=1 ../server
make -j4 aws_key_management 

```

ビルドしたプラグインを MariaDB プラグインディレクトリにコピーします。

```
sudo cp -pf plugin/aws_key_management/aws_key_management.so /usr/lib64/mysql/plugin/

```

### MariaDB Community Server 10.4.7 のインストール

レポジトリ設定を行い，MariaDB Community Server 10.4.7 をインストール，起動します。

```
curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash
sudo yum -y install MariaDB-server
sudo systemctl enable mariadb
sudo systemctl start mariadb

```

### IAM Role 作成，EC2 インスタンスへのアタッチ

[AWS KMS Encryption Plugin Setup Guide](https://staging-mdb.com/kb/en/library/aws-key-management-encryption-plugin-setup-guide/#configure-aws-credentials) には，`/var/lib/mysql/.aws/credentials` に AWS Access Key ID と Secret Access Key を記述するよう記載されていますが，MariaDB Server を EC2 上で稼働させる場合は，IAM Role をアタッチすることで AWS アクセスキーをテキストファイルに平文(plain text)で記述する必要がなくなり，よりセキュアとなります。

IAM / KMS管理権限を持つ AWS アカウントにて AWS CLI を利用し，AWSKeyManagementServicePowerUser ポリシーを割り当てた IAM Role を作成します。

以下のような [シェルスクリプト](https://github.com/goto-satoru/create-aws-kms-key/blob/master/create-role.sh)を作成，

```
#!/bin/sh

if [ $# -lt 1 ] ; then
  echo -e "Usage: $0 role_name\n"
  exit 1
fi

role_name=$1
managed_policy="arn:aws:iam::aws:policy/AWSKeyManagementServicePowerUser"

aws iam create-role --role-name $role_name \
    --assume-role-policy-document file://ec2-role-trust-policy.json \
    --description "Allows EC2 instances to call AWS services on your behalf"

aws iam attach-role-policy --role-name $role_name \
                           --policy-arn $managed_policy

aws iam create-instance-profile --instance-profile-name $role_name
aws iam add-role-to-instance-profile --instance-profile-name $role_name \
                                     --role-name $role_name

```

ここで，[ec2-role-trust-policy.json](https://github.com/goto-satoru/create-aws-kms-key/blob/master/ec2-role-trust-policy.json) は以下のようなポリシードキュメントです。

```
{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Principal": {"Service": "ec2.amazonaws.com"},
    "Action": "sts:AssumeRole"
  }
}

```

ここでは，`kms-power-user` という Role を作成してみます。

```
./create-role.sh kms-power-user

```

EC2 ダッシュボードで EC2 インスタンスを選択，Actions – Instance Settings – Attach/Replace IAM Role から作成した Role を Apply します。

[既存EC2インスタンスにIAMロールをアタッチ](https://aws.amazon.com/jp/blogs/news/easily-replace-or-attach-an-iam-role-to-an-existing-ec2-instance-by-using-the-ec2-console/)

### AWS KMS Key 作成

AWS CLI を用い，暗号鍵を作成します。

以下のような[シェルスクリプト](https://github.com/goto-satoru/create-aws-kms-key/blob/master/create-kms-key.sh)を用い暗号鍵を作成，aliasを設定，ポリシーJSONドキュメントを作成，適用します。

```
#!/bin/sh

key_id=`aws kms create-key | jq -r '.KeyMetadata.KeyId'`
echo "AWS KMS KeyId: $key_id"

echo -n "AWS KMS Master key alias: "
read key_alias

aws kms create-alias --alias-name "alias/$key_alias" --target-key-id $key_id

echo -e "\nexisiting IAM Roles:"
aws iam list-roles | jq -r '.Roles[] | .RoleName'

echo
echo -n "IAM Role name for KMS: "
read role_name

aws_id=`aws sts get-caller-identity | jq -r '.Account' `
echo "AWS Account ID: $aws_id"

policy_file='kms-key-policy.json'

cat <<EOF >$policy_file
{
  "Version": "2012-10-17",
  "Id": "key-consolepolicy-3",
  "Statement": [
    {
      "Sid": "Enable IAM User Permissions",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::${aws_id}:root"
      },
      "Action": "kms:*",
      "Resource": "*"
    },
    {
      "Sid": "Allow use of the key",
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::${aws_id}:role/$role_name"
        ]
      },
      "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:DescribeKey"
      ],
      "Resource": "*"
    },
    {
      "Sid": "Allow attachment of persistent resources",
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::${aws_id}:role/$role_name"
        ]
      },
      "Action": [
        "kms:CreateGrant",
        "kms:ListGrants",
        "kms:RevokeGrant"
      ],
      "Resource": "*",
      "Condition": {
        "Bool": {
          "kms:GrantIsForAWSResource": true
        }
      }
    }
  ]
}
EOF
dos2unix $policy_file
echo "AWS KMS KeyId: $key_id"
aws kms put-key-policy --key-id $key_id \
                       --policy-name default \
                       --policy file://$policy_file

```

ここでは，`alias/test-mariadb` という alias を設定し，`kms-power-user`という IAM Role を割り当てます。

```
$ ./create-kms-key.sh
AWS KMS KeyId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
AWS KMS Master key alias: test-mariadb

exisiting IAM Roles:
AWSServiceRoleForSupport
kms-power-user

IAM Role name for KMS: kms-power-user
AWS Account ID: 012345678901

```

### 動作確認

###### 暗号化(Data-at-Rest Encryption)無効の場合

まず比較のために Data-at-Rest Encryption 無効のままで，テストテーブルを作成，データを確認します。

```
MariaDB [test]> CREATE TABLE noencryption (note VARCHAR(10));

MariaDB [test]> INSERT INTO noencryption VALUES ('maria'),('monty'),('my');

MariaDB [test]> SELECT * FROM noencryption;
+-------+
| note  |
+-------+
| maria |
| monty |
| my    |
+-------+

```

strings コマンドでテーブルデータに含まれている文字列を確認します。

```
sudo su - 
cd /var/lib/mysql/test
strings noencryption.ibd
infimum
supremum
maria
monty

```

Data-at-Rest Encryption が無効にされている場合，テーブルデータ中の文字列が見えてしまいます。

###### 暗号化(Data-at-Rest Encryption)有効の場合

暗号化を行う場合は /etc/my.cnf.d/server.cnf を以下のように設定し，

```
[mariadb]
log_error

plugin_load_add = aws_key_management
aws-key-management
aws-key-management-master-key-id = alias/test-mariadb
aws-key-management-region = ap-northeast-1
!include /etc/my.cnf.d/enable_encryption.preset

```

mariadb service を再起動します。

```
sudo systemctl restart mariadb

```

エラーログに以下のようなログが記録されていれば，AMS KMS で作成された暗号鍵で正常に Data-at-Rest Encryption が行われています。

```
2019-08-01 10:04:07 0 [Note] mysqld: AWS KMS plugin: generated encrypted datakey for key id=2, version=1
2019-08-01 10:04:07 0 [Note] mysqld: AWS KMS plugin: loaded key 2, version 1, key length 128 bit
2019-08-01 10:04:07 0 [Note] Using encryption key id 2 for temporary files

```

```
MariaDB [(none)]> use test;
MariaDB [test]> CREATE TABLE encrypted (note VARCHAR(10));

MariaDB [test]> INSERT INTO encrypted VALUES ('Maria'),('Monty'),('My');
Records: 3  Duplicates: 0  Warnings: 0

MariaDB [test]> SELECT * FROM encrypted;
+-------+
| note  |
+-------+
| Maria |
| Monty |
| My    |
+-------+

```

暗号化なしの場合と同様に，/var/lib/mysql/test で strings コマンドを実行してみます。

```
0e#&
ebt0
l +2:
[(iRy
o(lO
7c3>Z
b`zY^
wqTV
_Et2E`m
Lh{?
nsV-
 q@<
42-2
SX-x
2~16-c
?{MI
no3W#
@k /    r
lxru
gV P=*
(&=B
...

```

データが暗号化されていることが確認できました。

### トラブルシューティング

エラーログに以下のようなエラーが記録されている場合は，SELinux が有効になっていると考えられますので，無効にするか，AWS API による KMS へのアクセスを許可してください。

```
2019-08-01 12:23:08 0 [ERROR] mysqld: AWS KMS plugin : KMS Client API 'Decrypt' failed :  - Unable to connect to endpoint

```

### まとめ

AWS KMS プラグインを用いて，MariaDB Server 10.4 のテーブルデータの暗号化を試しました。

今回 IAM Role 作成，KMS Key 作成に用いたシェルスクリプトは以下の GitHub レポジトリにあります。

<https://github.com/goto-satoru/create-aws-kms-key>