このページでは、Google Kubernetes Engine(GKE)クラスタを強化するための最新のベスト プラクティスを実装する方法について説明します。このガイドでは、クラスタの作成時にお客様の操作が必要となる価値のあるセキュリティ対策を優先します。重要性の低い機能、デフォルトでセキュアな設定、作成後に有効にできる項目についてはドキュメントの後半でご説明します。
このドキュメントは、組織のデータを不正アクセスから保護するためのポリシーと手順を定義、管理、実装するセキュリティ スペシャリストを対象としています。Google Cloud のコンテンツで参照する一般的なロールとタスク例の詳細については、一般的な GKE Enterprise ユーザーロールとタスクをご覧ください。
このページを読む前に、次のことをよく理解しておいてください。
GKE で新しいクラスタを作成する場合、こうした保護の大部分がデフォルトで有効になっています。既存のクラスタをアップグレードする場合は、この強化ガイドを定期的に確認し、新しい機能を有効にしてください。
Autopilot モードで作成されたクラスタは、デフォルトで多くの GKE 強化機能を実装しています。
セキュリティ状況の分析を使用すると、こうした推奨事項の多く、またその他構成の誤りが自動的に確認されます。
GKE インフラストラクチャを適切なタイミングでアップグレードする
CIS GKE ベンチマークの推奨事項: 6.5.3。ノードの自動アップグレードが GKE ノードに対して有効になっていることを確認する
セキュリティを向上させる最も簡単な方法の 1 つに、Kubernetes のバージョンを最新の状態に保つことがあります。Kubernetes は頻繁に新しいセキュリティ機能を導入し、セキュリティ パッチを提供しています。
セキュリティ パッチの詳細については、GKE セキュリティに関する情報を参照してください。
Google Kubernetes Engine では、コントロール プレーンへのパッチやアップグレードが自動的に行われます。ノードの自動アップグレードでも、クラスタ内のノードが自動的にアップグレードされます。
ノードの自動アップグレードは、Google Cloud コンソールを使用して作成されたクラスタに対しては 2019 年 6 月から、API を使用して作成されたクラスタに対しては 2019 年 11 月 11 日からデフォルトで有効になっています。
ノードの自動アップグレードを無効にする場合は、自身の都合に合わせて、毎月アップグレードすることを推奨します。古いクラスタでは、ノードの自動アップグレードを有効にする設定にしたうえで、重要なパッチについて GKE セキュリティ情報に厳密に従ってください。
詳細は、ノードの自動アップグレードをご覧ください。
コントロール プレーンとノードへのネットワーク アクセスを制限する
CIS GKE ベンチマークの推奨事項: 6.6.2. VPC ネイティブ クラスタを優先する、6.6.3. 認証ネットワークが有効であることを確認する、6.6.4.クラスタが非公開エンドポイント有効と公開アクセス無効で作成されていることを確認する、6.6.5. クラスタがプライベート ノードで作成されていることを確認する
GKE のクラスタ コントロール プレーンとノードには、任意の IP アドレスからアクセスできる、インターネット上でルーティング可能なアドレスがデフォルトで付与されています。
クラスタ コントロール プレーンとノードのインターネットへの公開を制限します。
コントロール プレーンへのアクセスを制限する
GKE クラスタ コントロール プレーンへのアクセスを制限するには、コントロール プレーン アクセスを構成するをご覧ください。ネットワーク レベルの保護には、次のオプションがあります。
DNS ベースのエンドポイントが有効(推奨): VPC Service Controls を使用して、DNS ベースのエンドポイントにアクセスできるユーザーを制御できます。VPC Service Controls を使用すると、ネットワーク送信元などのコンテキスト対応属性を使用して、プロジェクト内のすべての Google API に 1 つのセキュリティ パラメータを定義できます。これらの設定は、すべての Google API でプロジェクトに対して一元的に制御できるため、アクセスルールを構成する場所の数を減らすことができます。
外部 IP ベースのエンドポイントと内部 IP ベースのエンドポイントへのアクセスが無効: IP ベースのエンドポイントを介したコントロール プレーンへのすべてのアクセスがブロックされます。
外部 IP ベースのエンドポイント アクセスが無効: 両方のコントロール プレーンへのすべてのインターネット アクセスがブロックされます。Cloud Interconnect と Cloud VPN を使用してオンプレミス ネットワークから Google Cloud への接続を構成している場合に適しています。これらを用いれば、企業ネットワークとクラウド VPC を効率的に接続できます。
外部 IP ベースのエンドポイント アクセスが有効、承認済みネットワークが有効: このオプションでは、定義するソース IP アドレスからコントロール プレーンへのアクセスが制限されます。これは、既存の VPN インフラストラクチャがない場合や、リモート ユーザーや支社が企業 VPN や Cloud Interconnect / Cloud VPN を使用せずに公共のインターネット経由で接続する場合に適しています。
外部エンドポイント アクセスが有効、承認済みネットワークが無効: インターネット上の誰でもコントロール プレーンにネットワーク接続できるようになります。
IP ベースのエンドポイントを使用する場合は、クラスタで承認済みネットワークを使用することをおすすめします。
これにより、以下がコントロール プレーンにアクセス可能になります。
- 承認済みネットワークで許可された CIDR。
- クラスタの VPC 内のノード。
- クラスタ管理用に Google が予約した IP アドレス。
ノードへのアクセスを制限する
クラスタでプライベート ノードを有効にして、外部クライアントがノードにアクセスできないようにします。
ノードへの直接的なインターネット アクセスを無効にするには、クラスタの作成時に gcloud CLI オプション --enable-private-nodes
を指定します。
これにより GKE が内部 IP アドレスを持つノードをプロビジョニングするように指示するため、公共のインターネット経由でノードに直接アクセスすることはできません。
最小権限のファイアウォール ルールを使用する
ファイアウォール ルールには最小権限の原則を使用することで、意図しないアクセスのリスクを最小限に抑える
GKE は、システム機能を有効にし、適切なセキュリティ対策を適用するために、デフォルトの VPC ファイアウォール ルールを作成します。自動作成されるファイアウォール ルールの一覧については、自動的に作成されるファイアウォール ルールをご覧ください。
GKE は、これらのデフォルトのファイアウォール ルールを優先度 1000 で作成します。デバッグ用の allow-all
ファイアウォール ルールなど、優先度の高く制限の緩いファイアウォール ルールを作成すると、クラスタが意図しないアクセスを受けるリスクがあります。
グループ認証
CIS GKE ベンチマークの推奨事項: 6.8.3. RBAC 向け Google グループで Kubernetes RBAC ユーザーを管理することを検討する
グループを使用してユーザーを管理する必要があります。グループを使用すると、ID 管理システムと ID 管理者を使用して ID を制御できます。グループ メンバーシップを調整するだけで、メンバーをグループに追加または削除するたびに RBAC の構成を更新する必要がなくなります。
Google グループを使用してユーザー権限を管理するには、クラスタで RBAC 用 Google グループを有効にする必要があります。これにより、同じ権限を持つユーザーを簡単に管理でき、ID 管理者は、ユーザーの一貫した一元管理ができるようになります。
RBAC 向け Google グループを有効にする手順については、RBAC の Google グループをご覧ください。
コンテナノードを選択する
次のセクションでは、安全なノード構成の選択について説明します。
シールドされた GKE ノードを有効にする
CIS GKE ベンチマークの推奨事項: 6.5.5。シールドされた GKE ノードが有効になっていることを確認する
シールドされた GKE ノードは強固で検証可能なノード ID と完全性を備え、GKE ノードのセキュリティが高められているので、すべての GKE クラスタでこれを有効にすることをおすすめしています。
シールドされた GKE ノードは、クラスタの作成時または更新時に有効にできます。シールドされた GKE ノードを有効にするときは、セキュアブートも有効にしてください。サードパーティの未署名のカーネル モジュールが必要な場合は、セキュアブートを使用しないでください。シールドされた GKE ノードを有効にする方法と、シールドされた GKE ノードを使用してセキュアブートを有効にする方法については、シールドされた GKE ノードの使用をご覧ください。
containerd ランタイムで強化されたノードイメージを選択する
containerd を含む Container-Optimized OS(cos_containerd
)イメージは、containerd を含む Container-Optimized OS イメージのバリアントであり、メインのコンテナ ランタイムとして Kubernetes に直接統合されています。
containerd は Docker のコアランタイム コンポーネントで、Kubernetes Container Runtime Interface(CRI)にコアコンテナ機能を提供するように設計されています。完全な Docker デーモンよりもはるかに簡潔なので、攻撃対象領域が小さくなります。
クラスタで cos_containerd
イメージを使用するには、コンテナ イメージをご覧ください。
cos_containerd
イメージは、コンテナを実行するためにカスタムビルドされ、最適化され、強化されていることから、GKE の推奨イメージです。
Workload Identity Federation for GKE を有効にする
CIS GKE ベンチマークの推奨事項: 6.2.2。専用の Google Cloud サービス アカウントと Workload Identity を優先的に使用する
Google Cloud APIs に対する認証に推奨される方法は、GKE 用 Workload Identity 連携です。
GKE 用 Workload Identity 連携は、メタデータ隠蔽機能の使用に代わるものであるため、この 2 つのアプローチに互換性はありません。メタデータ隠蔽機能によって保護される機密メタデータは、GKE 用 Workload Identity 連携によっても保護されます。
GKE Sandbox によるワークロード分離の強化
CIS GKE ベンチマークの推奨事項: 6.10.4。信頼できないワークロードの場合は特に、ワークロードの分離を強化するために GKE Sandbox の使用を検討する
GKE Sandbox は、セキュリティに新たなレイヤを追加し、悪意のあるコードからクラスタノードのホストカーネルを保護します。
サンドボックス環境でコンテナを実行すると、ほとんどのコンテナ エスケープ攻撃(ローカル権限昇格攻撃とも呼ばれる)を軽減できます。過去のコンテナ エスケープの脆弱性については、セキュリティに関する公開情報をご覧ください。このタイプの攻撃では、攻撃者はコンテナのホスト VM にアクセスします。このため、同じ VM 上の他のコンテナにもアクセスされる可能性があります。GKE Sandbox などのサンドボックスは、このような攻撃の影響を抑えるのに役立ちます。
次のような状況では、ワークロードのサンドボックス化を検討する必要があります。
- ワークロードが信頼できないコードを実行する
- ワークロード内のコンテナが攻撃者によって不正使用された場合の影響を制限する必要がある。
GKE Sandbox の使用方法については、GKE Sandbox によるワークロード分離の強化をご覧ください。
セキュリティ情報の通知を有効にする
クラスタに関連するセキュリティ情報が利用可能になると、GKE はそれらのイベントに関する通知を構成済みの Pub/Sub トピックにメッセージとして公開します。これらの通知を Pub/Sub サブスクリプションで受信し、サードパーティ サービスと統合して、受信したい通知タイプをフィルタできます。
GKE クラスタ通知を使用したセキュリティ情報の受信の詳細については、クラスタ通知をご覧ください。
安全でない kubelet 読み取り専用ポートを無効にする
kubelet 読み取り専用ポートを無効にし、ポート 10255
を使用するワークロードがより安全なポート 10250
を使用するように切り替えます。
ノードで実行されている kubelet
プロセスは、安全でないポート 10255
を使用して読み取り専用 API を提供します。Kubernetes では、このポートに対して認証や承認のチェックが行われません。kubelet は、より安全な認証済みのポート 10250
で同じエンドポイントにサービスを提供します。
手順については、GKE クラスタで kubelet の読み取り専用ポートを無効にするをご覧ください。
権限
最小権限の IAM サービス アカウントを使用する
CIS GKE ベンチマークの推奨事項: 6.2.1. GKE クラスタの実行時に Compute Engine のデフォルト サービス アカウントを使用しないようにする
GKE は、ノードに接続されている IAM サービス アカウントを使用して、ロギングやモニタリングなどのシステムタスクを実行します。少なくとも、これらのノード サービス アカウントには、プロジェクトに対する Kubernetes Engine デフォルト ノード サービス アカウント(roles/container.defaultNodeServiceAccount
)ロールが必要です。デフォルトでは、GKE はプロジェクトで自動的に作成される Compute Engine のデフォルトのサービス アカウントをノード サービス アカウントとして使用します。
プロジェクトまたは組織内の他の機能に Compute Engine のデフォルトのサービス アカウントを使用すると、サービス アカウントに GKE が必要とする以上の権限が付与され、セキュリティ リスクにさらされる可能性があります。
ノードに接続されているサービス アカウントは、ロギングやモニタリングなどのタスクを実行するシステム ワークロードでのみ使用する必要があります。独自のワークロードの場合は、Workload Identity Federation for GKE を使用して ID をプロビジョニングします。
カスタム サービス アカウントを作成して GKE に必要なロールを付与する手順は次のとおりです。
console
- Google Cloud コンソールで、Cloud Resource Manager API を有効にします。
- [サービス アカウント] ページに移動します。
- [ サービス アカウントを作成] をクリックします。
- サービス アカウントの名前を入力します。[サービス アカウント ID] フィールドには、名前に基づいてサービス アカウントの一意の ID が自動的に生成されます。
- [作成して続行] をクリックします。
- [ロールを選択] メニューで、[Kubernetes Engine のデフォルト ノードサービス アカウント] ロールを選択します。
- [完了] をクリックします。
gcloud
- Cloud Resource Manager API を有効にします。
gcloud services enable cloudresourcemanager.googleapis.com
- サービス アカウントを作成します。
gcloud iam service-accounts create SERVICE_ACCOUNT_ID \ --display-name=DISPLAY_NAME
次のように置き換えます。
SERVICE_ACCOUNT_ID
: サービス アカウントの一意の ID。DISPLAY_NAME
: サービス アカウントの表示名。
- サービス アカウントに Kubernetes Engine デフォルト ノード サービス アカウント(
roles/container.defaultNodeServiceAccount
)のロールを付与します。gcloud projects add-iam-policy-binding PROJECT_ID \ --member="serviceAccount:SERVICE_ACCOUNT_ID@PROJECT_ID.iam.gserviceaccount.com" \ --role=roles/container.defaultNodeServiceAccount
次のように置き換えます。
PROJECT_ID
: Google Cloud プロジェクト IDSERVICE_ACCOUNT_ID
: 作成したサービス アカウント ID。
Config Connector
注: この手順には Config Connector が必要です。Config Connector をクラスタにインストールするには、インストール手順を実施してください。
- サービス アカウントを作成するには、次のリソースを
service-account.yaml
としてダウンロードします。次のように置き換えます。
[SA_NAME]
: 新しいサービス アカウントの名前。[DISPLAY_NAME]
: サービス アカウントの表示名。
- サービス アカウントを作成します。
kubectl apply -f service-account.yaml
- サービス アカウントに
roles/logging.logWriter
ロールを適用します。- 次のリソースを
policy-logging.yaml
としてダウンロードします。次のように置き換えます。
[SA_NAME]
: サービス アカウントの名前。[PROJECT_ID]
: Google Cloud プロジェクト ID
- ロールをサービス アカウントに適用します。
kubectl apply -f policy-logging.yaml
- 次のリソースを
- サービス アカウントに
roles/monitoring.metricWriter
ロールを適用します。- 次のリソースを
policy-metrics-writer.yaml
としてダウンロードします。[SA_NAME]
と[PROJECT_ID]
はお客様自身の情報に置き換えてください。次のように置き換えます。
[SA_NAME]
: サービス アカウントの名前。[PROJECT_ID]
: Google Cloud プロジェクト ID
- ロールをサービス アカウントに適用します。
kubectl apply -f policy-metrics-writer.yaml
- 次のリソースを
- サービス アカウントに
roles/monitoring.viewer
ロールを適用します。- 次のリソースを
policy-monitoring.yaml
としてダウンロードします。次のように置き換えます。
[SA_NAME]
: サービス アカウントの名前。[PROJECT_ID]
: Google Cloud プロジェクト ID
- ロールをサービス アカウントに適用します。
kubectl apply -f policy-monitoring.yaml
- 次のリソースを
- サービス アカウントに
roles/autoscaling.metricsWriter
ロールを適用します。- 次のリソースを
policy-autoscaling-metrics-writer.yaml
としてダウンロードします。次のように置き換えます。
[SA_NAME]
: サービス アカウントの名前。[PROJECT_ID]
: Google Cloud プロジェクト ID
- ロールをサービス アカウントに適用します。
kubectl apply -f policy-autoscaling-metrics-writer.yaml
- 次のリソースを
このサービス アカウントは、他のプロジェクトのリソースにも使用できます。手順については、プロジェクト間でのサービス アカウントの権限借用を有効にするをご覧ください。
限定公開イメージ リポジトリへのアクセス権を付与する
Artifact Registry で非公開イメージを使用するには、サービス アカウントに Artifact Registry 読み取りロール(roles/artifactregistry.reader
)を付与します。
gcloud
gcloud artifacts repositories add-iam-policy-binding REPOSITORY_NAME \
--member=serviceAccount:SA_NAME@PROJECT_ID.iam.gserviceaccount.com \
--role=roles/artifactregistry.reader
REPOSITORY_NAME
を Artifact Registry リポジトリの名前に置き換えます。
Config Connector
注: この手順には Config Connector が必要です。Config Connector をクラスタにインストールするには、インストール手順を実施してください。
次のマニフェストを
policy-artifact-registry-reader.yaml
として保存します。次のように置き換えます。
- SA_NAME: IAM サービス アカウントの名前。
- PROJECT_ID: Google Cloud プロジェクト ID。
- REPOSITORY_NAME: Artifact Registry リポジトリの名前。
Artifact Registry 読み取りロールをサービス アカウントに付与します。
kubectl apply -f policy-artifact-registry-reader.yaml
Container Registry の限定公開イメージを使用する場合は、それらのイメージに対するアクセス権も付与する必要があります。
gcloud
gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \
--member=serviceAccount:SA_NAME@PROJECT_ID.iam.gserviceaccount.com \
--role=roles/storage.objectViewer
イメージを保存するバケットには、次の形式の名前 BUCKET_NAME
が付いています。
artifacts.PROJECT_ID.appspot.com
。gcr.io
ホスト内のレジストリに push されたイメージの場合。STORAGE_REGION.artifacts.PROJECT_ID.appspot.com
次のように置き換えます。
PROJECT_ID
: Google Cloud コンソール プロジェクト ID。STORAGE_REGION
: ストレージ バケットの場所。us
:us.gcr.io
ホストのレジストリの場合eu
:eu.gcr.io
ホストのレジストリの場合asia
。asia.gcr.io
ホストのレジストリの場合
コマンドの詳細については、gcloud storage buckets add-iam-policy-binding
のドキュメントをご覧ください。
Config Connector
注: この手順には Config Connector が必要です。Config Connector をクラスタにインストールするには、インストール手順に従ってください。
storage.objectViewer
ロールをサービス アカウントに適用します。次のリソースを policy-object-viewer.yaml
としてダウンロードします。[SA_NAME]
と [PROJECT_ID]
はお客様自身の情報に置き換えてください。
kubectl apply -f policy-object-viewer.yaml
他のユーザーがこのサービス アカウントで新しいクラスタまたはノードプールを作成できるようにするには、そのサービス アカウントのユーザーにサービス アカウント ユーザーロールを付与します。
gcloud
gcloud iam service-accounts add-iam-policy-binding \ SA_NAME@PROJECT_ID.iam.gserviceaccount.com \ --member=user:USER \ --role=roles/iam.serviceAccountUser
Config Connector
注: この手順には Config Connector が必要です。Config Connector をクラスタにインストールするには、インストール手順に従ってください。
iam.serviceAccountUser
ロールをサービス アカウントに適用します。次のリソースを policy-service-account-user.yaml
としてダウンロードします。[SA_NAME]
と [PROJECT_ID]
はお客様自身の情報に置き換えてください。
kubectl apply -f policy-service-account-user.yaml
既存の Standard クラスタの場合、この新しいサービス アカウントを使用して新しいノードプールを作成できるようになりました。Autopilot クラスタの場合は、このサービス アカウントを使用して新しいクラスタを作成する必要があります。手順については、Autopilot クラスタを作成するをご覧ください。
新しいサービス アカウントを使用するノードプールを作成します。
gcloud container node-pools create NODE_POOL_NAME \ --service-account=SA_NAME@PROJECT_ID.iam.gserviceaccount.com \ --cluster=CLUSTER_NAME
GKE クラスタが他の Google Cloud サービスにアクセスする必要がある場合は、GKE 用 Workload Identity 連携を使用する必要があります。
クラスタ API 検出へのアクセスを制限する
Kubernetes はデフォルトで、CustomResourceDefinitions の API など、クラスタの API に関する情報に幅広くアクセスできる、制約の緩いディスカバリ ClusterRoleBindings のセットでクラスタをブート ストラップします。
system:discovery
と system:basic-user
の ClusterRoleBindings のサブジェクトにある system:authenticated
グループには、認証済みユーザーなら誰でも含めることができ(Google アカウントを持つユーザーもこれに含まれます)、そのためこのグループは GKE のクラスタのセキュリティにとってむしろ無意味なレベルに相当することに留意する必要があります。詳細については、デフォルトのロールとグループを使用しないをご覧ください。
クラスタのディスカバリ API を強化する場合は、次のうち 1 つ以上を実施することを検討してください。
- コントロール プレーンへのアクセスに DNS ベースのエンドポイントのみを有効にします。
- 設定済みの IP 範囲へのアクセスを制限するように承認済みネットワークを構成します。
- コントロール プレーンへのアクセスを制限し、プライベート ノードを有効にします。
これらのオプションが GKE のユースケースに適していない場合、すべての API 検出情報(CustomResources のスキーマ、APIService の定義、拡張 API サーバーでホストされている検出情報)を一般公開として扱います。
Namespace とロールベース アクセス制御を使用してクラスタ リソースへのアクセスを制限する
CIS GKE ベンチマークの推奨事項: 5.6.1。Namespace を使用してリソース間の管理境界を作成する
各チームと環境に個別の Namespace またはクラスタを作成して、チームに付与する Kubernetes へのアクセス権限を最低限に抑えます。アカウンタビリティとチャージバックに基づいて各名前空間にコストセンターと適切なラベルを割り当てます。開発者に付与する名前空間へのアクセス権は(特に本番環境において)、アプリケーションのデプロイと管理に必要なレベルのみに制限します。ユーザーがクラスタに対して行う必要があるタスクをマッピングし、各タスクの実行に必要な権限を定義します。
Namespace の作成について詳しくは、Kubernetes のドキュメントをご覧ください。RBAC 構成を計画する際のベスト プラクティスについては、GKE RBAC のベスト プラクティスをご覧ください。
IAM とロールベースのアクセス制御(RBAC) は相互に連携するため、クラスタ内のリソースを操作するには、エンティティに双方のレベルで十分な権限を与える必要があります。
GKE に適した IAM ロールをグループやユーザーに割り当て、プロジェクト レベルで権限を提供します。RBAC を使ってクラスタと Namespace レベルで権限を付与します。詳細については、アクセス制御をご覧ください。
IAM と RBAC の権限を名前空間と併用すると、Google Cloud コンソールのクラスタ リソースに対するユーザー操作を制限できます。詳細については、アクセスを有効にしてクラスタ リソースを名前空間ごとに表示するをご覧ください。Pod 間のトラフィックをネットワーク ポリシーで制限する
CIS GKE ベンチマークの推奨事項: 6.6.7。ネットワーク ポリシーが有効であることを確認し、必要に応じて設定する
デフォルトでは、クラスタ内のすべてのポッドが相互通信できます。ポッド間通信は、ワークロードのニーズに応じて制御してください。
サービスへのネットワーク アクセスを制限することで、攻撃者によるクラスタ内移動の難易度を大幅に上げることができ、偶発的または意図的な DoS 攻撃に対してサービスをある程度は保護できます。トラフィックを制御する 2 つの推奨方法は次のとおりです。
- Istio を使用します。負荷分散、サービス許可、スロットリング、割り当て、指標などの詳細については、Google Kubernetes Engine に Istio をインストールするをご覧ください。
- Kubernetes ネットワーク ポリシーを使用します。クラスタ ネットワーク ポリシーの作成をご覧ください。Kubernetes で公開されている基本的なアクセス制御機能をお探しの場合は、これを選択します。ネットワーク ポリシーを使用してトラフィックを制限する一般的なアプローチを実装するには、GKE Enterprise セキュリティ ブループリントの実装ガイドに従ってください。Kubernetes のドキュメントには簡単な nginx デプロイに関する優れたチュートリアルがあります。ネットワーク ポリシー ロギングを使用して、ネットワーク ポリシーが期待どおりに動作していることを確認します。
Istio とネットワーク ポリシーは、必要に応じて併用できます。
Secret 管理
CIS GKE ベンチマークの推奨事項: 6.3.1. Cloud KMS で管理されている鍵を使用して Kubernetes Secrets を暗号化する
Secret を etcd に保存するなど、機密データを保護するために追加の層を設けることをおすすめします。これを行うには、GKE クラスタと統合されたシークレット マネージャーを構成する必要があります。一部のソリューションは GKE と Google Distributed Cloud の両方で機能するため、複数の環境にまたがってワークロードを実行している場合は、こうしたソリューションのほうが適している可能性があります。HashiCorp Vault などの外部シークレット マネージャーを使用する場合は、クラスタを作成する前に設定する必要があります。
Secret を管理する方法はいくつかあります。
- Kubernetes Secret は、GKE でネイティブに使用できます。アプリケーション レイヤで Application-layer secrets encryption を使用して、自分が管理している鍵で Kubernetes Secret を暗号化することもできます。
- HashiCorp Vault などのシークレット マネージャーを使用できます。強化 HA モードで実行すると、本番環境に適応した一貫性のあるシークレット管理が可能になります。HashiCorp Vault への認証には、Kubernetes サービス アカウントまたは Google Cloud サービス アカウントを使用できます。Vault と GKE を使用する詳しい方法については、Kubernetes での HashiCorp Vault の実行と接続を参照してください。
GKE の VM は、etcd を含むストレージ レイヤではデフォルトで暗号化されます。
アドミッション コントローラを使用してポリシーを適用する
アドミッション コントローラは、クラスタの使用方法を管理および適用するプラグインです。Kubernetes の高度なセキュリティ機能の一部を使用するには、アドミッション コントローラを有効にする必要があります。また、クラスタを強化するための多層防御アプローチの重要な部分でもあります。
デフォルトでは、Kubernetes のポッドは、必要とする以上の機能で動作します。Pod の機能は、そのワークロードに必要な機能だけに制限するようにしてください。
Kubernetes には、明示的に付与された機能のみを使用して Pod を実行するように制限する制御手段が多数あります。たとえば、Policy Controller はフリート内のクラスタで使用できます。Kubernetes には PodSecurity アドミッション コントローラが組み込まれており、個々のクラスタに Pod セキュリティ標準を適用できます。
Policy Controller は、宣言型ポリシーを使用して GKE クラスタにセキュリティを大規模に適用し、検証できる GKE Enterprise の機能です。Policy Controller を使用して GKE クラスタに宣言型制御を適用する方法については、Policy Controller のインストールをご覧ください。
PodSecurity アドミッション コントローラを使用すると、特定の Namespace またはクラスタ全体で事前定義済みのポリシーを適用できます。これらのポリシーは、異なる Pod セキュリティ標準に対応しています。
ワークロードの自己変更機能を制限する
特定の Kubernetes ワークロード(特にシステム ワークロード)には、自己変更の権限があります。たとえば、一部のワークロードは垂直方向に自動スケーリングされます。これは便利ですが、すでにノードを不正使用した攻撃者がクラスタ内でさらにエスカレーションする可能性があります。たとえば、攻撃者がノード上のワークロード自体を変更して、同じ名前空間内に存在する、より権限の高いサービス アカウントとして実行するおそれがあります。
理想的には、ワークロードにはそもそも自己変更機能を付与するべきではありません。自己変更が必要な場合は、オープンソースの Gatekeeper ライブラリから NoUpdateServiceAccount などの Gatekeeper または Policy Controller の制約を適用して権限を制限できます。これにより、いくつかの有用なセキュリティ ポリシーが提供されます。
ポリシーをデプロイする場合、通常はクラスタのライフサイクルを管理するコントローラがポリシーをバイパスできるようにする必要があります。これは、コントローラがクラスタに変更を加える(クラスタのアップグレードを適用するなど)ことができるようにするために必要です。たとえば、NoUpdateServiceAccount
ポリシーを GKE にデプロイする場合は、Constraint
で次のパラメータを設定する必要があります。
parameters:
allowedGroups:
- system:masters
allowedUsers:
- system:addon-manager
非推奨の gcePersistentDisk
ボリューム タイプの使用を制限する
非推奨の gcePersistentDisk
ボリューム タイプを使用すると、Compute Engine 永続ディスクを Pod にマウントできます。ワークロードでの gcePersistentDisk
ボリューム タイプの使用を制限することをおすすめします。GKE は、このボリューム タイプをマウントするときに Pod の IAM 認証チェックを行いません。ただし、Google Cloud は、基盤となる VM にディスクをアタッチするときに認証チェックを実行します。Namespace に Pod を作成する能力がすでにある攻撃者は、Google Cloud プロジェクトの Compute Engine 永続ディスクのコンテンツにアクセスできます。
Compute Engine 永続ディスクにアクセスして使用する場合は、代わりに PersistentVolumes と PersistentVolumeClaims を使用します。gcePersistentDisk
ボリューム タイプの使用を防止するセキュリティ ポリシーをクラスタに適用します。
gcePersistentDisk
ボリューム タイプの使用を防止するには、Baseline または PodSecurity アドミッション コントローラによる制限ありポリシーを適用するか、または Policy Controller か Gatekeeper アドミッション コントローラの中でカスタム制約を定義することもできます。
このボリューム タイプを制限するカスタム制約を定義する手順は次のとおりです。
Policy Controller や Gatekeeper OPA などのポリシーベースのアドミッション コントローラをインストールします。
Policy Controller
クラスタに Policy Controller をインストールします。
GKE ユーザーの場合、Policy Controller は有償の機能です。Policy Controller はオープンソースの Gatekeeper をベースにしていますが、完全な制約テンプレート ライブラリ、ポリシー バンドル、Google Cloud コンソール ダッシュボードとの統合にもアクセスして、クラスタのモニタリングとメンテナンスを行うことができます。ポリシー バンドルはクラスタに適用できる独自のベスト プラクティスで、CIS Kubernetes Benchmark のように推奨事項に基づくバンドルが含まれています。
Gatekeeper
Autopilot クラスタの場合は、テキスト エディタで Gatekeeper
gatekeeper.yaml
マニフェストを開きます。次の例のように、MutatingWebhookConfiguration
仕様のrules
フィールドを変更して、ワイルドカード(*
)文字を特定の API グループとリソース名に置き換えます。apiVersion: admissionregistration.k8s.io/v1 kind: MutatingWebhookConfiguration ... webhooks: - admissionReviewVersions: - v1 - v1beta1 ... rules: - apiGroups: - core - batch - apps apiVersions: - '*' operations: - CREATE - UPDATE resources: - Pod - Deployment - Job - Volume - Container - StatefulSet - StorageClass - Secret - ConfigMap sideEffects: None timeoutSeconds: 1
更新された
gatekeeper.yaml
マニフェストを Autopilot クラスタに適用して、Gatekeeper をインストールします。組み込みのセキュリティ対策として、Autopilot は変更用アドミッション Webhook にワイルドカード文字を使用を禁止しているため、これは必須です。組み込みの Pod Security Policy Volume Types ConstraintTemplate をデプロイします。
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/library/pod-security-policy/volumes/template.yaml
許可されたボリューム タイプのリストとして、次の制約を
constraint.yaml
として保存します。apiVersion: constraints.gatekeeper.sh/v1beta1 kind: k8sPSPVolumeTypes metadata: name: nogcepersistentdisk spec: match: kinds: - apiGroups: [""] kinds: ["Pods"] parameters: volumes: ["configMap", "csi", "projected", "secret", "downwardAPI", "persistentVolumeClaim", "emptyDir", "nfs", "hostPath"]
この制約は、ボリュームを
spec.parameters.volumes
フィールドのリストに制限します。制約をデプロイします。
kubectl apply -f constraint.yaml
クラスタ構成を監視する
クラスタ構成と定義した設定に矛盾がないか監査してください。
セキュリティの健全性分析を使用すると、この強化ガイドで説明した推奨事項の多くを自動的に確認できるだけでなく、構成の誤りも検出できます。
安全なデフォルト
以降のセクションでは、新しいクラスタにおいて、デフォルトで安全に構成されるオプションについて説明します。既存のクラスタが安全に構成されていることを確認する必要があります。
ノードのメタデータを保護する
CIS GKE ベンチマークの推奨事項: 6.4.1。従来の Compute Engine インスタンスのメタデータ API が無効であることを確認する、6.4.2. GKE メタデータ サーバーが有効になっていることを確認する
Compute Engine メタデータ サーバー エンドポイント v0.1
と v1beta1
は、2020 年 9 月 30 日にサポート終了となり、停止されました。これらのエンドポイントは、メタデータ クエリヘッダーを適用されませんでした。停止スケジュールについては、v0.1
と v1beta1
メタデータ サーバー エンドポイントのサポート終了をご覧ください。
Kubernetes に対する攻撃の中には、VM のメタデータ サーバーへのアクセスを使用して認証情報を抽出するものがあります。GKE 用 Workload Identity 連携またはメタデータ隠蔽を使用している場合、これらの攻撃はブロックされます。
以前のクライアント認証方式を無効のままにする
CIS GKE ベンチマークの推奨事項: 6.8.1。静的パスワードを使用する基本認証が無効になっていることを確認する、6.8.2. クライアント証明書を使用する認証が無効になっていることを確認する
Kubernetes API サーバーに対する認証方法は、複数存在します。GKE でサポートされる方法は、サービス アカウントの署名なしトークン、OAuth トークン、x509 クライアント証明書です。GKE では OAuth トークンベースで gcloud
での認証を管理し、Kubernetes 構成の設定、アクセス トークンの取得、トークンの更新を行います。
GKE を OAuth と統合する前は、1 回限りの x509 証明書または静的パスワードが唯一の認証方法でしたが、現在は推奨されておらず、無効にする必要があります。これらの方法は、クラスタの侵害に対する攻撃の範囲が広く、GKE バージョン 1.12 以降、デフォルトで無効になっています。以前の認証方法を使用している場合は、無効にすることをおすすめします。GKE バージョン 1.19 以降では、静的パスワードによる認証は非推奨となり、削除されています。
既存のクラスタは OAuth に移動する必要があります。クラスタの外部システムが長期間の認証情報を必要とする場合は、必要な権限を持つ Google サービス アカウントまたは Kubernetes サービス アカウントを作成し、そのキーをエクスポートすることをおすすめします。
既存のクラスタを更新して静的パスワードを削除するには、静的パスワードによる認証の無効化をご覧ください。
現在、既存のクラスタから発行済みの有効なクライアント証明書を削除する方法はありませんが、RBAC が有効で ABAC が無効ならば証明書に権限はありません。
Cloud Logging を有効のままにする
CIS GKE ベンチマークの推奨事項: 6.7.1。Stackdriver Kubernetes のロギングとモニタリングが有効になっていることを確認する
運用上のオーバーヘッドを削減し、ログの統合ビューを維持するには、クラスタがデプロイされているすべての場所に一貫性のあるロギング方法を実装します。GKE Enterprise クラスタはデフォルトで Cloud Logging と統合されており、その構成を維持する必要があります。
すべての GKE クラスタではデフォルトで Kubernetes 監査ロギングが有効になっています。これにより、Kubernetes API サーバーに対する呼び出しの記録が時系列で保持されます。Kubernetes 監査ログのエントリは、不審な API リクエストの調査、統計情報の収集、不要な API 呼び出しに対するモニタリング アラートの作成に役立ちます。
GKE クラスタは Kubernetes Audit Logging を Cloud Audit Logs と Cloud Logging に統合します。ログは、Cloud Logging から独自のロギング システムにルーティングできます。
Kubernetes ウェブ UI(ダッシュボード)を無効のままにする
CIS GKE ベンチマークの推奨事項: 6.10.1。Kubernetes ウェブ UI が無効になっていることを確認する
GKE での実行時に Kubernetes ウェブ UI(ダッシュボード)を有効にしないでください。
Kubernetes ウェブ UI(ダッシュボード)は、高い特権を持つ Kubernetes サービス アカウントと関連付けられています。Google Cloud コンソールにほぼ同じ機能があるため、こうした権限は必要ありません。
Kubernetes ウェブ UI を無効にするには、次のコマンドを実行します。
gcloud container clusters update CLUSTER_NAME \ --update-addons=KubernetesDashboard=DISABLED
ABAC を無効のままにする
CIS GKE ベンチマークの推奨事項: 6.8.4。以前の承認(ABAC)が無効になっていることを確認する
GKE で、属性ベースのアクセス制御(ABAC)を無効にし、代わりにロールベースのアクセス制御(RBAC)を使用してください。
ABAC は、GKE バージョン 1.8 以降を使用して作成されたクラスタではデフォルトで無効になります。Kubernetes では、RBAC を使用してリソースに対する権限をクラスタレベルと Namespace レベルで付与します。RBAC では、一連の権限を含むルールを使用してロールを定義できます。RBAC には、ABAC と比較して重要なセキュリティ上の利点があります。
現状で ABAC に依存している場合は、まず RBAC を使用する場合の前提条件を確認してください。クラスタを古いバージョンからアップグレードして ABAC を使用している場合は、次のようにアクセス制御の構成を更新する必要があります。
gcloud container clusters update CLUSTER_NAME \ --no-enable-legacy-authorization
上記の推奨に従って新しいクラスタを作成するには、次のコマンドを実行します。
gcloud container clusters create CLUSTER_NAME \ --no-enable-legacy-authorization
DenyServiceExternalIPs
アドミッション コントローラを有効のままにする
DenyServiceExternalIPs
アドミッション コントローラを無効にしないでください。
DenyServiceExternalIPs
アドミッション コントローラは、Service が ExternalIPs を使用できないようにするとともに、既知のセキュリティ脆弱性を緩和します。
GKE バージョン 1.21 以降で作成された新しいクラスタでは、DenyServiceExternalIPs
アドミッション コントローラがデフォルトで有効になります。GKE バージョン 1.21 以降にアップグレードしたクラスタでは、次のコマンドを使用してアドミッション コントローラを有効にできます。
gcloud beta container clusters update CLUSTER_NAME \
--location=LOCATION \
--no-enable-service-externalips
次のステップ
- セキュリティの概要で GKE セキュリティの詳細を確認する。
- GKE の共有責任モデルについての理解を深める。
- CIS GKE ベンチマークをクラスタに適用する方法を理解する。
- GKE でのアクセス制御の詳細を確認する。
- GKE ネットワークの概要を読む。
- GKE マルチ テナンシーの概要を読む。