Skip to main content

OpenID Connect を使ったセキュリティ強化について

OpenID Connect を使用すると、ワークフローによって、有効期間の短いトークンをクラウド プロバイダーから直接交換できます。

注: GitHub ホステッド ランナーは、現在 GitHub Enterprise Server でサポートされていません。 GitHub public roadmap で、今後の計画的なサポートの詳細を確認できます。

OpenID Connect の概要

多くの場合、GitHub Actions ワークフローは、ソフトウェアをデプロイするため、またはクラウドのサービスを使うために、クラウド プロバイダー (AWS、Azure、GCP、HashiCorp Vault など) にアクセスするように設計されています。 ワークフローは、このようなリソースにアクセスできるように、パスワードやトークンなどの資格情報をクラウド プロバイダーに事前に提供します。 通常、このような資格情報は GitHub にシークレットとして格納されており、ワークフローは、実行時に毎回このシークレットをクラウド プロバイダーに提示します。

ただし、ハードコーディングされたシークレットを使うには、クラウド プロバイダーで資格情報を作成し、それをシークレットとして GitHub に複製する必要があります。

OpenID Connect (OIDC) を使って、有効期間が短いアクセス トークンをクラウド プロバイダーに直接要求するようにワークフローを構成するという別の方法を採ることもできます。 クラウド プロバイダー側でも OIDC をサポートする必要がある場合は、アクセス トークンを要求できるワークフローを制御する信頼関係を構成する必要があります。 現在 OIDC をサポートしているプロバイダーとして、アマゾン ウェブ サービス、Azure、Google Cloud Platform、HashiCorp Vault などがあります。

OIDC を使う利点

OIDC トークンを使うようにワークフローを更新することで、次のような優れたセキュリティ プラクティスを採用できます。

  • クラウド シークレットなし: 有効期間が長い GitHub シークレットとしてクラウドの資格情報を複製する必要はありません。 代わりに、クラウド プロバイダー上で OIDC 信頼を構成し、OIDC を介して有効期間が短いアクセス トークンをクラウド プロバイダーに要求するようにワークフローを更新することができます。
  • 認証と認可の管理: クラウド プロバイダーの認証 (authN) および認可 (authZ) ツールを使ってクラウド リソースへのアクセスを制御することで、ワークフローから資格情報を使用する方法をより細かく制御できます。
  • 資格情報のローテーション: OIDC を使う場合、1 つのジョブに対してのみ有効であり、自動的に失効する有効期間が短いアクセス トークンがクラウド プロバイダーから発行されます。

OIDC の概要

次の図は、GitHub の OIDC プロバイダーがワークフローやクラウド プロバイダーとどのように統合されているかを示す概要です。

OIDC 図

  1. クラウド プロバイダー内に、クラウド ロールと、クラウドへのアクセスを必要とする GitHub ワークフローとの間に OIDC 信頼を作成します。
  2. ジョブを実行するたびに、GitHub の OIDC プロバイダーによって OIDC トークンが自動生成されます。 このトークンには、認証対象の特定のワークフローに関する、セキュリティが強化された検証可能な ID を確立するための複数の要求が含まれています。
  3. このトークンを GitHub の OIDC プロバイダーに要求し、クラウド プロバイダーに提示するステップまたはアクションをジョブ内に含めることができます。
  4. クラウド プロバイダーは、トークンで提示した要求の検証を完了した後に、ジョブの期間中にのみ使用できる有効期間の短いクラウド アクセス トークンを提供します。

クラウドを使った OIDC 信頼の構成

GitHub の OIDC プロバイダーを信頼するようにクラウドを構成する場合は、受信する要求をフィルター処理する条件を追加する 必要があります。これは、信頼できないリポジトリやワークフローがクラウド リソースに対してアクセス トークンを要求できないようにするためです。

  • クラウド プロバイダーは、アクセス トークンを付与する前に、信頼設定で条件を設定するために使われた subject と他の要求が、要求の JSON Web トークン (JWT) 内のものと一致するかどうかを確認します。 そのため、クラウド プロバイダーで subject や他の条件を正しく定義するように注意する必要があります。
  • OIDC 信頼の構成手順と、(Subject やその他の要求を使って) クラウド ロールの条件を設定する構文は、利用しているクラウド プロバイダーによって異なります。 例については、「サブジェクト要求の例」を参照してください。

