Git でサーバに認証したユーザと Author が同じであることを強制するフックスクリプト

Git は Subversion とは異なり、リモートサーバに認証したユーザと Author や Committer の名前が一致している必要が無いため、認証さえ通れば任意の名前でプッシュすることが出来ます(任意の Author のコミットをプッシュ出来る、の方が正しいか・・・)。


分散リポジトリだと Author や Committer とリモートサーバにプッシュするユーザが異なることがあるため、そのような制限を設けることが出来ないのだと思います。


例えば GitHub でどこかのリポジトリを Fork した場合、本家から pull して自分のリポジトリに push するときは当然コミットの Author*1と push する人*2は異なります。


以前 Subversion から Git への移行を考えていた時、Subversion のように共通のリポジトリが 1 つだけあって開発者全員がそのリポジトリにプッシュするような状況であれば、Author とリモートサーバに認証するユーザは同じになるので、プッシュ時のフックスクリプトで制限できるのでは思って作成してみました。


ただ、なんとなくその制限は Git っぽく無い気がしたのと、結局 gitolite で管理することになり、gitolite を弄るのは面倒だったので、この方法は実験だけ行なって実際に運用していません*3

前提

次のような感じでリモートサーバが構築されているものとします。

  • リモートサーバにリポジトリ用の git アカウントを作成している(git-shell でシェルを制限)
  • リポジトリは git アカウントの $HOME/repositories/ にある
  • git アカウントの authorized_keys に開発者全員の公開鍵を記載してアクセス制御を行う

設定方法

authorized_keys で environment を使うので、sshd の設定ファイルに下記を追記しておきます。

/etc/ssh/sshd_config
PermitUserEnvironment yes


git アカウントの authorized_keys に、公開鍵ごとに environment で Author を書いておきます。
下記の例では "aa zz" が Author の名前で "az@example.com" がメールアドレスです。

.ssh/authorized_keys
environment="SSH_GIT_USER=aa zz",environment="SSH_GIT_MAIL=az@example.com",...


リポジトリに次のような pre-receive フックスクリプトを設置します。

pre-receive

試してみる

間違った Author でコミット→プッシュしてみます。

git commit -am "x" --author="xx xx <xx@example.com>"
git push origin master

拒否られました。

Counting objects: 5, done.
Delta compression using up to 6 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 358 bytes, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Author NG ... b95f68c94accad2a5c49a7f90872c6a743ca3d03 xx xx <xx@example.com> != aa zz <az@example.com>
To git@gitserver:repositories/test.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'git@gitserver:repositories/test.git'


Author を修正して再度プッシュします。

git commit --amend -m "x" --author="aa zz <az@example.com>"
git push origin master

成功しました。

Counting objects: 5, done.
Delta compression using up to 6 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 365 bytes, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Author OK ... 6454d59a1a273fd330fbd08b3ae93b0622413a75 aa zz <az@example.com>
To git@gitserver:repositories/test.git
   61fc019..6454d59  master -> master

*1:本家の開発者

*2:自分

*3:なのでバグバグで穴だらけかも