目的
アドベンドカレンダーを埋めたい
Docker ホスト-コンテナ間でのユーザー/グループの分離をしたい。
Dockerのデフォルト設定では、コンテナ内のプロセスはroot権限で実行される。
コンテナ内のプロセスがコンテナ内のファイルシステムにのみアクセスするのであれば問題ない。
しかし、もしホストのディレクトリをコンテナにマウントすると、コンテナ内のプロセスはroot権限でマウントしたディレクトリにアクセスできてしまう。
例えば、以下のようにホストのルートディレクトリをマウントした場合、コンテナ内から/usr/src/root経由で、ホストのすべてのディレクトリにアクセスできてしまう。
docker run -it -v /:/usr/src/root
「コンテナに攻撃されても、ホストはセーフ」ということはなく、正直、どんな脆弱性を突かれるか分からないので、出来る限りのセキュリティ面での対策はしておきたい。
※コンテナ内で root として振る舞うのはいいけど、ホストでも root として振る舞われたりしたらなんて恐ろしい
その対策の一つとして、「Docker ホスト-コンテナ間でのユーザー/グループの分離」をしてみる
※同じような記事はたくさんありますが、初めて試してみたという観点で書きます(ご了承ください)
環境(ホスト)
Operating System: Ubuntu 18.04.2 LTS
Kernel: Linux 4.15.0-51-generic
Docker version 20.10.7, build 20.10.7-0ubuntu5~18.04.3
ユーザー名前空間(UID,GID)でコンテナを分離する
コンテナからの特権昇格攻撃を防ぐ方法として、コンテナのアプリケーションを特権のないユーザーとして実行するように構成する。
具体的には、プロセスがコンテナ内で root ユーザーとして実行される場合、このユーザーをDockerホスト側では、より権限の低いユーザーに再マップする。
マップされたユーザーには、名前空間内で0〜65536の通常のUIDとして機能する一連のUIDが割り当てられるが、ホストマシン自体に対する権限はない。
Dockerではこの再マップする機能を userns-remap として提供している。
userns-remap を有効化するために使うユーザー、グループを指定する
ホスト側の「/etc/docker/daemon.json」にマップするユーザー、グループを指定します。
私はこのファイルを新規で作成しました。
/etc/docker/daemon.json
{
"userns-remap": "mydockermap"
}
ホスト側にこのユーザーを作成します。
※これが存在しないと、docker のサービスを起動した時に失敗します
sudo adduser mydockermap
コンテナ内とコンテナ外でのユーザー/グループの対応付けを設定する(マッピング)
ホスト側の /etc/subuid と /etc/subgid に以下の記述を追加し、ユーザー/グループをマッピングします。
※100000は変更OK
[書式]
<ユーザー名/グループ名>:<コンテナ内でrootユーザーとして使用するUID/GID):65536
mydockermap:100000:65536
設定変更を反映するために、docker daemon を再起動する
systemctl restart docker
※ここで起動に失敗した場合、ユーザーが正しく作成されているか、typo が無いか確認する
設定が有効になっているか確認してみる
ホスト上にマウントするディレクトリを作成しておきます。
sudo mkdir /var/mounttest && ls -ld /var/mounttest
docker コンテナを起動(/var/mounttest をコンテナの /mounttest にマウントする)
※centos:7である必要はありません
docker run -it --rm -v /var/mounttest:/mounttest centos:7 bash
CHECK1:プロセスを実行しているユーザを確認すると、/etc/subuid で設定した値(100000)になっている
$ ps aux | grep 100000
100000 27081 0.0 0.0 11840 2864 pts/0 Ss+ 19:26 0:00 bash
CHECK2:/mounttest の所有者/グループが root ではなく、65534 になっている
# ls -ld /mounttest
drwxr-xr-x 2 65534 65534 4096 Dec 18 10:24 /mounttest
CHECK3:コンテナから /mounttest に対してファイル作成や権限変更は拒否されるはず
# touch /mounttest/hoge
touch: cannot touch '/mounttest/hoge': Permission denied
# chown root:root /mounttest
chown: changing ownership of '/mounttest': Operation not permitted
CHECK4:/var/mounttest の所有者を 100000 にしたら、/mounttest にファイル作成できるようになるはず
$ sudo chown 100000 /var/mounttest && ls -ld /var/mounttest
drwxr-xr-x 2 100000 root 4096 Dec 18 19:24 /var/mounttest
# コンテナ起動
$ docker run -it --rm -v /var/mounttest:/mounttest centos:7 bash
# touch /mounttest/hoge && ls -l /mounttest/
total 0
-rw-r--r-- 1 root root 0 Dec 18 10:45 hoge
補足1
/etc/subuid に手動で「mydockermap:100000:65536」を追加した後に、adduser で mydockermap を作ったので、以下のような状態になってしまった。
$ less /etc/subuid | grep mydockermap
mydockermap:100000:65536
mydockermap:296608:65536
mydockermap:296608:65536 の方を手動で削除した後、docker daemon を再起動しても動作した。同じユーザが重複して書かれている場合は、上の方に記載されているのが優先されている様子。
補足2
typo に気づかずに、動かないから、docker のバージョンを上げたり色々してたら、docker image が消えてしまった。。( ◞‸◟ )
一旦、きれいに掃除できたと捉えよう!