Shielded GKE Nodesでのノードの保護について

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

この記事では、GKEクラスタでShielded GKE Nodesを使用し、ノードの認証と保護を強化する方法について解説します。

ポリシーの説明

Shielded GKE Nodesは、Google CloudのShielded VM技術をGKEノードに適用したセキュリティ機能です。これにより、ノードレベルでの高度なセキュリティ保護が実現され、ブートレベルおよびカーネルレベルの攻撃から保護されます。

Shielded GKE Nodesの3つの主要コンポーネント:

  1. Secure Boot(セキュアブート)
    • UEFI署名検証によるブートプロセスの保護
    • 信頼されたソフトウェアのみの実行を保証
  2. Virtual Trusted Platform Module (vTPM)
    • ハードウェアベースの暗号化キー管理
    • measured bootによるブート整合性の証明
    • シークレットの安全な保存
  3. Integrity Monitoring(整合性監視)
    • ブート時の測定値をCloud Loggingに記録
    • ベースラインからの逸脱を検出
    • リアルタイムでの改ざん検知

これらの機能を組み合わせることで、ノードの完全性を継続的に検証し、高度な脅威から保護することができます。

修復方法

コンソールでの修復手順

既存のGKEクラスタでShielded GKE Nodesを有効化するには、新しいノードプールを作成する必要があります:

  1. Google Cloud Consoleにアクセスし、対象のプロジェクトを選択します。
  2. Kubernetes Engine > クラスタに移動し、対象のクラスタを選択します。
  1. ノードプールタブをクリックします。
  2. ノードプールを追加をクリックします。
  1. ノードプールの詳細で基本設定を行います:
    • 名前: shielded-node-pool
    • ノード数: 要件に応じて設定
  2. ノードセクションで、セキュリティまで下にスクロールします。
  3. Shielded optionsで以下を有効にします
    • 整合性モニタリングを有効にする
    • セキュアブートを有効にする
  4. その他の必要な設定(マシンタイプ、ディスクサイズなど)を構成します。
  5. 作成をクリックして新しいノードプールを作成します。
  6. ワークロードを新しいノードプールに移行し、古いノードプールを削除します。

Terraformでの修復手順

Terraformを使用してShielded GKE Nodesを有効にしたクラスタを構築する完全な例:

# プロバイダー設定
terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

# GKEクラスタの定義
resource "google_container_cluster" "secure_cluster" {
  name     = var.cluster_name
  location = var.region

  # デフォルトノードプールを削除(カスタムノードプールを使用)
  initial_node_count       = 1
  remove_default_node_pool = true

  # ネットワーク設定
  network    = google_compute_network.vpc.name
  subnetwork = google_compute_subnetwork.subnet.name

  # プライベートクラスタ設定
  private_cluster_config {
    enable_private_nodes    = true
    enable_private_endpoint = false
    master_ipv4_cidr_block  = "172.16.0.0/28"
  }

  # IPアロケーションポリシー
  ip_allocation_policy {
    cluster_secondary_range_name  = "pods"
    services_secondary_range_name = "services"
  }

  # マスター認証設定
  master_auth {
    client_certificate_config {
      issue_client_certificate = false
    }
  }

  # ワークロードアイデンティティ
  workload_identity_config {
    workload_pool = "${var.project_id}.svc.id.goog"
  }

  # アドオン設定
  addons_config {
    network_policy_config {
      disabled = false
    }

    gce_persistent_disk_csi_driver_config {
      enabled = true
    }
  }

  # セキュリティ設定
  binary_authorization {
    evaluation_mode = "PROJECT_SINGLETON_POLICY_ENFORCE"
  }

  # メンテナンスポリシー
  maintenance_policy {
    daily_maintenance_window {
      start_time = "03:00"
    }
  }
}

