Skip to main content

GitHub App を作成するためのベスト プラクティス

GitHub App のセキュリティとパフォーマンスを向上させるには、次のベスト プラクティスに従ってください。

必要な最低限のアクセス許可を選択する

GitHub App を登録するときは、GitHub App に必要な最小限のアクセス許可を選択します。 アプリのキーまたはトークンが侵害された場合、こうすることで発生する可能性のある損害の量を制限できます。 アクセス許可の選択方法について詳しくは、「GitHub アプリのアクセス許可を選択する」をご覧ください。

GitHub App でインストール アクセス トークンやユーザー アクセス トークンを作成する際に、アプリがアクセスできるリポジトリとトークンに与えるアクセス許可をさらに制限できます。 詳細については、「GitHub アプリのインストール アクセス トークンの生成」および「GitHub アプリのユーザー アクセス トークンの生成」を参照してください。

レート制限を超えないようにする

API でデータをポーリングする代わりに、Webhook イベントをサブスクライブします。 こうすることで、GitHub App が API レート制限を超えないようにできます。 詳細については、「GitHub Apps での Webhook の使用」および「Webhook イベントに応答する GitHub App の構築」を参照してください。

レート制限を超えないようにするのに役立つ条件付き要求を使用することを検討してください。 条件付きの要求について詳しくは、「REST API を使用するためのベスト プラクティス」を参照してください。

可能であれば、REST API 要求ではなく統合 GraphQL クエリを使用して、レート制限を超えないようにすることを検討してください。 詳細については、「GitHub の REST API と GraphQL API の比較」および「GitHub GraphQL API に関するドキュメント」を参照してください。

レート制限に達し、API 要求を再試行する必要がある場合は、x-ratelimit-reset または Retry-After の応答ヘッダーを使用します。 これらのヘッダーが利用できない場合は、再試行の間の時間が指数関数的に増えるのを待機し、再試行を特定の回数実施後にエラーをスローします。 詳しくは、「REST API を使用するためのベスト プラクティス」を参照してください。

アプリの資格情報をセキュリティで保護する

GitHub App の秘密キーとクライアント シークレットを生成できます。 これらの資格情報を使用すると、アプリでインストール アクセス トークン、ユーザー アクセス トークン、更新トークンを生成できます。 これらのトークンを使用すると、アプリのインストールまたはユーザーに代わって API 要求を実施できます。

これらの資格情報を安全に保存する必要があります。 保存方法は、統合アーキテクチャと稼働するプラットフォームによって異なります。 一般に、使用中のプラットフォームに機密データを保存することを目的とした保存方法を使用する必要があります。

秘密キー

GitHub App の秘密キーは、アプリがインストールされるすべてのアカウントへのアクセスを許可します。

GitHub App の秘密キーを Azure Key Vault などのキー コンテナーに保存し、署名専用にすることを検討してください。

または、キーを環境変数として格納することもできます。 ただし、これはキー コンテナーにキーを保存するほど強力ではありません。 攻撃者が環境へのアクセス権を獲得した場合、秘密キーを読み取り GitHub App として永続的な認証を受けることができます。

コードがプライベート リポジトリに保存されている場合でも、アプリに秘密キーをハードコーディングしないでください。 アプリがネイティブ クライアントやクライアント側アプリの場合、またはユーザー デバイス上で稼働している (サーバー上で稼働しているのではなく) 場合は、秘密キーをアプリに配布しないでください。

必要以上に多くの秘密キーを生成しないでください。 不要になった秘密キーは削除する必要があります。 詳しくは、「GitHub Apps の秘密キーの管理」を参照してください。

クライアント シークレット

アプリでデバイス フローを使用しない限り、クライアント シークレットを使用してアプリのユーザー アクセス トークンを生成できます。 詳しくは、「GitHub アプリのユーザー アクセス トークンの生成」を参照してください。

アプリが Web サイトまたは Web アプリの場合は、Azure Key Vault などのキー コンテナーにクライアント シークレットを保存するか、暗号化された環境変数またはサーバー上のシークレットとして保存することを検討してください。

アプリがネイティブ クライアントやクライアント側アプリの場合、またはユーザー デバイスで稼働している (サーバー上で稼働しているのではなく) 場合は、クライアント シークレットをセキュリティ保護することはできません。 誰でもクライアント シークレットにアクセスしてトークンを生成できるため、アプリが生成するトークンに基づいて独自のサービスへのアクセスを制御する場合は注意が必要です。

インストール アクセス トークン、ユーザー アクセス トークン、および更新トークン

インストール アクセス トークンを使用すると、アプリのインストールに代わって API 要求を実施できます。 ユーザー アクセス トークンを使用すると、ユーザーに代わって API 要求を実施できます。 更新トークンを使用すると、ユーザー アクセス トークンを再生成できます。 アプリは秘密キーを使用することで、インストール アクセス トークンを生成できます。 アプリはクライアント シークレットを使用することで、ユーザー アクセス トークンと更新トークンを生成できます。

