チェックポイント
Create a simple GKE cluster
/ 20
Deploy a pod that mounts the host filesystem
/ 20
Deploy a second node pool
/ 20
Deploy PodSecurityPolicy objects
/ 20
Deploy a blocked pod that mounts the host filesystem
/ 20
デフォルトの GKE クラスタ構成の強化
GSP496
概要
このラボでは、デフォルトの GKE クラスタ構成におけるセキュリティ上の懸念事項と、それに対応する強化策について説明します。強化策では、Pod のエスケープとクラスタの権限昇格を発生させる複数の方法を防止します。具体的には、次のようなシナリオにおける攻撃方法です。
- 外部に接続された Pod 内のアプリケーションに、サーバー側のリクエスト フォージェリ(SSRF)攻撃を可能にする不具合がある場合。
- Pod 内のコンテナが完全に不正使用され、リモート コマンド実行(RCE)が可能になっている場合。
- 悪意のある内部ユーザーがいる場合や、特定の名前空間で Pod の作成や更新を行える内部ユーザーの認証情報セットを攻撃者が不正使用する場合。
このラボは、デフォルトの GKE クラスタ構成を強化する方法について理解を深められるように、GKE Helmsman のエンジニアによって作成されました。
このラボのサンプルコードは現状のまま提供されるもので、いかなる保証もありません
目標
このラボを完了すると、GKE Instance Metadata を保護し、環境に適した PodSecurityPolicy ポリシーを定義する必要性を理解できます。
このチュートリアルでは、次のことを行います。
- デフォルトの設定を使用して小規模な GKE クラスタを作成する。
- 悪意のある内部ユーザーの視点で、Pod のエスケープとクラスタの権限昇格を行う一般的な方法を検証する。
- これらの問題に対応できるよう GKE クラスタを強化する。
- これらのアクションを実行できなくなったことをクラスタで検証する。
設定と要件
[ラボを開始] ボタンをクリックする前に
こちらの手順をお読みください。ラボの時間は記録されており、一時停止することはできません。[ラボを開始] をクリックするとスタートするタイマーは、Google Cloud のリソースを利用できる時間を示しています。
このハンズオンラボでは、シミュレーションやデモ環境ではなく、実際のクラウド環境を使ってご自身でラボのアクティビティを行うことができます。そのため、ラボの受講中に Google Cloud にログインおよびアクセスするための、新しい一時的な認証情報が提供されます。
このラボを完了するためには、下記が必要です。
- 標準的なインターネット ブラウザ(Chrome を推奨)
- ラボを完了するために十分な時間を確保してください。ラボをいったん開始すると一時停止することはできません。
ラボを開始して Google Cloud コンソールにログインする方法
-
[ラボを開始] ボタンをクリックします。ラボの料金をお支払いいただく必要がある場合は、表示されるポップアップでお支払い方法を選択してください。 左側の [ラボの詳細] パネルには、以下が表示されます。
- [Google Cloud コンソールを開く] ボタン
- 残り時間
- このラボで使用する必要がある一時的な認証情報
- このラボを行うために必要なその他の情報(ある場合)
-
[Google Cloud コンソールを開く] をクリックします(Chrome ブラウザを使用している場合は、右クリックして [シークレット ウィンドウでリンクを開く] を選択します)。
ラボでリソースが起動し、別のタブで [ログイン] ページが表示されます。
ヒント: タブをそれぞれ別のウィンドウで開き、並べて表示しておきましょう。
注: [アカウントの選択] ダイアログが表示されたら、[別のアカウントを使用] をクリックします。 -
必要に応じて、下のユーザー名をコピーして、[ログイン] ダイアログに貼り付けます。
{{{user_0.username | "Username"}}} [ラボの詳細] パネルでも [ユーザー名] を確認できます。
-
[次へ] をクリックします。
-
以下のパスワードをコピーして、[ようこそ] ダイアログに貼り付けます。
{{{user_0.password | "Password"}}} [ラボの詳細] パネルでも [パスワード] を確認できます。
-
[次へ] をクリックします。
重要: ラボで提供された認証情報を使用する必要があります。Google Cloud アカウントの認証情報は使用しないでください。 注: このラボでご自身の Google Cloud アカウントを使用すると、追加料金が発生する場合があります。 -
その後次のように進みます。
- 利用規約に同意してください。
- 一時的なアカウントなので、復元オプションや 2 要素認証プロセスは設定しないでください。
- 無料トライアルには登録しないでください。
その後、このタブで Google Cloud コンソールが開きます。
Cloud Shell をアクティブにする
Cloud Shell は、開発ツールと一緒に読み込まれる仮想マシンです。5 GB の永続ホーム ディレクトリが用意されており、Google Cloud で稼働します。Cloud Shell を使用すると、コマンドラインで Google Cloud リソースにアクセスできます。
- Google Cloud コンソールの上部にある「Cloud Shell をアクティブにする」アイコン をクリックします。
接続した時点で認証が完了しており、プロジェクトに各自の PROJECT_ID が設定されます。出力には、このセッションの PROJECT_ID を宣言する次の行が含まれています。
gcloud
は Google Cloud のコマンドライン ツールです。このツールは、Cloud Shell にプリインストールされており、タブ補完がサポートされています。
- (省略可)次のコマンドを使用すると、有効なアカウント名を一覧表示できます。
-
[承認] をクリックします。
-
出力は次のようになります。
出力:
- (省略可)次のコマンドを使用すると、プロジェクト ID を一覧表示できます。
出力:
出力例:
gcloud
ドキュメントの全文については、gcloud CLI の概要ガイドをご覧ください。
タスク 1. シンプルな GKE クラスタを作成する
- MY_ZONE という環境変数にゾーンを設定します。このラボでは「
」を使用しますが、必要に応じてゾーンを選択することもできます。
- 次のコマンドを実行して、Kubernetes Engine が管理する
simplecluster
という Kubernetes クラスタを起動し、ノードが 2 つ実行されるように構成します。
Kubernetes Engine によって仮想マシンがプロビジョニングされるため、クラスタの作成には数分かかります。新しいバージョンで利用できる機能についての警告が表示されたら、このラボでは無視してかまいません。
- クラスタが作成されたら、
kubectl version
コマンドを使用して、インストール済みの Kubernetes のバージョンを確認します。
kubectl
は、gcloud container clusters create
コマンドで自動的に認証されました。
- Google Cloud コンソールで実行中のノードを表示します。ナビゲーション メニューで、[Compute Engine] > [VM インスタンス] をクリックします。
Kubernetes クラスタを使用する準備が整いました。
[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。
タスク 2. Google Cloud SDK Pod を実行する
- Cloud Shell のプロンプトで、Google Cloud SDK コンテナの単一のインスタンスを起動します。
完了するまでに数分かかります。
- これで、Pod のコンテナ内で bash シェルを使用できるようになりました。
コンテナが起動してコマンド プロンプトが表示されるまでに数秒かかる場合があります。コマンド プロンプトが表示されない場合は、Enter キーを押してください。
Compute Metadata エンドポイントを確認する
- 次のコマンドを実行して、
v1
Compute Metadata エンドポイントにアクセスします。
出力は以下のようになります。
/computeMetadata/v1/instance/name
from this server. Missing Metadata-Flavor:Google header.
...snip...
カスタム HTTP ヘッダーが必要であることを示すエラーがどのように返されるか確認します。
- 次のコマンドを実行してカスタム ヘッダーを追加し、この Pod を実行している Compute Engine インスタンスの名前を取得します。
出力は以下のようになります。
このシェルを、次のステップで利用できる Pod 内に残しておきます。
- 誤って Pod を閉じた場合は、次のコマンドで再実行してください。
GKE ノードのブートストラップ用認証情報を確認する
- 同じ Pod シェル内から次のコマンドを実行して、基盤となる Compute Engine インスタンスに関連付けられた属性のリストを取得します。必ず最後にスラッシュを含めてください。
このリストで最も機密性が高いデータは kube-env
であると考えられます。kubelet
がノードを GKE クラスタに関連付ける際に初期の認証情報として使用する複数の変数が含まれています。CA_CERT
、KUBELET_CERT
、KUBELET_KEY
の変数にこの情報が含まれているため、クラスタ管理者以外には機密と見なされます。
- 機密の可能性がある変数やデータを表示するには、次のコマンドを実行します。
次のいずれかの状況で懸念事項が発生する可能性があります。
- Pod アプリケーションで SSRF が発生する可能性がある不具合
- Pod で RCE が発生する可能性がある、アプリケーションまたはライブラリの不具合
- Pod の作成や Pod に対する操作を実行できる内部ユーザー
Compute Metadata エンドポイント経由で、kubelet
の機密のブートストラップ用認証情報が不正使用されたり流出したりする可能性が高くなります。kubelet
の認証情報を利用すると、特定の環境で権限を cluster-admin
に昇格させることができます。そのため、データ、アプリケーション、基盤となるノードへのアクセス権限など、GKE Cluster を完全に制御できます。
このノードプールのサービス アカウントに割り当てられた権限を利用する
デフォルトでは、Compute API が有効になっている Google Cloud プロジェクトにはデフォルトのサービス アカウントがあります。プロジェクト内で NNNNNNNNNN-compute@developer.gserviceaccount.com
の形式になっており、編集者
のロールが割り当てられています。また、デフォルトでは、サービス アカウントを指定せずに作成された GKE クラスタは、デフォルトの Compute のサービス アカウントを利用し、そのサービス アカウントをすべてのワーカーノードに関連付けます。
- 次の
curl
コマンドを実行して、基盤となる Compute Engine インスタンスに関連付けられたサービス アカウントに紐付いている OAuth スコープのリストを取得します。
(出力)
認証スコープとサービス アカウントの権限の組み合わせによって、このノードのアプリケーションがアクセスできる対象が決まります。ほとんどの GKE クラスタで上記のリストが必要最小限のスコープとなりますが、ユースケースによっては追加のスコープが必要になる場合があります。
警告: クラスタ作成中に、認証スコープに「https://www.googleapis.com/auth/cloud-platform」が含まれるよう構成した場合、任意の Google Cloud API がスコープ内と見なされ、サービス アカウントに割り当てられた IAM 権限のみがアクセス権を決定します。
また、編集者
のデフォルト IAM ロールを使用するデフォルトのサービス アカウントが使用中の場合、GKE クラスタがデプロイされていれば、このノードプールの任意の Pod に Google Cloud プロジェクトに対する編集者
権限が付与されます。編集者
IAM ロールには、プロジェクト リソース(Compute インスタンス、Cloud Storage バケット、GCR レジストリなど)を操作できる広範な読み取りと書き込みの権限があるため、これは重大なセキュリティ リスクとなります。
- 次のコマンドを入力してこの Pod を閉じます。
タスク 3. ホストのファイルシステムをマウントする Pod をデプロイする
基盤となるホストに「エスケープ」するシンプルな方法の 1 つは、Pod
の仕様で Kubernetes の標準の volumes
と volumeMounts
を使用して、ホストのファイルシステムを Pod のファイルシステムにマウントすることです。
- これを確認するために、次のコマンドを実行して、基盤となるホストのファイルシステム
/
を、コンテナ内の/rootfs
というフォルダにマウントする Pod を作成します。
-
kubectl get pod
を実行します(「Running」の状態になるまで何度か実行します)。
(出力)
[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。
タスク 4. 基盤となるホストを確認し、不正使用する
- 次のコマンドを実行して、先ほど作成した Pod 内のシェルを取得します。
- Pod シェルのルート ファイルシステムを、基盤となるホストのルート ファイルシステムを参照するように切り替えます。
このシンプルなコマンドを実行することで、Pod はノード上で root
シェルになりました。これで、以下の操作を実行できます。
完全な権限で標準の docker コマンドを実行する |
|
docker イメージのリストを取得する |
|
|
|
マウントされた Kubernetes の Secret を調べる |
|
|
|
root
ユーザーが実行できるほとんどの操作は、この Pod シェルで実行できます。これには、永続的に利用できるメカニズムが含まれます(SSH ユーザー / 認証鍵の追加、Kubernetes が参照できないホスト上の特権付き docker コンテナの実行など)。
- Pod シェルを閉じるには、
exit
を 2 回実行します。1 回目でchroot
、2 回目で Pod のシェルが閉じます。
- これで、
hostpath
Pod を削除できます。
利用可能なコントロールを理解する
このデモの次のステップでは、以下の内容を確認します。
-
Legacy Compute Engine Metadata API エンドポイントを無効化する - カスタム メタデータのキーと値を指定すると、
v1beta1
メタデータ エンドポイントはインスタンスから利用できなくなります。 - メタデータ隠蔽を有効にする - クラスタまたはノードプールの作成時に追加の構成を渡すことで、各ノードに軽量のプロキシがインストールされ、Metadata API に対するすべてのリクエストをプロキシ処理し、機密のエンドポイントへのアクセスを防ぎます。
- PodSecurityPolicy を有効化、構成する - GKE クラスタ上でこのオプションを構成すると、PodSecurityPolicy アドミッション コントローラが追加されます。これは、Pod の作成中に安全でない設定の使用を制限するために使用できます。このデモのケースでは、コンテナが root ユーザーとして実行されることを防ぎ、基盤となるホストのファイルシステムをマウントできます。
タスク 5. 2 つ目のノードプールをデプロイする
メタデータ エンドポイントが保護されている場合と保護されていない場合のテストが実施できるように、追加の設定を 2 つ含む 2 つ目のノードプールを作成します。1 つ目の一般的なノードプールに対してスケジュール設定された Pod は保護されず、2 つ目のノードプールに対してスケジュール設定された Pod は保護されます。
- 2 つ目のノードプールを作成します。
[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。
タスク 6. Google Cloud SDK Pod を実行する
- Cloud Shell で、保護されている 2 つ目のノードプールでのみ実行され、かつ root ユーザーとして実行されない Google Cloud SDK コンテナの単一のインスタンスを起動します。
- これで、
second-pool
というノードプール上で実行される Pod のコンテナ内で bash シェルを利用できます。次の結果が表示されます。
コンテナが起動し、コマンド プロンプトが開くまで数秒かかることがあります。
コマンド プロンプトが表示されない場合は Enter キーを押してください。
さまざまなブロックされたエンドポイントを調べる
- 2 つ目のノードプールの構成が
--workload-metadata-from-node=SECURE
に設定されていると、機密ファイルkube-env
を取得する次のコマンドがエラーになります。
(出力)
- 機密でないエンドポイントに対して他のコマンドを実行すると、適切な HTTP ヘッダーが渡された場合は引き続き正常に動作します。
(出力例)
- Pod を閉じます。
Cloud Shell に戻ります。
タスク 7. PodSecurityPolicy オブジェクトをデプロイする
- 続行に必要な権限を設定するために、
cluster-admin
になるための明示的な権限を独自のユーザー アカウントに付与します。
(出力)
- 次に、デフォルトの名前空間内のすべての認証済みユーザーに、より制限の厳しい
PodSecurityPolicy
をデプロイします。
(出力)
- 次に、
ClusterRole
を追加して、この PodSecurityPolicy を「使用」できるようにします。
(出力)
- 最後に、デフォルトの名前空間に RoleBinding を作成して、任意の認証済みユーザー権限で PodSecurityPolicy を利用できるようにします。
(出力)
system:authenticated
ユーザーを、デフォルトの名前空間で Pod を作成できるようにする特定のユーザーまたはサービス アカウントに置き換えることを検討してください。
[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。
PodSecurity ポリシーを有効にする
- PodSecurityPolicy アドミッション コントローラを有効にします。
こちらは、完了するまでに数分かかります。
タスク 8. ホストのファイルシステムをマウントするブロックされた Pod をデプロイする
GKE クラスタのデプロイに使用するアカウントには、前のステップで cluster-admin の権限が付与されました。そのため、クラスタを操作して PodSecurityPolicy が適用されていることを検証する別の「ユーザー」アカウントを作成する必要があります。
- これを行うには、次のコマンドを実行します。
(出力)
- 次に、以下の各コマンドを実行して、クラスタの操作と Pod の作成を行える権限をサービス アカウントに付与します。
- 次のコマンドを実行して、サービス アカウントの認証情報ファイルを取得します。
-
kubectl
を構成して、このサービス アカウントとして認証します。
- 次のコマンドを実行して、クラスタと通信する際にこれらの認証情報を使用するように
kubectl
を構成します。
- 基盤となるホストのファイルシステム
/
を、コンテナ内の/rootfs
というフォルダにマウントする別の Pod を作成します。
- この出力では、PSP によってブロックされていることを確認できます。
-
restrictive-psp
の基準を満たす別の Pod をデプロイします。
(出力)
- 次のコマンドを実行して、作成を承認した PodSecurityPolicy を示す Pod に追加されるアノテーションを表示します。
(Cloud Shell コマンドラインに出力が追加されます)
[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。
お疲れさまでした
このラボでは、Google Kubernetes Engine でデフォルトの Kubernetes クラスタを構成しました。その後、Pod に対して利用できるアクセスをプローブ、悪用してからクラスタを強化し、悪意のあるアクションが実行できなくなっていることを確認しました。
クエストを完了する
このセルフペース ラボは、「Google Kubernetes Engine Best Practices: Security」クエストの一部です。クエストとは学習プログラムを構成する一連のラボのことで、完了すると成果が認められてバッジが贈られます。バッジは公開して、オンライン レジュメやソーシャル メディア アカウントにリンクできます。このラボの修了後、こちらのクエストまたはこのラボが含まれるクエストに登録すれば、すぐにクレジットを受け取ることができます。受講可能なすべてのクエストについては、Google Cloud Skills Boost カタログをご覧ください。
次のラボを受講する
「Google Kubernetes Engine Security: Binary Authorization」に進んでクエストを続けるか、以下の Google Cloud Skills Boost ラボをご確認ください。
次のステップと詳細情報
重要: このラボでは複数のセキュリティ上の問題について詳しく説明しましたが、実際の環境内で検討が必要な点は他にもあります。追加情報については、クラスタのセキュリティを強化するガイドをご覧ください。
PodSecurityPolicy: PodSecurityPolicies を使用するガイドおよびクラスタのセキュリティを強化するガイド
ノードのサービス アカウント: 権限ガイド
ノードのメタデータを保護する: ノードのメタデータを保護するガイド
Google Cloud トレーニングと認定資格
Google Cloud トレーニングと認定資格を通して、Google Cloud 技術を最大限に活用できるようになります。必要な技術スキルとベスト プラクティスについて取り扱うクラスでは、学習を継続的に進めることができます。トレーニングは基礎レベルから上級レベルまであり、オンデマンド、ライブ、バーチャル参加など、多忙なスケジュールにも対応できるオプションが用意されています。認定資格を取得することで、Google Cloud テクノロジーに関するスキルと知識を証明できます。
マニュアルの最終更新日: 2023 年 10 月 3 日
ラボの最終テスト日: 2023 年 10 月 9 日
Copyright 2024 Google LLC All rights reserved. Google および Google のロゴは Google LLC の商標です。その他すべての企業名および商品名はそれぞれ各社の商標または登録商標です。