背景
gitolite って?
- gitolite : ユーザごとのアクセス権管理などなどができる git hosting ツール
- gitosis : gitolite よりちょっと古いやつ、似たようなもの
ユーザ管理はどんな仕組み?
http://qiita.com/yuku_t/items/46d1d834fbdae271d66c の記事が大変わかり易いです。
gitolite / gitosis は SSH authorized_keys の command=xx
機能を使っており、
gitolite 自身が持つ管理リポジトリ内に gitolite-admin.git/keydir/username.pub
といったユーザ名の公開鍵を配置して push することで、hosting ユーザの authorized_keys に各ユーザの公開鍵が識別可能な形で追記される。
gitosis もこの辺は同様なので以下 gitosis については省略。
やりたいこと
- LDAP サーバによって組織ユーザの公開鍵が集中管理されている状況において、その鍵とユーザ識別子を使って gitolite を使いたい。
-
gitolite-admin.git/keydir/
には LDAP で管理されているユーザの鍵をダブって管理させたくない。 - LDAP サーバに無いユーザが使うケースを考慮し、従来通り
keydir
に入れたものも併用できるようにしておきたい。
前提
LDAP 上のデータ
LDAP サーバからユーザ識別子と公開鍵 (それぞれ uid
, sshPublicKey
という属性名とする) が取得できること。
$ ldapsearch ${MY_QUERY} -o ldif-wrap=no -LLL 'uid' 'sshPublidKey' | my_filter_cmd
uid: user1-name
sshPublicKey: ssh-rsa AAAAxxxxxxxxxxxxx...
uid: user2-name
sshPublicKey: ssh-rsa AAAAyyyyyyyyyyyyy...
uid: user3-name
sshPublicKey: ssh-rsa AAAAzzzzzzzzzzzzz...
のような出力が得られるものとする。
gitolite 設定
hosting ユーザは git
とする。
$ git clone git@gitolite-server.com:myrepository.git
のようにして使える状態。
gitolite コマンドユーティリティは /home/git/bin
にインストールされ、setup により下記のような authorized_keys
を生成しているものとする。
# gitolite start
command="/home/git/bin/gitolite-shell admin",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAxxxxxxxxxxxyyyyyyyyyyyyyyyzzzzzzzzzzzzzz admin@somehost
command="/home/git/bin/gitolite-shell localuser",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAaaaaaaaaaaaaaabbbbbbbbbbbbbbbbcccccccc localuser@somehost
...
# gitolite end
実現方法
案1. LDAP 参照用の authorized_keys を分ける (汎用)
従来の方法で git
ユーザが参照する $HOME/.ssh/authorized_keys
はそのままにし、LDAP からの情報をセカンダリで参照するファイルに持っておく。
AuthorizedKeysFile %h/.ssh/authorized_keys %h/.ssh/ldap_authorized_keys
/usr/local/bin/gitolite-ssh-ldap
のような LDAP のデータを上手いこと整形するスクリプトを作成し、以下のような出力が得られるようにする。
$ /usr/local/bin/gitolite-ssh-ldap gitolite
command="/home/git/bin/gitolite-shell user1-name", no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAxxxxxxxxxxxxx... user1-name@somehost
command="/home/git/bin/gitolite-shell user2-name", no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAyyyyyyyyyyyyy... user2-name@somehost
command="/home/git/bin/gitolite-shell user3-name", no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAzzzzzzzzzzzzz... user3-name@somehost
...
...
上記の結果を定期的に拾うなどしてセカンダリの authorized_keys ファイルに書き込む。
*/30 * * * * git /usr/local/bin/gitolite-ssh-ldap gitolite > /home/git/.ssh/ldap_authorized_keys
これでOK。sshd が両方を参照して認証を行うので gitolite-admin.git/keydir
から生成された既存の鍵も変更無しで使用可能。他の一般ユーザに対しても、 $HOME/.ssh/ldap_authorized_keys
が無ければ何も起きないので多くの場合は競合しないと思われる。
この方法では定期的にデータを拾っているため、LDAP サーバ上のデータ反映に多少の時間差が発生する。
案2. sshd の AuthorizedKeysCommand を使う (要 openssh-server >= 6.2)
このオプションについて
AuthorizedKeysCommand
を使うと、SSH 認証時に実行する任意のコマンドを指定できる。ここに指定したコマンドにはログインユーザ名が渡され、そのユーザの公開鍵が標準出力されることが期待される。例えば下記のような挙動をするコマンドを指定する。
$ my_pubkey_cmd user-name
ssh-rsa AAAAaqwsedrftgyhujiko.... user-name@somehost
openssh-server >= 6.2 以降で有効になっている。Ubuntu の場合は 13.10 から公式パッケージが配布されている。
スクリプト準備
hosting のユーザ名が渡ってきた場合のみ異なる挙動をするコマンドを作成する。
前述の上手いこと整形するスクリプト /usr/local/bin/gitolite-ssh-ldap
もあるものとすると、下記のように引数で渡されたユーザで出力を分岐させる。
#!/bin/sh
...
...
case $1 in
git)
# gitolite 用に LDAP 上の複数ユーザの鍵を command="/home/git/bin/gitolite-shell を含んだ形で出力
/usr/local/bin/gitolite-ssh-ldap gitolite
;;
*)
# 普通に個人の鍵を出力
/path/my_pubkey_cmd $1
;;
esac
sshd 設定
先ほどのコマンドを指定することで gitolite のユーザ認証と連携する。
AuthorizedKeysCommand /usr/local/bin/gitolite-helper
AuthorizedKeysCommandUser git
これで OK。まず AuthorizedKeysCommand
で認証が試みられ、その中にマッチする鍵がなければ AuthorizedKeysFile
などの次の認証にうつるため既存の方法も併用できる。
SSH 毎に LDAP サーバに取りにいけるためリアルタイムで反映できるが、ユーザ数が増えると重くなりやすいのと、前の方法よりも sshd への影響が大きいので他のサービスと共存しているような場合にあまり向かない。