フリートの Workload Identity を使用する際のベスト プラクティス

フリート ワークロードから API とサービスに対して認証するで説明したように、フリート全体の Workload Identity 連携は、プロジェクト全体のアプリケーションに対して Google Cloud の認証を簡単に設定できる強力なフリート機能です。ただし、通常の GKE 用 Workload Identity 連携よりもアクセス制御の考慮事項が増える可能性があります。このガイドでは、このような問題の例と、潜在的なリスクを最小限に抑えるようにフリートを設定する方法について説明します。

このガイドを読む前に、フリート ワークロードから API とサービスに対して認証するで説明されているコンセプトを理解しておく必要があります。

その他のフリート機能の導入に関するベスト プラクティスについては、フリート機能を計画するをご覧ください。

フリートとプロジェクトの ID プール

フリート全体の Workload Identity 連携を導入する際に、特にマルチプロジェクト フリートを使用する際に慎重な対応が必要となる理由を理解するため、GKE 用の通常の Workload Identity 連携とフリート Workload Identity 連携の仕組みを詳しく見てみましょう。どちらの場合も、ワークロードはクラスタによって生成された有効期間の短いトークンを使用して認証を行います。各クラスタは、特別な Workload Identity プールに ID プロバイダとして追加されます。特定の Namespace で実行されているワークロードは、クラスタ間で同じ IAM ID を共有できます。

クラスタで GKE 用 Workload Identity 連携が有効になっている場合、通常の Workload Identity 連携では次のような動作になります。GKE 用 Workload Identity 連携は、Autopilot クラスタでデフォルトで有効になっています。

  1. GKE は、クラスタのプロジェクト PROJECT_ID.svc.goog.id に Google マネージド Workload Identity プールを作成します。
  2. GKE は、クラスタを ID プロバイダとしてプールに追加します。
  3. その結果、特定の Namespace で実行されているワークロードは、プロジェクト内のクラスタ間で同じ IAM ID を共有します。ID の形式は serviceAccount:PROJECT_ID.svc.id.goog[K8S_NAMESPACE/KSA_NAME] です。

フリート全体の Workload Identity 連携は、GKE 用 Workload Identity 連携が有効になっているクラスタをフリートに追加すると自動的に有効になります。これには、Autopilot クラスタ、この機能が明示的に有効になっている Standard クラスタ、Google Cloud 外の GKE クラスタが含まれます。

ユーザーが GKE 用 Workload Identity 連携を有効にしてクラスタをフリートに登録すると、次のような動作が行われます。

  1. フリート ホスト プロジェクトに、Google が管理するフリート全体の Workload Identity プール FLEET_PROJECT_ID.svc.goog.id が作成されます(プールがまだ存在しない場合)。これは、フリート ホスト プロジェクトのプロジェクト Workload Identity プールと同じです
  2. クラスタが ID プロバイダとしてプールに追加されます。
  3. その結果、特定の Namespace で実行されているワークロードは、フリート内のクラスタ間で同じ IAM ID を共有します。これは、フリートの Workload Identity の暗黙の同一性と呼ばれます。ID の形式は serviceAccount:FLEET_PROJECT_ID.svc.id.goog[K8S_NAMESPACE/KSA_NAME] です。異なるプロジェクトのフリート ワークロードは、認証に同じ ID を使用して Google API を呼び出すことができます。

つまり、フリートに 1 つのプロジェクトのクラスタのみが含まれ、それらがすべてフリートに登録されている場合、フリートを使用せずに GKE 用 Workload Identity 連携のみを使用した場合と同じ結果になります。すべてのクラスタがプロジェクト全体の Workload Identity プールの ID プロバイダであり、ワークロードは GKE 用 Workload Identity 連携で使用するのと同じ ID を使用します。ただし、フリートに複数のプロジェクトのメンバー クラスタがある場合、フリート Workload Identity 連携は、プロジェクトごとの ID プールをフリート全体の単一の ID プールに統合し、フリート ホスト プロジェクトでホストします。

次の例でわかるように、プロジェクト内のクラスタと、そのプロジェクト内のフリートのメンバーであるクラスタとの間に部分的な重複がある場合、複雑な状況が発生する可能性があります。

シナリオ 1: すべてのクラスタが登録されている単一プロジェクトのフリート

このシナリオでは、フリートのすべてのメンバー クラスタがフリート ホスト プロジェクトにあり、そのプロジェクト内のすべてのクラスタがフリートのメンバーです。

すべてのクラスタが同じフリートにあるプロジェクトを示す図

前のセクションで説明したように、このシナリオでフリート全体の Workload Identity 連携を使用することは、GKE 用通常の Workload Identity 連携を使用する場合と同じであり、追加のリスクはありません。

