Pro Git - Pro Git 4.7 服务器上的 Git 权限管理器 Gitosis
From Pro Git
Pro Git
professional version control
To help translate the book, please fork the book at GitHub and push your contributions.
权限管理器 Gitosis
把所有用户的公钥保存在 authorized_keys 文件的做法只能暂时奏效。当用户数量到了几百人的时候,它会变成一种痛苦。每一次都必须进入服务器的 shell,而且缺少对连接的限制——文件里的每个人都对所有项目拥有读写权限。
现在,是时候向广泛使用的软件 Gitosis 求救了。Gitosis 简单的说就是一套用来管理 authorized_keys 文件和实现简单连接限制的脚本。最有意思的是,该软件用来添加用户和设定权限的界面不是网页,而是一个特殊的 Git 仓库。你只需要设定好某个项目;然后推送,Gitosis 就会随之改变服务器设定,酷吧?
Gitosis 的安装算不上傻瓜化,不过也不算太难。用 Linux 服务器架设起来最简单——以下例子中的服务器使用 Ubuntu 8.10 系统。
Gitosis 需要使用部分 Python 工具,所以首先要安装 Python 的 setuptools 包,在 Ubuntu 中名为 python-setuptools:
$ apt-get install python-setuptools
接下来,从项目主页克隆和安装 Gitosis:
$ git clone git://eagain.net/gitosis.git
$ cd gitosis
$ sudo python setup.py install
这会安装几个 Gitosis 用的可执行文件。现在,Gitosis 想把它的仓库放在 /home/git,倒也可以。不过我们的仓库已经建立在 /opt/git 了,这时可以创建一个文件连接,而不用从头开始重新配置:
$ ln -s /opt/git /home/git/repositories
Gitosis 将为我们管理公钥,所以当前的文件需要删除,以后再重新添加公钥,并且让 Gitosis 自动控制 authorized_keys 文件。现在,把 authorized_keys文件移走:
$ mv /home/git/.ssh/authorized_keys /home/git/.ssh/ak.bak
然后恢复 ‘git’ 用户的 shell,假设之前把它改成了 git-shell 命令。其他人仍然不能通过它来登录系统,不过这次有 Gitosis 帮我们实现。所以现在把 /etc/passwd 文件的这一行
git:x:1000:1000::/home/git:/usr/bin/git-shell
恢复成:
git:x:1000:1000::/home/git:/bin/sh
现在就可以初始化 Gitosis 了。需要通过自己的公钥来运行 gitosis-init。如果公钥不在服务器上,则必须复制一份:
$ sudo -H -u git gitosis-init < /tmp/id_dsa.pub
Initialized empty Git repository in /opt/git/gitosis-admin.git/
Reinitialized existing Git repository in /opt/git/gitosis-admin.git/
这样该公钥的拥有者就能修改包含着 Gitosis 设置的那个 Git 仓库了。然后手动将这个新的控制仓库中的 post-update 脚本加上执行权限。
$ sudo chmod 755 /opt/git/gitosis-admin.git/hooks/post-update
万事俱备了。如果设定过程没出什么差错,现在可以试一下用初始化 Gitosis 公钥的拥有者身份 SSH 进服务器。看到的结果应该和下面类似:
$ ssh git@gitserver
PTY allocation request failed on channel 0
fatal: unrecognized command 'gitosis-serve schacon@quaternion'
Connection to gitserver closed.
说明 Gitosis 认出了该用户的身份,但由于没有运行任何 Git 命令所以它切断了连接。所以,现在运行一个确切的 Git 命令——克隆 Gitosis 的控制仓库:
# 在自己的电脑上
$ git clone git@gitserver:gitosis-admin.git
得到一个名为 gitosis-admin 的目录,主要由两部分组成:
$ cd gitosis-admin
$ find .
./gitosis.conf
./keydir
./keydir/scott.pub
gitosis.conf 文件是用来设置用户、仓库和权限的控制文件。keydir 目录则是保存所有具有访问权限用户公钥的地方——每人一个。你 keydir 中的文件名(前例中的 scott.pub)应该有所不同—— Gitosis 从使用 gitosis-init 脚本导入的公钥尾部的描述中获取该名。
看一下 gitosis.conf 的内容,它应该只包含与刚刚克隆的 gitosis-admin 相关的信息:
$ cat gitosis.conf
[gitosis]
[group gitosis-admin]
writable = gitosis-admin
members = scott
它显示用户 scott ——初始化 Gitosis 公钥的拥有者——是唯一能访问 gitosis-admin 项目的人。
现在我们添加一个新的项目。我们将添加一个名为 mobile 的新节段,在这里罗列手机开发团队的开发者以及他们需要访问权限的项目。由于 ‘scott’ 是系统中的唯一用户,我们把它加成唯一的用户,从创建一个叫做 iphone_project 的新项目开始:
[group mobile]
writable = iphone_project
members = scott
一旦修改了 gitosis-admin 项目的内容,只有提交并推送至服务器才能使之生效:
$ git commit -am 'add iphone_project and mobile group'
[master]: created 8962da8: "changed name"
1 files changed, 4 insertions(+), 0 deletions(-)
$ git push
Counting objects: 5, done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 272 bytes, done.
Total 3 (delta 1), reused 0 (delta 0)
To git@gitserver:/opt/git/gitosis-admin.git
fb27aec..8962da8 master -> master
第一次向新工程 iphone_project 的推送需要在本地的版本中把服务器添加为一个 remote 然后推送。从此手动为新项目在服务器上创建纯仓库的麻烦就是历史了—— Gitosis 会在第一次遇到推送的时候自动创建它们:
$ git remote add origin git@gitserver:iphone_project.git
$ git push origin master
Initialized empty Git repository in /opt/git/iphone_project.git/
Counting objects: 3, done.
Writing objects: 100% (3/3), 230 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@gitserver:iphone_project.git
* [new branch] master -> master
注意到路径被忽略了(加上它反而没用),只有一个冒号加项目的名字—— Gitosis 会为你找到项目的位置。
要和朋友们共同在一个项目上共同工作,就得重新添加他们的公钥。不过这次不用在服务器上一个一个手动添加到 ~/.ssh/authorized_keys 文件末端,而是在 keydir 目录为每一个公钥添加一个文件。文件的命名将决定在 gitosis.conf 文件中用户的称呼。现在我们为 John,Josie 和 Jessica 添加公钥:
$ cp /tmp/id_rsa.john.pub keydir/john.pub
$ cp /tmp/id_rsa.josie.pub keydir/josie.pub
$ cp /tmp/id_rsa.jessica.pub keydir/jessica.pub
然后把他们都加进 ‘mobile’ 团队,让他们对 iphone_project 具有读写权限:
[group mobile]
writable = iphone_project
members = scott john josie jessica
如果你提交并推送这个修改,四个用户将同时具有该项目的读写权限。
Gitosis 也具有简单的访问控制功能。如果想让 John 只有读权限,可以这样做:
[group mobile]
writable = iphone_project
members = scott josie jessica
[group mobile_ro]
readonly = iphone_project
members = john
现在 John 可以克隆和获取更新,但 Gitosis 不会允许他向项目推送任何内容。这样的组可以有尽可能有随意多个,每一个包含不同的用户和项目。甚至可以指定某个组为成员,来继承它所有的成员。
如果出现了什么问题,把 loglevel=DEBUG 加入到 [gitosis] 部分或许有帮助(译注:把日志设置到调试级别,记录更详细的信息)。如果你一不小心搞错了配置,失去了推送权限,可以手动修改服务器上的 /home/git/.gitosis 文件—— Gitosis 从该文件读取信息。一次推送会把 gitosis.conf 保存在服务器上。如果你手动编辑该文件,它将在你下次向 gitosis-admin 推送之前它将保持原样。