アプリが Web サイトや Web アプリの場合は、バックエンドでトークンを暗号化し、トークンにアクセスできるシステムのセキュリティを確保する必要があります。 アクティブなアクセス トークンとは別の場所に更新トークンを保存することを検討してください。

アプリがネイティブ クライアントやクライアント側アプリの場合、またはユーザー デバイスで稼働している (サーバー上で稼働しているのではなく) 場合は、トークンとサーバー上で稼働するアプリをセキュリティ保護できないことがあります。 これを行うには秘密キーが必要なため、インストール アクセス トークンを生成しないでください。 その代わりに、ユーザー アクセス トークンを生成する必要があります。 アプリのプラットフォームに推奨される方法を使用してトークンを保存する必要があり、保存方法が完全に安全ではないことがあることに注意してください。

適切なトークンの種類を使用する

GitHub Apps は、認証された API 要求を行うため、インストール アクセス トークンまたはユーザー アクセス トークンを生成できます。

インストール アクセス トークンはアクティビティをアプリに関連付けます。 これらは、ユーザーに関係なく動作する自動化機能に役立ちます。

ユーザー アクセス トークンはアクティビティをユーザーとアプリに関連付けます。 これらは、ユーザーによる入力に基づくアクションやユーザーの代理のアクションを実行する場合に役立ちます。

インストール アクセス トークンは、GitHub App のアクセス許可とアクセスに基づいて制限されます。 ユーザー アクセス トークンは、GitHub App のアクセス許可とアクセスおよびユーザーのアクセス許可とアクセスの両方に基づいて制限されます。 したがって、GitHub App がユーザーの代理のアクションを実行する場合は、インストール アクセス トークンではなく常にユーザー アクセス トークンを使用する必要があります。 そうでない場合、アプリを通じてユーザーが表示・実行できない操作を表示・実行できる場合があります。

アプリでは、認証に personal access token または GitHub パスワードを使用しないでください。

徹底的かつ永続的な承認

ユーザーにサインインした後、アプリ開発者は追加の手順を実行して、ユーザーがシステム内のデータにアクセスできるようにする必要があります。 各サインインには、メンバーシップ、アクセス、現在の SSO 状態に関する新しいチェックが必要です。

永続的で一意の id を使用してユーザーを格納する

ユーザーがサインインしてアプリケーションでアクションを実行するときは、次回サインインしたときに同じリソースへのアクセス権を付与するために、どのユーザーがそのアクションを実行したかを覚えておく必要があります。

ユーザーをデータベースに正しく格納するには、常にユーザーの id を使用します。 この値は、ユーザーに対して変更されることも、別のユーザーを指し示すために使用されることもないため、意図したユーザーへのアクセスを確実に提供できます。 ユーザーの idGET /user REST API エンドポイントで確認できます。 「ユーザーの REST API エンドポイント」をご覧ください。

リポジトリ、組織、および企業へのリファレンスを格納する場合は、それらの id を使用して、リンクが正確であることを確認します。

ユーザー ハンドル、組織の置換フィールド、メール アドレスなど、時間の経過に伴い変化する可能性のある識別子を 絶対に 使用しないでください。

新しい認証ごとに組織へのアクセスを検証する

ユーザー アクセス トークンを使用する場合は、トークンが承認されている組織を追跡する必要があります。 組織が SAML SSO を使用していて、ユーザーが SAML SSO を実行していない場合、ユーザー アクセス トークンはその組織にアクセスできません。 REST API エンドポイントを GET /user/installations 使用して、ユーザー アクセス トークンがアクセスできる組織を確認できます。 ユーザーが組織へのアクセスを許可されていない場合は、SAML SSO を実行するまで、独自のアプリケーション内の組織所有データへのアクセスを防止する必要があります。 詳しくは、「GitHub Appインストール用 REST API エンドポイント」を参照してください。

organization コンテキストと Enterprise コンテキストを使用してユーザー データを格納する

id フィールドを使用してユーザー ID を追跡するだけでなく、各ユーザーが操作している組織または企業のデータを保持する必要があります。 これにより、ユーザーがロールを切り替えた場合に、機密情報が漏えいしないようにすることができます。

次に例を示します。

  1. ユーザーは、SAML SSO を必要とする Mona 組織にいて、SSO の実行後にアプリにサインインします。 これで、アプリはユーザーが Mona 内で行うあらゆるものにアクセスできるようになりました。
  2. ユーザーは、Mona 内のリポジトリから多数のコードを抜き取り、分析するためにアプリに保存します。
  3. その後、ユーザーはジョブを切り替え、Mona 組織から削除されます。

ユーザーがアプリにアクセスしても、ユーザー アカウントに Mona 組織のコードと分析をまだ表示できますか?

このため、アプリが保存しているデータのソースを追跡することが重要です。 それ以外の場合、アプリは組織のデータ保護にとって脅威であり、アプリがデータを正しく保護しているか信頼できない場合は、そのアプリを禁止する可能性があります。

