GCP VPCサブネットで限定公開のGoogleアクセス(Private Google Access)を有効化する手順

このブログシリーズ 「クラウドセキュリティ 実践集」 では、一般的なセキュリティ課題を取り上げ、「なぜ危険なのか?」 というリスクの解説から、 「どうやって直すのか?」 という具体的な修復手順(コンソール、gcloud CLI、Terraformなど)まで、分かりやすく解説します。

この記事では、VPCサブネットの限定公開のGoogleアクセス(Private Google Access)有効化設定手順について、リスクと対策を解説します。

ポリシーの説明

限定公開のGoogleアクセス(Private Google Access)は、外部IPアドレスを持たないVMインスタンスが、Google APIやサービス(Cloud Storage、BigQuery、Cloud Loggingなど)にアクセスできるようにする機能です。この機能を有効にすることで、VMインスタンスはパブリックインターネットを経由せずに、Googleのプライベートネットワーク内でこれらのサービスと通信できます。すべてのサブネットでこの機能を有効化することで、内部通信の安全性を確保し、セキュリティリスクを最小化できます。

Private Google Accessが無効な場合、Google APIアクセスのためにVMに外部IPが必要となり、攻撃対象となるリスクが増大します。外部IPを持つインスタンスはFirewallルールの誤設定により外部からアクセス可能になる可能性があるため不必要に保持しないようにしましょう。

修復方法

コンソールでの修復手順

Google Cloud コンソールを使用して、すべてのサブネットで限定公開のGoogleアクセスを有効化します。

1. VPCネットワークページにアクセス

  • Google Cloud コンソールにログイン
  • ナビゲーションメニューから「VPCネットワーク」を選択

2. サブネットの一覧を確認

  • 「サブネット」タブをクリック
  • すべてのサブネットのリストが表示される

3. 各サブネットでPrivate Google Accessを有効化

  • 対象のサブネット名をクリック
  • 「編集」ボタンをクリック
  • 「プライベート Googleアクセス」のトグルスイッチを「オン」に設定
  • 「保存」をクリック

Terraformでの修復手順

限定公開のGoogleアクセスを有効にするTerraformコードと、主要な修正ポイントを説明します。

# ------------------ ① 既存サブネットの更新 ------------------
resource "google_compute_subnetwork" "private_subnet" {
  name          = "subnet-private-${var.environment}"
  network       = google_compute_network.vpc_network.id
  region        = var.region
  ip_cidr_range = var.subnet_cidr

  # 限定公開のGoogleアクセスを有効化
  private_ip_google_access = true

  # フローログも併せて有効化(推奨)
  log_config {
    aggregation_interval = "INTERVAL_5_SEC"
    flow_sampling        = 0.5
    metadata             = "INCLUDE_ALL_METADATA"
  }
}

# ------------------ ② 複数サブネットの一括設定 ------------------
# サブネット設定をマップで定義
variable "subnets" {
  type = map(object({
    region        = string
    ip_cidr_range = string
  }))
  default = {
    "tokyo" = {
      region        = "asia-northeast1"
      ip_cidr_range = "10.0.0.0/24"
    }
    "osaka" = {
      region        = "asia-northeast2"
      ip_cidr_range = "10.1.0.0/24"
    }
    "singapore" = {
      region        = "asia-southeast1"
      ip_cidr_range = "10.2.0.0/24"
    }
  }
}

# 動的にサブネットを作成
resource "google_compute_subnetwork" "subnets" {
  for_each = var.subnets

  name                     = "subnet-${each.key}"
  network                  = google_compute_network.vpc_network.id
  region                   = each.value.region
  ip_cidr_range            = each.value.ip_cidr_range

  # すべてのサブネットでPrivate Google Accessを有効化
  private_ip_google_access = true

  log_config {
    aggregation_interval = "INTERVAL_5_SEC"
    flow_sampling        = 0.5
    metadata             = "INCLUDE_ALL_METADATA"
  }
}

# ------------------ ③ Cloud NATとの併用設定 ------------------
# Private Google AccessとCloud NATを併用
resource "google_compute_router" "router" {
  name    = "router-${var.region}"
  network = google_compute_network.vpc_network.id
  region  = var.region
}

resource "google_compute_router_nat" "nat" {
  name                               = "nat-${var.region}"
  router                             = google_compute_router.router.name
  region                             = google_compute_router.router.region
  nat_ip_allocate_option             = "AUTO_ONLY"
  source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES"

  # Google APIへの通信はPrivate Google Access経由
  # 外部(非Google)サービスへの通信のみNAT経由
}

# ------------------ ④ Private Service Connect設定(より高度な制御が必要な場合) ------------------
# より高度な制御が必要な場合はPrivate Service Connectを使用
resource "google_compute_global_address" "psc_address" {
  name          = "psc-google-apis"
  purpose       = "PRIVATE_SERVICE_CONNECT"
  address_type  = "INTERNAL"
  prefix_length = 24
  network       = google_compute_network.vpc_network.id
}

