サービス アカウントの使用に関するベスト プラクティス

サービス アカウントは人間以外のユーザーを表します。これは、カスタム アプリケーションなどのワークロードで、エンドユーザーの関与なしにリソースにアクセスする場合や、アクションを実行する必要がある場合を対象としています。

サービス アカウントは、通常のユーザー アカウントと次の点で異なります。

  • パスワードが設定されていないため、ブラウザベースのログインには使用できません。
  • Google Cloud プロジェクトに属するリソースとして作成され、管理されます。これに対して、ユーザーは Cloud Identity または Google Workspace のアカウントで管理されます。
  • Google Cloud に固有です。一方、Cloud Identity または Google Workspace で管理されるユーザーは、Google の多数のプロダクトとサービスで動作します。
  • どちらもリソースで、プリンシパルです。
    • プリンシパルとしてのサービス アカウントには、Cloud Storage バケットなどのリソースへのアクセス権を付与できます。
    • リソースとしてアクセスできるサービス アカウントは、ユーザーやグループなどの他のプリンシパルがなりすます可能性もあります。

サービス アカウントは便利なツールですが、悪用する方法がいくつかあります。

  • 権限昇格: 不正な行為者がサービス アカウントになりすますことにより、通常ではアクセス権を付与されることのないリソースへのアクセス権を取得する可能性があります。
  • なりすまし: 不正な行為者がサービス アカウントの権限を借用して、自分の ID を隠蔽する可能性があります。
  • 否認防止: 不正な行為者が、サービス アカウントを使用して自身の代理でオペレーションを実行することで、ID とアクションを隠蔽する場合があります。場合によっては、これらのアクションを追跡して不正な行為者にまでたどりつけないことがあります。
  • 情報開示: 不正な行為者が、特定のサービス アカウントの存在からインフラストラクチャ、アプリケーション、またはプロセスに関する情報を引き出す可能性があります。

サービス アカウントを保護するには、アカウントの 2 つの性質を考慮してください。

  • サービス アカウントはプリンシパルであることから、サービス アカウントの不正使用により発生する可能性がある損害を軽減するために、権限を制限する必要があります。
  • サービス アカウントはリソースであることから、不正使用されないように保護する必要があります。

このガイドでは、サービス アカウントを管理、使用、保護するためのベスト プラクティスについて説明します。

サービス アカウントを使用するタイミングを選択する

すべてのシナリオで、Google Cloud サービスにアクセスするためのサービス アカウントが必要になるわけではありません。多くのシナリオでは、サービス アカウント キーを使用するよりも安全な方法で認証を行うことができます。サービス アカウント キーは、可能な限り使用しないことをおすすめします。

Google Cloud CLI、Cloud クライアント ライブラリ、Terraform など、アプリケーションのデフォルト認証情報(ADC)をサポートするツールまたは REST リクエストを介して Google Cloud サービスにアクセスする場合は、次の図を参考にして認証方法を選択してください。

ユースケースに基づいて認証方法を選択するためのディシジョン ツリー

この図には、次の質問が記載されています。

  1. シングル ユーザー開発環境(独自のワークステーション、Cloud Shell、仮想デスクトップ インターフェースなど)でコードを実行していますか?
    1. 「はい」の場合は、質問 4 に進みます。
    2. 「いいえ」の場合は、質問 2 に進みます。
  2. Google Cloud でコードを実行していますか?
    1. 「はい」の場合は、質問 3 に進みます。
    2. 「いいえ」の場合は、質問 5 に進みます。
  3. Google Kubernetes Engine または GKE Enterprise でコンテナを実行していますか?
    1. 「はい」の場合は、GKE 用 Workload Identity 連携を使用して、サービス アカウントを Kubernetes Pod に接続します。
    2. そうでない場合は、リソースにサービス アカウントを接続します。
  4. ユースケースにサービス アカウントが必要ですか?

    たとえば、すべての環境でアプリケーションの認証と認可を一貫して構成したいとします。

    1. 「いいえ」の場合は、ユーザー認証情報で認証を行います。
    2. 「はい」の場合は、ユーザー認証情報を使用してサービス アカウントの権限を借用します。
  5. ワークロードは Workload Identity 連携をサポートする外部 ID プロバイダで認証されますか?
    1. 「はい」の場合は、Workload Identity 連携を構成して、オンプレミスや他のクラウド プロバイダで実行されているアプリケーションがサービス アカウントを使用できるようにします。
    2. 「いいえ」の場合は、サービス アカウント キーを作成します。

サービス アカウントを管理する

サービス アカウントは通常のユーザー アカウントとは異なり、使用方法だけでなく、管理方法も異なります。以降のセクションでは、サービス アカウントを管理する際のベスト プラクティスについて説明します。

サービス アカウントをリソースとして管理する

通常のユーザー アカウントは組織の joiner-mover-leaver プロセスで管理されます。新しい従業員が入社すると、新しいユーザー アカウントが作成されます。従業員が異動した場合は、そのユーザー アカウントが更新されます。退職した場合、そのユーザー アカウントは一時停止または削除されます。

これに対し、サービス アカウントは特定の従業員に関連付けられていません。サービス アカウントはリソースとして考えてください。このアカウントは、特定の VM インスタンスやアプリケーションなど、別のリソースまたはその一部に属しています。

サービス アカウントを効果的に管理するには、サービス アカウントを単独では捉えないでください。関連付けられているリソースのコンテキストでサービス アカウントを考慮し、サービス アカウントと関連付けられているリソースを 1 つのユニットとして管理します。サービス アカウントと関連付けられているリソースに同じプロセス、同じライフサイクル、同じデュー デリジェンスを適用し、同じツールで管理します。