トークンを期限切れにする

GitHub では、有効期限があるユーザー アクセス トークンを使用することを強くお勧めします。 以前に有効期限があるユーザー アクセス トークンの使用をオプトアウトしたものの、この機能を再び有効化したい場合は、「GitHub アプリのオプション機能のアクティブ化」を参照してください。

インストール アクセス トークンは 1 時間後に期限切れになり、有効期限があるユーザー アクセス トークンは 8 時間後に期限切れになり、更新トークンは 6 か月後に期限切れになります。 ただし、不要になったトークンはすぐに取り消すこともできます。 詳細については、「DELETE /installation/token」を参照してインストールのアクセス トークンを取り消し、「DELETE /applications/{client_id}/token」を参照してユーザー アクセス トークンを取り消してください。

トークンをキャッシュする

ユーザー アクセス トークンとインストール アクセス トークンは期限切れまで使用されます。 作成したトークンはキャッシュしてください。 新しいトークンを作成する前に、有効なトークンが残っていないか、キャッシュを確認してください。 トークンを再利用すれば、トークン生成要求の数が減るため、アプリがそれだけ速くなります。

セキュリティ侵害を処理するための計画を立てる

セキュリティ侵害をタイムリーに処理できるように、計画を立てる必要があります。

アプリの秘密キーやシークレットが侵害された場合は、新しいキーやシークレットを生成し、新しいキーまたはシークレットを使用するようにアプリを更新し、古いキーやシークレットを削除する必要があります。

インストール アクセス トークン、ユーザー アクセス トークン、または更新トークンが侵害された場合は、直ちにこれらのトークンを取り消す必要があります。 詳細については、「DELETE /installation/token」を参照してインストールのアクセス トークンを取り消し、「DELETE /applications/{client_id}/token」を参照してユーザー アクセス トークンを取り消してください。

定期的な脆弱性スキャンを実施する

アプリで定期的な脆弱性スキャンを実行する必要があります。 たとえば、アプリのコードをホストするリポジトリに対して、コード スキャンとシークレット スキャンを設定できます。 詳細については、「コード スキャンについて」および「シークレット スキャンについて」を参照してください。

適切な環境を選択する

アプリがサーバー上で稼働している場合は、サーバー環境がセキュリティ保護され、アプリで予想される量のトラフィックを処理できることを確認します。

最低限の Webhook をサブスクライブする

アプリに必要な Webhook イベントのみをサブスクライブします。 これにより、アプリが必要としないペイロードを受信しないため、待機時間を短縮できます。

Webhook シークレットを使用する

GitHub App の Webhook シークレットを設定し、受信 Webhook イベントの署名がシークレットと一致することを確認する必要があります。 これにより、受信 Webhook イベントが有効な GitHub イベントであることを確認できます。

詳しくは、「GitHub Apps での Webhook の使用」を参照してください。 例については、「Webhook イベントに応答する GitHub App の構築」をご覧ください。

ユーザーが新しいアクセス許可を受け入れる時間を与える

GitHub App にリポジトリや組織へのアクセス許可を追加すると、個人用アカウントまたは組織にアプリがインストールされているユーザーに新しいアクセス許可の確認を求める電子メールが届きます。 ユーザーが新しいアクセス許可を承認するまで、アプリのインストールは古いアクセス許可しか受け付けません。

アクセス許可を更新する際には、アプリに下位互換性を持たせることで、ユーザーに新しいアクセス許可を受け入れる時間を与えることを検討する必要があります。 インストール Webhook と new_permissions_accepted アクション プロパティを使用すると、ユーザーがアプリの新しいアクセス許可を受け入れるタイミングを確認できます。

安全な方法でサービスを使用する

アプリでサードパーティのサービスを利用する場合は、セキュリティで保護された方法で利用する必要があります。

  • アプリで利用するすべてのサービスでは、固有のログイン情報とパスワードを指定する必要があります。
  • アプリケーションは、SaaSサービスを管理するためのメールやデータベースサービスのようなサービスアカウントを共有するべきではありません。
  • 管理業務を行う従業員のみが、アプリをホストするインフラストラクチャへの管理者アクセス権を持つ必要があります。

ログと監視を追加する

アプリにログ記録と監視機能を追加することを検討してください。 セキュリティ ログには、以下が含まれている場合があります。

  • 認証及び認可イベント
  • サービス設定の変更
  • オブジェクトの読み書き
  • ユーザーとグループのアクセス許可の変更
  • ロールの管理者への昇格

ログでは、各イベントで一貫したタイムスタンプを使う必要があります。また、ログに記録されたすべてのイベントのユーザー、IP アドレス、ホスト名を記録する必要があります。

データの削除を有効にする

他のユーザーや組織が GitHub App を使用できる場合は、ユーザーと組織の所有者が自分のデータを削除できる方法を提供する必要があります。 ユーザーは、自分のデータを削除するためにサポート担当者にメールしたり、電話したりする必要がないようにすべきです。

参考資料