シナリオ 2: 一部のクラスタが登録されている単一プロジェクトのフリート

このシナリオでは、フリートには 2 つのクラスタが含まれており、どちらもフリート ホスト プロジェクト(プロジェクト 1)にあります。フリート ホスト プロジェクトには、フリート メンバーではない 3 つ目のクラスタも含まれており、GKE 用 Workload Identity 連携が有効になっています。

同じフリートに複数のクラスタがあるプロジェクトを示す図。

つまり、以下のようになります。

  • クラスタ 1、2、3 は、GKE によってプロジェクトの Workload Identity プール project-1.svc.goog.id に追加されます。
  • クラスタ 1 と 2 はフリートによってフリート Workload Identity プールに追加されます。これはフリート ホスト プロジェクトであるため、プロジェクト Workload Identity プール project-1.svc.goog.id でもあります。

管理者は、フリート内のすべてのクラスタの Namespace で実行されているワークロードに権限を付与したいと考えています。アクセス権を付与する ID として serviceAccount:project-1.svc.goog.id[namespace/ksa] を使用します。ただし、クラスタ 3 の Namespace 内のワークロード(フリートには含まれない)は、同じアクセス権を共有するようになります。これは、クラスタ 3 がプロジェクト Workload Identity プールにあるためです。これはフリート Workload Identity プールと同じです(フリート ホスト プロジェクトであるため)。つまり、管理者がフリート内のクラスタにのみ権限を付与することを意図している場合でも、フリート Workload Identity 連携の実装により、フリート外のクラスタにもアクセスが許可される可能性があります。

考えられる対応策

解決策として、クラスタのないフリート専用のプロジェクトを作成し、コンテナ API のカスタム組織ポリシーで適用する方法があります。これにより、フリート Workload Identity プールの信頼ドメインと GKE プロジェクト レベルの信頼ドメインが明確に分離されます。

2 つのプロジェクト(1 つはクラスタを含むプロジェクト、もう 1 つはフリート ホスト プロジェクトとして機能するプロジェクト)を示す図

管理者は、ワークロードに権限を付与するときに、適切な信頼ドメインを選択できます。たとえば、serviceAccount:project-0.svc.goog.id[namespace/ksa] を使用して、フリート全体で Namespace 方式のワークロードに権限を付与できます。フリート メンバーではないクラスタ 3 は、この設定ではその Workload Identity プールの一部ではないため、アクセス権を取得できません。

このソリューションは、Google Cloud 上のクラスタと接続クラスタで機能します。

シナリオ 3: 一部のクラスタが登録されているマルチプロジェクト フリート

このシナリオでは、フリートにはプロジェクト 1 とプロジェクト 2 の 2 つのプロジェクトのメンバーが含まれています。

2 つのプロジェクトのクラスタを含むフリートを示した図。

管理者は、通常の GKE 用 Workload Identity 連携を使用して、プロジェクト 1 のすべてのクラスタの Namespace で実行されているワークロードに権限を付与したいと考えています。ただし、クラスタ 4 はフリートに登録されており、プロジェクト 1 はフリート ホスト プロジェクトであるため、プロジェクト 2 のクラスタ 4 のワークロードにも同じ権限が付与されます。

考えられる対応策

前のシナリオと同様に、クラスタのない専用のフリートホスト プロジェクトを作成することで、この問題を軽減できます。これにより、管理者はアクセス制御を設定するときに、フリート ID プールと各クラスタのプロジェクト ID プールの ID を区別できます。

シナリオ 4: Namespace の同一性を考慮する

Workload Identity 連携を使用する際に混乱する可能性があるのは、Workload Identity プールだけではありません。フリート機能を計画するで説明したように、フリート Workload Identity 連携など、多くのフリート機能では、Namespace の同一性に基づいて、フリート全体の構成と管理を簡素化しています。つまり、この機能では、複数のフリート メンバー クラスタで同じ名前を持つ Namespace が、同じ Namespace であるかのように扱われます。この例では、フリート メンバー クラスタのクラスタ 1 とクラスタ 2 で実行されている NS1 Namespace のワークロードに、管理者が権限を付与しています。

同じ Namespace を持つ 2 つのプロジェクトのクラスタの図。

しかし、ユーザーが別のフリート メンバー クラスタに同じ名前の Namespace を(誤ってまたは悪意を持って)作成しました。Namespace の同一性が前提となるため、その Namespace のワークロードは、クラスタ 1 とクラスタ 2 の正当な NS1 ワークロードと同じ権限を自動的に取得します。

考えられる対応策

信頼できるロールの小規模なグループのみがクラスタで Namespace を作成できるように権限を設定します。