読者です 読者をやめる 読者になる 読者になる

gitoliteはどうやってユーザを判別しているか

ちょっとしたコネタの紹介

gitリポジトリを複数人で共有する時に、AさんはこのリポジトリにコミットできるがBさんはダメ、といった風にアクセス制御をしたくなるが、それを実現するソフトウェアでgitoliteというモノがある。

gitoliteを`host`に`git`というユーザ名でインストールし`reponame`というgitリポジトリを登録すると`ssh://git@host:reponame.git`でアクセス制御をすることができる。
当然ながらこれは`host`に`git`というユーザ名でSSH接続することを意味する。

で、不思議なのはgitoliteは一体どうやってユーザの判別をしているのか、ということだ。

なんせgitoliteはサーバ上にインストールされているのだから、gitoliteから見たらどのアクセスも`git`というユーザなのだ。どうやってgitoliteは「このアクセスはid:yuku_tからだ」という風に判断しているのだろう。(むしろこれができなければアクセス制御なんてできっこない)

答えは`git`ユーザの`authorized_keys`ファイルにある。

`authorized_keys`が単なる公開鍵置き場だと思ったら大間違い。実はもっといろいろな設定ができるのだ。
以下にgitoliteによって自動作成される`authorized_keys`の例を引用する。(見やすさのために適宜改行をいれている)

# gitolite start
command="/home/git/gitolite/src/gitolite-shell yuku_t",
no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
ssh-rsa AAAAB3NzaC1y...== yuku_t
# gitolite end

`ssh-rsa`以降が普段我々が公開鍵を設定している箇所だ。
そしてその前半部分に`command`や`no-port-forwarding`など見覚えのない部分がある。
実はsshdは公開鍵でユーザの認証を取ったあとの制御をこの部分で記述することができるのだ。
そして、`command`というのがユーザがログイン後に実行するコマンドになる。よくよく見てみると

command="/home/git/gitolite/src/gitolite-shell yuku_t"

`gitolite-shell`というコマンドに対して引数でユーザ名が渡されている。
先ほどの疑問の答えがこれで、このスクリプトの中でアクセス制御が行われる。
またこのユーザ名は`$GL_USER`という環境変数に格納されるためgitoliteで管理されているgitリポジトリのhookの中でユーザの判別もできる、という訳。

なかなか面白い実装だと思う。