単一目的のサービス アカウントを作成する

複数のアプリケーションで単一のサービス アカウントを共有すると、サービス アカウントの管理が複雑になる場合があります。

  • アプリケーションによってライフサイクルが異なる場合があります。アプリケーションが廃止された場合、サービス アカウントを廃止可能かどうか、必要かどうか判断できない場合があります。
  • アプリケーションのアクセス要件は時間とともに変化する可能性があります。アプリケーションが同じサービス アカウントを使用している場合、サービス アカウントにアクセス権を付与する必要がある対象リソースの数が増加すると、全般的なリスクが増大する可能性があります。
  • Cloud Audit Logs には、データの変更またはデータへのアクセスを行ったサービス アカウントの名前が含まれますが、サービス アカウントを使用したアプリケーションの名前は表示されません。複数のアプリケーションが 1 つのサービス アカウントを共有している場合は、アクティビティを適切なアプリケーションに対してトレースできない可能性があります。

特に、App Engine や Compute Engine など一部の Google Cloud サービスでは、プロジェクトに対する編集者のロール(roles/editor)を持つデフォルトのサービス アカウントが作成されます。Compute Engine 仮想マシン(VM)インスタンスなどのリソースを作成するときにサービス アカウントを指定しないと、そのリソースではデフォルトのサービス アカウントが自動的に使用されます。デフォルトのサービス アカウントは簡単に使い始めることができますが、このアカウントを複数のアプリケーションで共有することは非常に危険です。

この問題を回避するには、次のような方法があります。

命名とドキュメントの規則に従う

サービスとアプリケーションまたはリソースの関連付けを追跡できるように、新しいサービス アカウントを作成する際は、命名規則に従います。

  • アカウントの使用方法を表すプレフィックスをサービス アカウントのメールアドレスに追加します。例:
    • VM インスタンスに接続されているサービス アカウントには vm-
    • Workload Identity で使用されるサービス アカウントには wi-
    • Workload Identity 連携で使用されるサービス アカウントには wif-
    • オンプレミス アプリケーションで使用されるサービス アカウントには onprem-
  • アプリケーションの名前をサービス アカウントのメールアドレスに埋め込みます。たとえば、VM が出張費用に関連するアプリケーションを実行している場合は、vm-travelexpenses@ を使用します。
  • 説明フィールドを使用して、担当者の連絡先、関連ドキュメントへのリンク、その他のメモを追加します。

サービス アカウントのメールアドレスに機密情報を埋め込まないでください。

未使用のサービス アカウントを特定して無効にする

サービス アカウントを使用しなくなった場合は、サービス アカウントを無効にします。未使用のサービス アカウントを無効にすると、攻撃者によるラテラル ムーブメントや権限昇格などの不正行為に悪用されるリスクを軽減できます。

VM インスタンスなどの特定のリソースに関連付けられている単一目的のサービス アカウントの場合は、関連付けられたリソースが無効化または削除されたときにすぐサービス アカウントを無効にします。

複数の目的で使用されているサービス アカウントや複数のリソースで共有されているサービス アカウントの場合、サービス アカウントが引き続き使用されているかどうかを特定できないことがあります。このような場合は、Activity Analyzer を使用して、サービス アカウントの最新の認証アクティビティを確認できます。

未使用のサービス アカウントを削除する前にサービスを無効にする

サービス アカウントを削除した後、同じ名前で新しいサービス アカウントを作成した場合、新しいサービス アカウントには別の ID が割り当てられます。そのため、元の IAM バインディングが新しいサービス アカウントに適用されることはありません。これに対して、サービス アカウントを無効にして再度有効にした場合は、すべての IAM バインディングがそのまま残ります。

IAM バインディングが誤って失われないようにするには、サービス アカウントを直ちに削除しないことをおすすめします。代わりに、不要になったサービス アカウントを無効にし、特定の時間が経過した後に削除します。

App EngineCompute Engine のデフォルトのサービス アカウントなど、デフォルトのサービス アカウントは削除しないでください。これらのサービスは、それぞれの API を無効にして再度有効にしない限り再作成できません。このため、既存のデプロイが中断される可能性があります。デフォルトのサービス アカウントを使用しない場合は、これらのアカウントを無効にします。

サービス アカウントの権限を制限する

サービス アカウントはプリンシパルであり、通常のユーザー アカウントと同様にリソースへのアクセス権が付与されています。ただし、サービス アカウントは一般的なユーザーよりも多くのリソースにアクセスできます。また、アプリケーションに機能を追加すると、サービス アカウントのアクセス権も増えていく傾向があります。不要になったアクセス権の取り消しを忘れる可能性もあります。

デフォルトのサービス アカウントへの自動的なロール付与を使用しない

一部の Google Cloud サービスでは、Google Cloud プロジェクトで API を初めて有効にする際に、デフォルトのサービス アカウントが作成されます。デフォルトでは、これらのサービス アカウントに、Google Cloud プロジェクトに対する編集者のロール(roles/editor)が付与され、Google Cloud プロジェクト内のすべてのリソースの読み取りと変更が許可されます。このロールは便宜上付与されますが、サービスの動作に不可欠なものではありません。Google Cloud プロジェクトのリソースにアクセスする際に、Google Cloud サービスは、デフォルトのサービス アカウントではなくサービス エージェントを使用します。

デフォルトのサービス アカウントに編集者のロールが自動的に付与されないようにするには、組織に対してデフォルトのサービス アカウントに対する IAM ロールの自動付与の無効化constraints/iam.automaticIamGrantsForDefaultServiceAccounts)制約を有効にします。この制約を複数の Google Cloud プロジェクトに適用するには、フォルダまたは組織ノードで制約を構成します。制約を適用しても、既存のデフォルト サービス アカウントからは編集者のロールは削除されません。

