GitHub OAuth2令牌:如何限制访问以只读取单个私有存储库

135

用例:

  1. 需要能够通过GitHub API(v3)从一个属于组织的私有存储库下载tarball副本的命令行应用程序(已部署到第三方计算机)

  2. 应用程序只能使用只读权限访问此一个私有存储库,无法访问其他存储库。

我已经通过在我的GitHub帐户上注册client_id/secret并为应用程序创建授权来完成(1)。但是,似乎授权返回的令牌不允许只读访问该存储库,也不限制于一个存储库(例如,可能会使用该令牌修改属于组织的此存储库以及其他存储库)。

有没有可能通过适当的范围限制访问?我在API文档中没有找到任何相关内容(https://developer.github.com/v3/oauth/#scopes)。


5
我也对这样的东西很感兴趣,但不需要只读限制。看起来似乎只有为存储库创建的部署密钥相关,但我不确定能否通过API使用它们。似乎唯一的解决办法是将某个虚拟用户添加为该存储库的合作者,并使用该用户登录API。 - Thomas Shields
5个回答

69
我不相信你可以以那种方式限制github OAuth令牌。Github OAuth文档说道:
“虽然使用OAuth的Git over HTTP减少了某些类型应用的摩擦力,但请记住,与部署密钥不同,OAuth令牌适用于用户具有访问权限的任何存储库。”
因此,虽然您可以限制令牌的范围,但无法将其限制为存储库子集。 部署密钥可以限制为单个存储库,但允许写入访问权限。
显然的策略(如Thomas所述)是创建代表应用程序的虚拟帐户。鉴于OAuth的目标,这在任何情况下都可能是更好的工作流程 - 它将使您轻松地更改应用程序的权限,就像它实际上是一个用户一样。

Github明确提到并认可这种策略,称其为机器用户


1
虽然这样做可以工作,但对于一个组织来说并不方便,因为您无法撤销特定用户的令牌。 - Willem D'Haeseleer
18
默认情况下,部署密钥只能读取/拉取代码,但是您可以选择为它们提供写入/推送代码的权限。 - nooitaf
3
如果我理解正确的话,在 GitHub Actions 中不能使用部署密钥,因为您必须将私钥存储在某个地方。如果能够创建用于单个存储库的访问令牌或部署密钥,并具有在操作中使用它的功能,那将是非常好的。 - Maksim Nesterenko
@maksim-nesterenko 有一个ssh-agent action,你可以通过GitHub secrets设置提供的ssh私钥。 - Stevan

18

部署密钥是最好的选择.

默认情况下,它们不允许写入访问权限,并且它们仅限于特定存储库(不像GitHub个人访问令牌)。因此,您现在可以生成一个私钥/公钥对,在GitHub上将其中一个设置为只读取/拉取的部署密钥,并在您的CI中使用私钥。

例如运行bash脚本:

eval "$(ssh-agent -s)";
ssh-add <your private deploy key>;

现在你的 CI 在构建过程中有权限访问私有存储库。

您可以通过转到 Github 上的存储库,然后单击 设置 > 部署密钥 > 添加部署密钥 来添加部署密钥。


3
但它们也可以拥有写入权限,这使它们成为密码的完美替代品(在泄漏的情况下,损害仅限于单个代码库!) - krassowski
这对我来说是最好的答案!!! 使用带有_ssh-key_参数的_actions/checkout@v3_操作 - Vincent Guyard

8

更新

Github终于推出了细粒度个人访问令牌。这种方法(或机器用户)现在应该是授权选择性访问的首选方法。

了解更多:https://github.blog/changelog/2022-10-18-introducing-fine-grained-personal-access-tokens

原始回答

我想在我的Github Actions中拥有更好的访问控制,同时还能够同时访问多个存储库。Deploy Keys就是去的方法。您可以选择读取/写入权限,但不幸的是每次需要为新存储库创建一对新的密钥。下面我将向您展示如何让它正常工作。

假设您需要从第三个运行的Github Actions访问2个存储库

  • Generate your keys
    ssh-keygen -N '' -t ed25519 -C "First Key Name" -f ./first_key
    ssh-keygen -N '' -t ed25519 -C "Second Key Name" -f ./second_key
    
    You don't need a passphrase as long as you'll remove keys from the filesystem after adding them to the secrets in the Github repository.
  • Add contents of *.pub files as Deploy keys of respective repositories (select write permissions if needed)
  • Add contents of first_key and second_key files to third repository's secrets as DEPLOY_KEY_FIRST and DEPLOY_KEY_SECOND respectively
  • Now you can remove generated key files - you don't want to keep them around anymore. You can always generate a new ones.
  • Setup workflows file
    name: Some automatic action
    
    on:
      # on push event
      push:
      # allow manual run
      workflow_dispatch:
    
    env:
      # sockets for multiple ssh agents (1 per key)
      SSH_AUTH_SOCK_FIRST: /tmp/ssh_agent_first.sock
      SSH_AUTH_SOCK_SECOND: /tmp/ssh_agent_second.sock
    
    jobs:
      build:
        runs-on: ubuntu-latest
        steps:
          # first step is to setup ssh agents
          - name: Setup SSH Agents
            run: |
              # load deploy keys from the secrets
              echo "${{ secrets.DEPLOY_KEY_FIRST }}" > ./ssh_key_first
              echo "${{ secrets.DEPLOY_KEY_SECOND }}" > ./ssh_key_second
    
              # set chmods (required to use keys)
              chmod 0600 ./ssh_key_*
    
              # start agents
              ssh-agent -a $SSH_AUTH_SOCK_FIRST > /dev/null
              ssh-agent -a $SSH_AUTH_SOCK_SECOND > /dev/null
    
              # add each key to their own ssh agent
              SSH_AUTH_SOCK=$SSH_AUTH_SOCK_FIRST ssh-add ./ssh_key_first
              SSH_AUTH_SOCK=$SSH_AUTH_SOCK_SECOND ssh-add ./ssh_key_second
    
              # you can now remove keys from the filesystem
              rm -f ./ssh_key_*
    
          # now you can use these keys in normal git commands
          - name: Clone first
            env:
              # assign relevant agent for this step
              SSH_AUTH_SOCK: ${{ env.SSH_AUTH_SOCK_FIRST }}
            run: |
              git clone git@github.com:user/first.git ./first
    
          - name: Clone second
            env:
              SSH_AUTH_SOCK: ${{ env.SSH_AUTH_SOCK_SECOND }}
            run: |
              git clone git@github.com:user/second.git ./second
    
  • Profit

免责声明

正如您可能从上面的解决方案中猜测到的那样,这种方法并不具有扩展性。在某些时候,您可以考虑设置一个机器用户(starwed的答案中建议使用),它适用于组织帐户(即使是免费的),并提供对个人访问令牌和OAuth的访问权限。


1

现在(2022年10月)可以使用以下方法:

介绍精细化个人访问令牌(2022年10月)

今天,我们为GitHub.com上的所有用户帐户启用了公共测试版中的精细化个人访问令牌(PATs)。
这种新类型的令牌为开发人员和资源所有者提供了更多关于令牌访问的控制和可见性。
今天的博客文章中了解更多有关这种新令牌类型的信息。

这些新令牌提供了更多的权限可供选择,必须被范围限定到特定的组织或帐户,并且必须过期。
组织所有者还将找到管理可以访问其组织的令牌的新工具,并且可以要求在使用这些令牌之前批准这些令牌。

https://i0.wp.com/user-images.githubusercontent.com/1666363/196268191-dd27554f-746e-45cf-9b92-a62f1846cd9e.gif?ssl=1 -- PATsv2-light2

您可以尝试新的令牌创建流程,并在我们的社区讨论中提供反馈。

有关更多信息,请参阅“创建精细化个人访问令牌”。

这允许选择特定的存储库(如果需要)。


我创建了一个细粒度的令牌,只能读取“内容”,但是当我尝试使用该令牌克隆时,出现“remote: Write access to repository not granted.” :( - chrismarx
@chrismarx 这可能是一个需要向GitHub支持报告的错误:只需读取权限即可克隆存储库。 - VonC
是的,切换回经典令牌就可以了 ‍♂️ - chrismarx

0

正如顶部答案所建议的那样,目前在GitHub上不可能实现这一点。

这不是对你问题的直接回答,但我寻找相同内容的原因是为了遵守仅允许限制区域从TCP 443出站的政策。

GitHub接受文档此处中记录的TCP 443上的SSH。

简而言之:如果您将ssh从ssh://git@github.com修改为ssh://git@ssh.github.com:443,则应该会成功。

要将github设置为使用TCP443,请编辑位于〜/ .ssh / config的配置文件,并添加此部分:

Host github.com
Hostname ssh.github.com
Port 443
User git

您可以使用以下方法测试此功能:

$ ssh -T git@github.com
> Hi username! You've successfully authenticated, but GitHub does not
> provide shell access.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接