iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
🙆

No More Machine Users! Use GitHub Apps with GitHub Actions

に公開

Introduction

Hello! I'm tatsuo48 from Hamee Corp.
GitHub Actions has a default secret called GITHUB_TOKEN. By setting it in an environment variable, you can perform operations on the repository where the Actions were triggered.
About the GITHUB_TOKEN secret

While this is convenient, it poses some problems under certain conditions.

The Problem: How to Use Other Repositories Within CI

As mentioned above, the scope of permissions for GITHUB_TOKEN is limited to the repository where the Actions were triggered. Therefore, it is not suitable for use cases such as:

  • Referencing another private repository within CI
    • e.g., Private Terraform modules

In such cases, a "machine user" (a user not linked to a specific person) is often created, and that user's Personal Access Token (PAT) is used.
GitHub's Terms of Service also permit machine users.
3. Account Requirements

A machine account is an Account set up by an individual human who accepts the Terms on behalf of the Account, provides a valid email address, and is responsible for its relevant actions. A machine account is used exclusively for performing automated tasks. Multiple users may direct the actions of a machine account, but the owner of the Account is ultimately responsible for the machine's actions. You may not maintain more than one free machine account in addition to your free User Account.

While it's easy and permissible under the terms to create a machine user, there are several disadvantages:

  • Token expiration management
    • If you don't set the issued PAT to "no expiration," you have to replace it every time it expires.
  • User billing
    • Even if it's a machine user, it's still a user. It consumes a GitHub seat, so payment is required.

Using GitHub Apps is a way to resolve these drawbacks.
By using GitHub Apps:

  • Token expiration management
    • You don't need to worry about it because tokens become unusable shortly after issuance.
  • User billing
    • Since it's not a user, it doesn't consume a seat.

It's all advantages!
Below, I'll explain what GitHub Apps are, how to use them, and how to set them up.

What is GitHub Apps?

First, here is the official documentation.
GitHub Apps

For a clear explanation of what GitHub Apps are, I found this article very helpful!
Learning by Building: GitHub Apps

Traditional OAuth Apps are installed per user—if the user is deleted or loses permissions to a repository, they disappear. Access tokens are valid indefinitely unless revoked by the user.
In contrast, GitHub Apps are installed per repository—or more accurately, you install them for a repository owner (Organization or User) and grant permissions to specific repositories under them.
Simply put, OAuth Apps are user-level apps, while GitHub Apps are repository-level apps.

This was a very concise and easy-to-understand explanation.

The diagram in Determining which integration to build is also very clear and has a nice "warm" feel to it.

Next, let's talk about how to actually set up GitHub Apps for GitHub Actions.

How to do it

Create a GitHub App

Access https://github.com/organizations/{{org_name}}/settings/apps and create an app.
Give the app a name in GitHub App name.
Homepage URL can be anything.
Uncheck Active for Webhook.
Assign the necessary permissions.
To perform a git clone, set Contents under Repository permissions to Read or higher.

Install the GitHub App

Access https://github.com/organizations/{{org_name}}/settings/apps/{{app_name}} and click Generate a private key to create a private key.
Keep this private key safe, as it will be used to issue temporary tokens within the CI.
Also, take note of the App ID.

https://github.com/organizations/{{org_name}}/settings/apps/{{app_name}}/installations
Access this URL to install the app.
In the repository selection, specify the repositories you want to grant access to.

Repository permissions can also be changed after installation via the following link:
https://github.com/organizations/{{org_name}}/settings/installations/{{AppID}}

Set up secrets

Configure the following two items as secrets in the target repository for your CI:
https://github.com/{{org_name}}/{{repository_name}}/settings/secrets/actions

  • The private key created earlier
  • App ID

Issuing a token within CI

Once you've done this, all that's left is to use it in your CI!
The task of issuing a temporary token from the private key and App ID can be easily done using the following Action:
https://github.com/marketplace/actions/create-github-app-token
*Note: Previously, only unofficial Actions were available, but now that there is the official Action mentioned above, let's use that.
Thank you for providing this information!: https://docs.google.com/presentation/d/10-HgSST2xR5H3xCwGLKCk_PBwq4zHcxD2393ifwOsiM/edit#slide=id.g2608d78f5c0_0_585

It looks like this:

jobs:
  job:
    runs-on: ubuntu-latest
    steps:
      - name: Generate token
        id: generate_token
        uses: actions/create-github-app-token@v1
        with:
          app-id: ${{ secrets.APP_ID }}
          private_key: ${{ secrets.PRIVATE_KEY }}
      - name: Use token
        env:
          TOKEN: ${{ steps.generate_token.outputs.token }}
        run: |
          echo "The generated token is masked: ${TOKEN}"

Bonus

Although this is for the GitHub Actions Advent Calendar, I'll also include how to use it in CircleCI as a bonus.
Since issuing tokens manually is tedious, I'm using the following tool. Thank you!
https://github.com/mackee/git-credential-github-apps

jobs:
  first:
    executor: hogehoge
    steps:
      - checkout
      - run: |
          wget https://github.com/mackee/git-credential-github-apps/releases/download/v1.1.1/git-credential-github-apps_1.1.1_Linux_x86_64.tar.gz 
          tar -zxvf git-credential-github-apps_1.1.1_Linux_x86_64.tar.gz
          chmod 755 git-credential-github-apps
          mv git-credential-github-apps /usr/bin/git-credential-github-apps
      - run: |
          echo -e $PRIVATE_KEY > /tmp/key.pem
          export $(echo -e 'host=github.com\\nprotocol=https' |  git-credential-github-apps -privatekey /tmp/key.pem -appid $APP_ID -login {{org_name}} get | grep password)
          export GIT_TOKEN=$password

Conclusion

Phew, the setup is quite an effort, isn't it?
I believe there are cases where machine users or OAuth Apps are more suitable based on the required permissions, so it's best to use them effectively while keeping a good balance! [1]
Tomorrow, Day 7 of the GitHub Actions Advent Calendar 2021, will be "About the custom Action I recently published" by kt15!

脚注
  1. Differences between GitHub Apps and OAuth Apps ↩︎

Discussion