Claude CodeのBedrock OIDC認証をGitLab CI/CDで組む — GCPのWIFも
Claude CodeをGitLab CI/CDからBedrockやGoogle Cloudで動かすOIDC/WIF設定を、IAMロール・トラストポリシー・ジョブYAMLまで実装単位で確認します。
Claude Code GitLab BedrockのOIDC認証とはどんな仕組みか
Claude CodeのGitLab CI/CD統合はbeta機能で、GitLab自体の保守下にあります。認証や挙動は今後変わる可能性があります。
Claude Code GitLab BedrockのOIDC認証とは、GitLabのCI/CDジョブが発行する短命なOIDCトークンをAWS IAMロールに交換する仕組みです。ANTHROPIC_API_KEYのような静的なキーを保存せずに、Amazon Bedrock経由でClaude Codeを動かせます。Google Cloud側では同じ発想をWorkload Identity Federation(WIF)が担います。サービスアカウントキーのダウンロードなしに、ジョブがサービスアカウントを借用します。
GitLab CI/CD版のClaude Codeは、認証プロバイダーを3つから選べます。Claude API(SaaSのAPIキー)、Amazon Bedrock(IAMベース)、Google CloudのAgent Platform(GCPネイティブ)です。個人開発や小規模チームはClaude APIキーで足りますが、AWSやGCPとの既存契約でデータレジデンシー要件を満たしたいエンタープライズは、後の2つを選びます。ジョブ本体の作り方やWebhookでの@claudeメンショントリガーの設定はClaude CodeをGitLab CI/CDに組み込むにまとまっているので、そちらを先に見てからここに戻ると、AWS/GCPの認証設計だけをスムーズに追えます。
AWS BedrockでOIDC認証を組む手順
AWS側の下準備は4つです。
- Amazon Bedrockで対象のClaudeモデルへのアクセスを有効化する
- GitLabをAWS IAMのOIDCアイデンティティプロバイダーとして登録する
- GitLabプロジェクト・保護されたref(ブランチやタグ)に信頼を絞ったIAMロールを作成する
- Bedrock呼び出しAPIに絞った最小権限のポリシーをそのロールへアタッチする
GitLab側で必要なCI/CD変数は2つだけです。AWS_ROLE_TO_ASSUME(引き受けるIAMロールのARN)とAWS_REGION(Bedrockのリージョン、例: us-west-2)。ジョブのid_tokens:ブロックでGitLabがOIDCトークンを発行し、GITLAB_OIDC_TOKENとして渡されます。aud(audience)には、AWS側のIAM OIDCプロバイダーに設定した値、たとえば自社のGitLabインスタンスURLを指定します。
claude-bedrock:
stage: ai
image: node:24-alpine3.21
id_tokens:
GITLAB_OIDC_TOKEN:
aud: https://gitlab.example.com
before_script:
- apk add --no-cache bash curl jq git aws-cli
- curl -fsSL https://claude.ai/install.sh | bash
- export PATH="$HOME/.local/bin:$PATH"
- export AWS_WEB_IDENTITY_TOKEN_FILE="/tmp/oidc_token"
- printf "%s" "$GITLAB_OIDC_TOKEN" > "$AWS_WEB_IDENTITY_TOKEN_FILE"
- >
aws sts assume-role-with-web-identity
--role-arn "$AWS_ROLE_TO_ASSUME"
--role-session-name "gitlab-claude-$(date +%s)"
--web-identity-token "file://$AWS_WEB_IDENTITY_TOKEN_FILE"
--duration-seconds 3600 > /tmp/aws_creds.json
- export AWS_ACCESS_KEY_ID="$(jq -r .Credentials.AccessKeyId /tmp/aws_creds.json)"
- export AWS_SECRET_ACCESS_KEY="$(jq -r .Credentials.SecretAccessKey /tmp/aws_creds.json)"
- export AWS_SESSION_TOKEN="$(jq -r .Credentials.SessionToken /tmp/aws_creds.json)"
script:
- /bin/gitlab-mcp-server || true
- claude -p "$AI_FLOW_INPUT" --permission-mode acceptEdits --allowedTools "Bash Read Edit Write mcp__gitlab" --debug
variables:
AWS_REGION: "us-west-2"
CLAUDE_CODE_USE_BEDROCK: "1"sts assume-role-with-web-identityが返す一時的なアクセスキー・シークレットキー・セッショントークンの3点を環境変数へ展開してからclaudeコマンドを呼ぶ、という流れです。有効期限は--duration-secondsで指定した秒数(例では3,600秒)で切れるため、ジョブが終わればAWS側に残る認証情報はありません。BedrockのモデルIDにはリージョン固有のプレフィックスが付きます(例: us.anthropic.claude-sonnet-4-6)。使うモデルはジョブ設定かプロンプト経由で指定します。Bedrock経由での単価がClaude API直接契約とどう違うかはAWS BedrockのClaude料金にまとめているので、CI費用を見積もる前に確認しておくと想定外の請求を避けられます。
Google CloudのAgent PlatformでWorkload Identity Federationを組む手順
GCP側の下準備も4つです。
- IAM Credentials API・STS API・Google Cloud's Agent Platform APIの3つを有効化する
- GitLab OIDCを信頼するWorkload Identity Poolとプロバイダーを作成する
- Agent Platformの権限だけを持つ専用サービスアカウントを用意する
- そのサービスアカウントを借用(impersonate)できる権限をWIFプリンシパルへ与える
必要な変数は4つです。GCP_WORKLOAD_IDENTITY_PROVIDER(//iam.googleapis.com/プレフィックスを除いたプロバイダーのリソース名。例: projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider)、GCP_SERVICE_ACCOUNT(サービスアカウントのメールアドレス)、GCP_PROJECT_ID(GCPプロジェクトID)、CLOUD_ML_REGION(Agent Platformのリージョン、例: us-east5)です。
Bedrockのsts assume-roleと違い、GCP側はクレデンシャル設定ファイルをその場で組み立ててGOOGLE_APPLICATION_CREDENTIALSに渡す構成です。GitLabのOIDCトークンをファイルへ書き出し、credential_sourceでそのファイルパスを指すJSONを生成します。
claude-vertex:
stage: ai
image: gcr.io/google.com/cloudsdktool/google-cloud-cli:slim
id_tokens:
GITLAB_OIDC_TOKEN:
aud: https://gitlab.example.com
before_script:
- apt-get update && apt-get install -y git && apt-get clean
- curl -fsSL https://claude.ai/install.sh | bash
- export PATH="$HOME/.local/bin:$PATH"
- printf "%s" "$GITLAB_OIDC_TOKEN" > /tmp/oidc_token
- |
cat > /tmp/cred.json <<EOF
{
"type": "external_account",
"audience": "//iam.googleapis.com/${GCP_WORKLOAD_IDENTITY_PROVIDER}",
"subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
"token_url": "https://sts.googleapis.com/v1/token",
"credential_source": { "file": "/tmp/oidc_token" },
"service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${GCP_SERVICE_ACCOUNT}:generateAccessToken"
}
EOF
- export GOOGLE_APPLICATION_CREDENTIALS=/tmp/cred.json
- gcloud auth login --cred-file=/tmp/cred.json
- gcloud config set project "$GCP_PROJECT_ID"
script:
- /bin/gitlab-mcp-server || true
- claude -p "$AI_FLOW_INPUT" --permission-mode acceptEdits --allowedTools "Bash Read Edit Write mcp__gitlab" --debug
variables:
CLOUD_ML_REGION: "us-east5"
CLAUDE_CODE_USE_VERTEX: "1"
ANTHROPIC_VERTEX_PROJECT_ID: "$GCP_PROJECT_ID"GOOGLE_APPLICATION_CREDENTIALSにこのファイルを指すことで、Claude CodeはGoogleのApplication Default Credentials(ADC)の仕組みを通じて認証情報を取得します。サービスアカウントキーは一切ダウンロードしません。信頼関係はプロジェクト・ref単位に絞れるため、あるブランチのパイプラインが漏洩しても他のブランチのサービスアカウント借用権限には波及しません。ローカルで対話的にBedrockを試す場合の認証手順はClaude Code Bedrockセットアップの/setup-bedrockウィザードが対応する範囲で、CI環境のOIDCとは別の入り口になります。
OIDCとWIFの認証設計を比較する
同じ「キーレス認証」でも、AWSとGCPでは仕組みの単位が違います。信頼をどこに設定するか、認証情報がどれだけ生き続けるか、CI変数の数はいくつ必要か、監査ログの粒度はどうか、の4観点で比べると差がはっきりします。
| 観点 | Amazon Bedrock(OIDC) | Google CloudのAgent Platform(WIF) |
|---|---|---|
| 信頼の設定単位 | Amazon Bedrock(OIDC)IAMロールのトラストポリシー(プロジェクト・ref単位) | Google CloudのAgent Platform(WIF)Workload Identity Poolのプロバイダー条件 |
| 認証情報の実体 | Amazon Bedrock(OIDC)一時的なアクセスキー3点セット(sts assume-role-with-web-identity) | Google CloudのAgent Platform(WIF)サービスアカウント借用トークン(credential_source経由) |
| 必要なCI/CD変数 | Amazon Bedrock(OIDC)2つ(AWS_ROLE_TO_ASSUME / AWS_REGION) | Google CloudのAgent Platform(WIF)4つ(プロバイダー名・サービスアカウント・プロジェクトID・CLOUD_ML_REGION) |
| 有効期限の指定方法 | Amazon Bedrock(OIDC)--duration-secondsで明示(既定例は3,600秒) | Google CloudのAgent Platform(WIF)Google側のデフォルトトークン有効期限に従う |
| 事前に有効化するAPI | Amazon Bedrock(OIDC)Amazon Bedrockのモデルアクセスのみ | Google CloudのAgent Platform(WIF)Agent Platform API・IAM Credentials API・STS APIの3つ |
AWS側は「ロールを引き受ける」1ステップの操作が中心なのに対し、GCP側は「サービスアカウントを借用する」ための認証設定ファイルをジョブ内で組み立てる分、手順が1段階増えます。どちらも最終的にジョブが受け取るのは有効期限付きの一時的な認証情報という点は共通です。
なぜ静的キーではなくOIDC/WIFが既定になりつつあるか
CI/CDパイプラインに長期間有効なクラウド認証情報を変数として保存する運用は、変数の閲覧権限を持つ全員が実質的にそのキーへアクセスできることを意味します。OIDC/WIFは、ジョブが実行されている間だけ有効な認証情報に置き換えることで、この露出時間を数十分単位まで縮めます。ローテーションの運用も不要になります。キーが漏れて初めて気づく事故と、そもそも漏れる対象が数十分しか存在しない構成では、事故の起きうる規模が違います。
もう一つの理由は監査の追跡しやすさです。静的キーは「誰がいつ使ったか」をキー自体からは判別できません。一方でOIDCトークンにはGitLabプロジェクト・ref・パイプラインIDといったクレームが含まれます。そのためAWS CloudTrailやGoogle Cloud Audit Logsの記録は、どのパイプライン実行から来たかをそのまま示します。エンタープライズ環境でBedrock・GCPを選ぶ動機は、データレジデンシーだけではありません。この監査可能性も動機のひとつです。ジョブに与える権限とネットワーク送信先を必要最小限に絞る考え方は、Claude Codeのサンドボックス実行や権限モードの原則(Claude Codeセキュリティ・権限ガイド)とも地続きです。
つまずきやすいポイント
認証エラーで止まる場合、まずaudの値がAWS・GCP側で設定したオーディエンス値と一致しているかを確認します。次にIAMロールのトラストポリシー、またはWIFプロバイダーの属性条件が実際のGitLabプロジェクト・refと一致しているかを見直します。ロールやサービスアカウントの権限借用(impersonation)権限が不足しているケースも多い原因です。
リージョンとモデルの組み合わせでエラーになる場合、Bedrockはリージョンごとに利用可能なモデルが異なります。AWS_REGIONで指定したリージョンで対象のClaudeモデルへのアクセスが有効化されているかを確認します。GCP側もCLOUD_ML_REGIONとモデルの組み合わせを同様に確認します。
sts assume-role-with-web-identityが失敗する場合、まずAWS_WEB_IDENTITY_TOKEN_FILEの中身を見ます。トークンが空になっていないかを確認します。GITLAB_OIDC_TOKEN変数がid_tokens:ブロックで正しく発行されているかも見直します。id_tokens:はGitLab Runnerのバージョンによっては未対応です。Runnerのバージョンも合わせて確認します。
よくある質問
Claude APIキーとOIDC/WIFはどちらを先に試すべきですか
まずClaude APIキーでのクイックセットアップを動かし、@claudeメンションからMRが作られる一連の流れを確認するのが近道です。IAMロールやWIFプールの作成は、そのあとエンタープライズ要件が固まった段階で行う構成で問題ありません。
AWS RegionとBedrockのモデルリージョンは同じにする必要がありますか
AWS_REGION変数はBedrockのAPI呼び出し先リージョンを指定するものなので、対象のClaudeモデルへのアクセスがそのリージョンで有効化されている必要があります。クロスリージョン推論のオプションを使う場合はBedrock側の設定を別途確認します。
sts assume-role-with-web-identityのセッション時間は延ばせますか
--duration-secondsで指定できますが、上限はIAMロール側の「最大セッション期間」設定に従います。ジョブの実行時間がこの値を超えそうな場合は、ロール側の上限を先に見直します。
GCPのサービスアカウントキーは一切不要になりますか
WIFを使う構成では、ダウンロード可能な鍵ファイルを発行せずにサービスアカウントを借用できます。既存の鍵ファイルが残っている場合は、移行後に無効化しておくと露出面をさらに減らせます。
まとめ
Claude CodeをGitLab CI/CDからAmazon BedrockやGoogle Cloudで動かす認証設計は、どちらも「ジョブの間だけ生きる一時的な認証情報に置き換える」という同じ目的に向かいます。AWSはOIDCトークンをIAMロールへ交換する1ステップ、GCPはWIFの認証設定ファイルをその場で組み立てる構成という違いはありますが、静的キーの保存・ローテーションから解放される点は共通です。すでにBedrockやGCPをAnthropic以外の用途でも使っている組織であれば、既存のIAM/WIF運用ノウハウをそのまま転用できます。