gitolite是什么
gitolite是git的权限控制系统。有如下特性:
a. 在git服务器上需要一个真实的unix用户
b. 能用不同的账号访问git服务器,这些账号不是真实的unix用户也没有shell权限
c. 能控制多个git仓库的读写权限。读权限只能控制到仓库级,写权限可以控制branch/tag/文件/文件夹的层级,
包括branch/tag的创建、删除和修改
安装时不需要root用户权限,只需要普通用通常创建一个名为git的用户。
认证方式通常是采用ssh,也可以用smart http(安装配置时需要root权限)
为什么需要gitolite
git本身不提供任何权限控制,它的权限控制依赖于访问协议认证(控制是谁)和服务器上文件或目录权限(控制能做什么)。
gitolite其他控制特性
a. 可以基于branch/tag名称的控制,文件或目录的控制,变更文件大小或变更文件多少的控制等等
b. 方便的写权限控制按仓库组、用户组、使用LDAP等等
c. 高度可定制、自定义脚本、特别是定义用户命令,多个内置命令和操作选项。
d. 强大、灵活的镜像库操作
f. 用户可以自己创建仓库(只要有权限)
gitolite可以使用unix的权限和ACLs
gitolite和gerrit的底层权限控制方式不同,gitolite的权限是存在配置文件中的,gerrit是存在数据库中的,所以这个两个系统不能配合使用。
安装了gitolite之后,此过程首先运行的是gitolite-shell命令。gitolite-shell通过ssh的账号名称和命令的仓库名称来确定是否有权限进行push操作。
如果有权限进行push操作,就会调用git-receive-pack。接下来用仓库中由gitolite提供的update hook检查branch/tag/文件的权限。处理过程如下
4 概念和术语解释
a. 认证和授权
gitolite不做认证,只负责授权管理。
认证是检验你是谁的过程。
授权是检验此操作你是否有权限进行。
gitolite采用ssh或http的认证方式,通过服务端的sshd或者web server进行认证。认证成功sshd或者httpd将会把控制权交给gitolite进行权限控制,
认证失败的直接返回,就不会走到gitolite。
b. ssh和http两认证方式
ssh方式很方便安装和使用,大部分linux系统都已经默认安装了,客户端只需要提供ssh生成公匙对并将公匙加入到gitolite。
http方式安装和配置麻烦一点,但客户端使用简单,它是通过用户名和密码进行认证的,所以安全性不如ssh方式,有点是用户使用简单。
c. hosting user
当你使用ssh方式时需要制定一个linux账号作为hosting user。这个账号的名称将会出现在仓库克隆路径中如ssh://git@server/repo或git@server:repo
通常都是创建名为git的账号作为hosting user,你可以使用任何其他账号作为hosting user
d. gitolite-admin仓库
gitolite通过gitolite-admin仓库管理服务器上的仓库、git账号和权限。gitolite-admin中keydir目录存放ssh的公匙文件,每一个公匙文件对应一个账号
config/gitolite.conf控制git仓库的访问权限。管理方式是先克隆gitolite-admin仓库到本地,在本地仓库中做完修改后,将修改提交并推送回服务器,
使其生效。服务器处理gitolite-admin更新的过程如下
1. gitolite-admin仓库中post-update钩子,这个钩子是gitolite安装时设置的,它由git-receive-pack调用(git仓库更新时会触发这个钩子的执行)。
2. gitolite用gitolite-admin仓库中的keydir中公匙文件更新authorized_keys,这样ssh就知道哪些账号是有效的
3. 更新~/.gitolite中的配置文件,~/.gitolite中存放有conf/gitolite.conf(权限配置文件) keydir(用户公匙文件)
hooks(存放gitolite默认的钩子和自定义的钩子文件)和logs(gitolite操作日志文件)
4. 创建config/gitolite.conf中涉及的,但~/repositories中不存在的仓库。
5. 更新所有仓库中的配置文件,配置文件中只存放和此仓库有关的权限配置
使用前提条件
linux 系统
Perl 5.8.8以上版本
git1.6.6以上版本
openssh
gitolite3的安装
su -git
mkdir -p ~/bin
git clone git://github.com/sitaramc/gitolite
gitolite/install -ln ~/bin 还可以使用gitolite/install 或者gitolite/install -to ~/bin
gitolite setup -pk youradmin.pub
将~/bin 加入环境变量$PATH中
下图是安装过程中涉及到文件或目录
a. 将管理员的公匙拷贝到服务器上,重命名为alice.pub
b. 下载gitolite源码
c. 执行gitolite/install -ln 命令
d. gitolite setup -pk alice.pub 初始化管理员
保证安装能成功的前提是在服务器上创建一个新用户,在新用户下进行安装。如果想在现有用户下进行安装,请保证没有如下文件或目录
~/.gitolite.rc ~/.gitolite ~/repositories 和~/.ssh/authorized_keys
git服务器迁移
将git仓库用一台服务器迁移到另一台服务器,具体操作步骤如下
a. 从旧服务器clone gitolite-admin仓库,保证你有写的权限
b. 在新服务器上安装gitolite
c. 将就服务器的rc文件拷贝覆盖到新服务器上
d. 关闭旧服务器上git仓库的读写权限
e. 将旧服务器上所有的git仓库拷贝到新服务器上并设置仓库的所有者和所有组,但不用覆盖gitolite-admin仓库
f. 在旧服务器的gitolite-admin添加新服务器的gitolite-admin仓库远程地址,并强制更新新服务器的gitolite-admin仓库
g. 执行gitolite setup命令
添加和删除用户
通过在gitolite-admin仓库的keydir目录中,增加或删除公匙文件,实现用户的新增和删除。下图是alice(管理员账号)新增bob和carol用户的过程。
如下操作都是在管理员机器上完成的
a. 克隆gitolite-admin仓库
b. 收集bob和carol的ssh公匙文件,按需求进行重命名(必须保留.pub这个后缀)
c. 将公匙文件拷贝到gitolite-admin/keydir目录中,进行add/commit和push
可以在keydir目录中创建任意层级的子目录,但账号的名称还是按公匙的文件名管理(不带.pub后缀)
删除用户
git rm keydir/bob.pub
然后commit/push
仓库的新增和删除
可以在config/gitolite.conf中单独新增一个仓库,也可以在现有仓库行后面,添加一个仓库名称。新仓库的权限将和老仓库的权限保持一致。修改完成后将
gitolite.conf 提交/推送,gitolite将在服务器上创建一个空的裸库。
gitolite不能自动删除和重命名仓库,修改gitolite.confi的同时还需要你登录到服务器上进行手动修改。
将现有的git仓库纳入gitolite进行管理
gitolite不但会影响你现有git仓库中的hook,还是影响已存在的"git-daemon-export-ok"文件。
操作步骤如下:
a. 将仓库移到$HOME/repositories目录下
b. 确保所有的仓库都是裸库,仓库的目录名称都以.git结尾,目录的所有者和所属组为git用户
c. 执行gitolite setup 如果不执行gitolie setup 对这些仓库你将只有读权限,没有写权限
e. 编辑conf/gitolite.conf,加入仓库。如果新加的仓库在仓库通配符中,你需要手动创建gl-creator文件
echo username > ~/repositories/path/to/repo.git/gl-creator
权限配置文件(conf/gitolite.conf)
此文件指定仓库的名称和控制权限规则。配置文件使用空格作分隔符,注释方式和shell相同。用户和仓库名称必须以字母开头可以包. - 或者_ 用户名称可以用邮箱
地址进行命名。用户组的名称和普通用户的命名规则相同但必须以@开头。仓库名称可以包括/这样可以方便指定仓库的目录层级。
gitolite允许你将配置文件分割成多个文件,通过include来组成一个大文件。例如 include “foo.conf” 这将包括conf/foo.conf文件,子文件也可以有目录层级
例如 include “foo/bar.conf"或者使用通配符include “repos/*.conf”。
从LDAP中获取组的信息,自己写个程序从LDAP中读取用户和组的信息,然后在rc中做如下配置
GROUPLIST_PGM => '/home/git/ldap-query-groups',
你的程序必须自己完成ldap登录,gitolite不提供任何处理
访问权限规则
一条规则通常由四个部分组成reponame/username/operation/ref
repo 行定义一个或多个git仓库(可以使用通配符)。一个repo行可以跟随多权限行配置。
权限行中有一个权限字段,零个或多个引用字段 等号后面是一个或多个用户或用户组
R 只读
RW 更新分支(fast-forward)、创建分支或tag
RW+ 更新分支(fast-forward)、强制更新、更新或删除分支/tag
拒绝操作权限
如果要控制分支或tag的新增权限,需要在规则中加入RWC或RW+C的配置,这样没有配置C的用户或组将没有创建分支或tag的权限
同理通过RWD或RW+D控制删除分支或TAG的权限
如果同时需要控制新增和删除分支或tag的权限,使用RWCD或RW+CD
如果要拒绝有合并commit的提交,可以通过M来进行控制,但这不常用。如果配置了M,那么有合并记录的push将被拒绝。
因为你在权限控制文件中不可能列出所有的git仓库分支或tag,所以通常使用正则表达式来配置。
gitolite完整的权限检查过程如下图,
图中的黄色表示是权限检查点。
左边的是读过程(操作包括git clone/fetch/is-remote),读不需要知道引用名称,如果有权限gitolite会调用git-puload-pack,否则结束此过程。
右边的是写过程,先判断是不是写操作,如果是调用git-receive-pack,有git-receive-pack调用update hook(gitolite已经重写了此hook),update hook会收到
此push的引用名称,还有此次push是否是fast-forward或引用更新push等信息,通过这些信息gitolite判断需要的权限是W还是W+ 然后判断用户是否有对应的权限
将判断结果返回给git-receive-pack
写过程中两次检查的细节,如下图
通过如下命令可以检查用户针对某个仓库是否有对应的操作权限
gitolite access -s 仓库名称 用户名称 权限操作 应用
例如:
gitolite access -s testing android W any
测试android用户是否有写testing仓库任务引用的权限
自定义update hooks,配置如下
a. 在.gitolite.rc %RC块中打开LOCAL_CODE => "$ENV{HOME}local", 的注释
b. 配置
#log on to server
cd $HOME
mkdir -p local/VREF
cp your-crlf-update-hook local/VREF/crlf
chmod +x local/VREF/crlf
c. 在gitolite-admin仓库的conf/gitolite.conf文件末尾添加
repo @all
- VREF/crlf = @all
或者针对单个仓库配置
- VREF/crlf = @all
添加非upadte hook (post-update,pre-receive,post-receive)如post-receive
a. 配置
#log on to server
cd $HOME
mkdir -p local/hooks/common
cp your-post-receive-hook local/hooks/common/post-receive
chmod +x local/hooks/common/post-receive
c. 最后执行gitolite setup 命令,将hook应用到所有的仓库
将所有的hook放入gitolite-admin进行管理,步骤如下
a. 编辑服务器上的.gitolite.rc文件放开LOCAL_CODE => "$rc{GL_ADMIN_BASE}/local", 的注释
b. 将hook脚本拷贝如gitolite-admin/local目录中,将文件提交并push到git服务器上,如果是update hooks还要在conf/gitolite.conf中配置VREF规则
将非update的hook应用于指定的仓库,而不是全部的仓库,配置步骤如下
a. 打开.gitolite.rc中LOCAL_CODE => "$rc{GL_ADMIN_BASE}/local", 的注释
b. 打开.gitolite.rc中repo-specific-hooks, 的注释, 如果你的。gitolite.rc中没有ENABLE这个配置列表,你需要将ENABLE加入POST_COMPILE和
POST_CREATE列表中。
c. 在gitolite-admin仓库创建目录 mkdir -p local/hooks/repo-specific
d. 将hook文件加入目录中,文件名不能使用标准的名称如(pre-receive,post-receive,post-update),而应使用描述性的文字如(deploy, "RSS-post"等)
e. 在conf/gitolite.conf中对应的仓库下进行配置,如
repo foo
option hook.post-update = jenkins
repo bar @baz
option hook.post-update = deploy RSS-post
f. 将gitolite-admin提交并push到远程库
添加自定义的VERFs,添加方法和update hooks的方法相同。
指定"git-config"的keys和values
首先需要设置.gitolit.rc中$GIT_CONFIG_KEYS的规则
基本配置语法是 config sectionname.keyname = value 如
repo gitolite
config hooks.mailinglist = [email protected]
config hooks.emaiprefix = “[gitolite]”
config foo.bar = “”
或者使用命令git config section.key value 进行配置,或使用git config –unset-all section.key 取消配置 但是不支持其他一些
git config命令(–add,value_regex等等)
在conf/gitolite.conf删除的配置,并不会再服务器的仓库中起效,还需要执行–unset-all命令。
gitolite配置项
gitolite的部分特性和功能是通过"options"控制的。option的配置方法和git-config是相同的,但在使用git config命令时看不到这些配置,需要通过
gitolite git-config命令才能看到。
gitolite中的五种脚本
a. commands脚本在.gitolite.rc的ENABLE中配置的,可以远程在客户端执行的
b. Hooks 标准的git hook
c. sugar 脚本方便修改conf语言
d. trigger gitolite的hook,起这名字是为了区分git hook
e. VREFs 是gitolite权限控制的扩展
gitolite query-rc GL_BINDIR 命令显示gitolite安装的位置
gitolite shell和perl接口
shell脚本的接口
a. gitolite access 检查用户的repo的读写权限 实现代码在src/commands/中
b. gitolite creator 检验或显示仓库的creator 实现代码在src/commands/中
c. gitolite git-config 检查gitolite的配置项和git的配置
c. gitolite query-rc 检查RC的设置值 实现代码在src/commands/中
perl的接口是Easy.pm 实现代码是src/lib/Giolite/Easy.pm
gitolite 日志
日志各字段之间使用TAB隔开的。
下面是两种日志行
a. 第三方字段为空的行, 这是实际的日志
b. 第三方字段不为空的行, 以两个TAB隔开第二个字段,显示额外的信息以便问题的诊断。可以通过RC中的LOG_EXTR设置,0为失效。
日志行的各字段解释
field 1: 本机实际格式是YYYY-MM-DD.HH:MM:SS
field 2: 事务Id或"TID",它的值通常是gitolite-shell的进程ID号,它的作用用于标识有关联的日志行(子命令,子进程的执行),可以作为一个事务看待。
从第三个字段开始,这些字段是否显示都指定的格式
a. start
标识gitolite操作的开始
field 3: 'ssh'或者'http'
field 4: ARGV=<comma-separated list of command line arguments> 通过是gitolite的用户名(这是gitolite-shell的参数,就是用于认证的
公匙文件名称),如果此用户有shell的权限,在用户民之前会显示-s 字段
field 5: SOC=<original command from client>用户在客户端执行的git客户端命令或者是自定义的命令,例如:
git-upload-pack 'reponame'
git-receive-pack 'reponame'
这个命令会包括单引号,因为这是客户端发送的,gitolite的命令也是用这个字段显示,所以会显示info或perms -l reponame 之类的命令
field 6: FROM=<IP Address> 显示客户端的ip地址
b. pre-git
这行日志只要用户认证成功就会显示(ssh或http验证成功,在git-upload-pack或git-receive-pack调用之前)
field 3: 'pre_git'
field 4: reponame
field 5: username
field 6: 'R'或'W'
field 7: 'any'
field 8: 允许访问
c. udpate
这行日志在gitolite权限验证成功后显示(第二次权限验证,在执行update hook确定是否运行push的时候)
field 3: 'update'
field 4: reponame
field 5: usernmae
field 6: 'W,'+','C','D','WM','+M','CM','DM'
field 7: ref name(例如refs/heads/master)
field 8: old SHA
field 9: new SHA
feild 10: 允许访问
field6的显示都是写类型的操作,如果是强制更新会显示+ 正常更新会显示W。 feild7到9字段执行的时候会作为update hook的参数使用
当gitolite权限控制push目录的时候,reponame会替换成绝对路径,username替换成unix的用户id field6为'bypass'
d. create
当用户通过通配符创建仓库
field 3: 'create'
field 4: reponame
field 5: username
field 6: 'R'或'W'
如果是通过perms命令的'-c'选项创建,feild 6会显示'perms-c'
e. end
事务的最后信息,在这个行之后你就不会有相同的事务ID的信息了
field 3: 'END'
f. warnings和errors
典型的访问拒绝信息
field 3: 'warn'或'die'
field 4: 消息,这部分信息不会被分隔符分割(同时是reponame,username 等)
g. cli
在服务执行giolite子命令是显示,例如执行gitolite setup
field 3: 'cli'
field 4: 'gitolite'
field 5 to end: 供gitolite命令使用的参数,是一个perl字段
通过.gitolite.rc中的LOG_DEST选项可以将gitolite log定向输出到syslog中。在syslog显示的log time和TID字段格式是不同的,另外还插入了gitolite字段,
格式为'gitolite[$GL_TID]'。 LOG_EXTRA选项可以指定debug调试信息的输出log文件
手动触发trigger例如执行 gitolite trigger POST_COMPILE 命令。但是如果trigger需要有参数,此方法就不适用。
trigger的参数来源
a. .gitolite.rc中提供的参数
b. triggerde的名称如"POST_COMPILE"
c. 0或者其他指定的参数
trigger指定的执行参数
如果传入的参数是仓库名称,名称是不带.git后缀的
a. INPUT
在其他程序之前执行,INPUT的trigger脚本必须是perl,因为它处理的是'gitolite-shell'程序的参数和环境变量。通常它会读写@ARGV或是
$ENV{SSH_ORIGINAL_COMMAND}
b. ACCESS_1
在第一次验证之后触发,扩展参数有repo/user/'R'或'W'/'any'/result
'result'就是access()函数的返回值。如果它包含了大写的'DENIED'就表示access()拒绝了,否则就是验证通过的引用反射符。注意如果被拒绝,
trigger会立即返回,然后gitolite-shell进程会立即停止
c. ACCESS_2
在第二次验证后触发,扩展参数有repo/user/any of W,+,C,D,WM,+M,CM,DM/引用('refs/heads/master')/result/old SHA/new SHA
ACCESS_2也可以用各个VREF脚本。在用VREF时引用参数是以VREF/开头的,也存在最后两个参数
d. PRE_GIT和POST_GIT
在git命令执行前后执行,扩展参数有repo/user/'R'或'W'/'any'/将被调用的git 命令
('git-receive-pack','git-uplaod-pack'或'git-upload-archive')
注意POST_GIT并不知道push命令的执行结果。因为git-shell或git-receive-pack执行后会做清理。
e. PRE_CREATE和POST_CREATE
在新仓库创建前后执行。其实不光是创建仓库,fork仓库或者仓库权限的变更(如perms)都可能触发POST_CREATE的执行
扩展参数repo/user/'R' fetch/clone/ls-remtoe或'W' push
f. POST_COMPILE
在管理员push成功配置文件自后触发。默认接下来的动作是更新ssh autheys文件任何是git-config's gitweb访问权限和daemon访问权限
没有扩展参数
将自定义脚本加入到trigger中
从v3.4之后在.gitolite.rc文件中并没有trigger列表,只有一个在ENABLE中的features列表。加入定义脚本的方式是在ENABLE之前加入配置,例如在
POST_CREATE中加入foo脚本配置如下
POST_CREATE =>
[
'foo'
]
如果POST_CREATE有其他gitolite默认的脚本,自定义的脚本必须写在顶端。配置完成后可以使用gitolite query-rc 命令查看脚本配置,如
gitolite query-rc POST_CREATE
如果有多个trigger使用了相同的脚本,可以用环境变量GL_TID来标识当前是哪个trigger在执行脚本。
triggers相关的命令
Alias: 允许对仓库设置别名
AutoCreate: 拒绝自动创建仓库的读写权限
bg: 允许后台运行长post-compile或post-create 任务
CpuTime: CPU和gitolite+git的耗时
Mirroring: 镜像所有或指定的仓库
Motd: 允许在ssh模式上向STDERR输出一段信息
partial-copy: 模拟分支的读取控制(通常配合partial-copy VREF使用)
RefexExpr: (通常配合VREF/refex-expr使用)正则表达式
renice:
RepoUmask: 指定仓库的umask设置
Shell: 显示有shell权限的gitolite用户
ssh-authkeys-split: 将公匙
update-descirption-file
upstream:
下面的post-compile trigger默认是有效的
ssh-authkeys: 处理keydir/目录中公匙文件,将其添加或更新到authorized keys文件中
update-gitc-configs: 在每个仓库中执行git config 命令添加或更新相应的配置
update-git-daemon-access-list: 在每个需要的仓库中创建或删除'git-daemon-export-ok'文件
update-gitweb-access-list: 创建projects.list文件决定哪些仓库可以显示在gitweb中
VREFs是个复杂的概念,下面一下简单的
COUNT: 现在push的变更的文件总数(修改或新增的)
EMAIL-CHECK: 检查所有新commit提交人和push人是否是同一个人
lock: 锁定二进制文件
MAX_NEWBIN_SIZE: 限制新的二进制文件的大小
NAME: 拒绝push指定的目录或文件
partial-copy:
refex-expr:
VOTES:
gitolite控制分支的读权限设置,步骤如下:
a. 在.gitolite.rc问的ENABLE中,开启'partical-copy'功能
b. 以下面的为例
注意:如果你还是使用了其他的VREFs,请确保这个配置在最下面
任何对partial-copy仓库的修改,都会影响真正的仓库,所以确保partial-copy仓库没有其他分支或tag的写权限
如果需要取消此设置需要执行
gitolite compile
gitolite trigger POST_COMPILE
[
'post-compile/ssh-authkeys',
],
然后写一个脚本将所有的公匙文件都放到$HOME/.gitolite/keydir目录或者其子目录总,然后定期执行gitolite trigger SSH_AUTHKYES 命令让用户可以自己管理自己的仓库,配置如下
这样用户就可以在的用户名下创建仓库并通过perms命令来控制WRITERS和READERS用户组中的成员,还可以定义更多个用户组。
gitolite服务器上安装生成的文件和目录
~/repositories: 服务器上裸仓库默认存放目录
~/.gitolite.rc: gitolite的服务器配置文件
~/.gitolite: gitolite的工作目录,这个目录包括了gitolite需要的所有文件,这个目录你应该通过push gitolite-admin仓库的方式进行修改,而不是直接
在服务器上直接修改
~/.ssh: 存放authorized_keys文件
如果有审计或其他需要可以备份~/.giotlite/logs gitolite的日志文件
有gitolite管理的裸库和普通裸库没有太大的区别,只是在仓库中有些gl开头的文件
如果你有超过200个仓库需要管理,建议使用gitolite v3.2或更高的版本。更高的版本对管理更多的仓库有更好的处理。
gitolite的性能
a. 当你认为gitolite比较慢时,在执行完操作后通过查看log文件可以看出时间消耗的细节,通常push admin和创建新仓库会花费更多的时间。
b. 如果你没有使用gitweb或git-daemon,或者使用了但没有做gitolite以外的权限控制,你可以在.gitolite.rc中的ENABLE里做说明
c. 如果你不想等待脚本执行完成,想在后台执行脚本,可以使用src/trigger/bg
d.