# Shielded GKE Nodesを有効にしたノードプール
resource "google_container_node_pool" "shielded_nodes" {
  name       = "${var.cluster_name}-shielded-pool"
  location   = var.region
  cluster    = google_container_cluster.secure_cluster.name

  # ノード数とオートスケーリング
  initial_node_count = var.min_node_count

  autoscaling {
    min_node_count = var.min_node_count
    max_node_count = var.max_node_count
  }

  # ノード管理設定
  management {
    auto_repair  = true
    auto_upgrade = true
  }

  # アップグレード設定
  upgrade_settings {
    max_surge       = 1
    max_unavailable = 0
  }

  # ノード設定
  node_config {
    preemptible  = false
    machine_type = var.machine_type

    # Shielded GKE Nodes設定(すべて有効化)
    shielded_instance_config {
      enable_secure_boot          = true  # Secure Boot有効化
      enable_integrity_monitoring = true  # 整合性監視有効化
    }

    # Confidential Nodes(オプション:より高度な保護)
    # confidential_nodes {
    #   enabled = true
    # }

    # ディスク設定
    disk_size_gb = 100
    disk_type    = "pd-ssd"

    # 暗号化設定(Customer-Managed Encryption Keys)
    boot_disk_kms_key = var.kms_key_id

    # GCEメタデータ設定
    metadata = {
      disable-legacy-endpoints = "true"
      block-project-ssh-keys   = "true"
    }

    # ワークロードメタデータ設定
    workload_metadata_config {
      mode = "GKE_METADATA"
    }

    # サービスアカウント
    service_account = google_service_account.gke_node_sa.email
    oauth_scopes = [
      "<https://www.googleapis.com/auth/cloud-platform>"
    ]

    # ラベルとタグ
    labels = {
      environment    = var.environment
      shielded_nodes = "enabled"
      secure_boot    = "enabled"
      integrity_mon  = "enabled"
    }

    tags = ["gke-node", "shielded"]
  }

  # ライフサイクル設定
  lifecycle {
    create_before_destroy = true
  }
}

# ノード用サービスアカウント
resource "google_service_account" "gke_node_sa" {
  account_id   = "${var.cluster_name}-node-sa"
  display_name = "GKE Node Service Account for Shielded Nodes"
  description  = "Service account for GKE nodes with minimal permissions"
}

# 必要最小限のIAMロール
resource "google_project_iam_member" "node_sa_log_writer" {
  project = var.project_id
  role    = "roles/logging.logWriter"
  member  = "serviceAccount:${google_service_account.gke_node_sa.email}"
}

resource "google_project_iam_member" "node_sa_metric_writer" {
  project = var.project_id
  role    = "roles/monitoring.metricWriter"
  member  = "serviceAccount:${google_service_account.gke_node_sa.email}"
}

resource "google_project_iam_member" "node_sa_monitoring_viewer" {
  project = var.project_id
  role    = "roles/monitoring.viewer"
  member  = "serviceAccount:${google_service_account.gke_node_sa.email}"
}

# VPCネットワーク
resource "google_compute_network" "vpc" {
  name                    = "${var.cluster_name}-vpc"
  auto_create_subnetworks = false
}

# サブネット
resource "google_compute_subnetwork" "subnet" {
  name          = "${var.cluster_name}-subnet"
  ip_cidr_range = "10.0.0.0/24"
  region        = var.region
  network       = google_compute_network.vpc.id

  secondary_ip_range {
    range_name    = "pods"
    ip_cidr_range = "10.1.0.0/16"
  }

  secondary_ip_range {
    range_name    = "services"
    ip_cidr_range = "10.2.0.0/20"
  }

  private_ip_google_access = true
}

# Cloud NATの設定(プライベートノード用)
resource "google_compute_router" "router" {
  name    = "${var.cluster_name}-router"
  region  = var.region
  network = google_compute_network.vpc.id
}

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

 

ベストプラクティス

  1. 完全なShielded VM保護の実装
    • Secure Boot、vTPM、Integrity Monitoringをすべて有効化
    • Confidential Nodesの検討(機密性の高いワークロード用)
    • Binary Authorizationとの組み合わせ
  2. 継続的な監視とアラート
    # 整合性監視アラートの設定
    gcloud alpha monitoring policies create \
      --notification-channels=[CHANNEL_ID] \
      --display-name="Shielded VM Integrity Failure" \
      --condition-display-name="Boot integrity check failed" \
      --condition-expression='
        resource.type="gce_instance"
        AND jsonPayload.earlyBootReportEvent.policyEvaluationPassed=false'
    

     

  3. 定期的なコンプライアンス確認
    • Security Command Centerでの脆弱性スキャン
    • Cloud Asset Inventoryでの設定確認
    • 定期的な設定ドリフトの検出
  4. インシデント対応の準備
    • 整合性違反時の対応手順の文書化
    • 自動修復フローの実装
    • フォレンジック調査の準備

最後に

この記事では、GKEクラスタでShielded GKE Nodesを使用し、ハードウェアレベルでのセキュリティ保護を実装する方法について解説しました。

Shielded GKE Nodesは、Secure Boot、vTPM、Integrity Monitoringの3つのコンポーネントを統合し、ファームウェアレベルからカーネルレベルまでの包括的な保護を提供します。高度な持続的脅威(APT)やルートキットからの保護には不可欠です。

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

参考情報

この記事をシェアする

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

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

料金プランを詳しく見る