この制約を適用すると、新しいプロジェクトのデフォルトのサービス アカウントは Google Cloud リソースにアクセスできなくなります。デフォルトのサービス アカウントに適切なロールを付与し、リソースにアクセスできるようにする必要があります。

サービス アカウントを VM インスタンスに接続する際にアクセス スコープに依存しない

サービス アカウントを VM インスタンスに接続する際に、1 つ以上のアクセス スコープを指定できます。アクセス スコープを使用すると、VM がアクセスできるサービスを制限できます。これらの制限は、許可ポリシーに加えて適用されます。

アクセス スコープはきめ細かいものではありません。たとえば、https://www.googleapis.com/auth/devstorage.read_only スコープを使用すると、Cloud Storage へのアクセスを読み取り操作に制限できますが、特定のバケットへのアクセスを制限することはできません。したがって、アクセス スコープは、きめ細かい許可ポリシーの代わりとして使用するには適していません。

アクセス スコープに依存するのではなく、専用のサービス アカウントを作成し、きめ細かい許可ポリシーを使用して、サービス アカウントがアクセスできるリソースを制限します。

サービス アカウントにリソースへのアクセス権を付与する際にグループを使用しないようにする

組織では、複数の従業員が類似した、または重複するジョブ機能を実行することから、リソースへの類似したアクセス権が必要となるケースが一般的にみられます。グループを使用すると、これらの類似点を活用して管理のオーバーヘッドを軽減できます。

サービス アカウントは、アプリケーションで使用されるよう意図されています。複数のアプリケーションが同じ機能を実行するからと言って、それらのアプリケーションに同様の、または同じアクセス要件があることはまれです。それよりも、アプリケーションは独自性を持つ傾向があり、アプリケーションがアクセスする必要のあるリソースはそれぞれに異なるのが通常です。

グループを使用してサービス アカウントにリソースへのアクセス権を付与すると、次のような悪い結果をもたらす可能性があります。

  • それぞれに 1 つまたは少数のサービス アカウントしか含まれないグループの急増。
  • 権限変更: グループの各メンバーはリソースのサブセットへのアクセス権のみを必要とするにもかかわらず、そのグループに付与されているアクセス権の対象が徐々に増えてきます。

グループの目的が限定的に定義されていない限り、グループの使用は避けることをおすすめします。代わりに、必要なリソースへのアクセス権をサービス アカウントに直接付与します。

ドメイン全体の委任を使用しないようにする

ドメイン全体の委任により、サービス アカウントは Cloud Identity または Google Workspace アカウント内の任意のユーザーになりすますことができます。ドメイン全体の委任を使用すると、サービス アカウントが Google Workspace や Cloud Identity で特定の管理タスクを実行することや、Google Cloud の外部に存在するサービス アカウントをサポートしていない Google API にアクセスすることが可能になります。

ドメイン全体の委任では、特定のユーザーを対象としたなりすましに制限されるのではなく、サービス アカウントが Cloud Identity または Google Workspace アカウントの任意のユーザー(特権管理者を含む)になりすますことができます。そのため、サービス アカウントにドメイン全体の委任の使用を許可すると、そのサービス アカウントは権限昇格攻撃の格好のターゲットになる可能性があります。

サービス アカウントで直接タスクを完了できる場合、または OAuth 同意フローを使用してタスクを完了できる場合は、ドメイン全体の委任の使用を避けてください。

ドメイン全体の委任の使用が不可避である場合は、サービス アカウントで使用できる 一連の OAuth スコープを制限します。OAuth スコープによってサービス アカウントがなりすませるユーザーが制限されることはありませんが、サービス アカウントがアクセスできるユーザーデータの種類は制限されます。

アプリケーションで、機密性の高いユーザーデータへのアクセスが必要になる場合があります。このようなデータの例としては、ユーザーのメールボックスやカレンダー、Google ドライブに保存されたドキュメント、機密データを含む BigQuery データセットなどがあります。

ユーザー不在のアプリケーションで、インデックス登録やデータ損失防止(DLP)のスキャンなどのバックグラウンド タスクが実行される場合や、エンドユーザーが Google ID で認証されていない場合には、サービス アカウントを使用してユーザーデータにアクセスできます。アプリケーションがエンドユーザーに代わって動作するその他のシナリオでは、サービス アカウントを使用しないことをおすすめします。

ユーザーデータにアクセスする場合は、サービス アカウントではなく(プリンシパルの移行を実行している可能性あるため)、OAuth 同意フローを使用してエンドユーザーに同意を求めます。その後、アプリケーションがエンドユーザー ID で処理を行うことができるようにします。サービス アカウントの代わりに OAuth を使用すると、次のことができるようになります。

  • ユーザーは、アプリケーションにアクセス権を付与しようとしているリソースを確認し、自身の同意または拒否を明示的に表明できます。
  • ユーザーは随時、[アカウント情報] ページで同意を取り消すことができます。
  • すべてのユーザーのデータに対して無制限のアクセス権を付与されたサービス アカウントは必要ありません。

アプリケーションにエンドユーザー認証情報の使用を許可することで、Google Cloud APIs に対する権限チェックを延期します。これにより、コーディング エラーが原因でユーザーがアクセスすることを許可しないようにする必要があるデータが、誤って公開されてしまうリスク(混乱した使節に関する問題)を低減できます。

一時的な権限の昇格に IAM Credentials API を使用する

