«前の日記(2017-05-13) 最新 次の日記(2017-08-30)» 編集

meta's blog - The Power To Serve

筆者について

FreeBSDを通じてOSSにささかな貢献を。

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ファイルで管理するというタイトルの要件は満たしていません。

そこで、AuthorizedKeysCommandAuthorizedKeysCommandUser を使います。これらの詳しい使い方については 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 でない上記スクリプト実行用のユーザ