Linux Advent Calendar 2017 の23日目です。
SSHなどでリモートのLinuxサーバーにログインするときは鍵認証を使えるため、パスワード認証を使う機会は少ないだろうと思います。
しかしデスクトップPCへのログインはどうでしょうか。まだまだパスワードが使われていますし、オンプレで設置している物理サーバーのrootパスワードを複数人で共有するといった運用もまだ残っているのではないでしょうか。
こんな時、物理的な認証トークンがあればずっと安全な運用になるのですが、私達はそんなデバイスを既に持っているではありませんか。そう、マイナンバーカードです。
今回はマイナンバーカード内の鍵でLinuxにログインしたり、sudoしたり、多要素認証デバイスとしてカードを活用する方法を紹介します。
LinuxにはPAMという認証モジュールとアプリケーションを分離するための仕組みが用意されています。
デフォルトの認証モジュール(pam_unix.so)は/etc/shadow
を参照してパスワード認証を行っていますが、パスワード認証以外にも様々な認証モジュール用意されていて、独自の認証モジュールを自作することだってできます。
PKCS#11に対応したデバイスで認証するためのpam_p11というPAMモジュールがあります。マイナンバーカードは既にOpenSC経由でPKCS#11 APIを扱えるようになっていますので、pam_p11.soからOpenSCのpkcs11モジュールをロードすればうまくいきそうです。
インストール
まずJPKIに対応したOpenSC 0.17とlibpam-p11をインストールします。
Debian Buster以降やUbuntu 17.10 Artful以降は標準でOpenSC 0.17が入っていますのでaptでインストールできます。 それ以外の方は自分でビルドしてください。
# apt install opensc libpam-p11
公開鍵の設置
pam_p11はユーザーのホームディレクトリに配置した公開鍵または証明書を参照してカードの所有を確認します。
公開鍵はSSHと同様に ~/.ssh/authorized_keys
に設置します。
ちょっと紛らわしいですがsshdだけでなくloginやsudoなどのプログラムがPAM経由でこのファイルを参照するということです。
以下のコマンドで公的個人認証の公開鍵を配置します。
$ mkdir ~/.ssh/
$ pkcs15-tool --read-ssh-key 1 >> ~/.ssh/authorized_keys
あるいは、証明書で認証する場合は ~/.eid/authorized_certificates
にPEM形式の証明書を配置します。
以下のコマンドで公的個人認証の証明書を配置します。
$ mkdir ~/.eid/
$ pkcs15-tool -r 1 >> ~/.eid/authorized_keys
PAMの設定
続いてPAMの設定を行いますが、今回はマイナンバーカードを利用した認証方式として、
- マイナンバーカードだけで認証
- マイナンバーカードとUNIXパスワードの両方を必要とする二要素認証
- マイナンバーカードとUNIXパスワードのどちらか一つを必要とする認証
の構成例を紹介します。
DebianやUbuntuでは共通のPAM設定ファイル/etc/pam.d/common-auth
に以下の様な記述が見つかるはずです。
auth [success=1 default=ignore] pam_unix.so nullok_secure
auth requisite pam_deny.so
(略)
この辺りを変更していきます。
マイナンバーカードだけで認証
これがマイナンバーカードだけで認証する設定例です。pam_unix.so
の設定をpam_p11_openssh.so
で置き換えます。
-auth [success=1 default=ignore] pam_unix.so nullok_secure
+auth [success=1 default=ignore] pam_p11_openssh.so opensc-pkcs11.so
auth requisite pam_deny.so
(略)
pam_p11_openssh.so
は設置した公開鍵~/.ssh/authorized_keys
を参照しますので証明書を設置した場合はpam_p11_opensc.so
に置き換えてください。
Ubuntuのログイン画面(gdm3)ではこの様にパスワードの代わりにカードの暗証番号を入力します。
他のログインマネージャーでも動作するはずです。
マイナンバーカードとUNIXパスワードの両方を必要とする二要素認証
以下のようにpam_unix.so
の前にpam_p11
の設定を記述します。
+auth [success=1 default=ignore] pam_p11_openssh.so opensc-pkcs11.so
+auth requisite pam_deny.so
auth [success=1 default=ignore] pam_unix.so nullok_secure
auth requisite pam_deny.so
(略)
たとえばこれでsudo su
を実行するとJPKI認証用の暗証番号を入力した後に通常のパスワードを入力し両方の認証が通ってからrootに成れます。
$ suod su
Password for token User Authentication PIN (JPKI): ****
[sudo] hamano のパスワード: ********
# id
uid=0(root) gid=0(root) groups=0(root)
マイナンバーカードとUNIXパスワードのどちらか一つを必要とする認証
+auth [success=2 default=ignore] pam_p11_openssh.so opensc-pkcs11.so
auth [success=1 default=ignore] pam_unix.so nullok_secure
auth requisite pam_deny.so
(略)
/etc/pam.d/以下の設定はしくじるとログインできなくなるので慎重にやりましょう。