OIDC トークンの概要

各ジョブは GitHub の OIDC プロバイダーに OIDC トークンを要求し、その応答として、自動的に生成された JSON Web トークン (JWT) が返されます。これは生成されたワークフロー ジョブごとに一意です。 このジョブを実行すると、OIDC トークンがクラウド プロバイダーに提示されます。 クラウド プロバイダーは、トークンを検証するために、OIDC トークンの subject とその他の要求がクラウド ロールの OIDC 信頼定義に事前に構成されている条件と一致するかどうかを確認します。

次の OIDC トークン例では、octo-org/octo-repo リポジトリ内の prod というジョブ環境を参照する subject (sub) を使っています。

{
  "typ": "JWT",
  "alg": "RS256",
  "x5t": "example-thumbprint",
  "kid": "example-key-id"
}
{
  "jti": "example-id",
  "sub": "repo:octo-org/octo-repo:environment:prod",
  "environment": "prod",
  "aud": "https://HOSTNAME/octo-org",
  "ref": "refs/heads/main",
  "sha": "example-sha",
  "repository": "octo-org/octo-repo",
  "repository_owner": "octo-org",
  "actor_id": "12",
  "repo_visibility": private,
  "repository_id": "74",
  "repository_owner_id": "65",
  "run_id": "example-run-id",
  "run_number": "10",
  "run_attempt": "2",
  "actor": "octocat",
  "workflow": "example-workflow",
  "head_ref": "",
  "base_ref": "",
  "event_name": "workflow_dispatch",
  "ref_type": "branch",
  "job_workflow_ref": "octo-org/octo-automation/.github/workflows/oidc.yml@refs/heads/main",
  "iss": "https://HOSTNAME/_services/token",
  "nbf": 1632492967,
  "exp": 1632493867,
  "iat": 1632493567
}

GitHub の OIDC プロバイダーがサポートするすべての要求を確認するには、https://HOSTNAME/_services/token/.well-known/openid-configurationclaims_supported のエントリを確認します。

このトークンには、標準の audience、issuer、subject 要求が含まれています。

要求説明
aud(Audience) 既定では、これはリポジトリ所有者 (リポジトリを所有する組織など) の URL です。 カスタマイズできるのは、この要求のみです。 ツールキットのコマンド (core.getIDToken(audience)) を使ってカスタムの対象ユーザーを設定できます
iss(Issuer) 。OIDC トークンの発行者: https://HOSTNAME/_services/token
sub(Subject) クラウド プロバイダーによって検証される subject 要求を定義します。 常に予測可能な方法でアクセス トークンを割り当てるには、この設定が不可欠です。

OIDC トークンには、標準の要求が他にもあります。

要求説明
alg(Algorithm) OIDC プロバイダーが使うアルゴリズム。
exp(Expires at) JWT の有効期限を特定します。
iat(Issued at) JWT が発行された時刻。
jti(JWT token identifier) OIDC トークンの一意の識別子。
kid(Key identifier) OIDC トークンの一意のキー。
nbf(Not before) この時刻より前に JWT を使用することはできません。
typ(Type) トークンの種類について説明します。 これは JSON Web トークン (JWT) です。

トークンには、GitHub が提供するカスタム要求も含まれています。

要求説明
actorワークフロー実行を開始した個人アカウント。
actor_idワークフロー実行を開始した個人アカウントの ID。
base_refワークフロー実行における pull request のターゲット ブランチ。
environmentジョブが使う環境の名前。
event_nameワークフローの実行をトリガーしたイベントの名前。
head_refワークフロー実行における pull request のソース ブランチ。
job_workflow_refこれは、このジョブが使う再利用可能なワークフローの参照パスです。 詳細については、「再利用可能なワークフローでの OpenID Connect の使用」を参照してください。
ref(Reference) ワークフロー実行をトリガーした git ref。
ref_typeref の種類。例: "branch"。
repo_visibilityワークフローが実行されているリポジトリの可視性。 次の値を受け入れます: internalprivate、または public
repositoryワークフローが実行されているリポジトリ。
repository_idワークフローが実行されているリポジトリの ID。
repository_ownerrepository が格納されている組織の名前。
repository_owner_idrepository が格納されている組織の ID。
run_idワークフローをトリガーしたワークフロー実行の ID。
run_numberこのワークフローが実行された回数。
run_attemptこのワークフロー実行が再試行された回数。
workflowワークフローの名前。

