Git:一个git用户来控制多个物理用户的回购

时间:2016-11-06 15:29:31

标签: git ssh

我有一个Raspberry Pi,我用它作为Git服务器。有多个物理用户访问它,目前每个用户在服务器上都有自己的登录。换句话说,用户John和Doe可以通过运行ssh john@server.comdoe@server.com来使用SSH登录服务器。

物理用户拥有私有Git存储库,其他用户无法访问。例如。 John的回购位于/home/john/repos,Doe的回购位于服务器上的/home/doe/repos

我想要的只是一个名为git的用户,它控制所有用户的回购。例如,他将使用john@server.com:repos/project.git而不是John拥有远程git@server.com:john/project.git。同样,Doe会推送到git@server.com:doe/some_other_project.git

如何在确保人们无法访问彼此的回购的同时实现这一目标?服务器通过SSH访问。

1 个答案:

答案 0 :(得分:0)

最简单的解决方案是设置像gitlab这样的东西,它提供了一个Web界面,各种访问控制,以及各种其他的花里胡哨。

如果你真的想自己动手:

directions in the Git book开始,设置服务器以允许通过ssh访问共享用户。

这些说明将为您提供一个共享的git帐户,每个人都可以访问该帐户,并允许任何人从任何存储库推送/提取。我们可以实现一个简单的授权层,将用户限制在特定目录中的存储库。

从一个小包装脚本开始:

#!/bin/sh

repo_prefix=$1

eval set -- $SSH_ORIGINAL_COMMAND
case "$1" in
    (git-receive-pack|git-upload-pack|git-upload-archive)

        # prevent attempts at using dir/../path to escape
        # repository directory
        case "$2" in
            (*..*) echo "Invalid repository name." >&2
                   exit 1
                   ;;
        esac

        repo_path="$repo_prefix/$2"
        eval exec $1 $repo_path
        ;;

    (*) echo "Unsupported command" >&2
        exit 1
        ;;
esac

这将为所有存储库路径添加前缀路径(作为命令行参数提供)。现在,我们需要安排这个包装器来拦截git操作。

要使用此功能,您需要修改添加到git用户authorized_keys文件的公钥。如果您按照Git书中的说明操作,authorized_keys文件中将包含一个或多个公钥,如下所示:

ssh-rsa AAAA...== some comment

对于每个公钥,您将需要添加一个配置选项,该选项将导致调用包装器脚本来代替原始命令。从sshd手册页:

  

文件的每一行都包含一个键(空行和行开头)   用'#'作为注释被忽略)。协议1公钥包括   以下以空格分隔的字段:options,bits,exponent,   模数,评论。协议2公钥包括:options,keytype,   base64编码的密钥,评论。选项字段是可选的......

稍微向下:

  

支持以下选项规范(请注意该选项   关键字不区分大小写):[...]

     

<强>命令=&#34;命令&#34;

     

指定在使用此密钥时执行命令   认证。用户提供的命令(如果有)是   忽略...客户端最初提供的命令可用   在SSH_ORIGINAL_COMMAND环境变量中。

考虑到这一点,我们修改我们的authorized_keys文件,看起来像这样:

command="/usr/bin/git-wrapper.sh username" ssh-rsa AAAA...===

这意味着当有人使用相应的私钥连接时,sshd将运行git-wrapper.sh username,导致我们的git-wrapper.sh脚本在字符串username前面添加存储库路径,确保git只会看到给定目录中的存储库。更具体地说,当你运行:

git push origin master

假设origin指向git服务器上的project.git,那么git将尝试在远程服务器上运行命令:

git-receive-pack project.git

我们的包装器脚本将拦截它,并将其转换为:

git-receive-pack $1/project.git

例如,如果我们的git git用户主目录没有存储库:

git$ ls

我们的authorized_keys文件如下所示:

git$ cat .ssh/authorized_keys
command="/usr/bin/git-wrapper.sh alice" ssh-rsa ... alice@example.com
command="/usr/bin/git-wrapper.sh bob" ssh-rsa ... bob@example.com

然后如果alice执行此操作:

alice$ git remote add origin git@mygitserver:project.git
git push origin master

她会看到:

fatal: 'alice/project.git' does not appear to be a git repository
fatal: Could not read from remote repository.

如果我们创建目标存储库:

git$ mkdir alice
git$ git init --bare alice/project.git

然后她可以推动:

alice$ git push origin master
[...]
To git@mygitserver:project.git
 * [new branch]      master -> master

但是如果bob试图克隆该存储库:

bob$ git clone git@mygitserver:project.git

它会失败:

fatal: 'bob/project.git' does not appear to be a git repository
fatal: Could not read from remote repository.

即使他尝试偷偷摸摸的东西:

bob$ git clone git@mygitserver:../alice/project.git
Invalid repository name
fatal: Could not read from remote repository.

而且,有点冗长的说法,就是如何访问git存储库服务器的授权。请注意,这只是为了演示目的而完成 ;您希望在生产环境中使用更强大的脚本。