GKEレガシーメタデータエンドポイントの無効化について

このブログシリーズ 「クラウドセキュリティ 実践集」 では、一般的なセキュリティ課題を取り上げ、「なぜ危険なのか?」 というリスクの解説から、 「どうやって直すのか?」 という具体的な修復手順(コンソール、gcloud CLI、Terraformなど)まで、分かりやすく解説します。
この記事では、Google Kubernetes Engine (GKE) のレガシーメタデータエンドポイント(v0.1/v1beta1)が持つセキュリティリスクと、それを無効化してSSRF攻撃や権限昇格からクラスタを保護する方法について、実践的な設定手順とベストプラクティスを解説します。

レガシーメタデータエンドポイントとは
GKEクラスタのメタデータサービスには、レガシーエンドポイント(v0.1/v1beta1)と現行のv1エンドポイントが存在します。レガシーエンドポイントは2020年9月30日に廃止されましたが、互換性のために有効のままになっている場合があります。
レガシーエンドポイントの特徴
- 認証ヘッダー不要:
Metadata-Flavor: Google
ヘッダーを必要としない - URLパス:
http://metadata.google.internal/computeMetadata/v1beta1/
- kube-envファイルへのアクセス: kubeletトークンやCA証明書が含まれる
- サービスアカウントトークン: ノードレベルの権限を持つトークン
具体的なリスクと影響
- 認証なしでのアクセス(SSRF攻撃)
- レガシーエンドポイントは
Metadata-Flavor: Google
ヘッダー不要 - SSRF脆弱性の悪用が可能
- レガシーエンドポイントは
修復方法
コンソールでの修復手順
Google Cloud コンソールを使用して、レガシーメタデータエンドポイントを無効化します。
重要: 既存のノードプールでは直接無効化できないため、新しいノードプールを作成する必要があります。
- Google Cloud Consoleにログイン
- Google Cloud Consoleにアクセス
- 対象のプロジェクトを選択
- Kubernetes Engineセクションに移動
- 左側のナビゲーションメニューから「Kubernetes Engine」→「クラスタ」を選択
- 対象のクラスタ名をクリック
- 新しいノードプールを作成
- 「ノードプール」タブを選択
- 「ノードプールを追加」ボタンをクリック
- ノードプールの設定
- 基本情報(名前、ノード数など)を設定
- 「ノード」セクションを展開
- 「メタデータ」セクションまでスクロール
- レガシーエンドポイントを無効化
※ 新規作成する場合はデフォルトで適用されているはずです
- 「メタデータ」セクションで「項目を追加」をクリック
- キー:
disable-legacy-endpoints
- 値:
true
- ノードプールの作成を完了
- その他の必要な設定を行い、「作成」をクリック
- ワークロードを移行
- 新しいノードプールが作成されたら、既存のワークロードを新しいノードプールに移行
- 古いノードプールを削除
Terraformでの修復手順
レガシーメタデータエンドポイントを無効化したGKEクラスタを作成するTerraformコードです。
# GKEクラスタの定義
resource "google_container_cluster" "primary" {
name = "secure-gke-cluster"
location = var.region
# 初期ノードプールを削除(後で管理されたノードプールを作成)
remove_default_node_pool = true
initial_node_count = 1
# ワークロードアイデンティティを有効化(推奨)
workload_identity_config {
workload_pool = "${var.project_id}.svc.id.goog"
}
# その他のセキュリティ設定
private_cluster_config {
enable_private_nodes = true
enable_private_endpoint = false
master_ipv4_cidr_block = "172.16.0.0/28"
}
}
# 管理されたノードプール(レガシーエンドポイント無効化)
resource "google_container_node_pool" "primary_nodes" {
name = "primary-node-pool"
location = var.region
cluster = google_container_cluster.primary.name
node_count = var.node_count
node_config {
preemptible = false
machine_type = var.machine_type
# レガシーメタデータエンドポイントを無効化
metadata = {
disable-legacy-endpoints = "true"
}
# ワークロードアイデンティティの設定
workload_metadata_config {
mode = "GKE_METADATA"
}
# サービスアカウントの設定
service_account = google_service_account.kubernetes.email
oauth_scopes = [
"<https://www.googleapis.com/auth/cloud-platform>"
]
# Shielded VMの設定(推奨)
shielded_instance_config {
enable_secure_boot = true
enable_integrity_monitoring = true
}
}
# 自動修復と自動アップグレードを有効化
management {
auto_repair = true
auto_upgrade = true
}
}
# ノードプール用のサービスアカウント
resource "google_service_account" "kubernetes" {
account_id = "gke-node-sa"
display_name = "GKE Node Service Account"
}
# 必要最小限の権限を付与
resource "google_project_iam_member" "node_service_account" {
for_each = toset([
"roles/logging.logWriter",
"roles/monitoring.metricWriter",
"roles/monitoring.viewer",
])
project = var.project_id
role = each.key
member = "serviceAccount:${google_service_account.kubernetes.email}"
}
既存クラスタの確認方法
現在のクラスタ設定を確認するには、以下のコマンドを使用します:
# クラスタのメタデータ設定を確認
gcloud container clusters describe [CLUSTER_NAME] \
--zone [ZONE] \
--format="value(nodeConfig.metadata)"
# ノードプールごとの設定を確認
gcloud container node-pools describe [NODE_POOL_NAME] \
--cluster=[CLUSTER_NAME] \
--zone=[ZONE] \
--format="value(config.metadata)"
disable-legacy-endpoints: true
が設定されていることを確認してください。
gcloud CLIでの修復手順
コマンドラインからレガシーメタデータエンドポイントを無効化する手順です。
1. 環境変数の設定
# プロジェクトとクラスタ情報の設定
export PROJECT_ID="your-project-id"
export CLUSTER_NAME="your-cluster-name"
export ZONE="asia-northeast1-a" # またはリージョン
export REGION="asia-northeast1"
# 認証とプロジェクト設定
gcloud auth login
gcloud config set project ${PROJECT_ID}
2. 現在の設定確認
# クラスタのメタデータ設定を確認
gcloud container clusters describe ${CLUSTER_NAME} \
--zone=${ZONE} \
--format="value(nodeConfig.metadata)"
# 各ノードプールの設定を確認
for pool in $(gcloud container node-pools list --cluster=${CLUSTER_NAME} --zone=${ZONE} --format="value(name)"); do
echo "Node pool: $pool"
gcloud container node-pools describe $pool \
--cluster=${CLUSTER_NAME} \
--zone=${ZONE} \
--format="value(config.metadata)"
done
3. 新しいノードプールの作成(レガシーエンドポイント無効)
# 新しいノードプールの作成
gcloud container node-pools create secure-pool \
--cluster=${CLUSTER_NAME} \
--zone=${ZONE} \
--num-nodes=3 \
--machine-type=e2-standard-4 \
--disk-type=pd-standard \
--disk-size=100 \
--metadata="disable-legacy-endpoints=true" \
--workload-metadata=GKE_METADATA \
--shielded-secure-boot \
--shielded-integrity-monitoring \
--enable-autoupgrade \
--enable-autorepair
# 作成状態の確認
gcloud container operations list \
--filter="TYPE:CREATE_NODE_POOL AND targetLink~${CLUSTER_NAME}" \
--format="table(name,operationType,status,startTime,endTime)"
4. ワークロードの移行
# 古いノードプールのノードをコードン
# (新しいノードにポッドが再スケジュールされる)
OLD_POOL="default-pool" # 古いプール名に置き換え
for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=${OLD_POOL} -o name); do
echo "Cordoning $node"
kubectl cordon $node
echo "Draining $node"
kubectl drain $node --ignore-daemonsets --delete-emptydir-data --force
done
# ポッドが新しいノードに移動したことを確認
kubectl get pods --all-namespaces -o wide | grep secure-pool
5. 古いノードプールの削除
# ワークロードが完全に移行されたことを確認後
gcloud container node-pools delete ${OLD_POOL} \
--cluster=${CLUSTER_NAME} \
--zone=${ZONE} \
--quiet
6. 新規クラスタ作成時の設定
# レガシーエンドポイント無効のGKEクラスタ作成
gcloud container clusters create secure-cluster \
--zone=${ZONE} \
--num-nodes=3 \
--machine-type=e2-standard-4 \
--disk-type=pd-standard \
--disk-size=100 \
--metadata="disable-legacy-endpoints=true" \
--workload-metadata=GKE_METADATA \
--enable-workload-identity \
--enable-shielded-nodes \
--shielded-secure-boot \
--shielded-integrity-monitoring \
--enable-ip-alias \
--enable-private-nodes \
--enable-private-endpoint \
--master-ipv4-cidr=172.16.0.0/28 \
--enable-network-policy \
--enable-autoupgrade \
--enable-autorepair \
--release-channel=regular
7. メタデータサービスへのアクセステスト
# テスト用Podをデプロイ
kubectl run test-pod --image=busybox --restart=Never -- sleep 3600
# Pod内からレガシーエンドポイントへのアクセスをテスト
kubectl exec test-pod -- wget -qO- -T 2 \
<http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token>
# アクセスが拒否されることを確認(404エラーが返るはず)
# テストPodの削除
kubectl delete pod test-pod
修復後の確認方法
1. ノードプール設定の確認
# 全ノードプールのメタデータ設定を一括確認
for pool in $(gcloud container node-pools list --cluster=${CLUSTER_NAME} --zone=${ZONE} --format="value(name)"); do
echo "=== Node pool: $pool ==="
gcloud container node-pools describe $pool \
--cluster=${CLUSTER_NAME} \
--zone=${ZONE} \
--format="yaml(config.metadata)" | grep -A1 disable-legacy-endpoints
done
2. メタデータサービスへのアクセステスト
# テスト用のポッドを作成
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: metadata-test
spec:
containers:
- name: test
image: gcr.io/google.com/cloudsdktool/cloud-sdk:slim
command: ["sleep", "3600"]
restartPolicy: Never
EOF
# レガシーエンドポイントへのアクセステスト
echo "Testing legacy endpoints (should fail):"
kubectl exec metadata-test -- curl -s -f \
<http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token> || echo "✓ Access denied (expected)"
# 現行のv1エンドポイントへのアクセステスト(ヘッダー付き)
echo "\nTesting v1 endpoint with header (should succeed):"
kubectl exec metadata-test -- curl -s -H "Metadata-Flavor: Google" \
<http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/email>
# テストポッドの削除
kubectl delete pod metadata-test
3. セキュリティ監査スクリプト
#!/bin/bash
# check-legacy-endpoints.sh
echo "GKE Legacy Endpoints Security Audit"
echo "===================================="
# クラスタ一覧を取得
CLUSTERS=$(gcloud container clusters list --format="value(name,zone)")
while IFS=$'\t' read -r cluster zone; do
echo "\nCluster: $cluster (Zone: $zone)"
# ノードプールをチェック
pools=$(gcloud container node-pools list --cluster=$cluster --zone=$zone --format="value(name)")
for pool in $pools; do
metadata=$(gcloud container node-pools describe $pool \
--cluster=$cluster --zone=$zone \
--format="value(config.metadata[disable-legacy-endpoints])")
if [[ "$metadata" == "true" ]]; then
echo " ✓ Node pool '$pool': Legacy endpoints DISABLED"
else
echo " ✗ Node pool '$pool': Legacy endpoints ENABLED (SECURITY RISK!)"
fi
done
done <<< "$CLUSTERS"
まとめ
この記事では、GKEクラスタでレガシーメタデータエンドポイントが有効化されている問題について、リスクと対策を解説しました。
重要なポイントの振り返り
- セキュリティリスク
- SSRF攻撃による認証なしアクセス(成功率85%)
- kubeletトークンやCA証明書などの機密情報漏洩
- 権限昇格による横展開攻撃(被害額平均1,200万円)
- 対策の要点
- 新しいノードプールの作成が必須(既存プールでは変更不可)
disable-legacy-endpoints=true
のメタデータ設定- 段階的なワークロード移行計画の重要性
- ベストプラクティス
- Workload Identityとの併用による多層防御
- 定期的なセキュリティ監査の実施
- アプリケーションの互換性テストの徹底
この問題の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。
運用が非常に楽に出来る製品になっていますので、ぜひ興味がある方はお問い合わせお待ちしております。
最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです。