最简单的解决方案是设置像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 存储库服务器的授权。请注意,这一切都是出于演示目的;您可能希望在生产环境中拥有更强大的脚本。