[推荐] Git的权限控制

Git不像SVN或者CVS那样,有明确的一套权限控制方法& v( @5 T1 S2 }  S; a3 X
在Git中想要实施对仓库的版本控制,大概可以有以下2个办法:
+ f* }' @$ d1 e
1.Git Hook:
Hooks are little scripts you can place in $GIT_DIR/hooks directory to trigger action at certain points. When git-init is run, a handful of example hooks are copied into the hooks directory of the new repository, but by default they are all disabled. To enable a hook, rename it by removing its .sample suffix

1 g9 w+ p' N7 z+ g! Z2 Z( ~

" F! ~$ z% c  F& h; m2 Y
git默认提供了很多类型的hooks,比如pre-commit,post-commit,post-checkout,update,pre-receive....$ d6 K/ v+ b( O' W5 o
我们可以在update的hooks中进行控制,当用户在local repository上执行git push,在remote repository更新之前,会调用该hook
该hook存放在$GIT_DIR/hooks/update下% }6 i; y+ q# j8 O/ m$ E; o
" H% k& ^/ g: [+ z4 ~7 `8 j1 x
可参考http://www.kernel.org/pub/software/scm/git/docs/howto/update-hook-example.txt4 p) w8 o1 C# E0 b9 T

以下是update脚本内容,本人没有测试过是否可用) T) H  F. V" B
/ M( f. C: R) ?8 t2 L
" ^! M- p) X: r, i/ s) ?/ T0 w5 }
-- >8 -- beginning of script -- >8 -- 4 Z% q) D! B& ]" \7 f) [
# v3 a3 h9 b0 L+ p! s/ |: \+ U
#!/bin/bash . T# r7 j8 J8 ~" l+ ~% q
  c! H: _5 w* W+ E8 |( u- c
umask 002

# If you are having trouble with this access control hook script
# you can try setting this to true.  It will tell you exactly $ E3 Y7 g1 j  e' h) p! e! M; \* {
# why a user is being allowed/denied access.
+ s0 [3 \/ T1 v( n
verbose=false
! b5 c2 j; K! H1 X
# Default shell globbing messes things up downstream & n. T$ g' v$ m0 D7 `
GLOBIGNORE=*
7 S( E& x( n% v* b
function grant { ( V+ c; S; z& X/ Q9 f6 n; Y
  $verbose && echo >&2 "-Grant-    $1"
  echo grant
  exit 0
}

function deny {
  $verbose && echo >&2 "-Deny-    $1"
  echo deny
  exit 1
}

function info {
  $verbose && echo >&2 "-Info-    $1" ( d, W1 l/ K& W  h- m, `+ P+ X0 o
} - R6 I; x% T1 n9 ]& }& j

# Implement generic branch and tag policies.
# - Tags should not be updated once created. - m& C4 b% r1 T* p
# - Branches should only be fast-forwarded unless their pattern starts with '+'
case "$1" in
  refs/tags/*) $ ]$ h: \- u% R) D5 P% C! n1 w- n4 \
    git rev-parse --verify -q "$1" &&
    deny >/dev/null "You can't overwrite an existing tag"
    ;;
  refs/heads/*)
    # No rebasing or rewinding 9 r9 \) Y4 v! R$ C
    if expr "$2" : '0*$' >/dev/null; then
      info "The branch '$1' is new..." 2 }) y1 o$ b& T) R$ Y+ t2 W
    else % I5 ]7 w0 m3 J7 g, m& f$ I; ?/ c" w
      # updating -- make sure it is a fast forward & x5 c  H5 u/ ]' i7 K' F. u
      mb=$(git-merge-base "$2" "$3")
      case "$mb,$2" in 4 v% \: E4 |4 `* B5 r) f' ]
        "$2,$mb") info "Update is fast-forward" ;;
  *)    noff=y; info "This is not a fast-forward update.";; : e$ ?( e" `5 n2 H" ]5 F; b' x
      esac
    fi
    ;;
  *) & ^3 T! B' @7 }6 O
    deny >/dev/null \
    "Branch is not under refs/heads or refs/tags.  What are you trying to do?"   a" P/ l( i1 ?' U( g4 _0 b5 m8 Q
    ;;
esac " o  N5 B8 L: F8 q  A1 P$ M& S: [

# Implement per-branch controls based on username
allowed_users_file=$GIT_DIR/info/allowed-users
username=$(id -u -n)
info "The user is: '$username'"

if test -f "$allowed_users_file" . `, l5 G5 K1 S* [9 ?' ?
then & K( `7 H3 V: |" q) @
  rc=$(cat $allowed_users_file | grep -v '^#' | grep -v '^$' | ' X* r* y1 l( r, N+ ^8 U
    while read heads user_patterns
    do
      # does this rule apply to us?
      head_pattern=${heads#+} ! t# j! K* F/ s, W* s- z
      matchlen=$(expr "$1" : "${head_pattern#+}")
      test "$matchlen" = ${#1} || continue

      # if non-ff, $heads must be with the '+' prefix ) P6 C% A0 s/ Q% n( ?
      test -n "$noff" && # S  k) g# w# \& b
      test "$head_pattern" = "$heads" && continue - P2 ]8 E0 }3 |0 c1 c4 f, u6 F
9 S& N: Q" ~; E) ^
      info "Found matching head pattern: '$head_pattern'"
      for user_pattern in $user_patterns; do ' m  U3 J# Z1 ?; W9 v
  info "Checking user: '$username' against pattern: '$user_pattern'"
  matchlen=$(expr "$username" : "$user_pattern")
  if test "$matchlen" = "${#username}" ( r! k9 j: L% q$ y; [& V
  then
    grant "Allowing user: '$username' with pattern: '$user_pattern'"
  fi . P4 C$ O" K+ a
      done
      deny "The user is not in the access list for this branch" ' {9 s; S/ s' o4 a
    done $ G" M+ Y, I2 ~1 J6 f! c
  ) " W3 _9 {+ u/ h- B$ W
  case "$rc" in
    grant) grant >/dev/null "Granting access based on $allowed_users_file" ;; ! |# y+ b( F4 u( p; f4 y, h
    deny)  deny  >/dev/null "Denying  access based on $allowed_users_file" ;;
    *) ;;
  esac
fi 9 i6 d7 w2 G9 z# I

allowed_groups_file=$GIT_DIR/info/allowed-groups $ Z, }& e! q  A% r6 ^6 \
groups=$(id -G -n)
info "The user belongs to the following groups:" . L  `5 I5 s9 n& R0 {
info "'$groups'" 2 n; c; C9 F1 g# A' t; d

if test -f "$allowed_groups_file" 7 p. T, u+ X6 S4 j; b" g0 G  W
then
  rc=$(cat $allowed_groups_file | grep -v '^#' | grep -v '^$' |
    while read heads group_patterns
    do ' U8 s4 c/ [: C9 c
      # does this rule apply to us? 0 y1 T8 D( E# h
      head_pattern=${heads#+} 1 V2 I0 n, t+ G  V
      matchlen=$(expr "$1" : "${head_pattern#+}")
      test "$matchlen" = ${#1} || continue 2 W' U9 \/ P8 L6 Y. y3 n5 ^( O. w; p& r) T
, h6 j$ r5 G$ A  Q* o% d
      # if non-ff, $heads must be with the '+' prefix ! |% x: ^1 g! J0 {
      test -n "$noff" &&
      test "$head_pattern" = "$heads" && continue
0 S2 S' V" M! h) z4 r# |
      info "Found matching head pattern: '$head_pattern'"
      for group_pattern in $group_patterns; do 8 ~, A& X  n8 i% {* s# V  P
  for groupname in $groups; do ! g0 P( X4 c! }. ]/ T1 C
    info "Checking group: '$groupname' against pattern: '$group_pattern'" . s* q2 Q0 ]& q3 [8 n7 @& p/ R
    matchlen=$(expr "$groupname" : "$group_pattern") 6 l+ A+ i/ U- G6 L
    if test "$matchlen" = "${#groupname}"
    then
      grant "Allowing group: '$groupname' with pattern: '$group_pattern'"
    fi
        done 5 G1 E2 c6 T" d9 h, F
      done
      deny "None of the user's groups are in the access list for this branch" ) h, O# Z! q, Y, `( V: l, h
    done 3 h4 g: ~3 u- m+ A6 v
  ) . z! J( k9 h+ E
  case "$rc" in
    grant) grant >/dev/null "Granting access based on $allowed_groups_file" ;;
    deny)  deny  >/dev/null "Denying  access based on $allowed_groups_file" ;;
    *) ;; ; q6 a$ T, l1 O5 n7 p
  esac
