筆者について
FreeBSDを通じてOSSにささかな貢献を。
- 日本xrdpユーザ会発起人
- xrdp developer
- FreeBSD developer
OSS活動をご支援いただける方を募集しています
2017-08-29
■ OpenSSH で全ユーザの公開鍵を1ファイルで管理する
この記事は、OpenSSH 6.6以上を使うことを前提とします。
OpenSSH ではユーザの公開鍵は通常 $HOME/.ssh/authorized_keys に置きますが、
- 各ユーザのホームディレクトリに置くので管理者権限で鍵を追加する際にオーナー&パーミッションを意識するのが面倒
- 置き場がホームディレクトリだと予めホームディレクトリを作成しなければならないのを避けたい (mkhomedir)
- ホームディレクトリを持たないまたは揮発性のホームディレクトリを持つユーザにログインさせたい
- ユーザに勝手に鍵を追加させたくない(管理者が鍵の追加・削除をコントロールしたい)
など、いくつかの理由で違う場所に置きたい場合もあります。
例えば sshd_config 内の AuthorizedKeysFile を使い、
AuthorizedKeysFile /etc/ssh/authorized_keys_%u
とすれば、ユーザごとに /etc/ssh/authorized_keys_<ユーザ名> というファイルが使われ、公開鍵ファイルを1ヶ所にまとめることができますが、ユーザごとに1ファイルとなっていて、全てを1ファイルで管理するというタイトルの要件は満たしていません。
そこで、AuthorizedKeysCommand と AuthorizedKeysCommandUser を使います。これらの詳しい使い方については man ページを参照してください。仕組みを雑に説明すると AuthorizedKeysCommand を使い、特定のユーザの公開鍵を検索して、その公開鍵を認証に使うというからくりです。
まず、全ユーザの公開鍵を置くファイルのフォーマットを考えます。ただ公開鍵を並べただけでは、どの鍵がどのユーザのものかという情報がないので、それを付け加えてやるだけです。今回は以下のようなフォーマットにしました。
%ユーザ名%公開鍵
具体的にはこんな感じ。
%alice%ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCg+hAJJvTWHD1Rv+H5RWu30QXXHRoLHdZbfUydG7... %bob%ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCh2o84D5La+7LnURTMJNYrNlL0v6BsTAa7Sg27BF...
このファイルからユーザごとの公開鍵を検索するためのコマンドを作成します。要件は引数にユーザ名が与えられたときに、通常の authorized_keys と同様の鍵リストを返すこと。
シェルスクリプトで実装して、こんな感じになります。/etc/ssh/authorized_keys というのは、上記のフォーマットで記述された、全ユーザの公開鍵を1つにまとめたファイルです。
#!/bin/sh AUTHORIZED_KEY_FILE=/etc/ssh/authorized_keys PATTERN="^%${1}%" if [ $# -ne 1 ]; then exit 1 fi grep ${PATTERN} ${AUTHORIZED_KEY_FILE} | sed -e "s|${PATTERN}||"
このスクリプトを /etc/ssh/find_authorized_keys.sh として保存して、所有者を root にし、所有者以外からは書き換えられないパーミッションにしておきます。
このスクリプトは AuthorizedKeysCommand を実行するための専用ユーザで実行することが推奨されているので、適切にパーミッションを設定します。実行するユーザは AuthorizedKeysCommandUser で指定しますが、これは必須です。また、前述の /etc/ssh/authorized_keys ファイルも当該ユーザで読めるパーミッションにする必要があります。
設定の差分を抜粋するとこんな感じ。sshd_config を書き換えたら、sshd を再起動してログインできることを確認。
AuthorizedKeysFile none # 通常の $HOME/.ssh/authorized_keys を無効化するため AuthorizedKeysCommand /etc/ssh/find_authorized_keys.sh # nobody ユーザで実行できるようにしておく AuthorizedKeysCommandUser nobody # root でない上記スクリプト実行用のユーザ