如何根据给定的 ssh 密钥限制 git SSH 访问
How to restrict git SSH access based on ssh key given
我有一个私人 git 服务器,只有一个用户 git
和 ssh 密钥身份验证。目前,只有我一个人在用,但我想加更多人,我希望每个人都使用用户 git
连接到服务器并执行 git clone
、git push
等。如果所有存储库都是“public”,那么我知道如何解决这个问题。但是例如我想要一个私有存储库,我仍然会使用我的 SSH 密钥通过 git clone git@server:repo
克隆它,但是我不希望其他用户能够使用他们的 SSH 密钥克隆它。
我查看了关于设置服务器的 git-scm 文档(这对 public 存储库很有帮助)和 this post,但是这个 post 似乎只能解决私有存储库的问题。
TLDR:当您在 GitHub 上克隆存储库时,您说 git clone git@github.com:user/repo
并且您的 git 用户名和 ssh 密钥正在发送过来。现在,根据您是否拥有此存储库的权限,您可以克隆它,否则不能。所以基本上,每个人表面上都在使用 git
用户,但在幕后进行了一些授权。 GitHub 如何处理这个例子?
要实现类似的功能,您可以依赖专用工具,例如 gitolite。
否则,您可以安装一个成熟的 GitLab server,它还可以提供对存储库的细粒度访问控制,具有“Git 个 URL”,例如 git@your-gitlab-domain.com:user/repo.git
(顺便说一句,GitLab 以前依赖于 gitolite
、before version 5.0.0)
gitolite
似乎正是您正在寻找的基于 ssh 密钥管理对 repositories/branches 的访问。
但是如果你想从头开始构建这样的东西,你需要查看 authorized_keys
文件中的选项,尤其是 command
and environment
。使用这些,您可以根据使用的 ssh 密钥强制使用特定的 command/script 或 add/overwrite 环境变量。
例如,您可以编写一个脚本,读取用户允许的存储库作为其参数,并针对选定的 ssh 密钥将其强制为 运行:
# file ~/.ssh/authorized_keys
command="/home/git/bin/git-only-shell /home/git/repos/repo1" ssh-rsa AAAAB2...
command="/home/git/bin/git-only-shell /home/git/repos/repo1 /home/git/repos/repo2" ssh-rsa AAAAB3...
脚本现在可以从 $SSH_ORIGINAL_COMMAND
读取请求的 repo 并检查它是否包含在传递的列表中。此脚本 git-only-shell
的完整但粗略的示例实现可能是这样的:
#!/bin/bash
# verify that $SSH_ORIGINAL_COMMAND starts with git-upload-pack, git-upload-archive or
# git-receive-pack, followed by a space
if ! [[ "$SSH_ORIGINAL_COMMAND" == git-upload-pack\ * || "$SSH_ORIGINAL_COMMAND" == git-upload-archive\ * || "$SSH_ORIGINAL_COMMAND" == git-receive-pack\ * ]]; then
echo "unsupported command" >&2
exit 1
fi
# remove first word (git command)
ARGUMENTS="${SSH_ORIGINAL_COMMAND#git-* }"
# use eval to un-quote repo path (it is passed in single-quotes)
REPO_PATH="$(eval "echo $ARGUMENTS")"
# allowed repos are passed as arguments to this script
ALLOWED_REPOS="$@"
# check if repo was whitelisted
IS_ALLOWED=false
for repo in $ALLOWED_REPOS; do
if [[ "$REPO_PATH" == "$repo" ]]; then
IS_ALLOWED=true
fi
done
if [[ $IS_ALLOWED == "false" ]]; then
echo "access to this repo not allowed" >&2
exit 1
fi
# execute the original command
eval "$SSH_ORIGINAL_COMMAND"
像 gitolite
这样的工具太复杂,使用起来不愉快,或者没有提供所需的功能。我最终得到了以下解决方案:
- 具有 tables
user
和 repo
以及多对多 table permissions
. 的 PostgreSQL 数据库
- 一个用 C 编写的程序,用于检查用户是否具有 read/write 权限来访问请求的存储库,该存储库是从
$SSH_ORIGINAL_COMMAND
中提取的。
- 在
.ssh/authorized_keys
中,每个密钥都有自己的 command
,当该密钥用于 [=18] 时,它会使用与该密钥关联的用户名和从 SSH 命令中提取的存储库调用 C 程序=] 操作。
因此,当用户将 SSH 密钥添加到他的帐户时,会添加 .ssh/authorized_keys
中的一行,例如
command="/home/git/check_perms username \"${SSH_ORIGINAL_COMMAND}\"" no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa ...
然后command
是运行每次使用这个键进行Git操作。如果用户没有足够的权限,Git 操作将终止。
我有一个私人 git 服务器,只有一个用户 git
和 ssh 密钥身份验证。目前,只有我一个人在用,但我想加更多人,我希望每个人都使用用户 git
连接到服务器并执行 git clone
、git push
等。如果所有存储库都是“public”,那么我知道如何解决这个问题。但是例如我想要一个私有存储库,我仍然会使用我的 SSH 密钥通过 git clone git@server:repo
克隆它,但是我不希望其他用户能够使用他们的 SSH 密钥克隆它。
我查看了关于设置服务器的 git-scm 文档(这对 public 存储库很有帮助)和 this post,但是这个 post 似乎只能解决私有存储库的问题。
TLDR:当您在 GitHub 上克隆存储库时,您说 git clone git@github.com:user/repo
并且您的 git 用户名和 ssh 密钥正在发送过来。现在,根据您是否拥有此存储库的权限,您可以克隆它,否则不能。所以基本上,每个人表面上都在使用 git
用户,但在幕后进行了一些授权。 GitHub 如何处理这个例子?
要实现类似的功能,您可以依赖专用工具,例如 gitolite。
否则,您可以安装一个成熟的 GitLab server,它还可以提供对存储库的细粒度访问控制,具有“Git 个 URL”,例如 git@your-gitlab-domain.com:user/repo.git
(顺便说一句,GitLab 以前依赖于 gitolite
、before version 5.0.0)
gitolite
似乎正是您正在寻找的基于 ssh 密钥管理对 repositories/branches 的访问。
但是如果你想从头开始构建这样的东西,你需要查看 authorized_keys
文件中的选项,尤其是 command
and environment
。使用这些,您可以根据使用的 ssh 密钥强制使用特定的 command/script 或 add/overwrite 环境变量。
例如,您可以编写一个脚本,读取用户允许的存储库作为其参数,并针对选定的 ssh 密钥将其强制为 运行:
# file ~/.ssh/authorized_keys
command="/home/git/bin/git-only-shell /home/git/repos/repo1" ssh-rsa AAAAB2...
command="/home/git/bin/git-only-shell /home/git/repos/repo1 /home/git/repos/repo2" ssh-rsa AAAAB3...
脚本现在可以从 $SSH_ORIGINAL_COMMAND
读取请求的 repo 并检查它是否包含在传递的列表中。此脚本 git-only-shell
的完整但粗略的示例实现可能是这样的:
#!/bin/bash
# verify that $SSH_ORIGINAL_COMMAND starts with git-upload-pack, git-upload-archive or
# git-receive-pack, followed by a space
if ! [[ "$SSH_ORIGINAL_COMMAND" == git-upload-pack\ * || "$SSH_ORIGINAL_COMMAND" == git-upload-archive\ * || "$SSH_ORIGINAL_COMMAND" == git-receive-pack\ * ]]; then
echo "unsupported command" >&2
exit 1
fi
# remove first word (git command)
ARGUMENTS="${SSH_ORIGINAL_COMMAND#git-* }"
# use eval to un-quote repo path (it is passed in single-quotes)
REPO_PATH="$(eval "echo $ARGUMENTS")"
# allowed repos are passed as arguments to this script
ALLOWED_REPOS="$@"
# check if repo was whitelisted
IS_ALLOWED=false
for repo in $ALLOWED_REPOS; do
if [[ "$REPO_PATH" == "$repo" ]]; then
IS_ALLOWED=true
fi
done
if [[ $IS_ALLOWED == "false" ]]; then
echo "access to this repo not allowed" >&2
exit 1
fi
# execute the original command
eval "$SSH_ORIGINAL_COMMAND"
像 gitolite
这样的工具太复杂,使用起来不愉快,或者没有提供所需的功能。我最终得到了以下解决方案:
- 具有 tables
user
和repo
以及多对多 tablepermissions
. 的 PostgreSQL 数据库
- 一个用 C 编写的程序,用于检查用户是否具有 read/write 权限来访问请求的存储库,该存储库是从
$SSH_ORIGINAL_COMMAND
中提取的。 - 在
.ssh/authorized_keys
中,每个密钥都有自己的command
,当该密钥用于 [=18] 时,它会使用与该密钥关联的用户名和从 SSH 命令中提取的存储库调用 C 程序=] 操作。
因此,当用户将 SSH 密钥添加到他的帐户时,会添加 .ssh/authorized_keys
中的一行,例如
command="/home/git/check_perms username \"${SSH_ORIGINAL_COMMAND}\"" no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa ...
然后command
是运行每次使用这个键进行Git操作。如果用户没有足够的权限,Git 操作将终止。