エムスリーテックブログ

エムスリー(m3)のエンジニア・開発メンバーによる技術ブログです

Workload Identity Federationの安全を支える技術

エンジニアリンググループ ゼネラルマネージャーの横本(@yokomotod)です。 このブログはAI・機械学習チームブログリレー 12日目の記事です。

ちょうど昨日の大垣さんの記事でも触れられていましたが、エムスリーではWorkload Identity Federation(以下WIF)*1を活用して、秘密情報を持つことなくGitLabのCI/CDからGoogle Cloudへ認証しています。 偶然ですが、昨日の活用方法の話に続き、今日はその裏側寄りの話をしようと思います。

www.m3tech.blog

なぜWIFは秘密情報なしに安全にアクセスできるんでしょうか? 攻撃者がなりすまそうとしたらどうやって検知されるんでしょうか? 何を根拠に信頼が成り立っているんでしょうか?

この記事では、WIFの信頼性の根拠を改めて整理し直してみます。「なんとなく安全」から「こういう仕組みで安全」へと理解をクリアにできればと思います。

※ この記事ではGoogle CloudのWorkload Identity FederationによるGitLab CI/CDとの連携を主な題材にしますが、GitLab以外との連携や、他クラウドでの類似機能でも参考になる、はず

Workload Identity Federation とは、を超要約

0. Google Cloud側で、Workload Identity Poolというリソースを作り、「どこから受け取るか」「どんな条件で受け取るか」を設定しておきます

1. GitLabはGoogle Cloudを使いたいとき(= CIジョブ実行時)にこんな内容のトークン (実際はJWT)をGoogle Cloudに送ります

{
  "iss": "https://gitlab.example.com",
  "sub": "project_path:myorg/myrepo:ref_type:branch:ref:main",
  "aud": "https://iam.googleapis.com/projects/123/locations/global/workloadIdentityPools/my-pool",
  "project_id": "123",
  "project_path": "myorg/myrepo",
  "namespace_path": "myorg",
  "ref": "main",
  "ref_type": "branch",
  // その他のクレーム...
}

2. Google Cloudは、送られてきた内容が「信頼できる」と判断できたら一時アクセストークンを返却します。

3. 無事、Gitlabは一時アクセストークンを使ってGoogle CloudのAPIにアクセスできるようになりました。

こんな流れで、GitLab側にGoogle CloudのCredential JSONなどを持つことなしにリソースにアクセスが出来るようになります。

さて、では送られてきた内容が「信頼できる」とはなんでしょうか?

先に結論

WIFの信頼の確立は以下の3つの層で成り立っています。

1. JWT署名検証:トークンの偽造を検出

JWTに署名が付いているので、IdPの公開鍵で署名を検証すれば偽造を検出できます。正しい秘密鍵を持っているのは本物のIdP(GitLabやGitHub)だけなので、有効な署名があれば確実にそこから発行されたトークンだとわかります。

WIFに限らず、ごく一般的なJWT署名検証です。

2. Identity情報の自動セット

JWT中の重要なAttribute(organization名、repository名など)は、IdP側で自動的にセットされます。ユーザーが勝手に「このリポジトリのトークンです」と発行できるようにはなっていません。

3. 認可制御:Attribute条件(目が行きがちな部分)

Google Cloud側でJWT中のAttributeに条件を設定し、許可されたワークロードのみがアクセスできるよう制御します。

見落とされがちな理由?

WIFを構築する際、私たちが実際に手を動かして設定するのは「3」のAttribute条件だけで、「1」のJWT署名検証と「2」のIdentity情報セットは、WIFの仕組みが裏側で自動的に処理してくれています。 また、公式のドキュメントでもあまり詳しく触れられていません。

そこで次節では、自動でやってくれているところも含めたWorkload Identity Federationの認証フローの全体像を、先ほどの三層構造に沿って追ってみましょう。

具体的なフロー

詳細なフローについてはクラスメソッドさんの記事で丁寧に解説されているので、ここでは信頼性の根拠の観点から重要なポイントを見ていきます。

