GitHub Actionsで別のプライベートリポジトリを参照したい

私が所属している会社ではソース管理にGitHub Organizationを使っており、会社のルールでリポジトリの可視性設定は必ずプライベートにしなければなりません。

自分のチームではよくTerraformを触るのですが、GitHub Actionsでterraform initする際に、別のリポジトリにあるTerraformモジュールを参照したい場合があります。

こういった場合、リポジトリを跨いでいるためsecrets.GITHUB_TOKENでは対応できません。
今までであればPersonal Access Token(以下PATとする。)を発行することが多かったのですが、PATには以下のようなデメリットがあります。

  • セキュリティの都合上、有効期限を設定することがベターとされており、無期限で作成したくない。
  • 個人で管理するリポジトリであればあまり問題になりませんが、Organization等で複数人が管理する場合、個人のPATを使うことはそもそも避けたい。(退職時どうするか?など)

そこでGitHub Appsを用いれば、個人のPATに依存せず、また短期限のトークンを随時発行するかたちで secrets.GITHUB_TOKENの権限を超えてGitHub を操作することが可能になります。

GitHub Appsの作り方

1. GitHub Appsを作成するページにアクセス

個人の場合:https://github.com/settings/apps/new
組織の場合:https://github.com/organizations/${ORG_NAME}/settings/apps/new

2. 作成するアプリの設定をする

"Register new GitHub App" セクション
  • GitHub App name: アプリの名前
    すべての GitHub ユーザーや組織でユニークにする必要があります。

  • Homepage URL: アプリのURL
    何でも良いので適当にいれてください。

"Webhook" セクション
  • **Active のチェックを外します。
"Permissions" セクション

トークンに付与する権限です。 今回はプライベートリポジトリを参照する用途なので以下の権限を付与します。

  • Contents > Read-only
  • Metadata > Read-only
"Subscribe to events" セクション
  • Where can this GitHub App be installed: アプリをインストールできるアカウント。
    「Only on this account」を設定すると、自分のみを対象にできます。

3. アプリ作成とAppID,秘密鍵情報の取得

[Create GitHub App]をクリックするとアプリが作成されます。

"About" セクションのApp IDをメモしておきます。
また "Private keys" セクションで[Generate a private key]をクリックし、 秘密鍵ファイルをダウンロードします。

GitHub App をインストールする

GitHub Appを利用するリポジトリに、作成したGitHub Appをインストールします。

  1. インストールするGitHub Appの左メニューから[Install App]をクリックします。
    もしくは https://github.com/settings/apps/<APP_SLUG>/installations にアクセスします。
  2. [Install App]をクリックします。
  3. インストールするリポジトリを選択します。 ユーザー(or組織)の全リポジトリ、または特定のリポジトリを選択できます。
    • All repositories
    • Only select repositories

リポジトリでも問題無い気はするのですが、一応セキュリティに考慮して必要なリポジトリのみを選択します。

GitHub Actionsを実行するリポジトリ』にインストールするのはもちろんですが、『参照(クローン)されるプライベートリポジトリ』にもインストールする必要があるの注意してください。

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

GitHub Actionsを実行するリポジトリのシークレットに、GitHub App IDと秘密鍵を登録します。 なお、『参照(クローン)されるプライベートリポジトリ』には登録する必要ありません。

  1. リポジトリの[Settings]をクリックします。
  2. "Secrets and variables" の[Actions]をクリックします。
  3. [New Repository secret]をクリックし、以下の2つのシークレットを登録します
    • APP_ID: GitHub Appを作成した際にメモしたApp ID。おそらく6桁の数字。
    • PRIVATE_KEY: ダウンロードした秘密鍵ファイルの内容。「-----BEGIN RSA PRIVATE KEY-----」から「-----END RSA PRIVATE KEY-----」まで

なおリポジトリ数が多い場合はGitHubのOrganization secretsを使ったほうが楽かもです。

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

GitHubの公式Actionactions/create-github-app-tokenを使ってトークンを作成します。 GiHub Actionsで以下のステップを入れておけば、 後続処理で他のプライベートリポジトリをクローンすることできるようになります。(Terraform のモジュール参照は裏でGit クローンしているのでこれでOK)

# 認証情報の取得
- name: Generate Github token
  id: generate_token
  uses: actions/create-github-app-token@v1
  with:
    app-id: ${{ secrets.APP_ID }}
    private-key: ${{ secrets.APP_PRIVATE_KEY }}
    owner: ${{ github.repository_owner }}

# GitHubのアクセス時に認証情報を使用するように設定
- name: Set token
  run: git config --global url."https://x-access-token:$GITHUB_TOKEN@github.com/OrgName/".insteadOf "https://github.com/OrgName/"
  env:
    GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}

おまけ1: tibdex/github-app-token からの乗り換え

実は公式がactions/create-github-app-tokenを出したのはわりと最近で、v1.0.0がリリースされたのが2023年6月9日でした。この公式Actionが出るまでは、個人が作成した Actiontibdex/github-app-tokenを使用するのがわりと一般的でした。私と同じようにtibdex/github-app-tokenを使用している人も多いと思うので、乗り換えする際にどういったことをすればよいのかを紹介したいと思います。

結論

GitHub Actions を以下のように変えるとうまくきます。

 - name: Generate token
    id: generate_token
-  uses: tibdex/github-app-token@v1
+  uses: actions/create-github-app-token@v1
    with:
-    app_id: ${{ secrets.APP_ID }}
-    private_key: ${{ secrets.APP_PRIVATE_KEY }}
+    app-id: ${{ secrets.APP_ID }}
+    private-key: ${{ secrets.APP_PRIVATE_KEY }}
+    owner: ${{ github.repository_owner }}

 # GitHubのアクセス時に認証情報を使用するように設定
 - name: Set token
   run: git config --global url."https://x-access-token:$GITHUB_TOKEN@github.com/OrgName/".insteadOf "https://github.com/OrgName/"
   env:
     GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}

ポイント1: owner オプション

tibdex/github-app-tokenは、GitHub Apps がアクセスできるすべてのリポジトリに対してアクセスすることができました。

actions/create-github-app-tokenはデフォルトだと、ワークフローが動いているリポジトリのみにアクセスできるトークンが発行されます。そのため、他のリポジトリにアクセスしたい場合はownerを指定する必要があります。またrepositoriesオプションを使えば、にアクセスするリポジトリを絞ることも可能です。 上記の例では、リポジトリは絞らずownerオプションのみ追加しています。

ポイント2: 引数名

tibdex/github-app-tokeは入力パラメータである AppID と PrivateKey をそれぞれapp_idprivate_keyという変数名で指定します。変数名そのままでもactions/create-github-app-tokenで動くは動くのですが、以下のような Warning がでます。

Warning: Input 'app_id' has been deprecated with message: 'app_id' is deprecated and will be removed in a future version. Use 'app-id' instead.
Warning: Input 'private_key' has been deprecated with message: 'private_key' is deprecated and will be removed in a future version. Use 'private-key' instead.

actions/create-github-app-tokenだと、入力パラメータである AppID と PrivateKey の変数名はapp-idprivate-keyとのこと。よって変数名を変えています。

おまけ2: 現状GitHub AppでGitHub PackageをReadすることはできない

GitHub PackageをReadするためには、従来通りPATを使うしか方法がなさそうです。 これは本当にイケてない...。

github.com