Chinachu を SELinux 有効にして使う

https://github.com/Chinachu/docker-mirakurun-chinachu

Chinachu の docker コンテナの README から抜粋
- SELinuxの無効化推奨
無効化推奨,じゃあないんだよ!有効化しろよ!ということで,SELinux を enforcing するまでの道程です。

まず最初に,ディストリビューション。Chinachu は Debian や Ubuntu での導入記事を多く見受けますが,今回は REHL/Fedora/CentOS 系統を使います。
SELinux のデフォルトのポリシーが充実してるのがその理由。
次に,Chinachu はコンテナ化したものを用います。Chinacu は npm のモジュールをローカルにインストールしたり ffmpeg をビルドしたり,パッケージ以外から導入するものが多すぎなので,それに対してラベル付けたりポリシーを書いたりするのがダルいからです。

私は Fedora 27 で設定を行い,この記事を書いてます。

では前置きはここまでにして,以下手順

1. SELinux 有効化
CentOS の場合は先にパッケージを入れておきましょう。
# yum -y install selinux-policy-targeted setools
とはいっても Red Hat 系のディストリビューションはデフォルトで有効のはずです。CentOS はパッケージいれてから再起動が必要ですが。

デ フ ォ ル ト で 有 効 の は ず で す が

もし無効化してたなら,とりあえず /etc/selinux/config の中で SELINUX=permissive にして再起動しときましょう。
なお,現状だと,docker のストレージに btrfs を使っていて,それで docker pull をすると,SELinux が enforcing のときだとコケるっぽいです。解決中。まあ pull のときだけ permissive にしてサービス動かしだしてから enforcing でも困らん気がする。

2. ラベリング

docker-compose.yml の volumes を次のように設定していると仮定します。
services:
    mirakurun:
        (略)
        volumes:
            - /etc/localtime:/etc/localtime:ro
            - /opt/tvs/mirakurun/conf:/usr/local/etc/mirakurun
            - /opt/tvs/mirakurun/db:/usr/local/var/db/mirakurun
    chinachu:
        (略)
        volumes:
            - /etc/localtime:/etc/localtime:ro
            - /opt/tvs/chinachu/conf/config.json:/usr/local/chinachu/config.json
            - /opt/tvs/chinachu/conf/rules.json:/usr/local/chinachu/rules.json
            - /opt/tvs/chinachu/data:/usr/local/chinachu/data
            - /opt/tvs/recorded:/usr/local/chinachu/recorded
そこで,次のようにします。
# semanage fcontext -a -t container_file_t '/opt/tvs/mirakurun/conf(/.*)?
# semanage fcontext -a -t container_file_t '/opt/tvs/mirakurun/db(/.*)?
# semanage fcontext -a -t container_file_t '/opt/tvs/chinachu/conf(/.*)?
# semanage fcontext -a -t container_file_t '/opt/tvs/chinachu/data(/.*)?
# semanage fcontext -a -t container_file_t '/opt/tvs/recorded(/.*)?
たまに chcon -t でラベル付けすると書いてあるブログとか見ますが,chcon は一時的なラベル付けなので,何かの拍子にラベルがデフォルトになることがあるので注意です。
docker からアクセスするディレクトリ/ファイルなので,container_file_t を設定します。このラベルはラベル

/etc/selinux/targeted/contexts/files/file_contexts.local に,先ほど設定したラベルがあるか確認してください。
Twitter で @yomi322 さんに指摘されましたが,volumes の設定を次のように変更するだけで良いようです(また,おそらくこのほうが MCS によるコンテナ間の分離も行われて善さそうです。)
services:
    mirakurun:
        (略)
        volumes:
            - /etc/localtime:/etc/localtime:ro
            - /opt/tvs/mirakurun/conf:/usr/local/etc/mirakurun:Z
            - /opt/tvs/mirakurun/db:/usr/local/var/db/mirakurun:Z
    chinachu:
        (略)
        volumes:
            - /etc/localtime:/etc/localtime:ro
            - /opt/tvs/chinachu/conf/config.json:/usr/local/chinachu/config.json:Z
            - /opt/tvs/chinachu/conf/rules.json:/usr/local/chinachu/rules.json:Z
            - /opt/tvs/chinachu/data:/usr/local/chinachu/data:Z
            - /opt/tvs/recorded:/usr/local/chinachu/recorded:Z

volume の各エントリの最後に :Z を付けてますがこれで勝手にラベリングするようです。他のコンテナと共有する volume の場合は,:Z(大文字)ではなく :z にしましょう。

3. 反映
# restorecon -R -v /opt/tvs
設定したラベルも含めてコンテキストを設定どおりに反映します。
これで,コンテナ内からホストのストレージ(の一部)へ読み書きができます。
最後に,/etc/selinux/config の中で SELINUX=enforcing にしてから,
# setenforce 1
として SELinux の強制アクセス制御を有効化します。
これだけで SELinux を有効化しながら Chinachu が使えます!やったあ!

たぶん素で Chinachu を動かすと,もっと色々手間がかかります。コンテナで隔離することは SELinux の設定の簡便さにも寄与してるんですね。
もし何か問題が起きた場合,# setenforce 0 にして enforcing から permissive に切り替え,そのあと監査ログである audit.log を眺めながら問題を修正していきましょう。


P.S.
samba_share_t を設定して samba も動かしてたのですが,Chinachu の volumes に設定しているディレクトリも samba で公開したかったので,結局 samba も docker 化して samba_share_t ではなく container_file_t にしてしまうことにしました。
ついでに docker-compose の version 3 に対応した設定ファイルにして,https://github.com/CWSpear/local-persist

ところで,この記事は,samba の docker 化の動作確認として別ホストの Kodi から samba 経由で録画を再生しているのですが,適当に選んだ録画がたまたま「ゆるゆり! なちゅやちゅみ!+」でした。再生しながらちなつちゃんが出てきたところで,そういえば Chinachu ってゆるゆり!由来だった!と気がついたのですが,自分の頭の血の巡りの悪さに愕然としたところです。