dev.classmethod.jp

1. GitLabによるJWT発行

GitLab CI/CDでジョブが実行されるとき、GitLabでID Tokenを発行できます*2。このトークンは以下のような内容のJSON Web Token(JWT)になっています:

{
  "iss": "https://gitlab.example.com",
  "sub": "project_path:myorg/myrepo:ref_type:branch:ref:main",
  "aud": "https://iam.googleapis.com/projects/123/locations/global/workloadIdentityPools/my-pool",
  "project_id": "123",
  "project_path": "myorg/myrepo",
  "namespace_path": "myorg",
  "ref": "main",
  "ref_type": "branch",
  // その他のクレーム...
}

先述のとおり、これらのクレーム(namespace_pathproject_pathなど)はGitLabが自動でセットします。ユーザーが勝手に指定できるものではありません。

2. Google CloudによるJWT署名検証

このJWTには署名が付いてます。Google Cloud STSがこのJWTを受け取ると、以下の検証を行います:

  1. Discovery: GitLabの/.well-known/openid-configurationでJWKSエンドポイントを取得
  2. 公開鍵取得: /.well-known/jwksからGitLabの公開鍵を取得
  3. 署名検証: GitLabの公開鍵でJWTの署名を検証

正しい秘密鍵を持っているのはJWTを発行した本物のGitLabだけなので、攻撃者がなりすまそうとしても、有効な署名を作ることはできません。 逆に言いうと、万が一秘密鍵が漏洩すると、偽造JWTが作成可能になってしまいます。

[宣伝]

このあたりの処理も含め「OpenID Connectをフルスクラッチする」という過去記事や、それをまとめた書籍があります。

www.m3tech.blog

techbookfest.org

3. 認可制御:Attribute条件による細かな制御

署名検証が通ると、Google Cloud STSでトークンの交換が行われ*3、最終的にGCPのAccess Tokenが発行されます。

この過程でAttributeが条件に一致するか評価され、指定した組織やプロジェクト、ブランチからのアクセスのみを許可できるわけです。

重要なことは、GitLabやGitHub SaaSなどマルチテナントな環境では、同じIdPを他のorganizationと共有しているという点です。 つまり、別のorganizationのユーザーが発行したJWTも、同じIdPから発行されているため有効な署名を持っています。そのためもしもAttribute条件でorganizationを絞らないと、他組織からの不正アクセスを許してしまいます

GitHubならrepository_owner、GitLabならnamespace_idなどを使って、必ず自組織のトークンのみを受け入れるよう設定しましょう*4

まとめ

Workload Identity Federationの信頼性は、以下の三層構造で成り立っています:

  1. JWT署名検証: 本物のIdPから発行されたトークンかをGoogleCloud側が確認
  2. Identity情報の自動セット: IdPが保証する実行環境の情報を信頼
  3. 認可制御: Attribute条件による細かなアクセス制御(これもGoogleCloud側が定義&チェック)

構築時に否応なしに意識するのは「3」ですが、「1」と「2」もWIFの信頼の土台です。この理解があると、より安心してWIFを活用できるのではないでしょうか。

WIFは決して魔法ではありません。「なんとなく安全」から「こういう仕組みで安全」への理解のアップデートができれば、この記事の目的達成です!

We're Hiring

エムスリーでは、セキュアかつ快適な認証の仕組みを構築して、信頼性と開発効率を両立してしまうエンジニアを募集しています!

エンジニア採用ページはこちら

jobs.m3.com

カジュアル面談もお気軽にどうぞ

jobs.m3.com

インターンも常時募集しています

open.talentio.com

*1:https://cloud.google.com/iam/docs/workload-identity-federation

*2:https://docs.gitlab.com/ci/secrets/id_token_authentication/

*3:このトークン交換は、RFC 8693で定義されたToken Exchangeという仕様に基づいているようです

*4:Google Cloudの公式ドキュメントでも、GitHub、GitLab SaaS、Terraform Cloudは全組織で単一のissuer URLを使用しており、spoofing threatから保護するためにAttribute条件が必要と警告されています