resource "google_compute_global_forwarding_rule" "psc_forwarding_rule" {
  name                  = "psc-google-apis-fr"
  target                = "all-apis"
  network               = google_compute_network.vpc_network.id
  ip_address            = google_compute_global_address.psc_address.id
  load_balancing_scheme = ""
}

# ------------------ ⑤ ファイアウォールルール ------------------
# Google APIへの通信を許可(必要に応じて)
resource "google_compute_firewall" "allow_google_apis" {
  name    = "allow-google-apis"
  network = google_compute_network.vpc_network.name

  allow {
    protocol = "tcp"
    ports    = ["443"]
  }

  direction = "EGRESS"
  destination_ranges = [
    "199.36.153.8/30",   # restricted.googleapis.com
    "199.36.153.4/30",   # private.googleapis.com
  ]

  # タグベースの適用(推奨)
  target_tags = ["allow-google-apis"]
}

# ------------------ ⑥ 内部DNSゾーン設定 ------------------
# Google APIのプライベートアクセス用DNS設定
resource "google_dns_managed_zone" "googleapis" {
  name        = "googleapis-private"
  dns_name    = "googleapis.com."
  description = "Private zone for Google APIs"

  visibility = "private"

  private_visibility_config {
    networks {
      network_url = google_compute_network.vpc_network.id
    }
  }
}

resource "google_dns_record_set" "googleapis_a" {
  name         = "*.googleapis.com."
  managed_zone = google_dns_managed_zone.googleapis.name
  type         = "A"
  ttl          = 300
  rrdatas      = ["199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11"]
}

# ------------------ ⑦ 検証用のVMインスタンス ------------------
resource "google_compute_instance" "test_vm" {
  name         = "pga-test-vm"
  machine_type = "e2-micro"
  zone         = "${var.region}-a"

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-11"
    }
  }

  # 外部IPを持たない設定
  network_interface {
    subnetwork = google_compute_subnetwork.private_subnet.id
    # access_config ブロックを記述しないことで外部IPなし
  }

  # Google APIアクセス用のサービスアカウント
  service_account {
    scopes = ["cloud-platform"]
  }

  metadata_startup_script = <<-EOF
    #!/bin/bash
    # Private Google Access の動作確認
    echo "Testing Private Google Access..."
    gsutil ls
    bq ls
    gcloud logging read "resource.type=gce_instance" --limit=1
  EOF
}

 

Terraform Moduleを使用した実装例

# Google公式のTerraform Moduleを使用
module "vpc" {
  source  = "terraform-google-modules/network/google"
  version = "~> 9.0"

  project_id   = var.project_id
  network_name = "secure-vpc"

  subnets = [
    {
      subnet_name           = "subnet-prod-tokyo"
      subnet_ip             = "10.0.0.0/24"
      subnet_region         = "asia-northeast1"
      subnet_private_access = "true"  # Private Google Accessを有効化
      subnet_flow_logs      = "true"
    },
    {
      subnet_name           = "subnet-prod-osaka"
      subnet_ip             = "10.1.0.0/24"
      subnet_region         = "asia-northeast2"
      subnet_private_access = "true"  # Private Google Accessを有効化
      subnet_flow_logs      = "true"
    }
  ]
}

# ------------------ ⑧ 組織ポリシーによる強制 ------------------
# 組織レベルでPrivate Google Accessを強制(推奨)
resource "google_organization_policy" "enforce_private_google_access" {
  org_id     = var.organization_id
  constraint = "compute.requirePrivateGoogleAccess"

  boolean_policy {
    enforced = true
  }
}

# プロジェクトレベルでの適用も可能
resource "google_project_organization_policy" "enforce_private_google_access" {
  project    = var.project_id
  constraint = "compute.requirePrivateGoogleAccess"

  boolean_policy {
    enforced = true
  }
}

まとめ

この記事では、VPCサブネットの限定公開のGoogleアクセス(Private Google Access)有効化設定手順について、リスクと対策を解説しました。

Private Google Accessの有効化は、セキュリティの強化だけでなく、コスト最適化にも貢献する重要な設定です。特に以下のポイントに注意してください:

  • 全てのサブネットでPrivate Google Accessを有効化
  • 組織ポリシーで新規サブネットの自動有効化を設定
  • restricted.googleapis.comの使用も検討(VPCサービスコントロールとの併用時)

この問題の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。 運用が非常に楽に出来る製品になっていますので、ぜひ興味がある方はお問い合わせお待ちしております。 最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです。

参考情報

Google Cloud公式ドキュメント

この記事をシェアする

クラウドセキュリティ対策実践集一覧へ戻る

貴社の利用状況に合わせた見積もりを作成します。

料金プランを詳しく見る