背景

サービスを利用するとき、提供者に悪意があることを前提にもの事を考えるべきである。 何かがあってからでは遅いからである。 クラウドサービスのストレージが暗号化されていないのが気に食わない。 万が一ストレージのデータが流出することに備え、ストレージを暗号化したい。 アプリケーションレイヤーではなく、fsレイヤーで暗号化したい。 さて、どうやるのかね。

透過的暗号 & 復号

gocryptfsという、透過的暗号化をディレクトリ単位でしてくれるツールがあります。 これが素晴らしい。ユーザランドで動く。すぐ動かせる。

インストール方法

sudo apt install gocryptfs  # または公式のバイナリをダウンロード

暗号化されるディレクトリの作成方法

mkdir ~/secure_data.encrypted
gocryptfs -init ~/secure_data.encrypted

復号されるディレクトリを暗号化されたディレクトリにマウント

mkdir ~/decrypted_data
gocryptfs ~/secure_data.encrypted ~/decrypted_data

gocryptfs はシンプルで信頼性が高く、後付けでも運用しやすいです。

実際に、mongodbのデータを移植した方法がこちら

# install 
sudo apt update
sudo apt install gocryptfs

# make directories
mkdir -p /secure/mongodb.encrypted
gocryptfs -init /secure/mongodb.encrypted  # パスワードを設定
mkdir /secure/mongodb

# mongodbのデータ領域の確認
docker volume inspect rocketchat_mongodb_data

# コピーを/secure/mongodbに移動 (allow_otherでしないとmongodb(非rootユーザが読めなくなる))
gocryptfs -o allow_other /secure/mongodb.encrypted /secure/mongodb
cp -a /var/lib/docker/volumes/rocketchat_mongodb_data/_data/* /secure/mongodb/

# バインドマウントからボリュームマウントに切り替える
vim compose.yml

volumes:
  - /secure/mongodb:/bitnami/mongodb

# docker composeで再起動
docker compose up -d

つまりポイント

権限回り。mongodbが実行するのですが、所有者と権限にはくれぐれもご注意。 1001をownerにしないとうまくいかないです。

gocryptfsのすごいところ

encrypted data -> decrepted dataがon the flyで実行されるってこと。これがすごい。 つまり、decrypted_dataというディレクトリ(インターフェース)を介して、 encrepted_dateのディレクトリにリアルタイムで読み書きが実行されている。

パスワードを忘れたら詰むっていうのがきついところだね。

hoge:/secure# gocryptfs -passwd /secure/mongodb.encrypted
Password: 
Decrypting master key
Please enter your new password.
Password: 

これで、パスワードの確認と更新もできます。

あと、再起動したらマウントし直す必要があります。 これも大事だね。

on the flyで暗号復号をしてくれるプロセス

root@x162-43-53-234:/secure# ^C
root@x162-43-53-234:/secure# ps aux | grep gocryptfs
root      273211  0.8  1.8 2540788 36256 ?       Ssl  19:11   1:09 /usr/bin/gocryptfs -fg -notifypid=273205 -o allow_other /secure/mongodb.encrypted /secure/mongodb
root      273220  0.0  0.1   9612  2560 ?        S    19:11   0:00 logger -t gocryptfs-273211-logger
root      292223  0.0  0.1   7080  2048 pts/0    S+   21:34   0:00 grep --color=auto gocryptfs

最後に気になったこと

root@x162-43-53-234:/secure# ls -la
total 136
drwxrwxrwx  4 root root  4096 May  3 18:57 .
drwxr-xr-x 23 root root  4096 May  3 18:57 ..
drwx------  3 1001 1001 65536 May  3 20:50 mongodb
drwx------  3 1001 1001 65536 May  3 20:50 mongodb.encrypted

これ、rootがmongodb.encryptedに書き込むと思うんだけど。 所有者はrootでない & パーミッション的にもrootは書き込めない。なのに問題なく動いている。 なんで??

✅ 結論:大丈夫な理由

  1. gocryptfs は root 権限で起動している /secure/mongodb.encrypted に直接アクセスするのは mongod ではなく、gocryptfs プロセス。 gocryptfs が root 権限で動作していれば、実体である /secure/mongodb.encrypted の読み書きは root によって問題なく実行可能。

  2. FUSE の allow_other オプションを使っている allow_other により、他ユーザー(この場合は MongoDB ユーザー=UID 1001)にも /secure/mongodb(復号ディレクトリ)へのアクセスが許可される。これがなければ、MongoDB は復号ディレクトリにアクセスできない。

  3. /secure/mongodb は FUSE 経由の仮想ディレクトリ MongoDB が実際に触っているのは 暗号化されたデータではなく、復号後のデータ(FUSEマウント)。

その裏で、gocryptfs が /secure/mongodb.encrypted に対して「暗号化・復号化」を自動で行っている。

🧠 まとめ(シンプル版)

/secure/mongodb.encrypted の所有者が 1001:1001 でも問題ない。

理由は: gocryptfs が rootで起動しているので、root がその中を操作できる。 allow_other を指定しているので、MongoDB(UID 1001)も /secure/mongodb にアクセスできる。 結果として、MongoDB は 復号された仮想ディレクトリを通して通常通り動作する。

あー研究室の環境が特殊だった

自分は、rootでも権限がないと見られないということがあるのでは??と思っていたが、rootは基本的には全てのファイルとディレクトリにアクセス 可能な権限を持っている

「root 他人のディレクトリ」は、一般的にLinuxなどのオペレーティングシステムにおけるセキュリティ上の問題や権限の取り扱いに関連するキーワードです。rootユーザーは、システム管理者の権限を持つユーザーで、すべてのファイルやディレクトリにアクセス可能です。したがって、他人のディレクトリにアクセスすることは、そのユーザーのプライバシーを侵害する可能性があり、場合によっては不正アクセスとみなされることもあります。

自分が所属していた研究室では、rootになっても他人のディレクトリを見られないことがあった。 しかしそれはADだったからで、単一のマシン内ではルートは全てのファイルを見られる。OK。理解しました。

ちなみにファイルシステムを見ると、ちゃんとマウントされているし動いている

root@x162-43-53-234:~# df -h
Filesystem                 Size  Used Avail Use% Mounted on
tmpfs                      197M  1.4M  195M   1% /run
efivarfs                   256K   25K  227K  10% /sys/firmware/efi/efivars
/dev/vda1                   48G   28G   20G  59% /
tmpfs                      982M     0  982M   0% /dev/shm
tmpfs                      5.0M     0  5.0M   0% /run/lock
/dev/vda16                 881M  112M  707M  14% /boot
/dev/vda15                 105M  6.1M   99M   6% /boot/efi
tmpfs                      197M   28K  197M   1% /run/user/0
/secure/mongodb.encrypted   48G   28G   20G  59% /secure/mongodb

これすげーわ。