GCPの「見えない防波堤」:VPC Service Controlsでデータ流出を物理的に封じ込める
クラウドの現場で「セキュリティ」という言葉が出ると、多くのエンジニアは真っ先にファイアウォールやIAMを思い浮かべるでしょう。しかし、それらはあくまで「門番」です。もし、権限を持った開発者が深夜の勢いで「本番DBのデータを自分の個人GCPプロジェクトへコピーしよう」としたら? あるいは、悪意あるコードがコンテナ内で実行され、外部へデータを持ち出そうとしたら?
従来のIAM制御だけでは、こうした「インサイダーのリスク」を完全に防ぐのは困難です。そこで登場するのが VPC Service Controls (VPC SC) です。これは、単なるネットワーク制限を超えた、GCPにおける「データ防波堤」とも呼べる存在です。
今日は、この強力なツールがいかにしてパケットとAPIリクエストを制御し、我々のインフラを守っているのか、泥臭い実務の視点から紐解いていきましょう。
—
VPC SCは「境界(Perimeter)」で何をしているのか
VPC SCの核心は、GCPの各サービス(Cloud Storage, BigQuery, Cloud SQLなど)を「サービス境界」で囲い込むことにあります。この境界の内側にあるリソースは、原則として外側の世界と通信できません。
ネットワークエンジニア的に言うと、「IAM権限があっても、境界外へのデータ転送はパケットレベル(実際にはAPI認証レベル)でDropされる」という状態を作ります。これは、TCP/IPのレイヤーを超えた、Googleのコントロールプレーンによる強制的なアクセス拒否です。
通信フローの裏側:何が起きているのか
通常、APIリクエスト(例えば gsutil cp)は以下のフローを辿ります。
1. 認証: IAMが「このユーザーに権限があるか」を確認。
2. 認可: VPC SCが「このリクエストは境界の内側から外側へデータを持ち出そうとしていないか」を評価。
3. 実行: 両方のチェックを通過して初めて、データが流れる。
VPC SCは、HTTPリクエストのヘッダーやコンテキスト(送信元IP、デバイスID、アクセス元ネットワーク)を精査し、ポリシーに違反していれば即座に 403 Forbidden を返します。ここでのポイントは、この制御がVPC内のVMだけでなく、開発者のローカルPCからのアクセスにも適用できる点です。
—
実践:VPC SCを構成するためのTerraform設定
VPC SCの導入で最も怖いのは「設定を間違えて本番環境のAPIが全滅すること」です。まずは dry-run モードで運用し、ログをじっくり眺めるのが鉄則です。
以下は、特定のプロジェクトをセキュリティ境界で囲むためのTerraformサンプルです。
# セキュリティ境界の定義
resource "google_access_context_manager_service_perimeter" "main_perimeter" {
parent = "accessPolicies/123456789" # 組織のアクセスポリシーID
name = "accessPolicies/123456789/servicePerimeters/prod_perimeter"
title = "production_perimeter"
status {
# 境界内に含めるプロジェクト
resources = ["projects/123456789012"]
# 制限対象とするAPIサービス(これらへのアクセスが監視される)
restricted_services = [
"storage.googleapis.com",
"bigquery.googleapis.com"
]
}
}
Tips: 疎通確認は「アクセス拒否ログ」が命
設定変更後、もしAPIが通らなくなったら迷わず Log Explorer を開きましょう。protoPayload.metadata.serviceName が accesscontextmanager.googleapis.com になっているログを探します。ここに、どのルールが原因で拒否されたのかが詳細に記されています。
—
APIクライアントからの拒否挙動を確認する
VPC SCによってブロックされると、クライアントにはどのような反応が返るのでしょうか。PythonでCloud Storageへアクセスする簡単なコードで見てみましょう。
from google.cloud import storage
from google.api_core import exceptions
def test_access():
client = storage.Client()
try:
# 境界外のバケット、または境界ルールに違反する操作を実行
bucket = client.get_bucket("forbidden-data-bucket")
print("アクセス成功")
except exceptions.Forbidden as e:
# ここでVPC SCによるブロックが検知される
print(f"VPC SCによるブロックが発生しました: {e}")
# 実行結果には、エラーコードと共に「VPC Service Controls」という明確なメッセージが含まれる
このエラーが返ってきた場合、それはネットワークの不調ではなく、境界による防御が正常に機能している証拠です。
—
現場のシニアSREからのアドバイス
VPC SCを運用する上で、いくつか「現場の知恵」を共有しておきます。
1. Ingress/Egressポリシーを舐めてはいけない:
初期設定では「外からは何にもアクセスできない」状態になります。特定の外部IPや、特定のサービスアカウントだけを通すには、ingress_policies や egress_policies を記述する必要があります。これらを疎かにすると、GitHub Actionsからのデプロイさえも止まります。
2. 「コンテキストアウェア」の強みを活かす:
特定のIPアドレス範囲(会社のVPNゲートウェイなど)からのみアクセスを許可する設定を組み合わせることで、万が一認証情報が流出しても、攻撃者は境界の外から手出しができなくなります。
3. 段階的移行(Dry Run)の徹底:
status セクションだけでなく spec セクションを使い、まずは「もしこの設定を適用したら何が拒否されるか」をシミュレーションしてください。本番環境でいきなりスイッチを入れるのは、地雷原をスキップで歩くようなものです。
最後に
VPC SCは、ただの「設定」ではなく、組織のインフラに対する「意思表示」です。「この境界を超えてデータは持ち出させない」という強い意志を、コードとして宣言する。これこそが、モダンなクラウドインフラにおけるエンジニアの守り方です。
皆さんのインフラが、強固な防波堤に守られ、かつ柔軟な開発スピードを維持できることを願っています。トラブルシューティングで行き詰まったら、まずは焦らず、Cloud Audit Logs に刻まれた拒否の理由を読み解くところから始めましょう。そこには必ず、答えが書いてあります。
コメント