概要
GKE はインスタンス メタデータを使用してノード VM を構成しますが、このメタデータの一部は潜在的に機密性が高く、クラスタ上で実行されているワークロードから保護する必要があります。
始める前に
作業を始める前に、次のことを確認してください。
- Google Kubernetes Engine API が有効になっていることを確認します。 Google Kubernetes Engine API の有効化
- Cloud SDK がインストール済みであることを確認します。
次のいずれかの方法で gcloud
のデフォルトの設定を指定します。
gcloud init
。デフォルトの設定全般を確認する場合に使用します。gcloud config
。プロジェクト ID、ゾーン、リージョンを個別に設定する場合に使用します。
gcloud init の使用
エラー One of [--zone, --region] must be supplied: Please specify
location
を受信した場合は、このセクションの内容を実施します。
-
gcloud init
を実行して、次の操作を行います。gcloud init
リモート サーバーで SSH を使用している場合は、
--console-only
フラグを指定して、コマンドがブラウザを起動しないようにします。gcloud init --console-only
- 手順に従って
gcloud
を承認し、Google Cloud アカウントを使用します。 - 新しい構成を作成するか、既存の構成を選択します。
- Google Cloud プロジェクトを選択します。
- デフォルトの Compute Engine ゾーンを選択します。
gcloud config の使用
- デフォルトのプロジェクト ID を設定します。
gcloud config set project project-id
- ゾーンクラスタを使用する場合は、デフォルトのコンピューティング ゾーンを設定します。
gcloud config set compute/zone compute-zone
- リージョン クラスタを使用する場合は、デフォルトのコンピューティング リージョンを設定します。
gcloud config set compute/region compute-region
gcloud
を最新バージョンに更新します。gcloud components update
ノードのサービス アカウントの構成
各ノードのサービス アカウント認証情報は引き続きワークロードに公開されるため、必要最小限の権限でサービス アカウントが構成されていることを確認してください。次に、このサービス アカウントをノードに接続して、攻撃者が Compute Engine API を使用してノード インスタンスに直接アクセスすることで GKE のメタデータ保護を回避することができないようにします。
compute.instances.get
権限、Compute インスタンス管理者の役割、またはその他の同様の権限を持つサービス アカウントを使用しないでください。これは、潜在的な攻撃者がこれらの権限を利用して、Compute Engine API 経由でインスタンス メタデータを取得可能になるためです。アクセス スコープではなく、サービス アカウント権限を使用して、ノード VM の権限を制限することをおすすめします。詳細については、Compute Engine のサービス アカウントのドキュメントをご覧ください。
ノードサービス アカウントを持っていない場合は、次のコマンドを使用してノードサービス アカウントを作成できます。
export NODE_SA_NAME=gke-node-sa gcloud iam service-accounts create $NODE_SA_NAME \ --display-name "Node Service Account" export NODE_SA_EMAIL=$(gcloud iam service-accounts list --format='value(email)' \ --filter='displayName:Node Service Account')
必要な役割と権限でサービス アカウントを構成するには、次のコマンドを実行します。PROJECT
は自分のプロジェクト ID です。
export PROJECT=$(gcloud config get-value project) gcloud projects add-iam-policy-binding $PROJECT \ --member serviceAccount:$NODE_SA_EMAIL \ --role roles/monitoring.metricWriter gcloud projects add-iam-policy-binding $PROJECT \ --member serviceAccount:$NODE_SA_EMAIL \ --role roles/monitoring.viewer gcloud projects add-iam-policy-binding $PROJECT \ --member serviceAccount:$NODE_SA_EMAIL \ --role roles/logging.logWriter
さらに、クラスタが Container Registry から非公開イメージを pull する場合は、storage.objectViewer
役割を追加します。
gcloud projects add-iam-policy-binding $PROJECT \ --member serviceAccount:$NODE_SA_EMAIL \ --role roles/storage.objectViewer
以前のメタデータ API の無効化と移行
Compute Engine のインスタンス メタデータ サーバーが公開する以前の v0.1 と v1beta1 エンドポイントは、メタデータ クエリヘッダーを適用しません。これは v1 API の機能であり、これにより潜在的な攻撃者はインスタンス メタデータを取得することがより困難になります。特に必要とされる場合を除き、こうした以前の API を無効にすることをおすすめします。
以下のセクションでは、次の方法について説明します。
廃止予定のエンドポイントにアクセスしているエンドポイントを特定する方法。ノードが廃止予定のエンドポイントを使用している場合は、これらのノードを移行する必要があります。
特定したノードに対して以前のメタデータ サーバーのエンドポイントを無効にして、新しいクラスタまたはノードプールを作成する方法。
以前のメタデータ サーバーのエンドポイントを使用してノードを特定する
check-legacy-endpoint-access ツール を使用すると、以前のメタデータ サーバーのエンドポイントを使用している Kubernetes Engine ノードを特定できます。このツールをお使いのクラスタに適用すると、5 分ごとに各ノードの v0.1 エンドポイントと v1beta1 エンドポイントへのリクエストをすべて記録します。このツールは、Kubernetes Engine で以前のエンドポイントの使用状況を確認し、デバッグと検証を行い場合にも使用できます。
check-legacy-endpoint-access ツールは次の手順で設定します。
各クラスタで、次のコマンドを実行します。
kubectl apply -f \ https://raw.githubusercontent.com/GoogleCloudPlatform\ /k8s-node-tools/master/check-legacy-endpoint-access/check-legacy-endpoint-access.yaml
収集されたログをクエリし、以前のエンドポイントの使用状況に関する情報を参照します。各クラスタでログをクエリするには、次のコマンドを実行します。
kubectl -n kube-system logs -l \ app=check-legacy-endpoint-access | grep "access count"
Stackdriver Logging で収集されたログを表示することもできます。
Cloud Console の [Cloud Logging] > [ログ](ログビューア)ページに移動します。
次のフィルタを適用します。
resource.type="container" resource.labels.namespace_id="kube-system" logName:"/check-legacy-endpoint-access"
ノードを特定したら、これらのエンドポイントを使用しているプロセスを特定する必要があります。これらのプロセスを特定する手順については、プロセスの特定をご覧ください。
v1 メタデータ サーバーのエンドポイントを使用するために、これらのプロセスを移行します。エンドポイントの Compute Engine ノードと差分を移行する方法については、v1 メタデータ サーバーのエンドポイントへの移行をご覧ください。
check-legacy-endpoint-access
DaemonSet を削除します。kubectl delete daemonset check-legacy-endpoint-access -n kube-system
以前のメタデータ API を無効にして新しいノードプールを作成する
サービス アカウントの作成後、gcloud
コマンドライン ツールで以前のメタデータ API を無効にして、新しいノードプールまたは(新しいクラスタのデフォルトのノードプール)を作成できます。
以前のメタデータ API を無効にして新しいノードプールを作成するには、--metadata disable-legacy-endpoints=true
フラグを使用します。例:
gcloud container node-pools create pool-name \ --service-account=$NODE_SA_EMAIL \ --metadata disable-legacy-endpoints=true
以前のメタデータ API を無効にした状態で新しいクラスタをデフォルトのノードプールに作成するには、同じフラグを使用します。例:
gcloud container clusters create cluster-name \ --service-account=$NODE_SA_EMAIL \ --metadata disable-legacy-endpoints=true
既存のクラスタを更新して以前のメタデータ API を無効にする
以前のメタデータ API を無効にした状態で新しいノードプールを作成した後に、既存のクラスタを更新してそのノードプールを使用するには、ノードプールの移行ガイドに従ってください。
以前のメタデータ API が無効であることを確認する
以前のインスタンス メタデータ API が無効になっていると、/0.1/
および /v1beta1/
メタデータ サーバー エンドポイントに対するリクエストで 403 Forbidden
が返されます。
以前のメタデータ API が無効になっていることを確認するには、ポッド内から curl
コマンドを実行します。
root@pod-name# curl -H 'Metadata-Flavor: Google' \ 'http://metadata.google.internal/computeMetadata/v1/instance/attributes/disable-legacy-endpoints' true root@pod-name# curl 'http://metadata.google.internal/computeMetadata/v1beta1/instance/id' ... Error 403 (Forbidden) ... Legacy metadata endpoint accessed: /computeMetadata/v1beta1/instance/id Legacy metadata endpoints are disabled. Please use the /v1/ endpoint. ...
メタデータ隠蔽
GKE のメタデータ隠蔽は、一部の潜在的に機密性が高いシステム メタデータを、クラスタ上で実行されているユーザー ワークロードから保護します。
Kubernetes v1.9.3 以降では、メタデータ隠蔽を有効にして、ユーザーのポッドがクラスタのノードの特定の VM メタデータ(Kubelet 認証情報や VM インスタンス情報など)にアクセスすることを防止できます。
具体的には、メタデータ隠蔽は、kube-env
(Kubelet 認証情報を含む)と VM のインスタンス ID トークンへのアクセスを保護します。
メタデータ隠蔽は、ユーザーポッド(HostNetwork
上で実行されていないポッド)からクラスタ メタデータ サーバーへのトラフィックをファイアウォール制御し、安全なクエリのみを許可します。ファイアウォールは、ユーザーポッドが、特権エスカレーション攻撃に Kubelet 認証情報を使用するのを防ぎます。また、インスタンス エスカレーション攻撃に VM ID を使用するのも防ぎます。
制限事項
- メタデータ隠蔽は、
kube-env
とノードのインスタンス ID トークンへのアクセスだけを保護します。 - メタデータ隠蔽は、ノードのサービス アカウントへのアクセスを制限しません。
- メタデータ隠蔽は、他の関連するインスタンス メタデータへのアクセスを制限しません。
- メタデータ隠蔽は、その他の以前のメタデータ API へのアクセスを制限しません。
メタデータ隠蔽を使用した新しいクラスタまたはノードプールの作成
サービス アカウントの作成後、gcloud
コマンドライン ツールを使用して新しいクラスタを作成し、メタデータ隠蔽を有効にできます。
メタデータ隠蔽が有効になっているクラスタを作成するには、シェルまたはターミナル ウィンドウで次のコマンドを実行します。
gcloud beta container clusters create cluster-name \
--workload-metadata-from-node=SECURE \
--service-account=$NODE_SA_EMAIL \
--metadata disable-legacy-endpoints=true \
[additional parameters and flags omitted]
ここで
- cluster-name は作成するクラスタの名前です。
--workload-metadata-from-node
は、SECURE
に設定されています。フラグをEXPOSED
またはUNSPECIFIED
に設定すると、メタデータ隠蔽が無効になります。
ID トークン メタデータがクラスタのワークロードから隠蔽されていることを確認する
メタデータを隠蔽するときは、ノードのインスタンス ID トークンを介して署名をリクエストできないようにする必要があります。リクエストが隠蔽されているメタデータをユーザーに明示的に通知することを確認するには、ポッド内から次の curl
コマンドを実行します。
root@pod-name# curl -H "Metadata-Flavor: Google" \ 'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://www.example.com' This metadata endpoint is concealed.