アプリケーションによっては、特定のタイミングや状況下でのみ特定のリソースへのアクセスが必要になることがあります。次に例を示します。

  • アプリケーションの起動時に構成データにアクセスする必要があり、初期化後はアクセスする必要がなくなる場合があります。
  • スーパーバイザー アプリケーションが、アクセス要件が異なるバックグラウンド ジョブを定期的に開始する場合があります。

このようなシナリオでは、1 つのサービス アカウントを使用してすべてのリソースにアクセス権を付与することは、最小権限の原則に反します。アプリケーションがいつでも必要以上に多くのリソースにアクセスできてしまう可能性があります。

アプリケーションのさまざまな部分が必要なリソースのみにアクセスできるようにするには、一時的な権限昇格に IAM Credentials API を使用します。

  • アプリケーションまたはユースケースごとに専用のサービス アカウントを作成し、必要なリソースにのみサービス アカウントへのアクセス権を付与します。
  • スーパーバイザーとして機能する別のサービス アカウントを作成します。他のサービス アカウントにサービス アカウント トークン作成者のロールを付与し、これらのサービス アカウントに有効期間の短いアクセス トークンをリクエストできるようにします。
  • アプリケーションを分割して、アプリケーションの 1 つの部分をトークン ブローカーとして機能させ、この部分のみがスーパーバイザー サービス アカウントを使用できるようにします。
  • トークン ブローカーを使用して、有効期間の短いサービス アカウントをアプリケーションの別の部分に発行します。

有効期間の短い認証情報の作成については、サービス アカウントに有効期間の短い認証情報を作成するをご覧ください。

認証情報のアクセス境界を使用してアクセス トークンの範囲を絞り込む

Google のアクセス トークンは署名なしトークンです。つまり、トークンの使用は特定のアプリケーションに関連付けられていません。アプリケーションがアクセス トークンを別のアプリケーションに渡すと、そのアプリケーションはご利用のアプリケーションと同じようにトークンを使用できます。同様に、アクセス トークンが不正な行為者に漏洩した場合は、その不正な行為者がトークンを使用してアクセス権を取得できます。

アクセス トークンは署名なしトークンであるため、権限を付与されていないユーザーに漏洩したり、表示されたりしないように保護する必要があります。アクセス トークンがアクセス権を付与する対象リソースを制限することで、漏洩したアクセス トークンによって生じる可能性がある損害を低減できます。このプロセスは「ダウンスコーピング」と呼ばれます。

アクセス トークンを別のアプリケーションやご利用のアプリケーションの別のコンポーネントに渡す場合は常に、認証情報アクセス境界を使用してアクセス トークンのダウンスコーピングを行ってください。アクセス境界を設定して、トークンが必要以上のリソースに対するアクセス権を付与しないようにします。

ロールの推奨事項を使用して未使用の権限を特定する

アプリケーションを初めてデプロイする際に、アプリケーションに実際に必要となるロールと権限が不明な場合があります。その場合、アプリケーションのサービス アカウントに必要以上の権限を付与してしまう可能性があります。

同様に、アプリケーションのアクセス要件は時間とともに変化する可能性があり、最初に付与したロールと権限の一部が不要になる可能性もあります。

ロールの推奨事項を使用して、アプリケーションが実際に使用している権限と、未使用の可能性がある権限を特定します。影響を受けるリソースの許可ポリシーを調整して、アプリケーションに対して実際に必要とする範囲を超えるアクセス権が付与されないようにします。

ラテラル ムーブメントの分析情報を使用してラテラル ムーブメントを制限する

ラテラル ムーブメントとは、あるプロジェクトのサービス アカウントが別のプロジェクトのサービス アカウントの権限を借用することです。たとえば、プロジェクト A に作成されたサービス A が、プロジェクト B のサービス アカウントの権限を借用する場合を表します。

これらの権限により、複数のプロジェクトにまたがる権限借用の連鎖が発生し、リソースに対する意図しないアクセスがプリンシパルに許可される可能性があります。たとえば、プリンシパルはプロジェクト A のサービス アカウントの権限を借用し、そのサービス アカウントを使用してプロジェクト B のサービス アカウントの権限を借用できます。プロジェクト B のサービス アカウントに、組織内の他のプロジェクトの他のサービス アカウントの権限借用が許可されている場合、プリンシパルは、引き続きサービス アカウントの権限借用を使用してプロジェクトからプロジェクトに移動し、権限を取得します。

Recommender は、この問題の対処に役立つラテラル ムーブメントの分析情報を提供します。ラテラル ムーブメントの分析情報により、あるプロジェクトのサービス アカウントが別のプロジェクトのサービス アカウントの権限を借用することを許可するロールが特定されます。ラテラル ムーブメントの分析情報を直接表示し、管理する方法については、ラテラル ムーブメントの分析情報の管理をご覧ください。

一部のラテラル ムーブメントの分析情報は、ロールの推奨事項に関連付けられています。推奨事項を適用することで、プロジェクト間のラテラル ムーブメントを減らすことができます。方法については、推奨事項を確認して適用するをご覧ください。

権限昇格の脅威からの保護

ロールが付与されていない、またはリソースへのアクセス権がなく、ファイアウォール ルールに関連付けされていないサービス アカウントは、通常は存在価値が限定的です。リソースへのアクセス権をサービス アカウントに付与すると、サービス アカウントの価値が向上します。つまり、ユーザーに対するサービス アカウントの有用性が向上しますが、それと同時に、権限昇格攻撃での格好のターゲットにもなります。

