Kubernetes Hardening Guidanceを訳してみた(随時更新中)
この文章について
米国土安全保障省サイバーセキュリティ・インフラストラクチャセキュリティ庁(CISA)と米国家安全保障局(NSA)によリ作成されたKubernetes Hardening Guidance, Kuebrnetes環境のセキュリティをより堅牢にするためのガイダンスを翻訳したみたものです。
訳者の英語力は壊滅的ですので、多くの誤訳などあるかと思いますが生暖かい目で見て頂ければと思いますのでよろしくお願いします。翻訳は以下で随時更新&修正していきます。
Kubernetes Hardening Guidance
Disclaimer of warranties and endorsement
このドキュメントに含まれる情報と意見は現状のままで提供されるものでありいかなる根拠や保証はありません。ここに記載されている特定の商用製品、プロセス、サービスについて商号、商標、製造者を米国政府が必ずしも保証、推奨、支持をしているのではなく、本ガイダンスを広告や製品推奨の目的で使用してはならない。
Purpose
NSAとCISAは、各自のサイバーセキュリティの仕様と緩和策を策定する責任を持ち、サイバーセキュリティのミッションを推進するためにこの文書を作成しました。この情報は、すべての適切な利害関係者に届くよう、広く共有することができます。
Executive summary
Kubernetesはコンテナ内で実行されるアプリケーションのデプロイ、スケール、管理を自動化するオープンソースシステムであり、多くの場合、クラウド環境でホストされます。このような仮想化されたインフラストラクチャの利用は、伝統的なモノリシックなソフトウェアプラットフォームと比較して、柔軟性とセキュリティ面で
いくつかの恩恵をもたらします。しかし、マイクロサービスからその基盤となるインフラストラクチャまで全てをセキュアに管理するのは別の複雑性をもたらします。このhardending guideの詳細なレポートでは、組織が関連するリスクへ対処し、この技術を利用する恩恵を享受できるように設計されています。
Kubernetesを侵害する3つの共通的な原因は、サプライチェーンリスク、悪意のあるアクター、内部における脅威です。
サプライチェーンのリスクはコンテナのビルドサイクルやインフラ環境の構築時に発生し、リスクを軽減するのは難しい場合が多いです。悪意のあるアクターはKubernetesアーキテクチャにおけるコントロールプレーン、ワーカーノード、コンテナ化されたアプリケーションのなどのコンポーネントの設定ミスや
脆弱性を利用することが可能です。内部における脅威は、管理者、ユーザ、クラウドサービスです。組織のKubernetes環境への特別なアクセス権を持つ内部の人や物が、これらの特権を悪用する可能性があります。
このガイダンスでは、Kubernetesクラスターのセットアップとセキュリティ確保に関連するセキュリティ上の課題について説明します。また設定ミスを避けるための強化策や国家安全保障システムの開発者や管理者がKubernetesの導入する場合の設定例、推奨されるセキュリティ強化策と緩和策を、設定例を示しています。このガイダンスでは以下の緩和策の詳細を説明しています。
- コンテナやPodの脆弱性や設定ミスのスキャン
- 最小限の権限でコンテナやPodを実行する
- ネットワークの分離により、ダメージの量をコントロールし食いとどめる
- 不必要なNWからのアクセスを制限するためにFirewallを利用し、通信は暗号化して機密性を確保する。
- 強力な認証と認可を使用してユーザと管理者のアクセスを制限し、攻撃対象領域を制限する
- 監査ログを利用して管理者がアクティビティを監視して悪意あるアクティビティの可能性となるものを警告できるようにする
- すべてのKubernetesの設定を定期的に見直し、かつ脆弱性スキャンを利用することでセキュリティパッチが適用されリスクが適切に考慮されていることを確実にする
その他のセキュリティ強化のガイダンスについては、Center for Internet SecurityのKubernetesベンチマーク、Docker and Kubernetes Security Technical Implementation Guides、
Cybersecurity and Infrastructure Security Agency(CISA)の分析レポート、Kubernetesのドキュメントなどを参照してください。
Introduction
K8sと略されることも多いKubernetesは、オープンソースのコンテナオーケストレーションシステムでありコンテナ化されたアプリケーションのデプロイ、スケーリング、管理を自動化するために利用されます。各マイクロサービスのアプリケーションからクラスター全体まで、クラスターを構成するすべての要素を管理します。コンテナ化されたマイクロサービスアプリケーションの利用は、モノリスなソフトウェアと比べてより柔軟性やセキュリティ面において恩恵をもたらしますが、別の複雑性をもたらします。
このガイダンスではセキュリティの課題とセキュリティの可能な限りの強化策を国家安全保障システムと重要なインフラストラクチャの管理者に提示します。このガイダンスは国家安全保障システムと重要なインフラストラクチャ組織を対象としていますが、連邦政府や州、地方政府の管理者でも推奨事項を実施することが求められます。Kubernetesクラスタのセキュリティは複雑で、設定ミスを悪用して危険な行為にしばしば悪用されてしまいます。このガイダンスでは、Kubernetesクラスタをよりセキュアにする具体的なのセキュリティ設定を紹介します。
Reccomendations
各セクションの主な推奨事項のまとめ:
- Kubernetes Pod security
- 非rootユーザでアプリケーションを実行するために作られたコンテナの使用
- 可能な限りイミュータブルなファイルシステムでコンテナを実行する
- 脆弱性や設定ミスの可能性を見つけるためコンテナイメージをスキャンする
- 最小限のセキュリティ権限にするためPodSecurityPolicyを利用する
- 特権コンテナの防止
- hostPID, hostIPC, hostNetwork, hostPathの許可のような脱獄に使われる機能を拒否する
- rootでの実行やrootへの昇格を許可するコンテナを拒否する
- SELinux, AppArmor, seccompなどのセキュリティサービスを利用してアプリケーションを悪用から守る
- Network separation and hardending
- RBACとFirewallでcontrol plane nodeへのアクセスを制限する
- さらにetcdへのアクセスを制限する
- TLS証明書を使用して認証された暗号化通信を行うようにControle planeのcomponentを構成する
- リソースを隔離するためにNetworkPolicyをセットする。異なるNamespaceのPodとServiceはNetworkPolicyで隔離を強制しない限りお互いに通信が可能である
- すべての認証情報と機密情報は設定ファイルではなくSecretに置く。強力な暗号化方式でSecretを暗号化する。
- Authentication and authorization
- 匿名Loginを無効にする(defaultでは有効)
- 強力なユーザ認証方式を利用する
- RBACを利用し管理者、ユーザ、ServiceAccountの活動を制限する
- Log auditing
- audit logを有効にする(defaultでは無効)
- node, Pod, containerレベルの障害に対しても可用性を確保してログを永続化する
- 必要ではなくなった時点でコンポーネントを環境から削除する
Architectural overview
※k8sのコンポーネント解説とかなのでSkip
Threat model
Kubernetesのデータや計算リソースは盗む価値のあるターゲットです。伝統的にデータ盗掘は第一目標である一方、計算リソース(多くの場合、暗号通貨のマイニングに)を求める攻撃者もKubernetes環境の利用に関心を引きます。計算リソースの盗掘に加えて、攻撃者はサービス妨害を目的としてターゲットとすることもあります。以下の脅威は、Kubernetesクラスターが危険になる可能性の高いものを示しています:
- サプライチェーンリスク - サプライチェーンの攻撃方法は多様であり、軽減するのが難しいです。サプライチェーンリスクは敵がシステムを構成する、製品の構成要素、最終的な製品を供給するサービスや人員などを含むあるゆる要素を破壊するリスクである。これはKubernetesクラスタを構築、管理するサードパーティソフトウェアやベンダーも含みます。サプライチェーンにおける危険性は複数のレベルでKubernetesに影響します:
- コンテナ/アプリケーションレベル - Kubernetesで実行しているアプリケーションと依存する3rdパーティのセキュリティは、開発者の信頼性と開発環境の防御力が頼りとなります。3rdパーティの悪意のあるコンテナやアプリケーションは攻撃者にクラスタ内で足場を与えることになります。
- インフラストラクチャ - Kubernetesをホストする基盤システムはそれぞれのソフトウェアとハードウェアに依存します。ワーカーノードやコントロールプレーンの一部として利用されるシステムへの侵入は攻撃者にクラスタ内で足場を与えることになります。
- 悪意のあるアクター - 悪意のあるアクターは脆弱性を突いてリモートから度々アクセスしてきます。Kubernetesアーキテクチャでは攻撃者が遠隔操作に利用可能となり得るいくつかのAPIを公開しています。
- コントロールプレーン - Kubernetesのコントロールプレーンはクラスタを追跡・管理するために通信する様々なコンポーネントがあります。攻撃者は適切なアクセス制限が行われていない、公開されているコントロールプレーンのエンドポイントを利用します。
- ワーカーノード - ワーカーノードはコンテナエンジンの実行に加えて、サイバー攻撃者に悪用される可能性のあるkubeletとkube-proxyサービスをホストします。さらにワーカーノードはロックダウンされたコントロールプレーンの外側に存在しており、攻撃者はよりアクセスしやすい可能性があります。
- コンテナアプリケーション - クラスタ内で実行されるアプリケーションは共通の攻撃対象です。アプリケーションはしばしばクラスタ外からアクセス可能であり、リモートの攻撃者から到達可能にさせます。攻撃者は既に侵入されたPodを利用したり、内部リソースにアクセス可能な公開されたアプリケーションを利用してクラスタ内で特権を昇格させます。
- 内部における脅威 - 脅威アクターは組織内で働いている間に脆弱性を突いたり、個別に与えられた権限を利用したりします。組織内の個人はKubernetesクラスタに対する特別な知識や権限が与えられます。
- 管理者 - Kubernetes管理者はコンテナ内の環境で任意のコマンドを実行できるなど 実行中のコンテナを制御することができます。KubernetesによるRBAC権限の強制により、機密情報へのアクセスを制限することでリスクを軽減することができます。しかしながらKubernetesは2人の人間による完全なコントロールを欠いているため、少なくても1つクラスタを制御できる管理的なアカウントが必要です。管理者はシステムやハイパーバイザーへの物理的なアクセスを持つことが多く、これが利用されKubernetes環境が危険に侵されることもあります。
- ユーザ - コンテナアプリケーションのユーザは、Kubernetesクラスタ内のコンテナサービスにアクセスできる情報と機密を持っているかもしれません。このレベルのアクセスは他のアプリケーションやクラスタのコンポーネント自身を悪用する十分な手段となります。
- クラウドサービスとインフラストラクチャプロバイダ - Kubernetesノードを管理する物理的なシステムやハイパーバイザへのアクセスはKubernetes環境を侵害することができます。多くの場合クラウドサービスプロバイダは特権的管理者からシステムを防御するために、技術的および管理的な制御を行います。
Kubernetes Pod security
PodはKubernetesにデプロイできる最小単位であり、1つまたはそれ以上のコンテナから構成されます。Podは攻撃者がコンテナを利用する最初の実行環境になります。こうした理由からPodは、脆弱性を利用されるのをより困難にし侵入された時の影響を制限するために堅牢にするべきです。
“Non-root” containers and “rootless” container engines
デフォルトでは多くのコンテナサービスが特権的なrootユーザで実行されており、特権による実行を必要としていないにもかかわらず、コンテナ内でアプリケーションはrootとして実行されています。非rootコンテナやrootlessコンテナエンジンの利用してroot実行を抑止することで、コンテナが侵入された際の影響を制限します。これらの方法はランタイム環境に大きく影響するので、アプリケーションの互換性を確実にするために十分なテストをする必要があります。
Non-root containers: コンテナエンジンはコンテナに非rootユーザ、非ルートグループでのアプリケーションでの実行を許可します。通常、このデフォルトでない設定はコンテナイメージのビルド時に設定されます。Appendix A: 非rootアプリケーションのDockerfileの例では、アプリケーションを非rootユーザで実行するDockerfileの例を紹介しています。あるいはKubernetesではSecurityContext:runAsUserでnon-zeroユーザ(rootユーザ以外)を設定することでコンテナをPodにロードすることができます。runAsUserはデプロイメントの実行を直接非rootで強制するのに効果的ですが、NSAとCISAは開発者にコンテナアプリケーションのビルドを非rootユーザで実行することを推奨します。ビルド時に非rootによる実行を行うことで、root権限がなくてもアプリケーションの動作が正しいことをより確実にします。
Rootless container engines: コンテナエンジンの中にはrootで実行するデーモンを使わずに、非特権コンテキストで実行できるものがあります。この場合コンテナエンジンの実行はコンテナアプリケーションからはrootユーザを利用して実行しているように見えますが、ホスト上のエンジンのユーザコンテキストにリマップされて実行されます。rootlessコンテナエンジンは効果的なセキュリティ層を提供しますが、現在リリースされているものの多くは実験的であり本番環境で使用すべきではありません。管理者は新しいこの技術を認識し、ベンダーがKubernetesと互換性のあるstable versionをリリースした時にrootlessコンテナエンジンの採用を考えるべきです。
Immutable container file systems
デフォルトではコンテナは自身のコンテキスト内でほぼ無制限の実行が許可されています。実行権限を奪取した攻撃者は、コンテナ内でファイルの作成、スクリプトのダウンロード、アプリケーションの変更が可能です。Kubernetesはコンテナのファイルシステムをロックダウン(書き込み不可)することで、攻撃者の侵入後の多くの活動を防ぐことが出来ます。しかしこれらの制限は正当なコンテナアプリケーションに影響し、クラッシュや例外的な動作を引き起こす結果となる可能性があります。正当なアプリケーションへのダメージを防ぐために、Kubernetes管理者はアプリケーションが書き込みを必要とするディレクトリに、read/writeファイルシステムをマウントすることができます。Appendix B: read-onlyのdeploymentテンプレートでは書き込み可能なディレクトリを使用したイミュータブルコンテナの例を紹介しています。
Building secure container images
コンテナイメージは通常scratchからコンテナをビルドするかレポジトリからpullしてきた既存のイメージを基に作成されます。信頼されたレポジトリを利用してコンテナをビルドすることに加えて、イメージスキャンはデプロイされたアプリケーションが安全性を確保する鍵となります。コンテナをビルドするワークフローを通じて、イメージをスキャンして期限切れのライブラリや既知の脆弱性、不要なポートやパーミッションなどの設定ミスを確認します。イメージスキャンを実装する方法の1つとしてadmission controllerを利用があります。admission controllerはKubernetesネイティブの機能であり、リクエストが認証と認可された後かつ、オブジェクト内容を永続化する前にKubernetes APIへのリクエストをインターセプトして処理することができます。カスタムまたは独自のWebhookを実装することでどのイメージもクラスタにdeployされる前にスキャンすることができます。このadmission controllerでは組織のセキュリティポリシーに従っていないイメージのdeployをブロックするWebhookの設定が定義されています。
Pod Security Policies
Pod Security Policy(PSP)はクラスタ内で実行されるPodにセキュリテイ要件/既定値を設定するクラスターワイドなポリシーです。多くの場合セキュリティ対策はPod/deploymentのマニフェスト内に設定されますが、PSPは全てのPodが順守しなければならない最低限のセキュリテイしきい値を設定します。PSPの設定項目ではPodの設定では省略されている場合に使用されるデフォルト値があります。他の設定項目では適合していないPodの作成を拒否するために使われます。PSPはKubernetesのadmission controllerを通じて強制されるので、Podを作成している間だけ要件を強制することができます。PSPは既にクラスタで実行中のPodには影響しません。
PSPはクラスタのセキュリティ対策を実行する有益な技術的コントロールです。PSPは階層化された役割を持つ管理者が管理するクラスタに非常に効果的です。このようなケースでは、最上位の管理者がデフォルトを賦課することで下位の管理者に要件を強制することができます。NSAとCISAは、Appendix C: Pod Security Policyの例にあるKubernetesを堅牢にするPSPテンプレートを組織の要件に応じて適合させることを奨励します。以下の表では、広く適用可能なPSPコンポーネントを説明します。
Table I: Pod Security Policy components
フィールド名 | 用途 | 推奨値 |
---|---|---|
privileged | Podが特権コンテナを実行できるか | false |
hostPID, hostIPC | コンテナとホストのprocess namespaceを共有できるか | false |
hostNetwork allowedHostPaths |
コンテナがホストのネットワークを利用できるか コンテナをホスト上の特定のファイルシステム のパスに制限する |
false ダミーのパス名を使う (read-onlyで "/foo"のような) このフィールを省略するとコンテナに admission controllerによる制限がかかりません |
readOnlyRootFilesystem | read-onlyのrootファイルシステムの利用が必要か | 可能であればtrue |
runAsUser, runAsGroup supplementalGroups, fsGroup |
コンテナアプリケーションがroot権限で実行できるか、 rootグループで実行できるか |
runAsUserはRunAsNonRootをセットしなければならない runAsGroupはnon-zero、0ではない値をセットする supplementalGroupsはnon-zero、0ではない値をセットする fsGroupはnon-zero、0ではない値をセットする |
allowPrivilegeEscalation seLinux |
root権限へのエスカレーションを制限する コンテナにSELinuxコンテキストをセットする |
falseにする。"runAsUser: MustRunAsNonRoot"の設定を効果的に実施するために必要な手段です もし環境がSELinuxをサポートしているのであれば、コンテナをより強固にするため SELinuxのラベルを追加することを考えましょう |
AppArmor annotations seccomp annotations |
コンテナで利用するAppArmorプロファイルをセットする コンテナで利用するseccompプロファイルをセットする |
可能であればAppArmorを採用してコンテナアプリケーションを堅牢にして搾取を制限します。 可能であればseccompのauditプロファイルを利用して実行中のアプリケーションが必要なsyscallを特定します それからseccompプロファイルで他のすべてのsyscallをブロックします |
Note: PSPは以下の利用からクラスタ全体に自動的に適用されません。
- まず初めにPSPを適用する前に、Kubernetes admission controllerのPodSecurityPolicyのプラグインをkube-apiserverで有効にします。
- 次にポリシーはRBACを通じて認証される必要があります。管理者はクラスタの組織内のそれぞれのroleから実装されたPSPは正しく機能しているか検証すべきです。
複数のPSPが存在する環境では管理者は、Podの作成が最も制限の少ないポリシーに沿っているかどうかに注意する必要があります。以下のコマンドはNamespaceに存在する全てのPod Securiry Policyを表示し、問題のあるポリシーの重複を特定するのに役立ちます。
kubectl get psp -n <namespace>
Protecting Pod service account tokens
デフォルトではKubernetesはPod作成時に自動的にservice accountをプロビジョニングし、実行時にPod内にアカウントのsecret tokenをマウントします。多くのコンテナアプリケーションはKubernetesのオーケストレーションがバックグラウンドで透過的に実行されるので、service accountに直接アクセスする必要はありません。もしアプリケーションに侵入されると、Pod内のaccount tokenを攻撃者に拾われ、さらにクラスタの侵入に利用されてしまいます。アプリケーションが直接service accountにアクセスする必要がない時は、Kubernetes管理者はPodがsecret tokenをmountする仕様を確実にdisableにするべきです。これは automountServiceAccountToken: false
をPodのyamlファイルに記述することで達成されます。
Hardening container engines
いくつかのプラットフォームとコンテナエンジンは、コンテナ環境を堅牢にする追加の方法を提供します。ハイパーバイザーを利用したコンテナの隔離は強力な例です。ハイパーバイザーはオペレーティングシステムではなく、ハードウェアを頼りに仮想化の境界を実行します。ハイパーバイザーの隔離はコンテナの隔離よりセキュアです。Windows OS上で実行するコンテナエンジンは、セキュリティを高めるためにWindowsビルドインのハイパーバイザーであるHyper-Vを使用するように設定することができます。またセキュリティに特化したコンテナエンジンは多重防御のために各コンテナを軽量なハイパーバイザー内で実行します。ハイパーバイザーを元にしたコンテナは、コンテナのブレイクアウトを軽減します。
Network separation and hardening
KubernetesクラスタのネットワークはKubernetesの中心的なコンセプトです。コンテナ、Pod、サービス、外部のサービス間の通信を考慮しなければいけません。デフォルトでは、クラスタに侵入された場合でもリソースを分離し、NW内での移動やエスカレーションを防ぐためのnetwork policyはほとんどありません。リソースの分離と暗号化は攻撃者のクラスタ内での行動とエスカレーションを制限する有効な手段です。
Key points
- リソースを分離、隔離するためnetwork policyとファイアウォールを利用する
- コントロールプレーンをセキュアにする
- 通信や機密情報(Secretなど)を暗号化する
Namespaces
Kubernetesのnamespacesは同一クラスタ内の多数のユーザ、チーム、アプリケーション間においてクラスタのリソースを分割する1つの方法です。デフォルトではnamespacesは自動的に分離されません。しかしnamespacesはスコープにラベルを付与することで、RBACやnetwork policyによる権限を指定することができます。ネットワークの分離に加えて、ポリシーによりストレージとコンピュータリソースを制限することでnamespaceレベルでPodに対して制限を強化することができます。
デフォルトでは3つのnamespacesが存在し、それらは削除できません。
- kube-system(Kubernetesコンポーネント用)
- kube-public(publicなリソース用)
- default(ユーザリソース用)
クラスタサービス用に用意されたkube-system, kube-publicにユーザのPodを置くべきではありません。Appendix D: Example namespaceのyamlファイルでは新しくnamespaceを作成する例を紹介しています。異なるnamespacesに存在するPodとServiceはnetwork policyなどで分離を強制しない限り、互いに通信可能です。
Network Policies
Network policyはPod, namespace, 外部のIPアドレス間の通信を制御します。デフォルトではPodやnamespaceにnetwork policyは適用されていないので、結果的にPodネットワーク内のingress、egressの通信は制限されていません。Podは、PodかPodのnamespaceに適用されるnetwork policyによって隔離されます。network policyでPodが選択されると、適用可能なポリシーオブジェクトで明示的に通信許可を設定されていない接続はすべて拒否されます。
Network Policies Checklist
- 使用するCNIプラグインがNetwork Policyをサポートしているか
- Podの選択にpodSelectorやnamespaceSelectorを使用してポリシーを作成する
- 全てのingress、egress通信を拒否するデフォルトのポリシーを使う。選択されていないPodがkube-system以外のnamespaceで隔離されるようにする。
- LimitRangeとResourceQuotaを使用してPodとnamespaceレベルでリソースを制限する
network policyを作成するには、ネットワークプラグイン(CNI)がNetworkPolicy APIをサポートしていることが必要です。PodはpodSelector
かnamespeceSelector
を使用して選択します。 Appendix E: Example network policyはnetwork policyの例を紹介しています。network policyのフォーマットはクラスタで使用されるCNIプラグインにより異なるかもしれません。管理者はすべてのPodを対象とするすべてのingress・egress通信を拒否するデフォルトポリシーを適用させて、選択されていないPodが隔離されるようにする必要があります。追加のポリシーはこれらの制限を緩和して接続を許可します。
外部のIPアドレスはingress・egressのポリシー内のipBlock
で指定することができますが、CNIプラグイン、クラウドプロバイダー、サービスの実装が異なると、NetworkPolicyの処理やクラスタ内のアドレス書き換えに影響する可能性があります。
Resource policies
network policyに加えてLimitRangeとResourceQuotaは、namespaceやノードのリソースの使用量を制限することができるポリシーです。LimitRangeポリシーは特定のnamespace内のPodやコンテナごとに、例えば最大のコンピュータリソースやストレージリソースなど個々のリソースを制限するものです。Appendix F: Example LimitRangeのyamlファイルで紹介するように、1つのnamespaceには1つのLimitRange制約のみ作成することができます。Kubernetes 1.10か1.10より新しいVersionで、LimitRangeはデフォルトでサポートされます。個々のPodやコンテナに適用するLimitRangeポリシーとは異なり、ResourceQuotaはnamespace全体においてリソース使用量を制限するもので、CPUやメモリ使用量の合計を制限するなどがあります。ユーザがLimitRangeやResourceQuotaポリシーに違反するPodを作成しようとすると、Podの作成は失敗します。Appendix G: Example ResourceQuotaにResourceQuotaポリシーの例を紹介します。
Control plane hardening
コントロールプレーンはKubernetesのコアであり、ユーザにコンテナの表示、新規Podのスケジューリング、Secretの読み込み、クラスタ内でのコマンド実行などの機能を提供します。このような機能を持つコントロールプレーンは大いに防御されている必要があります。TLS暗号化のようなセキュアな設定に加えて、RBACと強力な認証手法、ネットワークの分離は認証されていないユーザからのコントロールプレーンへのアクセスを防ぐのに役立ちます。Kubernetes APIサーバは6443と8080ポートで実行されますが、これらのポートをファイアウォールで保護し、期待されるトラフィックのみ受信するようにしてください。デフォルトで8080ポートはTLS暗号化なしでもローカルマシンからアクセス可能であり、リクエストは認証、認可モジュールをバイパスします。安全ではないポートは、APIサーバの--insecure-port=0
フラグを使用して無効にすることができます。Kubernetes APIサーバはインターネットや信頼できないネットワークに公開するべきではありません。kube-system namespaceにNetworkPolicyを適用することで、インターネットからkube-systemへのアクセスを制限することができます。デフォルトで拒否するポリシーがすべてのnamespaceに適用されている場合、kube-system namespaceは他のコントロールプレーンのセグメントやワーカーノードと通信できる必要があります。
以下の表はコントロールプレーンのポートとサービスの一覧です。
Table II: Control plane ports
プロトコル | 通信方向 | ポート | サービス |
---|---|---|---|
TCP | Inbound | 6443 or 8080(無効にしていなければ) | Kubernetes APIサーバ |
TCP | Inbound | 2379-2378 | etcdサーバ |
TCP | Inbound | 10250 | kubelet |
TCP | Inbound | 10251 | kube-scheduler |
TCP | Inbound | 10252 | kube-controller-manager |
TCP | Inbound | 10258 | cloud-controller-manager(オプション) |
Etcd
etcdのバックエンドデータベースには、Kubernetesクラスタの状態の情報とSecretが保存されています。コントロールプレーンの重要なコンポーネントであり、攻撃者がetcdへの書き込み権限を得るとクラスタ全体にrootアクセスが可能になります。etcdはクラスタの認証方法やRBACポリシーでユーザを制限できるAPIサーバを通じてのみアクセスする必要があります。etcdデータストアはコントロールプレーンのノードとは切り離して実行できるので、ファイアウォールでAPIサーバからのみアクセスを制限するようことができます。管理者はTLS証明書をセットアップし、APIサーバとetcdサーバ間のHTTPS通信で行うようにする必要があります。etcdサーバはAPIサーバに割り当てられたクライアント証明書のみを信頼するように設定する必要があります。
Kubeconfig Files
kubeconfig
ファイルにはクラスタ、ユーザ、namespace、認証メカニズムなど機密情報が含まれます。kubectl
コマンドはワーカーノードかコントロールプレーンのローカルマシンの$HOME/.kube
ディレクトリにある設定ファイルを利用します。攻撃者はこの設定ファイルが置かれたディレクトリへのアクセスを利用して、設定内容や認証情報を変更してクラスタのセキュリティを侵そうとします。設定ファイルは意図しない変更から防御されるべきであり、認証されていない非rootユーザによる設定ファイルへのアクセスはブロックする必要があります。
Worker node segmentation
ワーカーノードはクラスタの実装により、仮想マシンか物理マシンとなります。ノードはマイクロサービスの実行やクラスタのWebアプリケーションをホストするため、多くの場合攻撃対象となります。ノードに侵入された場合、管理者はワーカーノードがワーカーノードやKubernetesサービスと通信する必要のない他のネットワークセグメントから分離することで攻撃対象領域を積極的に制限する必要があります。ファイアウォールはネットワークに応じて、外部に公開しているワーカーノードやKubernetesのサービス全体を内部用ネットワークセグメントと分離するために使用できます。ワーカーノードの攻撃対象領域から分離する必要のあるサービスの例としては、機密情報を扱うデータベースやインターネットアクセスを必要としない内部サービスです。
以下の表はワーカーノードのポートとサービスの一覧です。
Table III: Worker node ports
プロトコル | 通信方向 | ポート | サービス |
---|---|---|---|
TCP | Inbound | 10250 | Kubelet API |
TCP | Inbound | 30000-32767 | NodePortサービス |
Encryption
管理者はKubernetesクラスタ内のすべての通信トラフィック、コンポーネント、ノード、コントロールプレーン間をTLS1.2か1.3を使用して暗号化する設定を行うべきです。暗号化の設定はインストール中に行うかインストール後にKubernetes documentationで説明されているTLSブートストラップを使用して証明書を作成し、ノードに配布することができます。いずれの方法でも安全に通信を行うため、ノード間に証明書を配布する必要があります。
Secret
Kubernetes SecretsはパスワードやOAuthトークン、SSHキーなど機密情報を扱います。機密情報をSecretsに保存することで、パスワードやトークンをyamlファイルやコンテナイメージ、環境変数に保存するよりも高度なアクセスコントロールが可能になります。デフォルトではKubernetesはSecretsを暗号化されていないbase64でエンコードした文字列を保存しており、APIにアクセスできる人なら誰でも取得することができます。APIアクセスはSecretsリソースへのRBACポリシーの適用で制限することができます。
SecretsはAPIサーバの保存時のデータ暗号化を行う設定やクラウドプロバイダーにより提供される外部のKey Management Service (KMS)で暗号化することができます。APIサーバで保存時のデータ暗号化を有効にするには、管理者はkube-apiserver
のマニフェストファイルを--encryption-provider-config
引数を使用して実行するように変更する必要があります。Appendix H: Example encryptionにencryptionprovider-config
の例があります。KMSプロバイダーを使用することで、生の暗号化キーをローカルディスクに保存されるのを防ぎます。KMSプロバイダーによるSecretsの暗号化は、Appendix I: Example KMS configurationのencryption-provider-config
ファイルのようにKMSプロバイダーを指定する必要があります。encryption-provider-config
ファイルを適用した後で、管理者は以下のコマンドを実行してすべてのSecretsを読み込んで暗号化する必要があります。
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
Protecting sensitive cloud infrastructure
多くの場合、Kubernetesはクラウド環境の仮想マシンにデプロイされます。そのため管理者はKubernetesのワーカーノードを実行する仮想マシンの攻撃対象領域を注意深く検討する必要があります。多くの場合、これらの仮想マシン上で実行するPodは、機密性の高いクラウドのメタデータサービスにルーティング不可能なアドレスでアクセスしています。これらのメタデータサービスは攻撃者にクラウド環境の情報やクラウドサービスへの一時的な認証情報を提供してしまいます。攻撃者はこれらのメタデータサービスを特権昇格を行うために悪用します。Kubernetes管理者はNetworkPolicyかクラウドの設定ポリシーの利用を通じて、Podからクラウドのメタデータサービスへのアクセスを防ぐ必要があります。これらのサービスはクラウドプロバイダーにより異なるので、管理者は各プロバイダーのガイドに沿って堅牢にする必要があります。
Authentication and authorization
認証と認可は、クラスタリソースへのアクセスを制限する重要な仕組みです。攻撃者はKubernetesのwell-knownポートをスキャンし、クラスタの設定ミスがあるとクラスタのデータベースにアクセスしたり認証せずにAPIを呼び出すことができます。ユーザ認証はKubernetesのビルトイン機能ではありません。しかし管理者がクラスタに認証を追加する方法はいくつかあります。
Authentication
KubernetesクラスタのユーザにはServiceAccountと一般ユーザの2つのタイプがあります。ServiceAccountはPodの代わりにAPIリクエストを処理します。認証はServiceAccount Admission Controllerを通じてKubernetesがbearerトークンを利用して自動的に管理します。bearerトークンはPod内のwell-knownな場所に自動的にマウントされており、トークンがセキュアではない状態だとクラスタ外部から利用可能です。このためPodのSecretsへのアクセスは、KubernetesのRBACを通じて表示する必要があるユーザのみに限定する必要があります。一般ユーザと管理者の場合、ユーザの自動認証方法はありません。管理者はクラスタに認証と認可の仕組みを実装するために、認証方法を追加する必要があります。
Kubernetesはクラスタから独立しているサービスがユーザ認証を管理することを想定としています。Kubernetes documentation ではクライアント証明書、bearerトークン、認証プラグイン、その他の認証プロトコルの実装方法をいくつか紹介しています。少なくともユーザ認証を1つは実装する必要があります。複数の認証方法を実装している場合、最初に認証リクエストが成功したモジュールで評価を短絡的に行います。管理者は静的なパスワードファイルのような弱い方法を使用すべきではありません。弱い認証方法は攻撃者が正当なユーザとして認証されてしまう可能性があります。
匿名のリクエストは設定されている他の認証方法で拒否されたリクエストであり、個々のユーザやPodに紐づけられることはありません。匿名リクエストを有効にしてトークン認証を設定したサーバでは、トークンが存在しないリクエストは匿名リクエストとして実行されます。Kubernetes 1.6以降では、匿名リクエストはデフォルトで有効になっています。RBACが有効の場合、匿名リクエストはsystem:anonymous
ユーザかsystem:unauthenticated
グループによる明示的な認可が必要です。匿名リクエストはAPIサーバに--anonymous=auth=false
オプションを渡すことで無効にするべきです。匿名リクエストを有効のままにしておくと、攻撃者がクラスタリソースに認証なしでアクセスできる可能性があります。
Role-based access control
RBACは組織内の個人の役割に基づきクラスタリソースへのアクセスを制御する方法の1つです。RBACはKubernetes 1.6以降でデフォルトで有効になっています。クラスタでRBACが有効になっているかkubectlコマンドで確認する場合は、kubectl api-version
を実行してください。.rbac.authorization.k8s.io/v1
のAPIバージョンが表示されれば有効です。クラウドのKubernetesサービスによってクラスタでRBACが有効かどうか確認する方法が異なる場合があります。RBACが有効でない場合は、APIサーバを--authorization-mode
フラグを付けて以下のコマンド開始します。
kube-apiserver --authorization-mode=RBAC
AlwaysAllow
のようなauthorization-modeのフラグを残しておくと、すべての認証リクエストは許可されてしまうため事実上すべての認証が無効となり、アクセスに対して最小限の権限を強制するように制限することができなくなります。
RoleとClusterRoleの2つのパーミッションタイプが設定できます: Roleは特定のNamespaceにパーミッションを設定しますが、ClusterRoleはNamespaceを関係なく全てのクラスタのリソースにパーミッションを設定します。 RoleとClusterRoleはパーミッションの追加にのみ使用できます。否定のルールはありません。クラスタにRBACの使用と匿名アクセスの無効が設定されている場合、KubernetesAPIサーバは明示的に許可されていないパーミッションを拒否します。RBAC Roleの例をAppendix J: Example podreader RBAC Roleで紹介します。
RoleとClusterRoleはパーミッションを定義しますが、パーミッションをユーザと紐付けることはしません。RoleBindingとClusterRoleBindingは、RoleとClusterRoleのパーミッションを定義されたNamespaceのユーザ、グループ、サービスアカウントに紐付けて付与します。ClusterRoleはNamespaceとは独立して作成され、RoleBindingを使用してNamespaceの範囲を制限して個人に付与します。ClusterRoleBindingはユーザ、グループ、サービスアカウントに全てのクラスタリソースを横断するClusterRoleを付与します。RoleBindingとClusterRoleBindingの例をAppendix K: Example RBAC RoleBinding and ClusterRoleBindingで紹介します。
RoleとClusterRoleを作成、更新するためには、ユーザが同じスコープで新しいロールに含まれるパーミッションを持っているか、rbac.authorization.k8s.io
APIグループのRoleかClusterRoleに対して操作を実行可能な明示的なパーミッションを持っている必要があります。bindingが作成された後はRoleとClusterRoleはイミュータブルです。roleを変更する場合はbindingを削除する必要があります。
ユーザ、グループ、サービスアカウントに割り当てられる権限は、最小権限の原則に従ってリソースに対して必要な権限のみを与える必要があります。ユーザやユーザグループは必要なリソースが存在する特定のNamespaceに制限することができます。デフォルトではサービスアカウントはPodがKubernetes APIにアクセスするためにそれぞれのNamespaceに作成されます。RBACポリシーを使用して、それぞれのNamespaceのサービスアカウントから許可するアクションを指定できます。Kubernetes APIへのアクセスは、適切なAPIリクエストの動作とアクションを適用する対象のリソースを持つRBACロールかClusterロールの作成で制限します。ユーザ、グループ、サービスアカウントに紐付けられたロールやClusterロールをプリントし、RBACポリシーの検査に役立つツールがあります。
Discussion