Git:一个git用户来控制多个物理用户的回购 [英] Git: one git user to control the repos of multiple physical users
问题描述
ssh john@server.com
或 doe@server.com
。 物理用户拥有私人Git存储库,其他用户无法访问。例如。 John的回购地点位于 / home / john / repos
,而Doe的回购地点位于 / 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访问服务器。
最简单的解决方案是设置一些像 gitlab ,它提供了一个Web界面,各种访问控制以及各种其他的花招和口哨声。
如果您确实想要推出自己的产品: Git手册中的说明,用于设置您的服务器以允许通过ssh访问共享用户。
这些指令将为您提供每个人都可以访问的共享 git
帐户,并且可以让任何人从任何位置库。我们可以实现一个简单的授权层,将用户限制在特定的目录中。
从一个小包装脚本开始:
#!/ bin / sh
repo_prefix = $ 1
eval set - $ SSH_ORIGINAL_COMMAND
case
(git-receive-pack | git-upload-pack | git-upload-archive)
#防止尝试使用dir /../路径转义
$存储库目录
在
中存在$ 2(* .. *)echo存储库名称无效。 >& 2
exit 1
;;
esac
repo_path =$ repo_prefix / $ 2
eval exec $ 1 $ repo_path
;;
$ b $(*)echoUnsupported command>& 2
exit 1
;;
esac
这将为所有用户提供一个作为命令行参数提供的前缀路径存储库路径。现在,我们需要安排这个包装来拦截git操作。
要使用这个,你需要修改添加到 git
用户的 authorized_keys
文件。如果您按照Git手册中的说明操作,那么 authorized_keys
文件中将包含一个或多个公钥,如下所示:
ssh-rsa AAAA ... ==某些注释
对于每个公钥,您都需要添加一个配置选项,该选项将导致调用wrapper脚本来代替原始命令。从 sshd
手册页:
文件的每一行都包含一个键作为注释忽略以'#'开始
的空行和行。协议1公钥由以下空格分隔的字段
组成:选项,位,指数,
模数,注释。协议2公钥包括:options,keytype,
base64编码密钥,注释。选项字段是可选的...
并稍微下降:
支持以下选项规范(请注意,选项
关键字不区分大小写):[...]
command =command
指定只要将此密钥用于
身份验证,就会执行该命令。用户提供的命令(如果有的话)是
被忽略的......客户端最初提供的命令在SSH_ORIGINAL_COMMAND环境变量中可用
。
考虑到这一点,我们将 authorized_keys
文件修改为如下所示:
command =/ usr / bin / git-wrapper.sh usernamessh-rsa AAAA ... ===
这意味着当有人连接相应的私钥时, sshd
会运行 git-wrapper.sh用户名
,导致我们的 git-wrapper.sh
脚本预先在存储路径中添加字符串用户名
,确保 git
只能在给定目录中看到存储库。更具体地说,当你运行:
git push origin master
假设 project.git
on 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 alicessh-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
她会看到:
致命:'alice / project.git'似乎不是git存储库
致命:无法从远程存储库读取。
如果我们创建目标存储库:
git $ mkdir alice
git $ git init --bare alice / project.git
然后她可以推送:
alice $ git push origin master
[。 ..]
给git @ mygitserver:project.git
* [new branch] master - > master
但是,如果bob尝试克隆该存储库:
bob $ git clone git @ mygitserver:project.git
它会失败:
致命:'bob / project.git'似乎不是git存储库
致命:无法从远程存储库读取。
即使他尝试了一些偷偷摸摸的事情:
bob $ git clone git @ mygitserver:../ alice / project.git
存储库名称无效
致命:无法从远程存储库读取数据。
并且,在一个简单的说明中,您可以如何访问您的git存储库服务器的授权。请注意,这仅仅是为了演示目的完成的;您会希望在生产环境中使用更强大的脚本。
I have a Raspberry Pi, which I use as a Git server. There are multiple physical users accessing it and currently each of these users has their own login on the server. In other words, the users John and Doe can login to the server with SSH by running ssh john@server.com
or doe@server.com
.
The physical users have private Git repositories, which no other user is able to access. E.g. John's repos are located in /home/john/repos
and Doe's repos are located in /home/doe/repos
on the server.
What I want is only one user called git
, which controls all users' repos. E.g, instead of John having the remote john@server.com:repos/project.git
, he would use git@server.com:john/project.git
. Similarly, Doe would push to git@server.com:doe/some_other_project.git
How can this be achieved while making sure that people cannot access each other's repos? The server is accessed via SSH.
The easiest solution is to set up someting like gitlab, which provides a web interface, various sorts of access control, and all sorts of other bells and whistles.
If you really want to roll your own:
Start with directions in the Git book for setting up your server to permit access to a shared user over ssh.
Those instructions will get you a shared git
account to which everyone has access, and would let anyone push to/pull from any repository. We can implement a simple authorization layer that will restrict users to repositories in particular directories.
Start with a small wrapper script:
#!/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
This will prepend a prefix path, provided as a command line argument, to all repository paths. Now, we need to arrange for this wrapper to intercept git operations.
To use this, you will need to modify the public keys you add to the git
user's authorized_keys
file. If you followed the instructions in the Git book, the authorized_keys
file will have one or more public keys in it, like this:
ssh-rsa AAAA...== some comment
For each public key, you will need to add a configuration option that will cause the wrapper script to be called in place of the original command. From the sshd
man page:
Each line of the file contains one key (empty lines and lines starting with a ‘#’ are ignored as comments). Protocol 1 public keys consist of the following space-separated fields: options, bits, exponent, modulus, comment. Protocol 2 public key consist of: options, keytype, base64-encoded key, comment. The options field is optional...
And slightly further down:
The following option specifications are supported (note that option keywords are case-insensitive): [...]
command="command"
Specifies that the command is executed whenever this key is used for authentication. The command supplied by the user (if any) is ignored...The command originally supplied by the client is available in the SSH_ORIGINAL_COMMAND environment variable.
With that in mind, we modify our authorized_keys
file to look something like this:
command="/usr/bin/git-wrapper.sh username" ssh-rsa AAAA...===
This means that when someone connects with the corresponding private key, sshd
will run git-wrapper.sh username
, causing our git-wrapper.sh
script to prepend repository paths with the string username
, ensuring that git
will only see repositories in the given directory. More specifically, when you run:
git push origin master
And assuming that origin
points to project.git
on the git server, thengit
will attempt to run on the remote server the command:
git-receive-pack project.git
Our wrapper script will intercept that, and transform it into:
git-receive-pack $1/project.git
So for example, if our git git
user home directory has no repositories:
git$ ls
And our authorized_keys
file looks like this:
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
Then if alice
does this:
alice$ git remote add origin git@mygitserver:project.git
git push origin master
She will see:
fatal: 'alice/project.git' does not appear to be a git repository
fatal: Could not read from remote repository.
If we create the target repository:
git$ mkdir alice
git$ git init --bare alice/project.git
Then she can push:
alice$ git push origin master
[...]
To git@mygitserver:project.git
* [new branch] master -> master
But if bob were try to clone that repository:
bob$ git clone git@mygitserver:project.git
It would fail:
fatal: 'bob/project.git' does not appear to be a git repository
fatal: Could not read from remote repository.
Even if he tried something sneaky:
bob$ git clone git@mygitserver:../alice/project.git
Invalid repository name
fatal: Could not read from remote repository.
And that, in a somewhat verbose nutshell, is how you can access authorization for your git repository server. Note that this was all done for demonstration purposes only; you would want a substantially more robust script in a production environment.
这篇关于Git:一个git用户来控制多个物理用户的回购的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!