OIDC 要求を使ったクラウド ロールに対する信頼条件の定義

OIDC を使う場合、クラウド プロバイダー内のリソースにアクセスするには、GitHub Actions ワークフローにトークンが必要です。 ワークフローはクラウド プロバイダーにアクセス トークンを要求します。そこで、JWT から提示された詳細が確認されます。 JWT の信頼構成が一致した場合、クラウド プロバイダーは、応答として一時的なトークンをワークフローに発行します。これを使って、クラウド プロバイダー内のリソースにアクセスできるようになります。 特定の組織のリポジトリから送信された要求のみに応答するようにクラウド プロバイダーを構成することができます。また、後述する追加の条件を指定することもできます。

通常、Audience と Subject の要求は、GitHub ワークフローへのアクセスにスコープを設定する目的で、クラウド ロールやリソースに対する条件の設定時に組み合わせて使います。

  • Audience: 既定では、この値には組織またはリポジトリ所有者の URL を使います。 これを使って、特定の組織内のワークフローのみがクラウド ロールにアクセスできるように条件を設定できます。
  • Subject: 既定では、事前に定義された書式があります。GitHub の Organization、リポジトリ、ブランチ、関連付けられた job 環境など、ワークフローに関する主要なメタデータの一部を連結したものです。 連結したメタデータからサブジェクト要求を組み立てる方法については、「サブジェクト要求の例」を参照してください。

より詳しい信頼条件が必要な場合は、JWT に含まれる issuer (iss) と subject (sub) の要求をカスタマイズできます。 詳しくは、「トークン クレームのカスタマイズ」を参照してください。

また、OIDC トークンでサポートされている要求は他にも多数あり、これらの条件設定にも使用できます。 さらに、クラウド プロバイダーがアクセス トークンへのロール割り当てを許可していて、さらに細かいアクセス許可を指定できる場合があります。

: クラウド プロバイダーがアクセス トークンを発行する方法を制御するには、少なくとも 1 つの条件を定義し、信頼できないリポジトリがクラウド リソースにアクセス トークンを要求できないようにする 必要があります

subject 要求の例

次の例は、"Subject" を条件として使う方法を示しています。また、連結したメタデータから "Subject" を組み立てる方法について説明します。 subjectjob コンテキストの情報を使い、特定のブランチ、環境内で動作するワークフローからの要求に対してのみアクセス トークン要求を許可するようにクラウド プロバイダーに指示します。 以下のセクションでは、使用できる一般的な subject について説明します。

特定の環境にフィルター処理する

ジョブから環境を参照するときに、subject 要求には環境名が含まれます。

特定の環境名にフィルター処理する subject を構成することができます。 この例で、ワークフロー実行は、octo-org 組織が所有する octo-repo というリポジトリ内にある Production という環境を持つジョブから開始されている必要があります。

構文:repo:<orgName/repoName>:environment:<environmentName>
例:repo:octo-org/octo-repo:environment:Production

pull_request イベントにフィルター処理する

pull request イベントによってワークフローがトリガーされたとき、ジョブが環境を参照していない場合に限り、subject 要求には pull_request 文字列が含まれます。

pull_request イベントにフィルター処理する subject を構成することができます。 この例で、ワークフロー実行は、octo-org 組織が所有する octo-repo というリポジトリ内の pull_request イベントによってトリガーされている必要があります。

構文:repo:<orgName/repoName>:pull_request
例:repo:octo-org/octo-repo:pull_request

特定のブランチにフィルター処理する

ジョブから環境を参照していない場合、かつ pull request イベントによってトリガーされたワークフローではない場合にのみ、subject 要求にはワークフローのブランチ名が含まれます。

特定のブランチ名にフィルター処理する subject を構成することができます。 この例で、ワークフロー実行は、octo-org 組織が所有する octo-repo というリポジトリ内にある demo-branch というブランチから開始されている必要があります。

