GitHub App インストールアクセストークンを使って GitHub Actions を実行する

Today I Learned

この記事では、GitHub Personal Access Token(PAT)の代わりに、GitHub App インストールアクセストークン(以降、GitHub App トークン)を使って GitHub Actions を実行する方法を説明する。

Info

2023 年 9 月 10 日 追記
GitHub App トークン を GitHub Actions で利用する action が GitHub からリリースされた。
actions/create-github-app-token
ただし v1.2.1 時点では、以下の制約がある。

  • インストールアクセストークンで操作できるのは、ワークフローのリポジトリのみ
  • ワークフロー側からの Permission の追加はできない

参照:actions/create-github-app-token でほかのリポジトリを操作できなかった話

PAT の問題点

GitHub Actions で GitHub への認証が必要な操作をするとき、GITHUB_TOKEN では権限不足に陥ることがある。
たとえば、GitHub Actions 内でプライベートリポジトリを clone したり、コミットを作ってリポジトリに push したりするケースである。 GITHUB_TOKEN で権限が足りない場合には Bot ユーザーに紐づく PAT を使うが、PAT には次の問題点がある。

  • PAT を発行するための Bot ユーザーが必要
  • PAT の有効期限を過ぎると動かなくなる
    • PAT を再発行する度に Secrets の設定変更が必要

GitHub App トークンとは

これらの PAT の問題点を解決する手段として、GitHub App を使って発行した GitHub App トークンを使う方法がある。
GitHub App トークンは、PAT と同様に権限を細かく設定でき、トークンの有効期限が短いため、万が一漏えいしても影響が小さくて済む。
また、ユーザーアカウントに依存しないため、上記に挙げた PAT の問題点を解決できるメリットがある。

GitHub App のセットアップ

STEP1:GitHub App を作成する

  1. 次の URL にアクセスする。

  2. アプリの設定内容を入力する。

    • 「Register new GitHub App」セクション
      • GitHub App name - アプリの名前
        すべての GitHub ユーザーや組織でユニークにする必要がある。
        自分のみがインストールできるアプリにしていても、「https://github.com/apps/<APP_SLUG>」にアクセスするとアプリ名は全ユーザーに表示される。
      • Homepage URL - アプリの URL
        何でも良い。
    • 「Webhook」セクション
      • Active - 選択を外す
    • 「Permissions」セクション - トークンに付与する権限
      権限はアプリ作成後に変更できる。
      今回はプライベートリポジトリのクローンで GitHub App トークンを使用するため、以下の権限を付与する。
      • Contents > Read-only
      • Metadata > Read-only
    • 「Subscribe to events」セクション
      • Where can this GitHub App be installed - アプリをインストールできるアカウント
        「Only on this account」を設定すると、自分のみを対象にできる。
  3. [Create GitHub App] をクリックすると、アプリが作成される。

  4. 「About」セクションの「App ID」をメモしておく。 GitHub App トークンを取得する際のサードパーティアクションで使用する。

  5. 「Private keys」セクションで、[Generate a private key] をクリックする。 秘密鍵ファイルがダウンロードされる。

後から「Permissions」を変更した場合

https://github.com/settings/installations/<APP_ID> の画面で GitHub App を再承認する必要がある。
スクリーンショット:permission を承認するメッセージ

STEP2:GitHub App をインストールする

GitHub App を利用するリポジトリに、GitHub App をインストールする。

  1. インストールする GitHub App の左メニューから[Install App] をクリックする。
    または、https://github.com/settings/apps/<APP_SLUG>/installations にアクセスする。

  2. [Install App] をクリックする。

  3. インストールするリポジトリを選択する。 ユーザー(または組織)の全リポジトリ、または特定のリポジトリを選択できる。

    • All repositories
    • Only select repositories

今回は、GitHub Actions でプライベートリポジトリをクローンする例を示すため、次の 2 つのリポジトリにインストールする。

  • GitHub Actions を実行するリポジトリ
  • クローンするプライベートリポジトリ

STEP3:リポジトリに GitHub App ID と秘密鍵を登録する

GitHub Actions を実行するリポジトリのシークレットに、GitHub App ID と秘密鍵を登録する。

  1. リポジトリの [Settings] をクリックする。

  2. 「Secrets and variables」の [Actions] をクリックする。

  3. [New Repository secret] をクリックし、次の 2 つの Secret を登録する。

    • APP_ID:STEP1 でメモした GitHub App の App ID
    • PRIVATE_KEY:秘密鍵ファイルの内容
      「-----BEGIN RSA PRIVATE KEY-----」から「-----END RSA PRIVATE KEY-----」まで
  4. 秘密鍵ファイルはこの先の手順で不要となるので、パソコン内から削除する。

GitHub Actions で GitHub App トークンを生成する

GitHub App トークンを生成する方法

GitHub App トークンの生成方法は、以下のドキュメントで紹介されている。

この記事では詳細を省略するが、大まかな流れは次の通り。

  1. アプリの JSON Web トークン (JWT) を生成する。
  2. インストールの ID を取得する。
  3. JSON Web トークンとインストール ID を使って、GitHub App トークンを生成する。

GitHub Actions で GitHub App トークンを利用するには、上記の処理を Actions 上で実施する必要がある。
この記事では、上記の処理で Actions で提供している、サードパーティアクションの「tibdex/github-app-token」を使用する。
改ざんの恐れのあるサードパーティアクションを利用することは、セキュリティ上好ましくないが、Commit SHA でバージョンを固定して影響を最小限にする。
参照:Using third-party actions

「tibdex/github-app-token」の利用方法

「tibdex/github-app-token」を使って GitHub App トークンを生成する action は、次のように利用する。
バージョンは、v1.8.0 の Commit SHA を指定して固定する。
生成した GitHub App トークンを、ほかの Step へ渡すために Step の id を指定しておく必要がある。

- name: Generate GitHub App Token
  id: app-token
  uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92 # v1.8.0
  with:
    app_id: ${{ secrets.APP_ID }}
    private_key: ${{ secrets.PRIVATE_KEY }}

トークンを利用する側は、${{ steps.app-token.outputs.token }} で GitHub App トークンを参照する。

- name: Use token
  env:
    GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
  run: |
    # 環境変数の GITHUB_TOKEN に GitHub App トークンが設定されている
    echo $GITHUB_TOKEN # 実際には Actions のログに出力されない

GitHub App トークンを利用してプライベートリポジトリをクローンするワークフロー

Pull Request を作成したときに、プライベートリポジトリをクローンするワークフローを作成する。

.github/workflows/clone-private-repository.yml
name: Clone a private repository

on: pull_request

jobs:
  clone:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - name: Generate GitHub App Token
        id: app-token
        uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92 # v1.8.0
        with:
          app_id: ${{ secrets.APP_ID }}
          private_key: ${{ secrets.PRIVATE_KEY }}

      - name: Clone private repository
        env:
          token: ${{ steps.app-token.outputs.token }}
        run: |
          # クローンするプライベートリポジトリ名に応じて <OWNER> と <REPO_NAME> を書き換える
          gh repo clone https://github.com/<OWNER>/<REPO_NAME>
          ls -la

動作確認

Pull Request を作成してみる。 GitHub Actions のログで、プライベートリポジトリをクローンできていることを確認する。

スクリーンショット:GitHub Actions のログにクローンしたリポジトリのディレクトリが表示されている