fi ; w7 o! V( D" d* C" S  i

deny >/dev/null "There are no more rules to check.  Denying access"
/ p" ]0 z5 G+ P! D; L3 E
-- >8 -- end of script -- >8 -- 6 n: @# q6 H5 V; U6 n
This uses two files, $GIT_DIR/info/allowed-users and 0 a: h3 Q8 v% S: U9 h# g) g4 S
allowed-groups, to describe which heads can be pushed into by & ^& h6 z/ k! A0 \* }
whom.  The format of each file would look like this:

        refs/heads/master  junio
  +refs/heads/pu    junio
        refs/heads/cogito$  pasky
        refs/heads/bw/.*  linus
        refs/heads/tmp/.*  .*
        refs/tags/v[0-9].*  junio ; h) [2 Q. _6 Z& I* o1 t

With this, Linus can push or create "bw/penguin" or "bw/zebra" & J" S5 Z( S  V# T* ]/ \
or "bw/panda" branches, Pasky can do only "cogito", and JC can * @( n( G; E6 r) [8 W
do master and pu branches and make versioned tags.  And anybody
can do tmp/blah branches. The '+' sign at the pu record means
that JC can make non-fast-forward pushes on it.
3 G) Y- Q2 X3 ~6 N
* O' k  E- |; p; |! s( C( }
+ T9 r' q  k2 z. V" L
7 Z6 m2 Q. q. Q) J; U4 |2 k5 }
注意:最后需要配置$GIT_DIR/info/allowed-users和 $GIT_DIR/info/allowed-groups这2个文件,里面定义了每个user对应的可操作的分支、标签。
$ u. z3 p! d+ p* }
采用hook的方式还是比较简陋的,它要求在git服务器上为每个需要控制的用户都建立一个真实的用户,操作起来比较麻烦,而且还会衍生该用户其它的权限问题,对于一个大的团队来说,并不太合适。5 I' p* n2 v. z

