Blog

GitHub App を使ってPATを使わずにActionsを動かそう

はじめに

おはようございます、IWSです。

Slack やローカル環境から GitHub Actions のワークフローを起動したい、あるいは API 経由で GitHub を操作したい。そんなシーンで避けて通れないのが Personal Access Token(PAT) の存在です。

しかし、PAT には以下のような悩みがつきまといます。

  • 発行した人に紐づくため、退職や異動で使えなくなる
  • 有効期限の更新・再発行など、運用コストが地味に高い
  • 権限スコープが広くなりがちで、セキュリティ的に扱いづらい

そこで本記事では、GitHub App を使って短期有効の一時トークンを払い出し、PAT 管理から解放される方法 を紹介します。あわせて、GitHub の GraphQL API を使ってブランチ名をあいまい検索する小ネタも載せています。

そもそも GitHub App とは

GitHub App は、GitHub の機能を操作して拡張するために構築できる統合の一種です。ユーザーのサインインやサービス アカウントの作成を必要とせずに、柔軟性を提供し、プロセスの摩擦を軽減できます。

引用:GitHub DocsGitHub アプリの作成について – GitHubドキュメント

ざっくり言うと、個人アカウントではなく「アプリ」として GitHub に対して権限を持てる仕組み です。インストールしたリポジトリに対して、必要最小限の権限で、短命な(最大1時間の)アクセストークンを発行できます。

これにより、

  • 個人に紐づかない
  • 権限スコープをリポジトリ単位・操作単位で絞れる
  • トークンは都度発行・短寿命なので漏洩リスクが低い

といった嬉しさが得られます。

ゴール

本記事のゴールは次のとおりです。

  1. GitHub App を作成し、対象リポジトリにインストールする
  2. Lambda から JWT を生成し、一時アクセストークンを取得する
  3. 取得したトークンでrepository_dispatchイベントを発火し、GitHub Actions を起動する
  4. (おまけ)GraphQL API でブランチ名をあいまい検索する

1. GitHub App を準備する

まずは GitHub App を作成します。個人アカウントの Settings → Developer settings → GitHub Apps → New GitHub App から作成します。

主な設定項目は次のとおりです。

  • GitHub App name: 好きな名前を設定
  • Homepage URL: 任意の URL(例: https://example.com
  • Webhook: 今回は利用しないのでチェックを外す
  • Permissions: 用途に合わせて設定。本記事では
    • Actions : Read and write
    • Contents : Read and write
  • Where can this GitHub App be installed?: Organization のリポジトリへインストールしたいので Any account を選択

作成が完了すると、App の設定画面に遷移します。ここで Client ID を控えておき、ページ下部の Private keys から Generate a private key で.pemファイルを発行してダウンロードしておきます。この秘密鍵は後ほど JWT の署名に使用します。

続いて Install App のページから、対象の Organization にインストールします。

権限を絞るために Only select repositories を選択し、対象リポジトリを指定してインストールしましょう。

インストール先リポジトリの Settings → GitHub Apps に作成した App が表示されれば準備完了です。

2. JWT を生成する

ここから先は AWS Lambda 上での実装例を紹介します(Zapier も検討しましたが、環境変数が扱えず断念しました)。

まずは秘密鍵を使って JWT を生成します。iss には GitHub App の Client ID を、exp は最大10分以内に設定します。

3. インストールアクセストークンを取得する

生成した JWT を使って、インストール単位のアクセストークンを取得します。トークンの有効期限は最大1時間です。

dataにさらに細かい権限やリポジトリ指定を加えることで、インストール時の権限からもう一段絞ったトークンを発行できます。

最小権限の原則を徹底したい場合は、呼び出しごとに必要な権限だけを付与したトークンを発行するのがおすすめです。

4. GitHub Actions を repository_dispatch で発火する

取得したトークンを使って、repository_dispatchエンドポイントを叩きます。これで GitHub Actions のワークフローを外部から起動できます。

呼び出される側のワークフローでは、on: repository_dispatchtypesに上で送ったevent_typeを指定しておきます。

のようにすることで、event_type で送った値と repository_dispatch の types で設定した値が一致したときに発火させることができます。

  • event_type が deploy-development
    • 発火する
  • event_type が deploy-check
    • 発火しない

あとは Slack の ChatBot から Lambda を起動するようにすれば、PAT を使わず Slack から GitHub Actions を叩く 仕組みが完成します。

GitHub 側にも「この App から実行された」という履歴が残るので、監査の観点でも安心です。

おまけ: GraphQL API でブランチ名をあいまい検索する

Slack コマンドから発火する場合、ユーザーが打ち込むブランチ名はタイポしがちです。そこで、発行したトークンを使って GraphQL API からブランチ一覧を取得し、あいまいマッチで最も近いブランチを選ぶ 処理を入れておくと便利です。

ブランチ一覧を取得する

類似度が最も高いブランチを選ぶ

Python 標準ライブラリのdifflib.SequenceMatcherで文字列の類似度を計算し、最も近いブランチ名を採用する、という単純なアプローチです。これだけでも「develp」を「develop」に寄せるくらいの手助けはしてくれます。

まとめ

  • PAT 管理はしんどい。GitHub App に置き換えると運用負荷もセキュリティリスクも下げられる。
  • JWT → インストールアクセストークン → repository_dispatch の流れで、外部から安全に GitHub Actions を起動できる。
  • GraphQL API と difflib を組み合わせれば、ブランチ名のタイポにも耐える Slack コマンドが作れる。

GitHub Actions 運用で PAT に消耗している方は、ぜひ GitHub App 化を検討してみてください。

Lambda 実装コード全体

ニフティでは、
さまざまなプロダクトへ挑戦する
エンジニアを絶賛募集中です!
ご興味のある方は以下の採用サイトより
お気軽にご連絡ください!

ニフティに興味をお持ちの方は
キャリア登録をぜひお願いいたします!

connpassでニフティグループに
参加いただくと
イベントの
お知らせが届きます!