【実務・中級編】 サービスアカウントのなりすましと権限委譲 – Cloud Spanner

やあ、現場で戦うアーキテクト諸君。

今日は、Cloud Spannerを単なる「スケーラブルなDB」としてではなく、「Google Cloudのエコシステムにおける信頼の起点(Root of Trust)」としてどう扱うかという話をしよう。

テーマは「サービスアカウントのなりすまし(Impersonation)と権限委譲」だ。

多くのエンジニアが、サービスアカウントのJSONキーを環境変数に突っ込んで「接続できました!」と喜んでいる。だが、私のチームでそんなコードを書いたら、即座にリジェクトだ。なぜか? それは、静的な秘密鍵の運用が、分散システムのセキュリティにおける最大の単一障害点(SPOF)であり、現代のクラウドネイティブな設計思想から最も遠いからだ。

Spannerが他のサービス(BigQueryやGCS)と連携する際、内部で何が起きているのか。その「権限のバトンパス」の裏側を解剖する。

—

1. 「静的なキー」を捨て、なりすまし(Impersonation)を選べ

まず大前提だ。SpannerへのアクセスにJSONキーを使うのは、令和の設計ではない。我々が採用すべきは、Service Account Impersonationだ。

これは、呼び出し元のエンティティ(開発者の個人アカウントや、GKE上のWorkload Identity)が、ターゲットとなるサービスアカウントの「権限を一時的に借りる」仕組みだ。

なぜこれが重要か

SpannerのようなミッションクリティカルなDBでは、権限は「固定」されるべきではなく、「文脈(Context)に応じて動的に生成」されるべきだからだ。

悪い例: JSONキーを直接使う
export GOOGLE_APPLICATION_CREDENTIALS=”path/to/dangerous-key.json”

良い例: なりすましによる短寿命トークンの生成
gcloud auth print-access-token \
–impersonate-service-account=”spanner-reader@my-project.iam.gserviceaccount.com”

このコマンドの裏側では、IAMの `iam.serviceAccounts.getAccessToken` 権限が検証されている。この「検証プロセス」こそが、Spannerの堅牢なエコシステムの門番だ。

—

2. Spanner Service Agent:権限委譲の真の主役

Spannerは単体で動いているわけではない。例えば、Cloud StorageからデータをImportしたり、BigQueryからFederated Queryを投げたりする際、「Spanner自身が他のサービスにアクセスする」シーンが登場する。

ここで暗躍するのが Spanner Service Agent だ。

プロジェクトを有効にすると、`service-{PROJECT_NUMBER}@gcp-sa-spanner.iam.gserviceaccount.com` という形式のアカウントが自動生成される。これがSpannerという「システム」の化身だ。

権限委譲の内部シーケンス

SpannerがGCSからAvroファイルを読み込む際の、内部的な検証プロセスを想像してほしい。

1. リクエストの受信: ユーザーがSpanner APIに `Import` をリクエストする。
2. Identityの検証: Spannerは、リクエストを送ってきたユーザーが「Spannerを操作する権限」を持っているか確認する。
3. 権限の委譲(Delegation): ここが肝だ。Spannerはユーザーの権限をそのままGCSに持っていくのではない。Spanner Service Agent が GCSバケットに対して `storage.objects.get` を持っているかをIAMが検証する。

設計のポイント:
実務では、この Service Agent に対して「必要最小限(Least Privilege)」の権限を付与する設計を徹底せよ。GCS全体への `Storage Admin` ではなく、特定のバックアップ用バケットへの `Storage Object Viewer` だけを与える。これが極限の設計だ。

—

3. Federated Queries(外部データソース連携)の深淵

SpannerからBigQueryのデータを参照する「Federated Queries」を例に、高度な権限委譲を見てみよう。

Spannerで `EXTERNAL_QUERY` を実行する際、認証のホップが一段階増える。

— SpannerからBigQueryを叩く
SELECT FROM EXTERNAL_QUERY(
“projects/my-project/locations/us-central1/connections/my-bq-conn”,
“SELECT customer_id FROM customers WHERE status = ‘active'”
);

この時、Spannerは Connection Resource を介してBigQueryを呼び出す。内部的には以下の検証が走る。

1. Spanner内部で、指定された `connection` オブジェクトへのアクセス権があるか。
2. その `connection` に紐付けられたサービスアカウント(多くの場合、BigQuery Connection Service Agent)が、BigQueryのデータセットへの読み取り権限を持っているか。

パフォーマンス上の注意点:
この権限検証は、クエリ実行のオーバーヘッドになる。特に多数の小さなクエリを外部ソースに投げる設計は、IAMの検証コスト(レイテンシ)を直撃する。バルク処理として設計するのが定石だ。

—

4. 堅牢な設計パターン:短寿命トークンと条件付きIAM

私がリードするプロジェクトでは、以下の「黄金律」を適用している。

A. Workload Identityの徹底

GKE上でSpannerを動かすなら、K8sのServiceAccountとIAMのServiceAccountを1:1で紐付けろ。これにより、ポッド内のアプリケーションは「自分が誰か」を知ることなく、自動的にSpannerへの短寿命アクセストークンを手に入れる。

B. IAM Conditionsによる「時間」と「場所」の制約

「なりすまし」を許可する際も、無条件に許してはならない。

IAMポリシーの例

  • members:
  • “user:lead-engineer@example.com”

role: “roles/iam.serviceAccountTokenCreator”
condition:
title: “Working Hours Only”
expression: “request.time < timestamp('2023-12-31T23:59:59Z') && request.auth.claims.email_verified == true" このように、「なりすまし権限自体に有効期限を設ける」。これが、万が一端末が盗難に遭った際の爆発半径(Blast Radius)を最小化する。

—

5. アーキテクトとしての結論

Cloud Spannerの権限設計の本質は、「誰が」ではなく「どの文脈で、どの鍵(Token)が、いつまで有効か」を制御することにある。

サービスアカウントのなりすましと権限委譲を理解することは、単なるセキュリティ設定ではない。それは、複雑な分散システムにおいて、コンポーネント間の「信頼の連鎖」を設計することそのものだ。

JSONキーを捨てろ。
Service Agentに魂を込めろ。
そして、すべての権限に「理由(Condition)」を与えろ。

これが、世界最高峰のインフラを、世界最高峰のまま使いこなす唯一の道だ。

諸君の健闘を祈る。

コメント

タイトルとURLをコピーしました