Subversion权限控制说明

2014-12-30 16:38:13
陈志新
23962
最后编辑:许强 于 2022-05-16 03:18:08
分享链接
摘要:这篇文章说明Subversion基于路径的权限控制。

很多管理员在第一次配置 Subversion 时,就急不可待地开始设置基于路径的授权。管理员通常知道团队成员与项目的对应关系,所以很容易就能决定应该把特定目录的权限授予给哪些人,不授予给哪些人。乍看起来非常自然。还可以缓解管理员过度控制仓库的欲望。

但是,这样做通常会产生一些可见 (和不可见) 的代价。可见的代价是服务器需要做大量的配置工作,以便确保用户对每个特定的目录都有正确的读写权限,在某些情况下,这会产生很明显的性能损失。对于不可见的代价,考虑一下你所创建的文化。在大多数情况下,特定的用户 不应该向特定的仓库目录提交修改,这种约定没必要通过技术手段加以约束。团队成员有时候会不由自主地与他们协作。例如通过向不属于他们的仓库目录提供修改,帮助别人完成工作。如果在服务器配置上禁止了这种形式的合作,无形中就树起了一道协作屏障。随着项目的发展与新成员的加入,管理员需要不停地创建新规则,这会带来大量额外的维护工作。

记住,这是一个版本控制系统!即使有人不小心向错误的目录提交了修改,这些修改也可以轻易地撤消。如果用户故意向错误地目录提交修改,这只能算 作人际问题,要在 Subversion 外部解决。

所以,在管理员限制用户的访问权限之前,要问一下自己这是否真的有必要,是否只是为了“听起来不错”,是否值得牺牲服务器的性能。放任用户的访问权限并不会带来非常大的风险,而且依赖技术手段来解决社交问题是一种不好的做法!

考虑一个例子,假设 Subversion 项目对哪些人应该向哪些目录提交,有一套自己约定俗成的规则,但这些规则总是通过社交来实施。这是一种良好地社区信任模型,特别是对于开源项目而言。当然,有时候确实需要 基于路径的访问控制,比如说在公司内部,某些数据非常敏感,只能把访问权授予给少数人。

一旦服务器知道了去哪儿查找你的访问权限配置文件,接下来需要做的就是 定义访问权限。

Subversion 访问权限配置文件的语法与 svnserve.conf 和运行时配置文件的语法相同。忽略以 # 开始的行,在最简单的形式中,文件的每一节的名字都指定了一个被版本控制的路径,可能还指定了包含该路径的仓库。换句话说,除了少数几个被保留的节外,节名只有这两种形式:如果使用了配置指令 AuthzSVNAccessFile, 则要么是 [repos-name:path], 要么是 [path]. 如果使用了配置指令 AuthzSVNReposRelativeAccessFile 指定了每个仓库的访问权限配置文件, 则只能使用 [path] 这种形式。已认证的用户名是每一节的选项的名字,选项的值描述了用户对该路径的访问权限:只读 (r) 或读写 (rw)。如果用户名未出现在节中,则不具有该路径的任何访问权限。

下面是访问权限配置文件的一个例子,文件把仓库 calc 的路径 /branches/calc/bug-142 (及其子目录) 的 读权限授予 Sally,把读写权限授予 Harry:

[calc:/branches/calc/bug-142]
harry = rw
sally = r

被授权模块检查的仓库名直接来自仓库的路径,具体的表现受到两个服务器选项的影响. mod_dav_svn 只使用仓库根目录 URL 的 最后一个分量,而 svnserve 则使用完整的,相对 于服务器根目录 (由命令行选项 --root (-r) 指定) 的仓库路径。

如果你使用了配置指令 SVNParentPath,在访问权限配置文件的节名中指定仓库名就非常重要,因为如果省略了仓库名,例如把节名写 成 [/home/dir], 那么该节将匹配每个仓库中的 /some/dir。然而,如果使用了配置指令 SVNPath,那么在节名中只提供路径也是可以的—毕竟这时候只存在一个仓库。

路径的权限继承自父目录,这意味着我们可以为 Sally 指定一个访问策略不同的子目录。继续我们前面的例子,现在我们要为 Sally 授予分支中某个子目录的写权限,而 Sally 原来只对分支拥有只读权限。

[calc:/branches/calc/bug-142]
harry = rw
sally = r
# give sally write access only to the 'testing' subdir
[calc:/branches/calc/bug-142/testing]
sally = rw

现在 Sally 对分支的子目录 testing 拥有写权限,但对于分支的其他部分仍然只具有只读权限。而 Harry 对整个分支拥有读写权限。

我们还可以通过规则的继承,显式地阻止用户的权限,方法是把用户名设置成空:

[calc:/branches/calc/bug-142]
harry = rw
sally = r
[calc:/branches/calc/bug-142/secret]
harry =

在这个例子里,Harry 对整个bug-142目录具有读写权限,但却无法访问其中的子目录 secret。

在默认情况下,任何用户对任意一个仓库都不具备访问权限,这意味着如果从头开始写访问权限配置文件,你可能希望所有用户至少对仓库的根目录具有只读权限。可以通过把用户名设置成通配符 (*) 实现这 种配置,此时通配符 * 表示 “所有用户”:

[/]
* = r

这是一种很常见的配置,注意在节的名字中没有指定仓库的名字,上面的配置将把所有仓库的读权限授予给所有用户。一旦用户对仓库具有了读权限,接下来就可以根据具体的需要,把特定仓库的特定目录的读写权限 (rw) 授予特定的用户。

虽然前面的例子都是针对目录的权限配置,因为这是最常见的情况,实际上管理员完全可以针对文件设置访问权限。

[calendar:/projects/calendar/manager.ics]
harry = rw
sally = r

访问权限配置文件还允许管理员定义用户组,就像 Unix 里的 /etc/group。为了定义用户组,在访问权限配置文件里创建一个名为 groups 的节,然后在节内描述每一个 用户组:变量名定义了用户组的名字,而变量的值则是逗号分隔的,属于该 用户组的用户名。

[groups]
calc-developers = harry, sally, joe
paint-developers = frank, sally, jane
everyone = harry, sally, joe, frank, jane

用户组的权限授予和用户名相同,为了与用户名相区别,在用户组的名字前要加一个 @ 符号:

[calc:/projects/calc]
@calc-developers = rw
[paint:/projects/paint]
jane = r
@paint-developers = rw

需要特别注意的是用户组权限并不会被用户权限所覆盖,而是会进行叠加。在上面的例子里,Jane 是用户组 paint-developers 的成员,因此她对仓库 paint 具有读写权限,再叠加上 jane = r, Jane 最终的权限仍然是可读写。如果用户已经是某个用户组的成员,那就不可能再把用户的权限限制得比用户组的权限还小。

用户组还可以包含其他的用户组:

[groups]
calc-developers = harry, sally, joe
paint-developers = frank, sally, jane
everyone = @calc-developers, @paint-developers


文章转载自:https://svnbook.red-bean.com/zh/1.8/svn.serverconfig.pathbasedauthz.html#ftn.idm9054