サービス アカウントは人間以外のユーザーを表します。これは、カスタム アプリケーションなどのワークロードで、エンドユーザーの関与なしにリソースにアクセスする場合や、アクションを実行する必要がある場合を対象としています。
サービス アカウントは、通常のユーザー アカウントと次の点で異なります。
- パスワードが設定されていないため、ブラウザベースのログインには使用できません。
- Google Cloud プロジェクトに属するリソースとして作成され、管理されます。これに対して、ユーザーは Cloud Identity または Google Workspace のアカウントで管理されます。
- Google Cloud に固有です。一方、Cloud Identity または Google Workspace で管理されるユーザーは、Google の多数のプロダクトとサービスで動作します。
- どちらもリソースで、プリンシパルです。
- プリンシパルとしてのサービス アカウントには、Cloud Storage バケットなどのリソースへのアクセス権を付与できます。
- リソースとしてアクセスできるサービス アカウントは、ユーザーやグループなどの他のプリンシパルがなりすます可能性もあります。
サービス アカウントは便利なツールですが、悪用する方法がいくつかあります。
- 権限昇格: 不正な行為者がサービス アカウントになりすますことにより、通常ではアクセス権を付与されることのないリソースへのアクセス権を取得する可能性があります。
- なりすまし: 不正な行為者がサービス アカウントの権限を借用して、ID を隠蔽する可能性があります。
- 否認防止: 不正な行為者が、サービス アカウントを使用して自身の代理でオペレーションを実行することで、ID とアクションを隠蔽する場合があります。場合によっては、これらのアクションを追跡して不正な行為者にまでたどりつけないことがあります。
- 情報開示: 不正な行為者が、特定のサービス アカウントの存在からインフラストラクチャ、アプリケーション、またはプロセスに関する情報を引き出す可能性があります。
サービス アカウントを保護するには、アカウントの 2 つの性質を考慮してください。
- サービス アカウントはプリンシパルであることから、サービス アカウントの不正使用により発生する可能性がある損害を軽減するために、権限を制限する必要があります。
- サービス アカウントはリソースであることから、不正使用されないように保護する必要があります。
このガイドでは、サービス アカウントを管理、使用、保護するためのベスト プラクティスについて説明します。
サービス アカウントを使用するタイミングを選択する
サービス アカウントは、バッチジョブ、キューにメッセージをディスパッチするワーカー プロセス、リソース モニタリング エージェントなど、ユーザー不在で実行されるアプリケーションの ID を提供します。サービス アカウントを使用すると、これらのアプリケーションをユーザーの操作なしで実行できます。また、アプリケーションがリソースにアクセスした場合、Cloud Audit Logs を使用して、アプリケーションが使用するサービス アカウントをトレースできます。
サービス アカウントは、ユーザーがカスタム認証スキームで認証を行い、Google Cloud リソースに間接的にアクセスするアプリケーションにも役立ちます。これらのアプリケーションは、ユーザーが認証および承認され、サービス アカウントを使用して Google Cloud サービスの認証を行い、リソースにアクセスしていることを確認できます。ユーザーがアクセスを確認する際に役立つように、ユーザーがリソースにアクセスするたびにアプリケーションでカスタム ログエントリを書き込むことができます。また、カスタム ログエントリを Cloud Audit Logs に関連付けて分析できます。
ユーザーとは異なり、サービス アカウントはパスワードまたはシングル サインオン(SSO)を使用してログインできません。サービス アカウントに対しては別の認証方法がサポートされています。以下のセクションでは、その選択方法について説明します。次の図を使用して、選択する認証方法を確認することもできます。
次のセクションでは、サービス アカウントを使用するタイミングと方法を選択する際のベスト プラクティスについて説明します。
ベスト プラクティス:
可能な場合には接続されたサービス アカウントを使用する。Workload Identity を使用してサービス アカウントを Kubernetes Pod に接続する。
Workload Identity 連携を使用して、オンプレミスまたは他のクラウド プロバイダで実行されているアプリケーションがサービス アカウントを使用できるようにする。
IAM Credentials API を使用して認証情報を仲介する。
他に有効な方法がない場合にサービス アカウント キーを使用する。
ユーザーの同意なしにサービスデータにアクセスするためにサービス アカウントを使用しない。
開発中にサービス アカウントを使用しない。
可能な場合には接続されたサービス アカウントを使用する
Google Cloud にデプロイされたアプリケーションでサービス アカウントを使用できるようにするには、基盤となるコンピューティング リソースにサービス アカウントを接続します。サービス アカウントを接続すると、アプリケーションはサービス アカウントのトークンを取得し、そのトークンを使用して Google Cloud APIs とリソースにアクセスできます。
アプリケーションでアクセス トークンを取得する場合、可能であればクライアント ライブラリを使用します。クライアント ライブラリは、アプリケーションのデフォルト認証情報(ADC)を使用して、関連付けられた認証情報を自動的に検索し、アプリケーションのアクセス トークンを取得します。
クライアント ライブラリの使用が現実的でない場合は、メタデータ サーバーからトークンをプログラムで取得するようにアプリケーションを調整します。メタデータ サーバーへのアクセスをサポートするコンピューティング リソースには次のものがあります。
サービス アカウントを接続できるコンピューティング リソースの一覧については、サービス アカウントの権限借用の管理をご覧ください。
Workload Identity を使用してサービス アカウントを Kubernetes Pod に接続する
Google Kubernetes Engine を使用する場合は、1 つの GKE クラスタで異なるアプリケーションを組み合わせて実行できます。アクセスする必要があるリソースと API は、アプリケーションごとに異なる可能性があります。
サービス アカウントを GKE クラスタまたはそのいずれかのノードプールに接続する場合、デフォルトでは、クラスタまたはノードプールで実行されているすべての Pod がサービス アカウントの権限を借用できます。異なるアプリケーション間で単一のサービス アカウントを共有すると、サービス アカウントに正しい権限セットを割り当てるのが難しくなります。
- すべてのアプリケーションが必要とするリソースへのアクセス権のみを付与すると、一部のアプリケーションが特定のリソースにアクセスできず、動作しないことがあります。
- 特定のアプリケーションが必要とするすべてのリソースへのアクセス権を付与すると、過剰なアクセス権を付与してしまう可能性があります。
GKE 環境内のリソースへのアクセスを管理する場合は Workload Identity を使用するのが良い方法です。
- GKE クラスタまたはノードプールにサービス アカウントを接続しないでください。
- Google API またはリソースへのアクセスが必要な Kubernetes Pod ごとに専用のサービス アカウントを作成します。
- Google API またはリソースにアクセスする必要がある Kubernetes Pod ごとに Kubernetes サービス アカウントを作成し、Pod に接続します。
- Workload Identity を使用して、サービス アカウントと対応する Kubernetes サービス アカウント間のマッピングを作成します。
Workload Identity 連携を使用して、オンプレミスまたは他のクラウド プロバイダで実行されているアプリケーションがサービス アカウントを使用できるようにする
オンプレミスまたは別のクラウド プロバイダでアプリケーションを実行する場合は、基盤となるコンピューティング リソースにサービス アカウントを接続することはできません。ただし、アプリケーションが次のような環境固有の認証情報にアクセスできる場合があります。
- AWS の一時的な認証情報
- Azure Active Directory アクセス トークン
- Active Directory フェデレーション サービス(AD FS)や KeyCloak などのオンプレミス ID プロバイダが発行する OpenID アクセス トークンまたは ID トークン
アプリケーションにこれらの認証情報のいずれかへのアクセス権が付与されており、Google Cloud APIs またはリソースへのアクセス権を必要とする場合は、Workload Identity 連携を使用します。
Workload Identity 連携を使用すると、Google Cloud プロジェクトと外部 ID プロバイダ間の一方向の信頼関係を作成できます。信頼を確立すると、アプリケーションは、信頼できる ID プロバイダによって発行された認証情報を使用して、次の 3 つのステップで構成されるプロセスに沿ってサービス アカウントの権限を借用できます。
- 信頼できる ID プロバイダから認証情報(OpenID Connect ID トークンなど)を取得します。
- Security Token Service(STS)API を使用して、有効期間の短い Google STS トークンと認証情報を交換します。
- STS トークンを使用して、IAM Service Account Credentials API に対する認証を行い、サービス アカウントには有効期間の短い Google アクセス トークンを取得します。
サポートされているクライアント ライブラリまたはコマンドライン ツールを使用して Google Cloud サービスにアクセスすると、この処理は自動的に行われます。
Workload Identity 連携を使用することで、外部環境に用意された認証メカニズムをアプリケーションが使用することを許可できます。これにより、サービス アカウント キーを保存して管理する必要がなくなります。
IAM Credentials API を使用して認証情報を仲介する
アプリケーションによっては、特定のタイミングや状況下でのみ特定のリソースへのアクセスが必要になることがあります。次に例を示します。
- アプリケーションの起動時に構成データにアクセスする必要があり、初期化後はアクセスする必要がなくなる場合があります。
- スーパーバイザー アプリケーションが、アクセス要件が異なるバックグラウンド ジョブを定期的に開始する場合があります。
このようなシナリオでは、1 つのサービス アカウントを使用してすべてのリソースにアクセス権を付与することは、最小権限の原則に反します。アプリケーションがいつでも必要以上に多くのリソースにアクセスできてしまう可能性があります。
アプリケーションのさまざまな部分が、必要なリソースのみにアクセスできるようにするには、IAM Credentials API を使用して有効期間の短い認証情報を仲介します。
- アプリケーションまたはユースケースごとに専用のサービス アカウントを作成し、必要なリソースにのみサービス アカウントへのアクセス権を付与します。
- スーパーバイザーとして機能する別のサービス アカウントを作成します。他のサービス アカウントにサービス アカウント トークン作成者のロールを付与し、これらのサービス アカウントに有効期間の短いアクセス トークンをリクエストできるようにします。
- アプリケーションを分割して、アプリケーションの 1 つの部分をトークン ブローカーとして機能させ、この部分のみがスーパーバイザー サービス アカウントを使用できるようにします。
- トークン ブローカーを使用して、有効期間の短いサービス アカウントをアプリケーションの別の部分に発行します。
有効期間の短い認証情報の作成方法については、サービス アカウントの有効期間が短い認証情報を作成するをご覧ください。
他に有効な方法がない場合にサービス アカウント キーを使用する
サービス アカウントの接続が不可能で、Workload Identity と Workload Identity 連携のいずれも使用できない状況が発生することもあります。たとえば、Google Cloud リソースにアクセスする必要があり、ID 連携をサポートしていないサードパーティ アプリケーションを使用するとします。
他の認証方法を使用できない場合は、アプリケーションのサービス アカウント キーを作成します。サービス アカウント キーを使用すると、ユーザーがユーザー名とパスワードを使用して認証する方法と同様に、サービス アカウントでアプリケーションの認証を行うことができます。サービス アカウント キーはシークレットの一つで、不正アクセスから保護する必要があります。
ユーザーの同意なしにサービスデータにアクセスするためにサービス アカウントを使用しない
アプリケーションで、機密性の高いユーザーデータへのアクセスが必要になる場合があります。このようなデータの例としては、ユーザーのメールボックスやカレンダー、Google ドライブに保存されたドキュメント、機密データを含む BigQuery データセットなどがあります。
ユーザー不在のアプリケーションで、インデックス登録やデータ損失防止(DLP)のスキャンなどのバックグラウンド タスクが実行される場合や、エンドユーザーが Google ID で認証されていない場合には、サービス アカウントを使用してユーザーデータにアクセスできます。アプリケーションがエンドユーザーに代わって動作するその他のシナリオでは、サービス アカウントを使用しないことをおすすめします。
ユーザーデータにアクセスする場合は、サービス アカウントではなく(プリンシパルの移行を実行している可能性あるため)、OAuth 同意フローを使用してエンドユーザーに同意を求めます。その後、アプリケーションがエンドユーザー ID で処理を行うことができるようにします。サービス アカウントの代わりに OAuth を使用すると、次のことができるようになります。
- ユーザーは、アプリケーションにアクセス権を付与しようとしているリソースを確認し、自身の同意または拒否を明示的に表明できます。
- ユーザーは随時、[アカウント情報] ページで同意を取り消すことができます。
- すべてのユーザーのデータに対して無制限のアクセス権を付与されたサービス アカウントは必要ありません。
アプリケーションにエンドユーザー認証情報の使用を許可することで、Google Cloud APIs に対する権限チェックを延期します。これにより、コーディング エラーが原因でユーザーがアクセスすることを許可しないようにする必要があるデータが、誤って公開されてしまうリスク(混乱した使節に関する問題)を低減できます。
開発中にサービス アカウントを使用しない
日常業務で Google Cloud CLI、gsutil
、terraform
などのツールを使用する場合があります。これらのツールの実行でサービス アカウントを使用しないでください。代わりに、gcloud auth login
(gcloud CLI と gsutil
の場合)または gcloud auth application-default login
(terraform
などのサードパーティ ツールの場合)を実行して、ツールがユーザーの認証情報を使用することを許可します。
Google Cloud にデプロイする予定のアプリケーションの開発とデバッグにも、同様の方法を使用できます。デプロイ後、アプリケーションでサービス アカウントが必要になる場合がありますが、ローカル ワークステーションで実行する場合は、個人用の認証情報を使用できます。
アプリケーションで個人の認証情報とサービス アカウント認証情報の両方をサポートするには、Cloud クライアント ライブラリとアプリケーションのデフォルト認証情報を使用します。
サービス アカウントを管理する
サービス アカウントは通常のユーザー アカウントとは異なり、使用方法だけでなく、管理方法も異なります。以降のセクションでは、サービス アカウントを管理する際のベスト プラクティスについて説明します。
ベスト プラクティス:
サービス アカウントをリソースとして管理する。単一目的のサービス アカウントを作成する。
命名とドキュメントの規則に従う。
未使用のサービス アカウントを特定して無効にする。
未使用のサービス アカウントを削除する前に、そのサービスを無効にする。
サービス アカウントをリソースとして管理する
通常のユーザー アカウントは組織の joiner-mover-leaver プロセスで管理されます。新しい従業員が入社すると、新しいユーザー アカウントが作成されます。従業員が異動した場合は、そのユーザー アカウントが更新されます。退職した場合、そのユーザー アカウントは一時停止または削除されます。
これに対し、サービス アカウントは特定の従業員に関連付けられていません。サービス アカウントはリソースとして考えてください。このアカウントは、特定の VM インスタンスやアプリケーションなど、別のリソースまたはその一部に属しています。
サービス アカウントを効果的に管理するには、サービス アカウントを単独では捉えないでください。関連付けられているリソースのコンテキストでサービス アカウントを考慮し、サービス アカウントと関連付けられているリソースを 1 つのユニットとして管理します。サービス アカウントと関連付けられているリソースに同じプロセス、同じライフサイクル、同じデュー デリジェンスを適用し、同じツールで管理します。
単一目的のサービス アカウントを作成する
複数のアプリケーションで単一のサービス アカウントを共有すると、サービス アカウントの管理が複雑になる場合があります。
- アプリケーションによってライフサイクルが異なる場合があります。アプリケーションが廃止された場合、サービス アカウントを廃止可能かどうか、必要かどうか判断できない場合があります。
- アプリケーションのアクセス要件は時間とともに変化する可能性があります。アプリケーションが同じサービス アカウントを使用している場合、サービス アカウントにアクセス権を付与する必要がある対象リソースの数が増加すると、全般的なリスクが増大する可能性があります。
- Cloud Audit Logs には、データの変更またはデータへのアクセスを行ったサービス アカウントの名前が含まれますが、サービス アカウントを使用したアプリケーションの名前は表示されません。複数のアプリケーションが 1 つのサービス アカウントを共有している場合は、アクティビティを適切なアプリケーションに対してトレースできない可能性があります。
特に、App Engine や Compute Engine など一部の Google Cloud サービスでは、プロジェクトに対する編集者のロール(roles/editor
)を持つデフォルトのサービス アカウントが作成されます。Compute Engine 仮想マシン(VM)インスタンスなどのリソースを作成するときにサービス アカウントを指定しないと、そのリソースではデフォルトのサービス アカウントが自動的に使用されます。デフォルトのサービス アカウントは簡単に使い始めることができますが、このアカウントを複数のアプリケーションで共有することは非常に危険です。
この問題を回避するには、次のような方法があります。
- デフォルトのサービス アカウントは使用せず、アプリケーションごとに専用のサービス アカウントを作成する。
- デフォルトのサービス アカウントへの自動的なロール付与を使用しない。
- サービス アカウントの使用状況を把握する Google のツールを使用する。これにより、使用状況をモニタリングし、サービス アカウントが複数のアプリケーションで共有されるのを防ぐことができます。
命名とドキュメントの規則に従う
サービスとアプリケーションまたはリソースの関連付けを追跡できるように、新しいサービス アカウントを作成する際は、命名規則に従います。
- アカウントの使用方法を表すプレフィックスをサービス アカウントのメールアドレスに追加します。例:
- VM インスタンスに接続されているサービス アカウントには
vm-
。 - Workload Identity で使用されるサービス アカウントには
wi-
。 - Workload Identity 連携で使用されるサービス アカウントには
wif-
。 - オンプレミス アプリケーションで使用されるサービス アカウントには
onprem-
。
- VM インスタンスに接続されているサービス アカウントには
- アプリケーションの名前をサービス アカウントのメールアドレスに埋め込みます。たとえば、VM が出張費用に関連するアプリケーションを実行している場合は、
vm-travelexpenses@
を使用します。 - 説明フィールドを使用して、担当者の連絡先、関連ドキュメントへのリンク、その他のメモを追加します。
サービス アカウントのメールアドレスに機密情報を埋め込まないでください。
未使用のサービス アカウントを特定して無効にする
サービス アカウントを使用しなくなった場合は、サービス アカウントを無効にします。未使用のサービス アカウントを無効にすると、攻撃者によるラテラル ムーブメントや権限昇格などの不正行為に悪用されるリスクを軽減できます。
VM インスタンスなどの特定のリソースに関連付けられている単一目的のサービス アカウントの場合は、関連付けられたリソースが無効化または削除されたときにすぐサービス アカウントを無効にします。
複数の目的で使用されているサービス アカウントや複数のリソースで共有されているサービス アカウントの場合、サービス アカウントが引き続き使用されているかどうかを特定できないことがあります。このような場合は、Activity Analyzer を使用して、サービス アカウントの最新の認証アクティビティを確認できます。
未使用のサービス アカウントを削除する前にサービスを無効にする
サービス アカウントを削除した後、同じ名前で新しいサービス アカウントを作成した場合、新しいサービス アカウントには別の ID が割り当てられます。そのため、元の IAM バインディングが新しいサービス アカウントに適用されることはありません。これに対して、サービス アカウントを無効にして再度有効にした場合は、すべての IAM バインディングがそのまま残ります。
IAM バインディングが誤って失われないようにするには、サービス アカウントを直ちに削除しないことをおすすめします。代わりに、不要になったサービス アカウントを無効にし、特定の時間が経過した後に削除します。
App Engine や Compute Engine のデフォルトのサービス アカウントなど、デフォルトのサービス アカウントは削除しないでください。これらのサービスは、それぞれの API を無効にして再度有効にしない限り再作成できません。このため、既存のデプロイが中断される可能性があります。デフォルトのサービス アカウントを使用しない場合は、これらのアカウントを無効にします。
サービス アカウントの権限を制限する
サービス アカウントはプリンシパルであり、通常のユーザー アカウントと同様にリソースへのアクセス権が付与されています。ただし、サービス アカウントは一般的なユーザーよりも多くのリソースにアクセスできます。また、アプリケーションに機能を追加すると、サービス アカウントのアクセス権も増えていく傾向があります。不要になったアクセス権の取り消しを忘れる可能性もあります。
ベスト プラクティス:
デフォルトのサービス アカウントへの自動的なロール付与を使用しない。サービス アカウントを VM インスタンスにアタッチする際にアクセス スコープに依存しない。
サービス アカウントにリソースへのアクセス権を付与する際にグループを使用しないようにする。
ドメイン全体の委任を使用しないようにする。
認証情報アクセス境界を使用してアクセス トークンの範囲を絞り込む。
ロールの推奨事項を使用して未使用の権限を特定する。
ラテラル ムーブメントの分析情報を使用してラテラル ムーブメントを制限する。
デフォルトのサービス アカウントへの自動的なロール付与を使用しない
一部の 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 のアクセス トークンは署名なしトークンです。つまり、トークンの使用は特定のアプリケーションに関連付けられていません。アプリケーションがアクセス トークンを別のアプリケーションに渡すと、そのアプリケーションはご利用のアプリケーションと同じようにトークンを使用できます。同様に、アクセス トークンが不正な行為者に漏洩した場合は、その不正な行為者がトークンを使用してアクセス権を取得できます。
アクセス トークンは署名なしトークンであるため、権限を付与されていないユーザーに漏洩したり、表示されたりしないように保護する必要があります。アクセス トークンがアクセス権を付与する対象リソースを制限することで、漏洩したアクセス トークンによって生じる可能性がある損害を低減できます。このプロセスは「ダウンスコーピング」と呼ばれます。
アクセス トークンを別のアプリケーションやご利用のアプリケーションの別のコンポーネントに渡す場合は常に、認証情報アクセス境界を使用してアクセス トークンのダウンスコーピングを行ってください。アクセス境界を設定して、トークンが必要以上のリソースに対するアクセス権を付与しないようにします。
ロールの推奨事項を使用して未使用の権限を特定する
アプリケーションを初めてデプロイする際に、アプリケーションに実際に必要となるロールと権限が不明な場合があります。その場合、アプリケーションのサービス アカウントに必要以上の権限を付与してしまう可能性があります。
同様に、アプリケーションのアクセス要件は時間とともに変化する可能性があり、最初に付与したロールと権限の一部が不要になる可能性もあります。
ロールの推奨事項を使用して、アプリケーションが実際に使用している権限と、未使用の可能性がある権限を特定します。影響を受けるリソースの許可ポリシーを調整して、アプリケーションに対して実際に必要とする範囲を超えるアクセス権が付与されないようにします。
ラテラル ムーブメントの分析情報を使用してラテラル ムーブメントを制限する
ラテラル ムーブメントとは、あるプロジェクトのサービス アカウントが別のプロジェクトのサービス アカウントの権限を借用することです。たとえば、プロジェクト A に作成されたサービス A が、プロジェクト B のサービス アカウントの権限を借用する場合を表します。
これらの権限により、複数のプロジェクトにまたがる権限借用の連鎖が発生し、リソースに対する意図しないアクセスがプリンシパルに許可される可能性があります。たとえば、プリンシパルはプロジェクト A のサービス アカウントの権限を借用し、そのサービス アカウントを使用してプロジェクト B のサービス アカウントの権限を借用できます。プロジェクト B のサービス アカウントに、組織内の他のプロジェクトの他のサービス アカウントの権限借用が許可されている場合、プリンシパルは、引き続きサービス アカウントの権限借用を使用してプロジェクトからプロジェクトに移動し、権限を取得します。
Recommender は、この問題の対処に役立つラテラル ムーブメントの分析情報を提供します。ラテラル ムーブメントの分析情報により、あるプロジェクトのサービス アカウントが別のプロジェクトのサービス アカウントの権限を借用することを許可するロールが特定されます。ラテラル ムーブメントの分析情報を直接表示し、管理する方法については、ラテラル ムーブメントの分析情報の管理をご覧ください。
一部のラテラル ムーブメントの分析情報は、ロールの推奨事項に関連付けられています。推奨事項を適用することで、プロジェクト間のラテラル ムーブメントを減らすことができます。方法については、推奨事項を確認して適用するをご覧ください。
権限昇格の脅威からの保護
ロールが付与されていない、またはリソースへのアクセス権がなく、ファイアウォール ルールに関連付けされていないサービス アカウントは、通常は存在価値が限定的です。リソースへのアクセス権をサービス アカウントに付与すると、サービス アカウントの価値が向上します。つまり、ユーザーに対するサービス アカウントの有用性が向上しますが、それと同時に、権限昇格攻撃での格好のターゲットにもなります。
例として、機密情報を格納する Cloud Storage バケットに対する完全アクセス権を付与されたサービス アカウントについて考えてみましょう。このような状況では、サービス アカウントは実質的に Cloud Storage バケット自体と同等の価値を有します。不正な行為者は、バケットに直接アクセスしようとするのではなく、サービス アカウントを支配しようと試みる可能性があります。その試行が成功した場合、不正な行為者はサービス アカウントになりすまして自身の権限を昇格させ、それによってバケット内の機密情報へのアクセス権を獲得できます。
通常、サービス アカウントに関連する権限昇格の手法は、次のカテゴリに分類されます。
直接的ななりすまし: ユーザーに誤って、サービス アカウントになりすます権限またはサービス アカウントのサービス アカウント キーを作成する権限が付与されてしまう可能性があります。サービス アカウントにユーザー自身の権限よりも高い権限が付与されていれば、ユーザーはその権限を使用して自身の権限を昇格し、本来はアクセスできないリソースへのアクセス権を取得できます。
間接的ななりすまし: ユーザーがサービス アカウントに直接なりすますことができない場合でも、CI / CD パイプライン、VM インスタンス、またはそのユーザーがアクセス可能な別の自動システムでサービス アカウントが使用されていれば、間接的になりすませる可能性が考えられます。その結果、システムでこのような操作が禁止されていない場合、ユーザーが本来許可されていない操作を実行する可能性があります。
たとえば、Compute Engine VM インスタンスへの SSH アクセス権を持つユーザーが、VM インスタンスに接続しているサービス アカウントの権限を間接的に使用して、そのサービス アカウントがアクセスできる Google Cloud リソースにアクセスする可能性があります。
許可ポリシー、グループ、またはカスタムロールの変更: 特権サービス アカウントへのアクセス権を付与されていないユーザーであっても、サービス アカウントの許可ポリシー、またはサービス アカウントに含まれている Google Cloud プロジェクトまたはフォルダの許可ポリシーを変更する権限が付与される可能性があります。ユーザーは、これらの許可ポリシーのいずれかを拡張して、サービス アカウントに(直接的または間接的に)なりすます権限を自身に付与できます。
以降のセクションでは、権限昇格の脅威からサービス アカウントを保護する際のベスト プラクティスについて説明します。
ベスト プラクティス:
ユーザーが自身よりも高い権限を付与されたサービス アカウントになりすませないようにする。ユーザーが自身よりも高い権限を付与されているサービス アカウントの許可ポリシーを変更できないようにする。
ユーザーがサービス アカウント キーを作成またはアップロードすることを許可しない。
Google Cloud プロジェクト レベルまたはフォルダレベルでサービス アカウントへのアクセス権を付与しない。
特権サービス アカウントが割り当てられているコンピューティング リソースに対しては、セキュリティ保護の程度が低いソースからコードを実行しない。
特権サービス アカウントが接続されている VM へのシェルアクセスを制限する。
メタデータ サーバーへのアクセスを選択したユーザーとプロセスに制限する。
ユーザーが自身よりも高い権限を付与されたサービス アカウントになりすませないようにする
ユーザーはサービス アカウントになりすますことで、そのサービス アカウントがアクセスできるリソースの一部またはすべてに対するアクセス権を取得できます。サービス アカウントにユーザーよりも広範なアクセス権がある場合、そのサービス アカウントには実質的にユーザーよりも高い権限が付与されています。
ユーザーに自身よりも高い権限を付与されたサービス アカウントになりすます権限を付与するということは、Linux では sudo
ツール、Windows ではプロセスの昇格を使用するのと同様に、ユーザーに対し、意図的に権限昇格を一時的に許可するということです。一時的な権限昇格が必要となる状況に対処する場合を除き、自身よりも高い権限を付与されたサービス アカウントになりすますことをユーザーに許可しないでください。
ユーザーがサービス アカウントになりすますことを可能にする権限には、次のものがあります。
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 ドメインのメンバーである場合、ユーザーが本来はサービス アカウントになりすますことが許可されないユーザーがログインできてしまいます。
OS Login を使用しない VM インスタンスでは特に、Identity-Aware Proxy によるシェルアクセス権の付与を検討してください。VM インスタンスに接続されたサービス アカウントになりすますことを許可される必要があるユーザーにのみ、IAP で保護されたトンネル ユーザーのロールを付与します。
メタデータ サーバーによるアクセスを選択したユーザーとプロセスに制限する
サービス アカウントを 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 にサービス アカウントによってアクティビティが実行されことが示されている場合、その情報だけで常に一連のイベントのすべてを再構築できるとは限りません。サービス アカウントがそのアクティビティを実行する発端となったユーザーまたはアプリケーションについても特定できる必要があります。
このセクションでは、否認防止に関する監査証跡を保持するうえで有用なベスト プラクティスについて説明します。
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 履歴が変更不可であり、不正な行為者がトレースを遡及的に隠蔽できないように構成します。
次のステップ
- サービス アカウント キーの管理に関するベスト プラクティスを理解する。
- デプロイ パイプラインでサービス アカウントを使用するためのベスト プラクティスを確認する。
- Workload Identity 連携の使用に関するベスト プラクティスを確認する。