GitHub OAuth2 Token: How to restrict access to read a single private repo GitHub OAuth2 Token: How to restrict access to read a single private repo git git

GitHub OAuth2 Token: How to restrict access to read a single private repo


I don't believe you can restrict github OAuth tokens in that way. The github docs for OAuth say that

While Git over HTTP with OAuth reduces friction for some types of applications, keep in mind that unlike deploy keys, OAuth tokens work for any repository for which the user has access.

So while you can limit the scope of the token in terms of the types of activities, you can't limit it to a subset of repos.

Deploy keys can be restricted to a single repo, but allow write access.

The obvious tactic (as mentioned by Thomas) is to create a dummy account that represents the application. Given the goals of OAuth, this might be a better workflow in any case -- it'll let you easily change the permissions the app has as if it were in fact a user.

Github even mentions/endorses this strategy explicitly, calling them machine users.


Deploy keys are the way to go.

By default they don't allow write access and they are scoped to the specific repository (unlike the GitHub personal access token). So you can now generate a private/public key pair, set one as read/pull only deploy key on a single repository in GitHub and use the private key in your CI.

For instance run a bash script:

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

Now your CI has rights to access private repo's during the build.

You can add a Deploy key by going to your repository on Github and then clicking Settings > Deploy keys > Add deploy key


I wanted to have better access control in my Github Actions, but also have access to multiple repositories at the same time. And sure enough Deploy Keys are way to go. You can choose read/write permissions, but unfortunately you need a new pair for every new repository. Bellow I'll show you how I made it to work.

Let's assume you need to access 2 repositories from the third running Github Actions

  • Generate your keys
    ssh-keygen -N '' -t ed25519 -C "First Key Name" -f ./first_keyssh-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 actionon:  # 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.sockjobs:  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

Disclaimer

As you may guess above solution is not scaling up, and at some point you may consider setting up a Machine user (suggested in starwed's answer), which works best with organization account (even free) and gives access to Personal Access Tokens and OAuth.