コンテナでcronを動かした時に出るPAMエラーの対処法

Jul 15, 2015   #Docker  #Cron  #PAM  #Linux 

Dockerで動かしているコンテナ上でcron(やsshd)を使おうとすると、PAMに引っかかってタスクが実行されません。 ネットで調べるとPAMの設定ファイルを変更する方法は出てくるのですが、そもそもPAMに引っかかる理由について言及しているケースがなかったので、自分で書きます。

事象の内容

このページを見ている方は既にご存知かと思いますが念のため。 コンテナでCronを起動すると、タスクの実行時にこんなエラーを吐いて実行されません。

cat /var/log/cron
Jul 16 05:26:01 badc11b5db52 crond[52]: (root) FAILED to open PAM security session (Cannot make/remove an entry for the specified session)
cat /var/log/secure
Jul 16 05:26:01 badc11b5db52 crond[52]: pam_loginuid(crond:session): set_loginuid failed

ネットでよくある解決法

ログに出ている通り、crondのpam_loginuidで失敗しています。 ネットで調べると、/etc/pam.d/crondの一部をコメントアウトすればOK、という情報がよく出てきます。

cat /etc/pam.d/crond
#
# The PAM configuration file for the cron daemon
#
#
# No PAM authentication called, auth modules not needed
account    required   pam_access.so
account    include    password-auth
# session    required   pam_loginuid.so
session    include    password-auth
auth       include    password-auth

確かに上記のようにpam_loginuid.soの行をコメントアウトすれば動きます。 ですが、解決できる理由が不明なので深掘りしてみます。

そもそもPAMでエラーが起きる理由

ホストでは問題なくcronが動くのに、なぜコンテナでは失敗するのか。

それは、コンテナに付与されたCapabilityが不足しているからです。

PAMはカーネルが持つAUDIT機能(Capabiliry)を使って認証を行っており、ホストはAUDITを利用できるので問題無しです。 しかし、コンテナは利用できるCapabilityが制限されている(AUDITが使えない)ため問題が起こります。

※制限がないと非常に危険で、コンテナからホストに影響を与えることができます(カーネルモジュールをいじったり、時刻を変えたり)。

参考:Capabilityのリスト
capabilities(7) - Linux manual page

参考:コンテナが利用できるCapability
default_template.go

default_template.goを見ると、CAP_AUDIT_WRITEはデフォルトで付与されるようになっていますがCAP_AUDIT_CONTROLが外れています。 これが怪しいですね。

解決策

動かないロジックが何となくわかったところで、解決策を考えてみます。

解決策1:privilegedでコンテナを起動する

単純な解決策としては、コンテナをprivilegedで起動する方法です。

docker run -it --privileged centos:6

privilegedであれば制限がなくなり、ホストのように振る舞えます。 しかし、前述の通り制限がないというのは危険な状態です。

解決策2:コンテナに対しCapabilityを追加する

コンテナに対し、一部だけCapabilityを付与することも可能です。 一部だけ付与するには、docker runの時に--cap-addを使います。

docker run -it --cap-add=AUDIT_CONTROL centos:6

この方法でもPAM越えできます。

ちなみに、付与したCapabilityはdocker inspectで確認可能です。

"HostConfig": {
    "Binds": null,
    "CapAdd": [
        "AUDIT_CONTROL"
    ],

解決策3:PAMの設定ファイルをコメントアウト

冒頭に書いた、PAMの設定ファイルを変更する方法です。 Docker公式で、PAM設定をコメントアウトしている例もありました。

cat /etc/pam.d/crond
#
# The PAM configuration file for the cron daemon
#
#
# No PAM authentication called, auth modules not needed
account    required   pam_access.so
account    include    password-auth
# session    required   pam_loginuid.so
session    include    password-auth
auth       include    password-auth

まとめ

現実的にはAUDIT_CONTROLだけ付与するか、コメントアウトの2択ですかね。 理由を知ってコメントアウトするのと、動くから良いでしょ的にコメントアウトするのは全然違うと思いますので、参考になれば幸いです。