Bitrise向けのGitHub Personal Access Tokensを駆逐する


## はじめに

株式会社ゆめみ Advent Calendar 2023の4日目の記事です

https://qiita.com/advent-calendar/2023/yumemi

### BitriseとGitHubの連携における課題

BitriseをCI環境で利用する際、Dangerを実行するためにGitHubのPersonal Access Tokensを使用していました。
GitHub Actionsの様に、`GITHUB_TOKEN`は利用できないためです

### GitHub Personal Access Tokensの使用に伴う懸念点

管理ユーザのPersonal Access Tokensを使用していたため権限が強く
流出した時のセキュリティリスクが高い問題があり、社内でメンバー(@s6n)からプロリク[^1]が出されました

![pr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228438/5e0970e9-9172-ef2a-9990-71b99e71df1c.png)

## GitHub Appsの導入

### GitHub Appsの設定手順

<details><summary>他でも解説記事があるので見たい人だけ</summary>

1. GitHubの「Developer settings」の「New GitHub Apps」から作成する
    - 直接Organizationに作成する権限がある場合
        1. `https://github.com/organizations/ORGS/settings/apps` から
    - 権限がない場合は、[Developer settings](https://github.com/settings/apps)で作成
![Developer settings](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228438/b2385dca-3fff-fec2-adf6-9de1bfa763f6.png)

2. GitHub Appsの設定
    - GitHub App name: 必須です、公開されます。アプリケーションのpublicなURLにもなります
        https://github.com/apps/yumemi-pat-expulsion
    - 説明： 必須です、公開されます
    - Homepage URL: 必須です、公開されます
![Register new GitHub Apps](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228438/725b3d77-4ed0-90ef-ded1-2debc7a532c6.png)
    - Callback URL: Danger用途では不要
    - Expire user authorization tokens: チェックをつけると`refresh_token`ができるようになりますDanger用途では不要
    - Request user authorization (OAuth) during installation: OAuthを使わないので、Danger用途では不要
    - Enable Device Flow: デバイス認証を組み込みます、Danger用途では不要
    - Webhook: Danger用途では不要なので、チェックを外します
    - Permissions
        - Repository permissions
            - Commit statuses, Issues, Pull requests: Read and write
    - Where can this GitHub App be installed?: 他のユーザやORGSへインストールしても使えないので、Only on this accountを 🔘
    ![Where can this GitHub App be installed?](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228438/3888ee3b-c374-4e78-d393-bdf4c4e14211.png)
3. private keyの作成
    - 上部のリンクかPrivate keysからprivate keyを作成すると、自動でprivate keyがDLされます
    ![Private keys annotation](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228438/a2f5213a-bcd0-d866-d2a6-0e81b6bf0d2e.png)
    ![Private keys](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228438/2b2eada9-65fd-553f-2253-1355fb55766c.png)
4. 移行
    - 直接Organizationに作成していない場合、アプリケーションをAdvancedからTransferします
    ![Advanced](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228438/c71cf968-eb34-7511-7f8a-2a15ef99a8c3.png)
    - ORGSの管理者に移行の確認と、対象アプリのApp managersに入れてもらう事で権限をつける依頼をします
    Developer SettingsのGitHub Appsから編集できます
5. インストール
    - ORGSにアプリケーションをインストールし、対象のリポジトリを選択します

</details>

## GitHub Appsへの移行

GitHub Appsを呼び出すStepはBitriseに用意されていないので
scriptsで書いてもよかったのですが、対象のリポジトリが多いためStepを作成しました

https://github.com/yumemi-inc/bitrise-step-github-app-token

private keyとApp IDを使って、GitHub Appsへtokenの発行リクエストを行います

:::note warn
private keyを扱うため、ご利用は自己責任の範囲でお願いします
:::

https://github.com/yumemi-inc/bitrise-step-download-bitrise-generic-file

BitriseのAPIを使って、指定SlugのGENERIC FILE STORAGEからDLを行います
private keyを複数のリポジトリへ配置したくなかったので、作成しました

:::note warn
Personal Access Tokensを扱うため、ご利用は自己責任の範囲でお願いします
:::

### 使い方

1. **step: github-app-token**の呼び出し
    bitrise.ymlでDangerを呼び出す前に追記
    ```yml:bitrise.yml
        steps:
        - git::https://github.com/yumemi-inc/bitrise-step-github-app-token@2.0.0:
            inputs:
            - github_app_id: {作成したGitHub AppsのApp ID}
        - ...
    ```

1. private keyをBitriseに登録
    - Secretsを使う場合
        - GITHUB_APP_KEY: 作成したGitHub Appsのprivate keyを内容をそのまま貼り付ける
        - Dangerで使うのでExpose for Pull Requests?を ✅
    ![Secrets](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228438/aa217ccf-96b0-1d06-c6c0-0b845704bddc.png)

    - <details><summary>GENERIC FILE STORAGEを使う場合</summary>

        1. 作成したGitHub Appsのprivate keyをGENERIC FILE STORAGEへ登録
        1. [Generic File Storage](https://github.com/bitrise-steplib/steps-generic-file-storage)でDL
            ![Generic File Storage](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228438/042e5bcf-4334-a89b-be93-bd16b171444a.png)
        1. bitrise-step-github-app-tokenの設定
            1. github_app_key_path: $GENERIC_FILE_STORAGE/{1.で登録したファイル名}
    </details>

    - <details><summary>Bitriseで別slugのGENERIC FILE STORAGEを使う場合</summary>

        1. 作成したGitHub Appsのprivate keyを別slugのGENERIC FILE STORAGEへ登録
        1. [download-bitrise-generic-file](https://github.com/yumemi-inc/bitrise-step-download-bitrise-generic-file)を使います[^2]
        ```yml:bitrise.yml
            steps:
            - git::https://github.com/yumemi-inc/bitrise-step-download-bitrise-generic-file.git@0.0.2:
                inputs:
                - BITRISE_API_TOKEN: $BITRISE_API_TOKEN
                - BITRISE_APP_SLUG: {1.で登録した時のslug}
                - TARGET_BITRISE_FILE_KEY: {1.で登録したFile Storage ID}
                - OUTPUT_FILE_NAME: private-key.pem
        ```
    </details>

1. Dangerで使うTokenにGITHUB_APP_TOKENを指定する
    ```bash
    DANGER_GITHUB_API_TOKEN=$GITHUB_APP_TOKEN swift run danger-swift ci
    ```

## 参考

- [シェルスクリプトで GitHub App のインストールアクセストークンを取得する](https://zenn.dev/gorohash/articles/e2c5f6ce50f4e6)
- [BitriseでGitHub Appのトークンを取得してDangerを動かす](https://note.com/nttrtech/n/nef467f66506e)
- [GitHub Apps + Dangerをやってみる](https://qiita.com/doihei/items/6dd338f2e55665cdaf28)
- [新しいステップの開発](https://devcenter.bitrise.io/ja/steps-and-workflows/developing-your-own-bitrise-step/developing-a-new-step.html)

[^1]: ゆめみでは[プロリク](https://notion.yumemi.co.jp/cxo/ceo)を使って、運用ルールの変更など、様々な事がメンバーが自発的に行う事ができます
[^2]: BITRISE_API_TOKENには[BitriseのPersonal Access Tokens]((https://app.bitrise.io/me/account/security))を発行してください