GCPワークロードアイデンティティフェデレーションでOpenID Connectを設定する
- プラン: Free、Premium、Ultimate
- 提供形態: GitLab.com、GitLab Self-Managed、GitLab Dedicated
CI_JOB_JWT_V2はGitLab 15.9で非推奨となり、GitLab 17.0で削除される予定です。代わりにIDトークンを使用してください。
このチュートリアルでは、JSON Webトークン(JWT)トークンとワークロードアイデンティティフェデレーションを使用して、GitLab CI/CDジョブからGoogle Cloudへの認証を実演します。この設定では、シークレットを保存する必要なく、オンデマンドの有効期間の短い認証情報を生成します。
まず、GitLabとGoogle Cloud間のアイデンティティプロバイダーフェデレーション用にOpenID Connect(OIDC)を設定します。GitLabでOIDCを使用する方法の詳細については、クラウドサービスへの接続をお読みください。
このチュートリアルでは、Google CloudアカウントとGoogle Cloudプロジェクトがあることを前提としています。お使いのアカウントには、Google Cloudプロジェクトに対する少なくともworkload identity pool Admin(ワークロードアイデンティティプロバイダープール管理者)権限が必要です。
このチュートリアルの代わりにTerraformモジュールとCI/CDテンプレートを使用する場合は、OIDCでGoogle CloudとのGitLab CI/CDパイプラインの認証をどのように簡素化できるかを参照してください。
このチュートリアルを完了するには、以下を行います:
- Google Cloudワークロードアイデンティティフェデレーションプールを作成します。
- ワークロードIDアイデンティティプロバイダーを作成する。
- サービスアカウント代理の権限を付与する。
- 一時的な認証情報を取得する。
Google Cloudワークロードアイデンティティフェデレーションプールを作成する
次のオプションを使用して、新しいGoogle Cloudワークロードアイデンティティフェデレーションプールを作成する:
- 名前:
GitLabなどの、ワークロードIDプールのわかりやすい名前。 - プールID:
gitlabなどの、ワークロードIDプールのGoogle Cloudプロジェクト内の一意のID。この値は、プールを参照するために使用され、URLに表示されます。 - 説明: オプション。プールの説明。
- Enabled Pool(有効なプール): このオプションが
trueであることを確認してください。
Google CloudプロジェクトごとにGitLabインスタンスごとに単一のプールを作成することをお勧めします。同じGitLabインスタンス上に複数のGitLabリポジトリとCI/CDジョブがある場合、同じプールに対して異なるアイデンティティプロバイダーを使用して認証できます。
ワークロードIDアイデンティティプロバイダーを作成する
次のオプションを使用して、前の手順で作成したワークロードIDプール内に新しいGoogle Cloudワークロードアイデンティティフェデレーションアイデンティティプロバイダーを作成する:
プロバイダータイプ: OpenID Connect(OIDC)。
Provider name(プロバイダー名):
gitlab/gitlabなどの、ワークロードIDアイデンティティプロバイダーのわかりやすい名前。プロバイダーID:
gitlab-gitlabなどの、ワークロードIDアイデンティティプロバイダーのプール内の一意のID。この値は、アイデンティティプロバイダーを参照するために使用され、URLに表示されます。Issuer (URL)(発行者(URL)):
https://gitlab.com/やhttps://gitlab.example.com/など、GitLabインスタンスのアドレス。- アドレスは
https://プロトコルを使用する必要があります。 - アドレスは末尾のスラッシュで終わる必要があります。
- アドレスは
Audiences(対象者):
https://gitlab.comやhttps://gitlab.example.comなど、許可された対象者リストをご自身のGitLabインスタンスのアドレスに手動で設定します。- アドレスは
https://プロトコルを使用する必要があります。 - アドレスは末尾のスラッシュで終わらないようにする必要があります。
- アドレスは
Provider attributes mapping(プロバイダー属性マッピング): 次のマッピングを作成します。
attribute.XはGoogleトークン内のクレームとして含める属性の名前で、assertion.XはGitLab claimから抽出する値です:属性(Google上) アサーション(GitLabから) google.subjectassertion.subattribute.Xassertion.XCommon Expression言語(CEL)を使用して、複雑な属性をビルドすることもできます。
権限の付与に使用するすべての属性をマップする必要があります。たとえば、次の手順でユーザーのメールアドレスに基づいて権限をマップする場合は、
attribute.user_emailをassertion.user_emailにマップする必要があります。
GitLab.comでホストされているプロジェクトの場合、GCPでは、GitLabグループによって発行されたトークンのみにアクセスを制限する必要があります。
サービスアカウント代理の権限を付与する
ワークロードIDプールとワークロードIDアイデンティティプロバイダーを作成すると、Google Cloudへの認証が定義されます。この時点で、GitLab CI/CDジョブからGoogle Cloudへの認証が可能です。ただし、Google Cloud(認可)に対する権限はありません。
Google Cloudに対するGitLab CI/CDジョブの権限を付与するには、次の手順を実行する必要があります:
- Google Cloudサービスアカウントを作成する。任意の名前とIDを使用できます。
- Google Cloudリソース上のサービスアカウントにIAM権限を付与する。これらの権限は、ユースケースによって大きく異なります。一般に、このサービスアカウントに、GitLab CI/CDジョブで使用できるようにするGoogle Cloudプロジェクトとリソースに対する権限を付与します。たとえば、GitLab CI/CDジョブでファイルをGoogle Cloud Storageバケットにアップロードする必要がある場合は、このサービスアカウントにGoogle Cloud Storageバケットに対する
roles/storage.objectCreatorロールを付与します。 - 外部アイデンティティプロバイダーにそのサービスアカウントを代理する権限を付与する。この手順により、サービスアカウント代理を介して、GitLab CI/CDジョブがGoogle Cloudへの認可を有効にできます。この手順では、サービスアカウント自体に対するIAM権限が付与され、そのサービスアカウントとして機能する外部アイデンティティプロバイダーに権限が付与されます。外部アイデンティティプロバイダーは、
principalSet://プロトコルを使用して表現されます。
前の手順と同様に、この手順は目的の設定に大きく依存します。たとえば、GitLab CI/CDジョブがユーザー名chrisのGitLabユーザーによって開始された場合、GitLab CI/CDジョブがmy-service-accountという名前のサービスアカウントを代理できるようにするには、my-service-accountの外部アイデンティティプロバイダーにroles/iam.workloadIdentityUser IAMロールを付与します。外部アイデンティティプロバイダーは、次の形式を取ります:
principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/attribute.user_login/chrisここで、PROJECT_NUMBERはGoogle Cloudプロジェクト番号、POOL_IDは最初のセクションで作成されたワークロードIDプールのID(名前ではない)です。
この設定では、前のセクションのアサーションからマップされた属性としてuser_loginを追加したことも前提としています。
一時的な認証情報を取得する
OpenID Connectとロールを設定すると、GitLab CI/CDジョブは、Google Cloud Security Token Service(STS)から一時的な認証情報を取得できます。
id_tokensをCI/CDジョブに追加します:
job:
id_tokens:
GITLAB_OIDC_TOKEN:
aud: https://gitlab.example.comIDトークンを使用して、一時的な認証情報を取得します:
PAYLOAD="$(cat <<EOF
{
"audience": "//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID",
"grantType": "urn:ietf:params:oauth:grant-type:token-exchange",
"requestedTokenType": "urn:ietf:params:oauth:token-type:access_token",
"scope": "https://www.googleapis.com/auth/cloud-platform",
"subjectTokenType": "urn:ietf:params:oauth:token-type:jwt",
"subjectToken": "${GITLAB_OIDC_TOKEN}"
}
EOF
)"FEDERATED_TOKEN="$(curl --fail "https://sts.googleapis.com/v1/token" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data "${PAYLOAD}" \
| jq -r '.access_token'
)"各設定項目の意味は次のとおりです:
PROJECT_NUMBERはGoogle Cloudプロジェクト番号(名前ではない)です。POOL_IDは、最初のセクションで作成されたワークロードIDプールのIDです。PROVIDER_IDは、2番目のセクションで作成されたワークロードIDアイデンティティプロバイダーのIDです。GITLAB_OIDC_TOKENはOpenID Connect IDトークンです。
次に、結果として得られたフェデレーショントークンを使用して、前のセクションで作成したサービスアカウントを代理できます:
ACCESS_TOKEN="$(curl --fail "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT_EMAIL:generateAccessToken" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer FEDERATED_TOKEN" \
--data '{"scope": ["https://www.googleapis.com/auth/cloud-platform"]}' \
| jq -r '.accessToken'
)"各設定項目の意味は次のとおりです:
SERVICE_ACCOUNT_EMAILは、前のセクションで作成された代理するサービスアカウントの完全なメールアドレスです。FEDERATED_TOKENは、前の手順で取得したフェデレーショントークンです。
結果はGoogle Cloud OAuth 2.0アクセストークンになり、ベアラトークンとして使用すると、ほとんどのGoogle Cloud APIとサービスへの認証に使用できます。この値を環境変数CLOUDSDK_AUTH_ACCESS_TOKENを設定して、gcloud CLIに渡すこともできます。
動作例
Terraformを使用してGCPでOpenID Connectをプロビジョニングし、一時的な認証情報を取得するサンプルスクリプトについては、この参照プロジェクトを確認してください。
トラブルシューティング
curl応答をデバッグする場合は、最新バージョンのcURLをインストールします。-fの代わりに--fail-with-bodyを使用してください。このコマンドは本文全体を出力します。これには役立つエラーメッセージが含まれている場合があります。詳細については、ワークロードIDフェデレーションの問題を解決するを参照してください。