はじめに
Elasticsearchのデータ暗号化について、検討する機会があったので、記事にまとめてみました^^:
利用した環境
product | version |
---|---|
cryptsetup | 1.7.4 |
Elasticsearch | 6.6.0 |
OS | Amazon Linux2 (4.14.88) |
Instance Type | m5.2xlarge |
EBS | ルート(8GB)、追加(30GB) |
AMI | ami-04677bdaa3c2b6e24 |
【ディスクの状態】
nvme0n1
が8GBのルートボリューム、nvme1n1
が追加の30GBボリュームです。
※m5はNitro世代のEC2インスタンスでEBS NVMeボリュームのため、/dev/nvmeXnX
という名称
[root@ip-172-31-34-49 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme1n1 259:0 0 30G 0 disk
nvme0n1 259:1 0 8G 0 disk
├─nvme0n1p1 259:2 0 8G 0 part /
└─nvme0n1p128 259:3 0 1M 0 part
[root@ip-172-31-34-49 ~]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 16G 0 16G 0% /dev
tmpfs 16G 0 16G 0% /dev/shm
tmpfs 16G 388K 16G 1% /run
tmpfs 16G 0 16G 0% /sys/fs/cgroup
/dev/nvme0n1p1 8.0G 1.2G 6.9G 15% /
tmpfs 3.1G 0 3.1G 0% /run/user/1000
基本的な考え方
Elasticsearchのデータ(=Index)暗号化では、日立ソリューションズ社のCredeon Secure Full-text Searchがありますが、あくまで全文検索のためのIndex暗号化であって、Kibanaが利用するaggregation
機能には対応していません。
Elastic Stackでは5.3.0から保存データの暗号化に対応しています。
サブスクリプションのPlatinum Editionで対応していますが、あくまでdm-crypt
を用いたボリュームの暗号化を利用した場合でもElasticsearchとしてサポートするというものです。暗号化機能が付いている訳ではありません。
dm-cryptとは
Device-Mapperの機能の1つでLinuxにおけるブロックデバイス暗号の仕組みです。
Kernel 2.6以降のdevice-mapperモジュールに標準で組み込まれていて、cyptsetup
という暗号化管理ツールを使ってストレージデバイスの暗号化を行います。
【参考】
・LUKSとは?
設定手順
- Java 1.8.0 インストール
- Elasticsearch 6.6.0 インストール
- JVMヒープサイズ設定
- Elasticsearch設定
- 暗号化ボリュームの設定
- Index保存領域の作成
- 設定確認
1. Java 1.8.0 インストール
Javaがインストールされていないことを確認した上でJava 1.8.0をインストールします。
[root@ip-172-31-34-49 ~]# java -version
-bash: java: command not found
[root@ip-172-31-34-49 ~]# yum install -y java-1.8.0-openjdk
<インストールの経過は省略>
[root@ip-172-31-34-49 ~]# java -version
openjdk version "1.8.0_191"
OpenJDK Runtime Environment (build 1.8.0_191-b12)
OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)
2. Elasticsearch 6.6.0 インストール
Elastic社公式のリポジトリを登録し、Elasticsearch 6.6.0をインストールします。
[root@ip-172-31-34-49 ~]# vi /etc/yum.repos.d/elastic.repo
[root@ip-172-31-34-49 ~]# cat /etc/yum.repos.d/elastic.repo
[elasticsearch-6.x]
name=Elasticsearch repository for 6.x packages
baseurl=https://artifacts.elastic.co/packages/6.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
[root@ip-172-31-34-49 ~]# yum install -y elasticsearch
<インストールの経過は省略>
[root@ip-172-31-34-49 ~]# systemctl status elasticsearch
● elasticsearch.service - Elasticsearch
Loaded: loaded (/usr/lib/systemd/system/elasticsearch.service; disabled; vendor preset: disabled)
Active: inactive (dead)
Docs: http://www.elastic.co
3. JVMヒープサイズ設定
Elasticsearchには物理メモリの半分を上限にJVMヒープを割り当てます。
m5.2xlargeのメモリは32GBなので、今回は15GBのメモリを割り当てます。
[root@ip-172-31-34-49 ~]# vi /etc/elasticsearch/jvm.options
-Xms15g
-Xmx15g
# 以下、設定の確認です。
[root@ip-172-31-34-49 ~]# cat /etc/elasticsearch/jvm.options | grep 15
4. Elasticsearch設定
ElasticsearchのIndex保存領域をpath.data
で指定します。今回は/mnt/es/elasticsearch
とします。
[root@ip-172-31-34-49 ~]# vi /etc/elasticsearch/elasticsearch.yml
path.data: /mnt/es/elasticsearch
# 以下、設定の確認です。
[root@ip-172-31-34-49 ~]# cat /etc/elasticsearch/elasticsearch.yml | grep path.data
5. 暗号化ボリュームの設定
cryptsetupコマンドで/dev/nvme1n1
にAES256/SHA1暗号化ボリューム(esvol
)を作成し、/mnt/es
にマウントします。
[root@ip-172-31-34-49 ~]# cryptsetup --key-size 512 --hash sha512 luksFormat /dev/nvme1n1
WARNING!
========
This will overwrite data on /dev/nvme1n1 irrevocably.
Are you sure? (Type uppercase yes): YES
Enter passphrase: #パスワードを設定
Verify passphrase: #パスワードの確認
[root@ip-172-31-34-49 ~]# cryptsetup luksOpen /dev/nvme1n1 esvol
Enter passphrase for /dev/nvme1n1: #上記で設定したパスワードを入力
[root@ip-172-31-34-49 ~]# ls /dev/mapper
control esvol
[root@ip-172-31-34-49 ~]# mkfs.ext4 /dev/mapper/esvol
mke2fs 1.42.9 (28-Dec-2013)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
1966080 inodes, 7863808 blocks
393190 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=2155872256
240 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done
[root@ip-172-31-34-49 ~]# mount /dev/mapper/esvol /mnt/es
[root@ip-172-31-34-49 ~]# ll /mnt
total 4
drwxr-xr-x 3 root root 4096 Feb 10 18:29 es
暗号化ボリュームが作成されていることを確認します。
[root@ip-172-31-34-49 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme1n1 259:0 0 30G 0 disk
└─esvol 253:0 0 30G 0 crypt /mnt/es
nvme0n1 259:1 0 8G 0 disk
├─nvme0n1p1 259:2 0 8G 0 part /
└─nvme0n1p128 259:3 0 1M 0 part
[root@ip-172-31-34-49 ~]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 16G 0 16G 0% /dev
tmpfs 16G 0 16G 0% /dev/shm
tmpfs 16G 392K 16G 1% /run
tmpfs 16G 0 16G 0% /sys/fs/cgroup
/dev/nvme0n1p1 8.0G 1.5G 6.6G 19% /
/dev/mapper/esvol 30G 45M 28G 1% /mnt/es
tmpfs 3.1G 0 3.1G 0% /run/user/1000
6. Index保存領域の作成
/mnt/es配下にelasticsearch
ディレクトリを作成し、適切な権限を付与します。
[root@ip-172-31-34-49 elasticsearch]# cd /mnt/es
[root@ip-172-31-34-49 es]# mkdir elasticsearch
[root@ip-172-31-34-49 es]# chown elasticsearch:elasticsearch elasticsearch/
[root@ip-172-31-34-49 es]# chmod 750 elasticsearch/
[root@ip-172-31-34-49 es]# ll
total 20
drwxr-x--- 2 elasticsearch elasticsearch 4096 Feb 10 21:47 elasticsearch
drwx------ 2 root root 16384 Feb 10 18:29 lost+found
Elasticsearchをサービス起動し、path.data
配下にNodeIDファイル(node-0.st
)が生成されていることを確認します。
[root@ip-172-31-34-49 es]# systemctl start elasticsearch
[root@ip-172-31-34-49 es]# cat elasticsearch/nodes/0/_state/node-0.st
?lstate:)
node_idUWTgg6zqmS2Cq72YdCOdCpA(
7. 設定確認
- 暗号化した30GBの追加EBSボリュームのSnapshotを作成します。
- 作成したSnapshotから別途EBSボリュームを作成し、別EC2にアタッチします。
EBSをアタッチしたEC2にログインし、追加EBSとしてnvme1n1
が存在していることを確認します。
[root@ip-172-31-6-22 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1 259:0 0 100G 0 disk
├─nvme0n1p1 259:1 0 100G 0 part /
└─nvme0n1p128 259:2 0 1M 0 part
nvme1n1 259:3 0 30G 0 disk
[root@ip-172-31-6-22 ~]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 3.8G 0 3.8G 0% /dev
tmpfs 3.8G 0 3.8G 0% /dev/shm
tmpfs 3.8G 380K 3.8G 1% /run
tmpfs 3.8G 0 3.8G 0% /sys/fs/cgroup
/dev/nvme0n1p1 100G 2.2G 98G 3% /
tmpfs 763M 0 763M 0% /run/user/1000
/mnt/esにマウントし、内容を確認してみます。
[root@ip-172-31-6-22 ~]# mkdir /mnt/es
[root@ip-172-31-6-22 ~]# mount -o discard /dev/nvme1n1 /mnt/es
mount: /mnt/es: unknown filesystem type 'crypto_LUKS'.
まとめ
LUKSで暗号化したボリュームを他マシンにマウントしても認識しませんでした。
これでElasticsearchノードにログインされない限り、OSレベルでのIndexデータの機密性は確保できました。
ElasticsearchのData Nodeをi3系インスタンスで構築し、NVMe SSDにIndexを配置することで暗号化することも可能です。
NVMe インスタンスストレージのデータは、インスタンスのハードウェアモジュールに実装されている XTS-AES-256 ブロック暗号を使用して暗号化されます。暗号化キーは、ハードウェアモジュールで作成され、NVMe インスタンスストレージデバイスごとに固有です。すべての暗号化キーは、インスタンスが停止または終了して復元できないときに破棄されます。この暗号化を無効にしたり、独自の暗号キーを指定したりすることはできません。
以上、いかがでしたでしょうか。
不明な点、誤植などありましたら、コメントをお願いします!!