構文:repo:<orgName/repoName>:ref:refs/heads/branchName
例:repo:octo-org/octo-repo:ref:refs/heads/demo-branch

特定のタグにフィルター処理する

ジョブから環境を参照していない場合、かつ pull request イベントによってトリガーされたワークフローではない場合にのみ、subject 要求にはワークフローのタグ名が含まれます。

特定のタグにフィルター処理する subject を作成できます。 この例で、ワークフロー実行は、octo-org 組織が所有する octo-repo というリポジトリ内の demo-tag というタグで開始されている必要があります。

構文:repo:<orgName/repoName>:ref:refs/tags/<tagName>
例:repo:octo-org/octo-repo:ref:refs/tags/demo-tag

クラウド プロバイダーでの subject の構成

クラウド プロバイダーの信頼関係で subject を構成するには、その信頼の構成に subject 文字列を追加する必要があります。 次の例は、さまざまなクラウド プロバイダーが同じ repo:octo-org/octo-repo:ref:refs/heads/demo-branch subject を異なる方法で受け入れる方法を示しています。

アマゾン ウェブ サービス"HOSTNAME/_services/token:sub": "repo:octo-org/octo-repo:ref:refs/heads/demo-branch"
Azurerepo:octo-org/octo-repo:ref:refs/heads/demo-branch
Google Cloud Platform(assertion.sub=='repo:octo-org/octo-repo:ref:refs/heads/demo-branch')
HashiCorp Vaultbound_subject="repo:octo-org/octo-repo:ref:refs/heads/demo-branch"

詳細については、「クラウド プロバイダーの OpenID Connect を有効にする」を参照してください。

OIDC 向けのアクションの更新

OIDC を使って認証するためにカスタム アクションを更新するには、Actions ツールキットの getIDToken() を使って、GitHub の OIDC プロバイダーに JWT を要求することができます。 詳細については、npm パッケージ ドキュメントの「OIDC トークン」を参照してください。

また、curl コマンドを使い、次の環境変数を使って JWT を要求することもできます。

ACTIONS_ID_TOKEN_REQUEST_URLGitHub の OIDC プロバイダーの URL。
ACTIONS_ID_TOKEN_REQUEST_TOKENOIDC プロバイダーに対する要求のベアラー トークン。

次に例を示します。

Shell
curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=api://AzureADTokenExchange"

アクセス許可設定の追加

ジョブまたはワークフローの実行には、id-token: writepermissions 設定が必要です。 id-tokenpermissions 設定が read または none の場合、OIDC JWT ID トークンを要求することはできません。

この id-token: write 設定により、次のいずれかの方法を使用して、GitHub の OIDC プロバイダーから JWT を要求できます。

  • ランナーで環境変数を使用する (ACTIONS_ID_TOKEN_REQUEST_URL および ACTIONS_ID_TOKEN_REQUEST_TOKEN)。
  • アクション ツールキットから getIDToken() を使用する。

ワークフローの OIDC トークンをフェッチする必要がある場合は、ワークフロー レベルでアクセス許可を設定できます。 次に例を示します。

YAML
permissions:
  id-token: write # This is required for requesting the JWT
  contents: read  # This is required for actions/checkout

1 つのジョブに対して OIDC トークンのみをフェッチする必要がある場合は、そのジョブ内でこのアクセス許可を設定できます。 次に例を示します。

YAML
permissions:
  id-token: write # This is required for requesting the JWT

ワークフローの要件に応じて、ここで追加のアクセス許可を指定する必要がある場合があります。

OIDC 向けのワークフローの更新

シークレットではなく OIDC アクセス トークンを使うように YAML ワークフローを更新できるようになりました。 一般的なクラウド プロバイダーは公式のログイン アクションを公開しているので、OIDC を簡単に使い始めることができます。 ワークフローの更新の詳細については、「クラウド プロバイダーの OpenID Connect を有効にする」の後半に掲載されているクラウド固有のガイドを参照してください。

クラウド プロバイダーの OpenID Connect を有効にする

特定のクラウド プロバイダーに対して OIDC を有効にして構成する方法については、次のガイドを参照してください。

別のクラウド プロバイダーに対して OIDC を有効にして構成する方法については、次のガイドを参照してください。