例として、機密情報を格納する Cloud Storage バケットに対する完全アクセス権を付与されたサービス アカウントについて考えてみましょう。このような状況では、サービス アカウントは実質的に Cloud Storage バケット自体と同等の価値を有します。不正な行為者は、バケットに直接アクセスしようとするのではなく、サービス アカウントを支配しようと試みる可能性があります。その試行が成功した場合、不正な行為者はサービス アカウントになりすまして自身の権限を昇格させ、それによってバケット内の機密情報へのアクセス権を獲得できます。

通常、サービス アカウントに関連する権限昇格の手法は、次のカテゴリに分類されます。

  • サービス アカウントとして認証: 誤ってユーザーに権限を付与してしまうと、サービス アカウントの権限が借用されたり、サービス アカウントにサービス アカウント キーが作成される可能性があります。サービス アカウントにユーザー自身の権限よりも高い権限が付与されている場合、ユーザーはサービス アカウントとして認証することで自身の権限を昇格し、本来はアクセスできないリソースへのアクセス権を取得できます。

  • サービス アカウントが接続されているリソースの使用: ユーザーが、CI / CD パイプライン、VM インスタンス、またはサービス アカウントが接続されている他の自動化システムにアクセスして変更する権限を持っている場合、リソースに接続されたサービス アカウントを使用してアクションを実行できる可能性があります。その結果、サービス アカウントの権限借用が許可されていなくても、サービス アカウントの権限を使用して、実行を許可されていないアクションを実行できます。

    たとえば、Compute Engine VM インスタンスへの SSH アクセス権を持つユーザーが、インスタンスでコードを実行して、インスタンスに接続されたサービス アカウントがアクセスできる任意のリソースにアクセスする可能性があります。

  • 許可ポリシー、グループ、またはカスタムロールの変更: 特権サービス アカウントへのアクセス権を付与されていないユーザーであっても、サービス アカウントの許可ポリシー、またはサービス アカウントに含まれている Google Cloud プロジェクトまたはフォルダの許可ポリシーを変更する権限が付与される可能性があります。ユーザーは、これらの許可ポリシーのいずれかを拡張して、サービス アカウントとして(直接的または間接的に)認証されるようにすることができます。

以降のセクションでは、権限昇格の脅威からサービス アカウントを保護する際のベスト プラクティスについて説明します。

ユーザーが自身よりも高い権限を付与されたサービス アカウントとして認証されないようにする

ユーザーはサービス アカウントの権限を借用することで、そのサービス アカウントがアクセスできるリソースの一部またはすべてに対するアクセス権を取得できます。サービス アカウントにユーザーよりも広範なアクセス権がある場合、そのサービス アカウントには実質的にユーザーよりも高い権限が付与されています。

ユーザーに自身よりも高い権限を付与されたサービス アカウントの権限借用を許可するということは、Linux では sudo ツール、Windows ではプロセスの昇格を使用するのと同様に、ユーザーに対し、意図的に権限昇格を一時的に許可するということです。一時的な権限昇格が必要となる状況に対処する場合を除き、自身よりも高い権限を付与されたサービス アカウントの権限借用をユーザーに許可しないでください。

ユーザーは、サービス アカウントの権限をリソースに接続し、そのリソースでコードを実行することで、間接的にサービス アカウントの権限を取得する可能性があります。この方法でコードを実行しても、認証される ID(サービス アカウントの ID)が 1 つしかないため、サービス アカウントの権限は借用されません。ただし、他の方法では得られないような権限を取得できます。

ユーザーがサービス アカウントの権限を借用したり、サービス アカウントをリソースに接続できる権限には、次のようなものがあります。

  • iam.serviceAccounts.getAccessToken
  • iam.serviceAccounts.getOpenIdToken
  • iam.serviceAccounts.actAs
  • iam.serviceAccounts.implicitDelegation
  • iam.serviceAccounts.signBlob
  • iam.serviceAccounts.signJwt
  • iam.serviceAccountKeys.create
  • deploymentmanager.deployments.create
  • cloudbuild.builds.create