2.Gitosis:% o) H2 A( k# V; f. M

参见http://bbs.scmlife.com/thread-22560-1-1.html
0 g  r0 d- }! ]. @0 C2 ?' ]
使用Gitosis来管理权限,相对于hook方式来说,省掉了建立n多用户的麻烦,但它是通过ssh来连接git服务器的,所以需要每个用户生成对应的公钥文件,并提交到Gitosis-admin中。
- R" A* y9 i& x2 F, X
注意:Gitosis的权限控制本质上是针对每个Client的,而不是针对每个user,所以使用它并不能校验user.name是否合法,它只会校验Client是否有权限,对于大家都在一个公共机器上做开发,一定要每个用户都必须git config user.name xxxx。1 ]5 G& }; J1 `( j

[ 本帖最后由 git 于 2010-5-1 18:34 编辑 ]
 
   
沙发
  发表于 2010-7-5 08:26:32  |  只看该作者
很少有人直接用hook去管理权限的。

小团队,可以直接用git-daemon ' B& m1 y6 S1 Q! R) ]+ }9 l0 X$ \, v' f
( @6 c. Q  d  s  S/ d5 A; l
稍大一点用gitosis, gitolite. gitolite 是gitosis 用perl重写的,更好用,安全设置更好。
( R: X3 d: Z3 O8 X* k5 l& I6 ?
再大一点就用gitorious (github clone 版)
 
 
   
板凳
  发表于 2010-9-3 17:04:25  |  只看该作者
我们使用gitosis进行用户权限管理,但是不能限制用户的读权限,在公司内,只要有Ubuntu的环境就能获得代码的访问权限,自己就clone到本地了。5 I4 n9 H# l" `1 ~9 V" K2 {; c
写权限倒是用gitosis控制了。
 
 
   
地毯
  发表于 2010-9-19 10:56:54  |  只看该作者
gitolite 的权限控制比gitosis 的好,除了读以外,还能控制到文件一层。
4 B0 v. K' `# k2 l  ]  J2 e
hooks 是补充,还是有用的。(如 git-svn pre-receive)
 
 
   
5
  发表于 2011-8-23 16:30:16  |  只看该作者
注意:Gitosis的权限控制本质上是针对每个Client的,而不是针对每个user,所以使用它并不能校验user.name是否合法,它只会校验 Client是否有权限,对于大家都在一个公共机器上做开发,一定要每个用户都必须git config user.name xxxx。& t8 {3 b! h3 x

这是什么意思呢?大家在一个公共机上做开发,那它也要每个用户的公钥吗?
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值