【问题标题】:How to restrict git SSH access based on ssh key given如何根据给定的 ssh 密钥限制 git SSH 访问
【发布时间】:2020-11-17 19:04:53
【问题描述】:

我有一个私人 git 服务器,有一个用户 git 和 ssh 密钥身份验证。目前只有我一个人在用,但是想加人,希望大家使用git用户连接服务器,执行git clonegit push等。如果所有的repositories都是" public”,那么我知道如何解决这个问题。但是例如我想要一个私有存储库,我仍然会使用我的 SSH 密钥通过git clone git@server:repo 进行克隆,但是我不希望其他用户能够使用他们的 SSH 密钥克隆它。

我检查了关于设置服务器的 git-scm 文档(这对公共存储库很有帮助)和 this 帖子,但是这篇帖子似乎只解决了私有存储库的问题。

TLDR:当您在 GitHub 上克隆存储库时,您说 git clone git@github.com:user/repo 并且您的 git 用户名和 ssh 密钥正在发送过来。现在,根据您是否拥有此存储库的权限,您可以克隆它,否则不能。所以基本上,每个人都在表面上使用git 用户,但在幕后,一些授权正在发生。例如 GitHub 是如何处理这个问题的?

【问题讨论】:

    标签: git ssh ssh-keys


    【解决方案1】:

    gitolite 似乎正是您正在寻找的基于 ssh 密钥管理对存储库/分支的访问。

    但是如果你想从头开始构建这样的东西,你需要查看authorized_keys 文件中的选项,尤其是commandenvironment。使用这些,您可以根据使用的 ssh 密钥强制执行特定的命令/脚本或添加/覆盖环境变量。

    例如,您可以编写一个脚本,读取用户允许的存储库作为其参数,并强制它针对选定的 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"
    

    【讨论】:

    • 这似乎正是我想要的,谢谢!我会对此进行测试,如果我觉得足够,我会接受你的回答。
    • eval "echo $ARGUMENTS" 对于命令注入和 CRE 漏洞很危险。
    【解决方案2】:

    要实现类似的功能,您可以依赖专用工具,例如 gitolite

    否则,您可以安装一个成熟的GitLab server,它还可以提供对存储库的细粒度访问控制,使用“Git URL”,例如git@your-gitlab-domain.com:user/repo.git

    (顺便说一句,GitLab 似乎以前依赖于 gitolitebefore version 5.0.0

    【讨论】:

    • 我不想依赖 GitLab,因为我想基本上从头开始构建 GitHub/GitLab。我看过 gitolite 但还没有找到解决方案。我想我需要更深入地研究它。
    【解决方案3】:

    gitolite 之类的工具过于复杂且难以使用,或者无法提供所需的功能。我最终得到了以下解决方案:

    • 一个 PostgreSQL 数据库,包含表 userrepo,以及一个多对多表 permissions
    • 用 C 编写的程序,用于检查用户是否具有访问请求的存储库的读/写权限,该存储库提取自 $SSH_ORIGINAL_COMMAND
    • .ssh/authorized_keys 中,每个密钥都有自己的command,当该密钥用于git 操作时,它会使用与该密钥关联的用户名和从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 操作将被终止。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-05
      • 2021-05-13
      • 2011-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-29
      • 2021-06-06
      相关资源
      最近更新 更多