SELinuxを有効化したままDockerコンテナから/var/run/docker.sockを使用する

Computer 9月 19, 2022
(Last Updated On: )

必要になる度に調べているのでメモ。少なくともRHEL系はこれで動くようになるはずです。出来れば/var/run/docker.sockにアクセスが必要なコンテナだけにアクセス許可を与えたいのですが良い方法を思い付きません。それでもSELinuxを無効化するより/var/run/docker.sockだけアクセス可能のする方がホストの安全性は高くなります。そもそもボリューム(ファイル)にアクセスできないとアクセスできないので、ほとんどの環境※では、リスクは大きく増えないでしょう。

※ Dockerコンテナを作る人を信用できない場合、無視できないリスクがあります。コンテナ好き勝手に弄られる可能性があります。古いDockerがloopbackでコマンドを受け付けていた時に外部ユーザーから好き勝手にコンテナを弄られる脆弱性がありました。これと同じです。

SELinuxのタイプエンフォースメントファイルを作成

dockersock.te

module dockersock 1.0;

require {
	type docker_var_run_t;
	type docker_t;
	type svirt_lxc_net_t;
	class sock_file write;
	class unix_stream_socket connectto;
}

allow svirt_lxc_net_t docker_t:unix_stream_socket connectto;
allow svirt_lxc_net_t docker_var_run_t:sock_file write;

コンパイル済みのポリシーパッケージファイルの作成とインストール

checkmodule -M -m -o dockersock.mod dockersock.te
semodule_package -o dockersock.pp -m dockersock.mod
semodule -i dockersock.pp

これでPortainerなどコンテナマネージャーコンテナなどが動くようになります。出来ればホストのUNIXドメインソケットへのアクセスを全て許可するのではなく、/var/run/docker.sockに限定したい所です。これを実現するには色々設定が必要なのでこれでOKとします。

SELinuxはアクセスエラーログからポリシーを作ってインストールできるので、エラーログからの作成するのが一般的でしょう。

grep <program_name> /var/log/audit/audit.log | audit2allow -­R -­M <program_name>
semodule ­-i <program_name>.pp

これで作ると余計な許可設定までしてしまう事が多いので、audit2whyで確認してからポリシーをインストールした方が良いです。

Portainerが起こしたSELinuxエラーは以下の通りです

type=AVC msg=audit(1663501403.842:1368): avc:  denied  { connectto } for  pid=59848 comm="portainer" path="/run/docker.sock" scontext=system_u:system_r:container_t:s0:c36,c892 tcontext=system_u:system_r:container_runtime_t:s0 tclass=unix_stream_socket permissive=0
	Was caused by:
		Unknown - would be allowed by active policy
		Possible mismatch between this policy and the one under which the audit message was generated.

		Possible mismatch between current in-memory boolean settings vs. permanent ones

このエラーからaudit2allowでポリシーを作るとこうなります。

#============= container_t ==============

#!!!! This avc is allowed in the current policy
allow container_t container_runtime_t:unix_stream_socket connectto;

これでソケットへのアクセスを許可しても、書き込みができないとコンテナ管理ができないです。接続許可をした後に起きる書き込みエラーも許可する必要があります。ということで最初に書いたteファイルをコンパイルしてインストールするのが手っ取り早いです。

この程度ならスイッチで有効化できそうですが

semanage boolean -l | grep -i docker

とすると空です。booleanのスイッチで設定できれば良いのですが、RedHatはDockerでなくPodman推しなので可能性はないでしょう。

投稿者: yohgaki