これらの権限の一部を含むロールには、以下のものがあります(これらに限定されません)。

  • オーナー(roles/owner
  • 編集者(roles/editor
  • サービス アカウント ユーザー(roles/iam.serviceAccountUser
  • サービス アカウント トークン作成者(roles/iam.serviceAccountTokenCreator
  • サービス アカウント キー管理者(roles/iam.serviceAccountKeyAdmin
  • サービス アカウント管理者(roles/iam.serviceAccountAdmin
  • Workload Identity ユーザー(roles/iam.workloadIdentityUser
  • Deployment Manager 編集者(roles/deploymentmanager.editor
  • Cloud Build 編集者(roles/cloudbuild.builds.editor

ユーザーにこれらのロールのいずれかを割り当てる前に、次の項目を確認してください。

  • サービス アカウントになりすますことでユーザーがアクセス権を獲得できる可能性がある、現在の Google Cloud プロジェクト内外のリソースはどのようなものか?
  • このレベルのアクセス権は正当であるか?
  • ユーザーがサービス アカウントになりすますことができる状況を制御するための、十分な保護対策を導入しているか?

上述の質問のすべてを確認できない場合は、ロールを割り当てないでください。代わりに、権限の低い別のサービス アカウントをユーザーに割り当てることを検討してください。

ユーザーが自身よりも高い権限を付与されているサービス アカウントの許可ポリシーを変更できないようにする

サービス アカウントの使用または権限借用が許可されるユーザーは、サービス アカウントの許可ポリシーによってキャプチャされます。許可ポリシーを変更または拡張できるのは、特定のサービス アカウントに対する iam.serviceAccounts.setIamPolicy 権限が付与されたユーザーです。この権限を含むロールには次のものがあります。

  • オーナー(roles/owner
  • セキュリティ管理者(roles/iam.securityAdmin
  • サービス アカウント管理者(roles/iam.serviceAccountAdmin

iam.serviceAccounts.setIamPolicy 権限を含むロールによって、ユーザーはサービス アカウントを完全に制御できます。

  • ユーザーはサービス アカウントの借用権限を自身に付与できます。これにより、サービス アカウントと同じリソースにアクセスする権限がユーザーに付与されます。
  • このユーザーは、同一または類似したレベルのサービス アカウントへのアクセス権を他のユーザーに付与できます。

これらのロールのいずれかをユーザーに割り当てる前に、サービス アカウントになりすますことでユーザーがアクセス権を取得できる可能性がある、現在の Google Cloud プロジェクト内外の対象リソースについて自問してください。サービス アカウントにユーザーよりも多くの権限が付与されている場合は、ユーザーにサービス アカウントの許可ポリシーの変更を許可しないでください。

ユーザーがサービス アカウント キーを作成またはアップロードすることを許可しない

サービス アカウント キーを使用すると、アプリケーションまたはユーザーはサービス アカウントとして認証されます。他の形式のサービス アカウントの権限借用とは異なり、サービス アカウント キーを使用する場合、事前に認証するという形をとる必要はありません。サービス アカウント キーを所有しているユーザーであれば、誰でもサービス アカウントを使用できます。

サービス アカウント キーを使用して認証した場合の最終的な影響は、サービス アカウントの権限借用と同様です。ユーザーにサービス アカウント キーへのアクセス権を付与した場合、または新しいサービス アカウント キーを作成する権限をユーザーに付与した場合、ユーザーはサービス アカウントとして認証され、サービス アカウントがアクセスできるすべてのリソースにアクセスできます。

サービス アカウント キーを作成またはアップロードするには、iam.serviceAccountKeys.create 権限が必要です。この権限は、サービス アカウント キー管理者(roles/iam.serviceAccountKeyAdmin)と編集者(roles/editor)のロールに含まれています。

iam.serviceAccountKeys.create 権限を含むロールをユーザーに割り当てる前に、サービス アカウントになりすますことでユーザーがアクセス権を取得できる可能性がある、現在の Google Cloud プロジェクト内外の対象リソースについて自問してください。必要以上の権限を付与されたサービス アカウントのサービス アカウント キーをユーザーが作成することを許可しないでください。

Google Cloud プロジェクトでサービス アカウント キーがまったく必要とされない場合は、サービス アカウント キーの作成の無効化サービス アカウント キーのアップロードの無効化の組織ポリシー制約を、Cloud プロジェクトまたはプロジェクトに含まれているフォルダに適用します。これらの制約により、サービス アカウントに対する iam.serviceAccountKeys.create 権限を付与されているユーザーを含め、すべてのユーザーがサービス アカウント キーの作成とアップロードを行うことができなくなります。

Google Cloud プロジェクトまたはフォルダレベルでサービス アカウントへのアクセス権を付与しない

サービス アカウントはリソースであり、リソース階層の一部です。したがって、サービス アカウントへのアクセスは、次のいずれかのレベルで管理できます。

  • 個別のサービス アカウント
  • それに含まれている Google Cloud プロジェクト
  • Google Cloud プロジェクトの祖先に含まれるフォルダ
  • 組織ノード

Google Cloud プロジェクト レベルまたはリソース階層の上位でアクセスを管理すると、管理オーバーヘッドを削減できますが、権限の過剰な付与につながる可能性もあります。たとえば、Google Cloud プロジェクトでサービス アカウント トークン作成者のロールをユーザーに付与すると、そのユーザーは Google Cloud プロジェクト内の任意のサービス アカウントになりすますことができます。サービス アカウントの権限が借用できるということは、該当する Google Cloud プロジェクト外部に存在するリソースを含め、サービス アカウントがアクセスできるすべてのリソースへのアクセス権をユーザーが取得できる可能性があることを意味します。

このような過剰な権限の付与を回避するため、Google Cloud プロジェクト レベルまたはフォルダレベルではサービス アカウントに対するアクセス権を管理しないでください。代わりに、サービス アカウントごとに個別にアクセス権を管理してください。

特権サービス アカウントが割り当てられているコンピューティング リソースに対しては、セキュリティ保護の程度が低いソースからコードを実行しない

VM インスタンスや Cloud Run アプリケーションなどのコンピューティング リソースにサービス アカウントを接続すると、そのリソースで実行中のプロセスがメタデータ サーバーを使用して、アクセス トークンと ID トークンをリクエストできます。これらのトークンにより、プロセスはサービス アカウントとして認証され、プロセスに代わってリソースにアクセスできます。

デフォルトでは、メタデータ サーバーへのアクセスは、特定のプロセスやユーザーに制限されません。コンピューティング リソースに対して実行されるコードは、メタデータ サーバーにアクセスしてアクセス トークンを取得できます。このようなコードには、次のものが含まれます。

  • アプリケーションのコード。
  • エンドユーザーから送信されたコード(アプリケーションがサーバー側のスクリプト評価を許可している場合)。
  • リモート ソース リポジトリから読み取ったコード(コンピューティング リソースが CI / CD システムの一部である場合)。
  • Cloud Storage バケットによって配信される起動スクリプトとシャットダウン スクリプト
  • VM Manager から配信されるゲストポリシー

コードがユーザーから送信されるか、リモートの保管場所から読み取られる場合は、信頼できるユーザーまたは保管場所であることと、リモートの保管場所が少なくとも接続されたサービス アカウントと同程度にセキュリティで保護されていることを確認する必要があります。リモートの保管場所がサービス アカウントと同程度に保護されていなければ、不正な行為者が権限を昇格させる可能性があります。その手段として、不正な行為者がサービス アカウントの権限を使用する悪意のあるコードを保管場所に挿入することが考えられます。

特権サービス アカウントが接続されている VM へのシェルアクセスを制限する

一部のコンピューティング リソースはインタラクティブ アクセスをサポートしており、ユーザーによるシステムへのシェルアクセス権の取得を許可します。次に例を示します。

  • Compute Engine では、SSH または RDP を使用して VM インスタンスにログインできます。
  • Google Kubernetes Engine では、kubectl exec を使用して、Kubernetes コンテナでコマンドを実行したり、シェルを起動したりできます。

VM インスタンスに特権サービス アカウントが接続されている場合、システムへのシェルアクセス権を持つすべてのユーザーが、サービス アカウントとして認証され、リソースへのアクセスが許可されます。ユーザーがこの権限を不正使用して自身の権限を昇格できないようにするには、少なくとも接続されたサービス アカウントと同程度に、シェルアクセス権を保護する必要があります。

Linux インスタンスの場合は、OS Login を使用して、接続されているサービス アカウントへのアクセスよりも SSH アクセスに対する制限を強化できます。OS Login が有効になっている VM インスタンスに接続するには、ユーザーは OS Login の使用を許可されていることに加え、接続されているサービス アカウントに対する iam.serviceAccounts.actAs 権限を付与されている必要があります。

同じレベルのアクセス制御は、メタデータ ベースの鍵を使用する VM インスタンスにも、Windows インスタンスにも適用されません。メタデータの SSH 認証鍵を公開したり、Windows 認証情報をリクエストしたりするには、VM インスタンスのメタデータへのアクセス権と、接続されたサービス アカウントに対する iam.serviceAccounts.actAs 権限が必要です。ただし、SSH 認証鍵の公開後または Windows 認証情報の取得後は、以降のログインに IAM 権限チェックが適用されることは一切ありません。

同様に、VM インスタンスで認証にカスタムの Linux プラグイン対応認証モジュールを使用している場合や、VM インスタンスが Active Directory ドメインのメンバーである場合、本来はサービス アカウントとして認証されないユーザーがログインできてしまいます。詳細については、Google Cloud で Active Directory を実行するためのベスト プラクティスをご覧ください。

OS Login を使用しない VM インスタンスでは特に、Identity-Aware Proxy によるシェルアクセス権の付与を検討してください。VM インスタンスに接続されたサービス アカウントとして認証される必要があるユーザーにのみ、IAP で保護されたトンネル ユーザー(roles/iap.tunnelResourceAccessor)ロールを付与します。

メタデータ サーバーによるアクセスを選択したユーザーとプロセスに制限する

サービス アカウントを VM インスタンスに接続すると、その VM にデプロイされたワークロードがメタデータ サーバーにアクセスし、サービス アカウントのトークンをリクエストできます。デフォルトでは、メタデータ サーバーへのアクセスは、VM 上の特定のプロセスやユーザーに制限されません。Linux の nobody や Windows 上の LocalService など、権限の低いユーザーとして実行されているプロセスでも、メタデータ サーバーへの完全アクセス権を使用して、サービス アカウントのトークンを取得できます。

メタデータ サーバーへのアクセスを特定のユーザーに制限するには、ゲスト オペレーティング システムのホスト ファイアウォールを構成して、これらのユーザーのみがメタデータ サーバーに対する送信接続を開くことができるようにします。

Linux では、--uid-owner オプションと --gid-owner オプションを使用して、特定のユーザーまたはグループにのみ適用される iptables ルールを設定できます。Windows では、Set-NetFirewallSecurityFilter コマンドを使用して、選択したユーザーまたはグループに適用されるようにファイアウォール ルールをカスタマイズできます。

情報開示の脅威からの保護

サービス アカウントのメールアドレスで機密情報を開示しない

別の Google Cloud プロジェクト内のリソースにサービス アカウントへのアクセス権を付与するには、リソースの許可ポリシーにロール バインディングを追加します。リソース自体と同様に、許可ポリシーは別の Google Cloud プロジェクトの一部であり、許可ポリシーの可視性も、その別の Google Cloud Platform プロジェクトによって管理されます。

許可ポリシーの表示は、通常は特権操作とみなされません。この操作に必要な *.getIamPolicy 権限は、基本的な閲覧者のロールをはじめ、多くのロールに含まれています。

許可ポリシーを表示できるユーザーは、リソースへのアクセスを許可されているプリンシパルのメールアドレスも表示できます。サービス アカウントの場合、メールアドレスが不正な行為者にヒントを与える可能性があります。

たとえば、許可ポリシーに、メールアドレスとして jenkins@deployment-project-123.gserviceaccount.com が設定されたサービス アカウントのバインディングが含まれているとします。不正な行為者にとって、このメールアドレスは ID が deployment-project-123 の Google Cloud プロジェクトがあることだけでなく、その Google Cloud プロジェクトが Jenkins サーバーを実行することも明かしています。deployer@deployment-project-123.gserviceaccount.com などの一般的な名前を選択すると、deployment-project-123 で実行しているソフトウェアの種類に関する情報の開示を避けることができます。

アクセスの制御が脆弱な Google Cloud プロジェクト内のリソース(サンドボックスや開発環境の Google Cloud プロジェクトなど)へのアクセス権をサービス アカウントに付与する場合は、サービス アカウントのメールアドレスによって情報が開示されないようにしてください。特に、機密性の高い情報や攻撃者にヒントを与える可能性のある情報は開示しないでください。

否認防止の脅威からの保護

Google Cloud 上のリソースに影響する不審なアクティビティが判明した場合、Cloud Audit Logs は常に、アクティビティの発生時刻と関与したユーザーを特定するための重要な情報源になります。

Cloud Audit Logs にサービス アカウントによってアクティビティが実行されことが示されている場合、その情報だけで常に一連のイベントのすべてを再構築できるとは限りません。サービス アカウントがそのアクティビティを実行する発端となったユーザーまたはアプリケーションについても特定できる必要があります。

このセクションでは、否認防止に関する監査証跡を保持するうえで有用なベスト プラクティスについて説明します。

他に有効な方法がない場合にのみサービス アカウント キーを使用する

より安全な認証方法を使用できない場合は、アプリケーションのサービス アカウント キーの作成が必要になる場合があります。ただし、サービス アカウント キーによる認証では、否認防止の脅威が発生します。Cloud Audit Logs は、サービス アカウントがリソースを変更するときにログを作成しますが、サービス アカウントがサービス アカウント キーで認証されている場合、誰が鍵を使用したかを確認する信頼できる方法はありません。これに対して、ユーザー認証情報を使用してサービス アカウントの権限を借用することでサービス アカウントとして認証すると、サービス アカウントとして動作したプリンシパルがログに記録されます。

Google Cloud プロジェクトまたはそれに含まれるフォルダに、サービス アカウント キーの作成を無効にする組織のポリシーの制約を適用して、サービス アカウント キーの作成を防ぐことをおすすめします。推奨する代替手段で対応できないシナリオでサービス アカウント キーを使用する必要がある場合は、ポリシー制約に可能な限り狭い例外を適用し、サービス アカウント キーを管理するためのベスト プラクティスを確認してください。

IAM API のデータアクセス ログを有効にする

Compute Engine などのサービスでは、サービス アカウントの権限借用を識別して把握できるように、Cloud Audit Logs に serviceAccountDelegationInfo セクションを追加しています。このセクションには、サービス アカウントのなりすましが行われているかどうか、行われている場合はどのユーザーがなりすましているかが示されます。

すべてのサービスで、Cloud Audit Logs になりすましの詳細を記録するわけではありません。すべてのなりすましのイベントを記録するには、次の API に対してデータアクセス ログを有効化する必要があります。

  • サービス アカウントを含むすべての Google Cloud プロジェクトの Identity and Access Management(IAM)API
  • Workload Identity プールが含まれるすべての Google Cloud プロジェクトの Security Token Service API

これらのログを有効にすることで、ユーザーがサービス アカウントのアクセス トークンまたは ID トークンをリクエストするたびに、そのエントリが Cloud Audit Logs に追加されます。

CI / CD の履歴を Cloud Audit Logs に関連付けできるようにする

サービス アカウントは一般に、コード変更の検証とデプロイの承認が完了した後に、CI / CD システムでデプロイを実行するために使用されます。通常、CI / CD システムは、デプロイにつながったイベントの履歴を保持します。この履歴には、対応するコードレビュー、commit、パイプライン実行の ID、デプロイの承認者に関する情報が含まれる場合があります。

デプロイによって Google Cloud 上のリソースが変更されると、該当するリソースの Cloud Audit Logs でこれらの変更が追跡されます。Cloud Audit Logs には、変更を開始したユーザーまたはサービス アカウントに関する情報が記録されます。ただし、CI / CD システムによってトリガーされたデプロイでは、多くの場合、サービス アカウント自体の情報だけでは変更の原因となった一連のイベントをすべて再構築できません。

CI / CD システムと Google Cloud で一貫した監査証跡を確立するには、Cloud Audit Logs のレコードを CI / CD システムの履歴でイベントに関連付けできるようにする必要があります。Cloud Audit Logs で予期しないイベントが発生した場合は、この関連付けを使用して、変更が実際に CI / CD システムによって行われたか否か、実行された理由、承認者について確認できます。

CI / CD システムの履歴で Cloud Audit Logs のレコードとイベントを関連付けるには、以下の方法があります。

  • CI / CD パイプラインが実行されるたびに、ログ API リクエストを実行する。
  • API がオペレーション ID を返すたびに、CI / CD システムのログに ID を記録する。
  • API リクエストに X-Goog-Request-Reason HTTP ヘッダーを追加し、CI / CD パイプライン実行の ID を渡す。リクエストの理由を指定すると、Terraform がこのヘッダーを自動的に追加できます。

    あるいは、User-Agent ヘッダーに情報を埋め込んで Cloud Audit Logs に取り込むようにする。

否認防止を確立するために、ログファイルと commit 履歴が変更不可であり、不正な行為者がトレースを遡及的に隠蔽できないように構成します。

アプリケーションの個々のユーザーにカスタム ログエントリを作成する

サービス アカウントは、ユーザーがカスタム認証スキームで認証を行い、Google Cloud リソースに間接的にアクセスするアプリケーションにも役立ちます。これらのアプリケーションは、ユーザーが認証および承認され、サービス アカウントを使用して Google Cloud サービスの認証を行い、リソースにアクセスしていることを確認できます。ただし、Cloud Audit Logs は、どのユーザーがアプリケーションを使用したかではなく、サービス アカウントがリソースにアクセスしたことをログに記録します。

アクセスからユーザーを追跡するには、ユーザーがリソースにアクセスするたびにカスタム ログエントリを書き込むようにアプリケーション ロジックを設計し、カスタム ログエントリと Cloud Audit Logs を関連付けます。

次のステップ