【问题标题】:Git: one git user to control the repos of multiple physical usersGit:一个git用户控制多个物理用户的repos
【发布时间】:2016-11-07 05:23:20
【问题描述】:

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

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

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

如何在确保人们无法访问彼此的存储库的同时实现这一点?服务器通过 SSH 访问。

【问题讨论】:

  • 您当前的方案使用 Unix 内置设施来隔离您不想使用的用户。这意味着您需要找到类似的功能来隔离用户并将该代码添加到您现在拥有的代码中。这可能比您预期的要复杂。您不希望 unix 用户登录的原因是什么?
  • 这个设置的主要原因是我想看看如何做,以便更多地了解 Git 和 UNIX。例如。 Github 和 Bitbucket 使用这种方法,所以我只是想了解它实际上是如何工作的,如果它看起来不错,我想我可以使用它。

标签: git ssh


【解决方案1】:

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

如果你真的想自己动手:

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 手册页:

文件的每一行包含一个键(空行和行开头 带有“#”的将被忽略为 cmets)。协议 1 公钥包括 以下空格分隔的字段:选项、位、指数、 模数,评论。协议 2 公钥包括:选项、密钥类型、 base64 编码的密钥,注释。选项字段是可选的...

再往下一点:

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

command="command"

指定每当此键用于 验证。用户提供的命令(如果有)是 忽略...客户端最初提供的命令可用 在 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 存储库服务器的授权。请注意,这一切都是出于演示目的;您可能希望在生产环境中拥有更强大的脚本。

【讨论】:

    猜你喜欢
    • 2010-11-28
    • 2015-04-12
    • 2017-09-29
    • 2013-09-21
    • 2018-10-22
    • 1970-01-01
    • 2018-10-08
    • 2017-06-08
    相关资源
    最近更新 更多