クラウドネイティブなワークロードをセキュアに維持するためのコンセプト
このセクションは、ワークロードをより安全に実行する方法やKubernetesクラスターのセキュリティを保つための重要な観点について学ぶのに役立ちます。
Kubernetesはクラウドネイティブアーキテクチャに基づいており、クラウドネイティブ情報セキュリティのグッドプラクティスについてのCNCF からのアドバイスを参考にしています。
クラスターとクラスター上で実行しているアプリケーションをどのように保護するかについての広い文脈を理解するためにクラウドネイティブセキュリティとKubernetesを参照してください。
KubernetesはいくつかのAPIとセキュリティコントロールを含んでいます。 Kubernetesには、情報セキュリティを管理する方法の一部を構成するポリシーを定義する方法のほか、いくつかのAPIとセキュリティコントロールが含まれています。
どのKubernetesのクラスターでも重要なセキュリティメカニズムはKubernetes APIへのアクセスコントロールです。
Kubernetesでは、コントロールプレーン内やコントロールプレーンとそのクライアント間でデータ転送中の暗号化を提供するために、TLSを設定し使用することが求められます。また、Kubernetesコントロールプレーン内に保存されているデータに対して保存データの暗号化を有効にすることもできます。これは、自身のワークロードのデータに対して保存データの暗号化を使用することとは別のもので、この方法もまた有効かもしれません。
Secret APIは機密性が必要な設定値の基本的な保護を提供します。
Podセキュリティ基準を順守して、Podやコンテナが適切に独立されるようにします。必要に応じてカスタムの分離を定義するためにRuntimeClassを使用することもできます。
ネットワークポリシーを使用すると、Pod間やPodとクラスター外との通信のネットワークトラフィックを制御できます。
Podやそのコンテナ、それらで実行されるイメージに対して、予防的または検出的なコントロールを実装するために周辺のエコシステムからセキュリティコントロールを導入することができます。
Kubernetesの監査ログはクラスター内でのアクションの一連の流れを時系列で記録し、セキュリティに関連する情報を提供します。クラスターはKubernetes APIを利用するユーザーやアプリケーション、コントロールプレーン自身によって生成されるアクティビティを監査します。
Kubernetesクラスターを自身のハードウェアや様々クラウドプロバイダーで実行している場合、セキュリティのベストプラクティスのドキュメントを参照してください。以下に、いくつかの主要なクラウドプロバイダーのセキュリティドキュメントへのリンクを示します。
| IaaSプロバイダー | リンク |
|---|---|
| Alibaba Cloud | https://www.alibabacloud.com/trust-center |
| Amazon Web Services | https://aws.amazon.com/security |
| Google Cloud Platform | https://cloud.google.com/security |
| Huawei Cloud | https://www.huaweicloud.com/intl/en-us/securecenter/overallsafety |
| IBM Cloud | https://www.ibm.com/cloud/security |
| Microsoft Azure | https://docs.microsoft.com/en-us/azure/security/azure-security |
| Oracle Cloud Infrastructure | https://www.oracle.com/security |
| Tencent Cloud | https://www.tencentcloud.com/solutions/data-security-and-information-protection |
| VMware vSphere | https://www.vmware.com/solutions/security/hardening-guides |
ネットワークポリシー(ネットワークパケットフィルタリングの宣言的制御)やアドミッションポリシーの検証 (Kubernetes APIを使用し誰が何を変更できるかの宣言的な制限)などのKubernetesネイティブメカニズムを使用し、セキュリティポリシーを定義することができます。
また、Kubernetesの周辺のエコシステムによるポリシーの実装に頼ることもできます。Kubernetesはエコシステムのプロジェクトに独自のポリシー制御を実装させるための拡張メカニズムを提供します。ソースコードレビューやコンテナイメージの承認、APIアクセスコントロール、ネットワーキングなどをポリシー制御に実装することができます。
関連するKubernetesセキュリティのトピックを学ぶためには:
背景について学ぶためには:
認定を取得するためには:
このセクションのさらなる詳細については:
この概要では、クラウドネイティブセキュリティにおけるKubernetesのセキュリティを考えるためのモデルを定義します。
セキュリティは階層で考えることができます。クラウドネイティブの4Cは、クラウド、クラスター、コンテナ、そしてコードです。
クラウドネイティブセキュリティモデルの各レイヤーは次の最も外側のレイヤー上に構築します。コードレイヤーは、強固な基盤(クラウド、クラスター、コンテナ)セキュリティレイヤーから恩恵を受けます。コードレベルのセキュリティに対応しても基盤レイヤーが低い水準のセキュリティでは守ることができません。
いろいろな意味でも、クラウド(または同じ場所に設置されたサーバー、企業のデータセンター)はKubernetesクラスターのトラステッド・コンピューティング・ベースです。クラウドレイヤーが脆弱な(または脆弱な方法で構成されている)場合、この基盤の上に構築されたコンポーネントが安全であるという保証はありません。各クラウドプロバイダーは、それぞれの環境でワークロードを安全に実行させるためのセキュリティの推奨事項を作成しています。
Kubernetesクラスターを所有しているハードウェアや様々なクラウドプロバイダー上で実行している場合、セキュリティのベストプラクティスに関するドキュメントを参考にしてください。ここでは人気のあるクラウドプロバイダーのセキュリティドキュメントの一部のリンクを紹介します。
| IaaSプロバイダー | リンク |
|---|---|
| Alibaba Cloud | https://www.alibabacloud.com/trust-center |
| Amazon Web Services | https://aws.amazon.com/security/ |
| Google Cloud Platform | https://cloud.google.com/security/ |
| Huawei Cloud | https://www.huaweicloud.com/intl/ja-jp/securecenter/overallsafety.html |
| IBM Cloud | https://www.ibm.com/cloud/security |
| Microsoft Azure | https://docs.microsoft.com/en-us/azure/security/azure-security |
| Oracle Cloud Infrastructure | https://www.oracle.com/security/ |
| VMWare VSphere | https://www.vmware.com/solutions/security/hardening-guides |
Kubernetesクラスターのインフラを保護するための提案です。
| Kubernetesインフラに関する懸念事項 | 推奨事項 |
|---|---|
| API Server(コントロールプレーン)へのネットワークアクセス | Kubernetesコントロールプレーンへのすべてのアクセスは、インターネット上での一般公開は許されず、クラスター管理に必要なIPアドレスに制限するネットワークアクセス制御リストによって制御されます。 |
| Nodeへのネットワークアクセス | Nodeはコントロールプレーンの特定ポート のみ 接続(ネットワークアクセス制御リストを介して)を受け入れるよう設定し、NodePortとLoadBalancerタイプのKubernetesのServiceに関する接続を受け入れるよう設定する必要があります。可能であれば、それらのNodeはパブリックなインターネットに完全公開しないでください。 |
| KubernetesからのクラウドプロバイダーAPIへのアクセス | 各クラウドプロバイダーはKubernetesコントロールプレーンとNodeに異なる権限を与える必要があります。最小権限の原則に従い、管理に必要なリソースに対してクラウドプロバイダーへのアクセスをクラスターに提供するのが最善です。KopsドキュメントにはIAMのポリシーとロールについての情報が記載されています。 |
| etcdへのアクセス | etcd(Kubernetesのデータストア)へのアクセスはコントロールプレーンのみに制限すべきです。設定によっては、TLS経由でetcdを利用する必要があります。詳細な情報はetcdドキュメントを参照してください。 |
| etcdの暗号化 | 可能な限り、保存時に全ドライブを暗号化することは良いプラクティスですが、etcdはクラスター全体(Secretを含む)の状態を保持しているため、そのディスクは特に暗号化する必要があります。 |
Kubernetesを保護する為には2つの懸念事項があります。
想定外または悪意のあるアクセスからクラスターを保護して適切なプラクティスを採用したい場合、クラスターの保護に関するアドバイスを読み従ってください。
アプリケーションを対象にした攻撃に応じて、セキュリティの特定側面に焦点をあてたい場合があります。例:他のリソースとの連携で重要なサービス(サービスA)と、リソース枯渇攻撃に対して脆弱な別のワークロード(サービスB)が実行されている場合、サービスBのリソースを制限していないとサービスAが危険にさらされるリスクが高くなります。次の表はセキュリティの懸念事項とKubernetesで実行されるワークロードを保護するための推奨事項を示しています。
| ワークロードセキュリティに関する懸念事項 | 推奨事項 |
|---|---|
| RBAC認可(Kubernetes APIへのアクセス) | https://kubernetes.io/ja/docs/reference/access-authn-authz/rbac/ |
| 認証 | https://kubernetes.io/docs/concepts/security/controlling-access/ |
| アプリケーションのSecret管理(およびetcdへの保存時に暗号化) | https://kubernetes.io/ja/docs/concepts/configuration/secret/ https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/ |
| PodSecurityPolicy | https://kubernetes.io/docs/concepts/policy/pod-security-policy/ |
| Quality of Service (およびクラスターリソース管理) | https://kubernetes.io/ja/docs/tasks/configure-pod-container/quality-service-pod/ |
| NetworkPolicy | https://kubernetes.io/ja/docs/concepts/services-networking/network-policies/ |
| Kubernetes IngressのTLS | https://kubernetes.io/ja/docs/concepts/services-networking/ingress/#tls |
コンテナセキュリティは本ガイドの範囲外になります。このトピックを検索するために一般的な推奨事項とリンクを以下に示します。
| コンテナに関する懸念事項 | 推奨事項 |
|---|---|
| コンテナの脆弱性スキャンとOS依存のセキュリティ | イメージをビルドする手順の一部として、既知の脆弱性がないかコンテナをスキャンする必要があります。 |
| イメージの署名と実施 | コンテナイメージを署名し、コンテナの中身に関する信頼性を維持します。 |
| 特権ユーザーを許可しない | コンテナの構成時に、コンテナの目的を実行するために必要最低限なOS特権を持ったユーザーをコンテナ内部に作成する方法のドキュメントを参考にしてください。 |
アプリケーションコードは、あなたが最も制御できる主要な攻撃対象のひとつです。アプリケーションコードを保護することはKubernetesのセキュリティトピックの範囲外ですが、アプリケーションコードを保護するための推奨事項を以下に示します。
| コードに関する懸念事項 | 推奨事項 |
|---|---|
| TLS経由のアクセスのみ | コードがTCP通信を必要とする場合は、事前にクライアントとのTLSハンドシェイクを実行してください。 いくつかの例外を除いて、全ての通信を暗号化してください。さらに一歩すすめて、サービス間のネットワークトラフィックを暗号化することはよい考えです。これは、サービスを特定した2つの証明書で通信の両端を検証する相互認証、またはmTLSして知られているプロセスを通じて実行できます。 |
| 通信ポートの範囲制限 | この推奨事項は一目瞭然かもしれませんが、可能なかぎり、通信とメトリクス収集に必要不可欠なサービスのポートのみを公開します。 |
| サードパティに依存するセキュリティ | 既知の脆弱性についてアプリケーションのサードパーティ製ライブラリーを定期的にスキャンすることを推奨します。それぞれの言語は自動でこのチェックを実行するツールを持っています。 |
| 静的コード解析 | ほとんどの言語ではコードのスニペットを解析して、安全でない可能性のあるコーディングを分析する方法が提供しています。可能な限り、コードベースでスキャンして、よく起こるセキュリティエラーを検出できる自動ツールを使用してチェックを実行すべきです。一部のツールはここで紹介されています。 https://owasp.org/www-community/Source_Code_Analysis_Tools |
| 動的プロービング攻撃 | よく知られているいくつかのサービス攻撃をサービスに対して試すことができる自動ツールがいくつかあります。これにはSQLインジェクション、CSRF、そしてXSSが含まれます。よく知られている動的解析ツールはOWASP Zed Attack proxytoolです。 |
関連するKubernetesセキュリティについて学びます。
Podに対するセキュリティの設定は通常Security Contextを使用して適用されます。Security ContextはPod単位での特権やアクセスコントロールの定義を実現します。
クラスターにおけるSecurity Contextの強制やポリシーベースの定義はPod Security Policyによって実現されてきました。 Pod Security Policy はクラスターレベルのリソースで、Pod定義のセキュリティに関する設定を制御します。
しかし、PodSecurityPolicyを拡張したり代替する、ポリシーを強制するための多くの方法が生まれてきました。 このページの意図は、推奨されるPodのセキュリティプロファイルを特定の実装から切り離して詳しく説明することです。
まず、幅広いセキュリティの範囲をカバーできる、基礎となるポリシーの定義が必要です。 それらは強く制限をかけるものから自由度の高いものまでをカバーすべきです。
特権ポリシーは意図的に開放されていて、完全に制限がかけられていません。この種のポリシーは通常、特権ユーザーまたは信頼されたユーザーが管理する、システムまたはインフラレベルのワークロードに対して適用されることを意図しています。
特権ポリシーは制限がないことと定義されます。gatekeeperのようにデフォルトで許可される仕組みでは、特権プロファイルはポリシーを設定せず、何も制限を適用しないことにあたります。 一方で、Pod Security Policyのようにデフォルトで拒否される仕組みでは、特権ポリシーでは全ての制限を無効化してコントロールできるようにする必要があります。
ベースライン、デフォルトのプロファイルは一般的なコンテナ化されたランタイムに適用しやすく、かつ既知の特権昇格を防ぐことを意図しています。 このポリシーはクリティカルではないアプリケーションの運用者または開発者を対象にしています。 次の項目は強制、または無効化すべきです。
| 項目 | ポリシー |
| ホストのプロセス |
Windows Podは、Windowsノードへの特権的なアクセスを可能にするHostProcessコンテナを実行する機能を提供します。ベースラインポリシーでは、ホストへの特権的なアクセスは禁止されています。HostProcess Podは、Kubernetes v1.22時点ではアルファ版の機能です。 ホストのネームスペースの共有は無効化すべきです。 制限されるフィールド
認められる値
|
| ホストのネームスペース |
ホストのネームスペースの共有は無効化すべきです。 制限されるフィールド: spec.hostNetwork spec.hostPID spec.hostIPC 認められる値: false, Undefined/nil |
| 特権コンテナ |
特権を持つPodはほとんどのセキュリティ機構を無効化できるので、禁止すべきです。 制限されるフィールド: spec.containers[*].securityContext.privileged spec.initContainers[*].securityContext.privileged spec.ephemeralContainers[*].securityContext.privileged 認められる値: false, undefined/nil |
| ケーパビリティー |
デフォルトよりも多くのケーパビリティーを与えることは禁止すべきです。 制限されるフィールド: spec.containers[*].securityContext.capabilities.add spec.initContainers[*].securityContext.capabilities.add spec.ephemeralContainers[*].securityContext.capabilities.add 認められる値: Undefined/nil AUDIT_WRITE CHOWN DAC_OVERRIDE FOWNER FSETID KILL MKNOD NET_BIND_SERVICE SETFCAP SETGID SETPCAP SETUID SYS_CHROOT |
| HostPathボリューム |
HostPathボリュームは禁止すべきです。 制限されるフィールド: spec.volumes[*].hostPath 認められる値: undefined/nil |
| ホストのポート |
HostPortは禁止するか、最小限の既知のリストに限定すべきです。 制限されるフィールド: spec.containers[*].ports[*].hostPort spec.initContainers[*].ports[*].hostPort spec.ephemeralContainers[*].ports[*].hostPort 認められる値: 0, undefined (または既知のリストに限定) |
| AppArmor(任意) |
サポートされるホストでは、AppArmorの'runtime/default'プロファイルがデフォルトで適用されます。デフォルトのポリシーはポリシーの上書きや無効化を防ぎ、許可されたポリシーのセットを上書きできないよう制限すべきです。 制限されるフィールド: metadata.annotations['container.apparmor.security.beta.kubernetes.io/*'] 認められる値: 'runtime/default', undefined, localhost/* |
| SELinux (任意) |
SELinuxのオプションをカスタムで設定することは禁止すべきです。 制限されるフィールド: spec.securityContext.seLinuxOptions spec.containers[*].securityContext.seLinuxOptions spec.initContainers[*].securityContext.seLinuxOptions spec.ephemeralContainers[*].securityContext.seLinuxOptions.type 認められる値:undefined/nil Undefined/"" container_t container_init_t container_kvm_t 制限されるフィールド: spec.securityContext.seLinuxOptions.user spec.containers[*].securityContext.seLinuxOptions.user spec.initContainers[*].securityContext.seLinuxOptions.user spec.ephemeralContainers[*].securityContext.seLinuxOptions.user spec.securityContext.seLinuxOptions.role spec.containers[*].securityContext.seLinuxOptions.role spec.initContainers[*].securityContext.seLinuxOptions.role spec.ephemeralContainers[*].securityContext.seLinuxOptions.role 認められる値:undefined/nil Undefined/"" |
| /procマウントタイプ |
攻撃対象を縮小するため/procのマスクを設定し、必須とすべきです。 制限されるフィールド: spec.containers[*].securityContext.procMount spec.initContainers[*].securityContext.procMount spec.ephemeralContainers[*].securityContext.procMount 認められる値:undefined/nil, 'Default' |
| Seccomp |
Seccompプロファイルを明示的に Restricted Fields
Allowed Values
|
| Sysctl |
Sysctlはセキュリティ機構を無効化したり、ホストの全てのコンテナに影響を与えたりすることが可能なので、「安全」なサブネットを除いては禁止すべきです。
コンテナまたはPodの中にsysctlがありネームスペースが分離されていて、同じノードの別のPodやプロセスから分離されている場合はsysctlは安全だと考えられます。 制限されるフィールド: spec.securityContext.sysctls 認められる値: kernel.shm_rmid_forced net.ipv4.ip_local_port_range net.ipv4.tcp_syncookies net.ipv4.ping_group_range undefined/空文字列 |
制限ポリシーはいくらかの互換性を犠牲にして、Podを強化するためのベストプラクティスを強制することを意図しています。 セキュリティ上クリティカルなアプリケーションの運用者や開発者、また信頼度の低いユーザーも対象にしています。 下記の項目を強制、無効化すべきです。
| 項目 | ポリシー |
| デフォルトプロファイルにある項目全て | |
| Volumeタイプ |
HostPathボリュームの制限に加え、制限プロファイルではコアでない種類のボリュームの利用をPersistentVolumeにより定義されたものに限定します。 制限されるフィールド: spec.volumes[*].hostPath spec.volumes[*].gcePersistentDisk spec.volumes[*].awsElasticBlockStore spec.volumes[*].gitRepo spec.volumes[*].nfs spec.volumes[*].iscsi spec.volumes[*].glusterfs spec.volumes[*].rbd spec.volumes[*].flexVolume spec.volumes[*].cinder spec.volumes[*].cephfs spec.volumes[*].flocker spec.volumes[*].fc spec.volumes[*].azureFile spec.volumes[*].vsphereVolume spec.volumes[*].quobyte spec.volumes[*].azureDisk spec.volumes[*].portworxVolume spec.volumes[*].scaleIO spec.volumes[*].storageos spec.volumes[*].photonPersistentDisk 認められる値: undefined/nil |
| 特権昇格 |
特権昇格(ファイルモードのset-user-IDまたはset-group-IDのような方法による)は禁止すべきです。 制限されるフィールド: spec.containers[*].securityContext.allowPrivilegeEscalation spec.initContainers[*].securityContext.allowPrivilegeEscalation spec.ephemeralContainers[*].securityContext.allowPrivilegeEscalation 認められる値: false |
| root以外での実行 |
コンテナはroot以外のユーザーで実行する必要があります。 制限されるフィールド: spec.securityContext.runAsNonRoot spec.containers[*].securityContext.runAsNonRoot spec.initContainers[*].securityContext.runAsNonRoot spec.ephemeralContainers[*].securityContext.runAsNonRoot 認められる値: true |
| root以外のグループ (任意) |
コンテナをrootのプライマリまたは補助GIDで実行することを禁止すべきです。 制限されるフィールド: spec.securityContext.runAsGroup spec.securityContext.supplementalGroups[*] spec.securityContext.fsGroup spec.containers[*].securityContext.runAsGroup spec.initContainers[*].securityContext.runAsGroup 認められる値: 0以外 undefined / nil (`*.runAsGroup`を除く) |
| Seccomp |
SeccompのRuntimeDefaultを必須とする、または特定の追加プロファイルを許可することが必要です。 制限されるフィールド: spec.securityContext.seccompProfile.type spec.containers[*].securityContext.seccompProfile spec.initContainers[*].securityContext.seccompProfile 認められる値: 'runtime/default' undefined / nil |
| Capabilities (v1.22+) |
コンテナはすべてのケイパビリティを削除する必要があり、 Restricted Fields
Allowed Values
Restricted Fields
Allowed Values
|
ポリシーの定義とポリシーの実装を切り離すことによって、ポリシーを強制する機構とは独立して、汎用的な理解や複数のクラスターにわたる共通言語とすることができます。
機構が成熟してきたら、ポリシーごとに下記に定義されます。それぞれのポリシーを強制する方法についてはここでは定義しません。
ここで定義されている3つのプロファイルは最も安全(制限)から最も安全ではない(特権)まで、直線的に段階が設定されており、幅広いワークロードをカバーしています。 ベースラインを超える特権が必要な場合、その多くはアプリケーションに特化しているため、その限られた要求に対して標準的なプロファイルを提供することはできません。 これは、このような場合に必ず特権プロファイルを使用すべきだという意味ではなく、場合に応じてポリシーを定義する必要があります。
将来、他のプロファイルの必要性が明らかになった場合、SIG Authはこの方針について再考する可能性があります。
Security Contextは実行時のコンテナやPodを設定するものです。 Security ContextはPodのマニフェストの中でPodやコンテナの仕様の一部として定義され、コンテナランタイムへ渡されるパラメーターを示します。
セキュリティポリシーはコントロールプレーンの機構で、Security Contextとそれ以外も含め、特定の設定を強制するものです。 2020年2月時点では、ネイティブにサポートされているポリシー強制の機構はPod Security Policyです。これはクラスター全体にわたってセキュリティポリシーを中央集権的に強制するものです。 セキュリティポリシーを強制する他の手段もKubernetesのエコシステムでは開発が進められています。例えばOPA Gatekeeperがあります。
Kubernetesでは、Linuxベースのワークロードと比べてWindowsの使用は制限や差異があります。 特に、PodのSecurityContextフィールドはWindows環境では効果がありません。 したがって、現段階では標準化されたセキュリティポリシーは存在しません。
Windows Podに制限付きプロファイルを適用すると、実行時にPodに影響が出る場合があります。 制限付きプロファイルでは、Linux固有の制限(seccompプロファイルや特権昇格の不許可など)を適用する必要があります。 kubeletおよび/またはそのコンテナランタイムがこれらのLinux固有の値を無視した場合、Windows Podは制限付きプロファイル内で正常に動作します。 ただし、強制力がないため、Windows コンテナを使用するPodについては、ベースラインプロファイルと比較して追加の制限はありません。
HostProcess Podを作成するためのHostProcessフラグの使用は、特権的なポリシーに沿ってのみ行われるべきです。 Windows HostProcess Podの作成は、ベースラインおよび制限されたポリシーの下でブロックされているため、いかなるHostProcess Podも特権的であるとみなされるべきです。
現在のところ、Podがサンドボックス化されていると見なされるかどうかを制御できるAPI標準はありません。 サンドボックス化されたPodはサンドボックス化されたランタイム(例えばgVisorやKata Containers)の使用により特定することは可能ですが、サンドボックス化されたランタイムの標準的な定義は存在しません。
サンドボックス化されたランタイムに対して必要な保護は、それ以外に対するものとは異なります。 例えば、ワークロードがその基になるカーネルと分離されている場合、特権を制限する必要性は小さくなります。 これにより、強い権限を必要とするワークロードが隔離された状態を維持できます。
加えて、サンドボックス化されたワークロードの保護はサンドボックス化の実装に強く依存します。 したがって、全てのサンドボックス化されたワークロードに推奨される単一のポリシーは存在しません。
Kubernetesはクラウドネイティブアーキテクチャに基づいており、クラウドネイティブ情報セキュリティのグッドプラクティスに関するアドバイスをCNCFから受けています。
このページを読み進めることで、安全なクラウドネイティブプラットフォームをデプロイするためにKubernetesがどのように設計されているかについての概要を知ることができます。
クラウドネイティブセキュリティに関するCNCFホワイトペーパーでは、さまざまな ライフサイクルフェーズ に適したセキュリティコントロールとプラクティスが定義されています。
これを実現するためには、次のようなことができます:
これを実現するためには、次のようなことができます:
何をデプロイできるか、誰がデプロイできるか、どこにデプロイできるかに関する適切な制限を確保します。 コンテナイメージアーティファクトの暗号化されたアイデンティティを検証するなど、Distribute フェーズからの対策を適用できます。
Kubernetesをデプロイすると、アプリケーションのランタイム環境の基盤、つまりKubernetesクラスター(または複数のクラスター)も設定されます。 ITインフラストラクチャは、より高いレイヤーが期待するセキュリティ保証を提供する必要があります。
Runtimeフェーズは、コンピューティング、アクセス、およびストレージの3つの重要な領域から構成されます。
Kubernetes APIはクラスターを機能させるためのものです。 このAPIを保護することは、効果的なクラスターセキュリティを提供するための鍵となります。
Kubernetesドキュメント内の他のページでは、アクセスコントロールの特定の側面を設定する方法について詳しく説明しています。 セキュリティチェックリストには、クラスターの基本的なチェックを行うための提案が記載されています。
さらに、APIアクセスのための効果的な認証と認可を実装することがクラスターのセキュリティを確保することにつながります。 サービスアカウントを使用して、ワークロードとクラスターコンポーネントのセキュリティアイデンティティを提供および管理します。
KubernetesはTLSを使用してAPIトラフィックを保護します。 (ノードとコントロールプレーン間のトラフィックを含めて)TLSを使用してクラスターをデプロイし、暗号化キーを保護してください。 CertificateSigningRequestsにKubernetes独自のAPIを使用する場合は、その悪用を制限するために特に注意を払ってください。
コンテナは、異なるアプリケーション間の分離と、それらの分離されたアプリケーションを同じホストコンピューターで実行するメカニズムの2つを提供します。 これらの2つの側面、分離と集約は、ランタイムセキュリティとのトレードオフがあり、適切なバランスを見つける必要があることを意味します。
Kubernetesは実際にコンテナを設定して実行するためにコンテナランタイムに依存しています。 Kubernetesプロジェクトは特定のコンテナランタイムを推奨しておらず、選択したランタイムが情報セキュリティの要件を満たしていることを確認する必要があります。
ランタイムでコンピューティングを保護するために、次のことができます:
アプリケーションのPodのセキュリティ標準を強制することで、アプリケーションが必要な権限のみで実行されるようにします。
コンテナ化されたワークロードを実行するために、特別に設計されたオペレーティングシステムをノード上で実行します。 これは通常、コンテナの実行に不可欠なサービスのみを提供する読み取り専用オペレーティングシステム(イミュータブルイメージ)に基づいています。
コンテナ固有のオペレーティングシステムは、システムコンポーネントを分離し、コンテナエスケープが発生した際の攻撃対象領域を減らすのに役立ちます。
ResourceQuotasを定義して、共有リソースを公平に割り当て、Podがリソース要件を指定できるようにするためにLimitRangesなどのメカニズムを使用します。
異なるノード間でワークロードを分割します。 Kubernetes自体またはエコシステムのいずれかからノードの分離メカニズムを使用して、異なる信頼コンテキストのPodが別個のノードセットで実行されるようにします。
セキュリティ制約を提供するコンテナランタイムを使用します。
クラスターのストレージとそこで実行されるアプリケーションの保護のために、次のことができます:
暗号化キーについては、専用のハードウェア内で生成することで、漏洩リスクに対する最善の保護を提供します。 ハードウェアセキュリティモジュール を使用すると、セキュリティキーを他の場所にコピーすることなく暗号化操作を実施できます。
ネットワークポリシーやサービスメッシュなどのネットワークセキュリティ対策の検討もまた重要です。 Kubernetesの一部のネットワークプラグインは、仮想プライベートネットワーク(VPN)オーバーレイなどの技術を使用して、クラスターネットワークの暗号化を提供します。 設計上、Kubernetesはクラスターに独自のネットワークプラグインを使用することを許可しています(マネージドKubernetesを使用している場合、クラスターを管理している個人または組織がネットワークプラグインを選択している可能性があります)。
選択したネットワークプラグインとその統合方法は、転送中の情報のセキュリティに大きな影響を与える可能性があります。
Kubernetesを使用すると、追加のツールを使用してクラスターを拡張できます。 サードパーティのソリューションをセットアップすることで、アプリケーションと実行中のクラスターを監視またはトラブルシューティングするのに役立ちます。 Kubernetes自体にもいくつかの基本的なオブザーバビリティ機能が組み込まれています。 コンテナ内で実行されるコードは、ログの生成、メトリクスの公開、その他の可観測性データの提供ができます。 デプロイ時に、クラスターが適切な保護レベルを提供していることを確認する必要があります。
メトリクスダッシュボードやそれに類似するものをセットアップする場合、そのダッシュボードにデータを投入する一連のコンポーネントと、ダッシュボード自体を確認してください。 クラスターの機能が低下するようなインシデントが発生している場合でも信頼できるように、全体のチェーンが十分な回復力と整合性保護を備えて設計されていることを確認してください。
必要に応じて、(ログや監査レコードの忠実性を確保するのに役立つ)暗号化されたメジャーブートや認証された時間配分など、Kubernetes自体よりも下位のセキュリティ対策をデプロイしてください。
高い信頼性の環境のために、ログの改ざん防止と機密性を確保するために暗号化保護をデプロイしてください。
Kubernetes v1.23 [beta]
KubernetesのPodセキュリティの標準はPodに対して異なる分離レベルを定義します。 これらの標準によって、Podの動作をどのように制限したいかを、明確かつ一貫した方法で定義することができます。
ベータ版機能として、KubernetesはPodSecurityPolicyの後継である組み込みの Pod Security アドミッションコントローラーを提供しています。 Podセキュリティの制限は、Pod作成時に名前空間レベルで適用されます。
PodSecurityアドミッションプラグインの有効化v1.23において、PodSecurityのフィーチャーゲートはベータ版の機能で、デフォルトで有効化されています。
v1.22において、PodSecurityのフィーチャーゲートはアルファ版の機能で、組み込みのアドミッションプラグインを使用するには、kube-apiserverで有効にする必要があります。
--feature-gates="...,PodSecurity=true"
PodSecurityアドミッションwebhookのインストールクラスターがv1.22より古い、あるいはPodSecurity機能を有効にできないなどの理由で、ビルトインのPodSecurityアドミッションプラグインが使えない環境では、PodSecurityはアドミッションロジックはベータ版のvalidating admission webhookとしても提供されています。
ビルド前のコンテナイメージ、証明書生成スクリプト、マニフェストの例は、https://git.k8s.io/pod-security-admission/webhookで入手可能です。
インストール方法:
git clone git@github.com:kubernetes/pod-security-admission.git
cd pod-security-admission/webhook
make certs
kubectl apply -k .
Podのセキュリティアドミッションは、PodのSecurity Contextとその他の関連フィールドに、Podセキュリティの標準で定義された3つのレベル、privileged、baseline、restrictedに従って要件を設定するものです。
これらの要件の詳細については、Podセキュリティの標準のページを参照してください。
この機能を有効にするか、Webhookをインストールすると、名前空間を設定して、各名前空間でPodセキュリティに使用したいadmission controlモードを定義できます。 Kubernetesは、名前空間に使用したい定義済みのPodセキュリティの標準レベルのいずれかを適用するために設定できるラベルのセットを用意しています。 選択したラベルは、以下のように違反の可能性が検出された場合にコントロールプレーンが取るアクションを定義します。
| モード | 説明 |
|---|---|
| enforce | ポリシーに違反した場合、Podは拒否されます。 |
| audit | ポリシー違反は、監査ログに記録されるイベントに監査アノテーションを追加するトリガーとなりますが、それ以外は許可されます。 |
| warn | ポリシーに違反した場合は、ユーザーへの警告がトリガーされますが、それ以外は許可されます。 |
名前空間は、任意のまたはすべてのモードを設定することができ、異なるモードに対して異なるレベルを設定することもできます。
各モードには、使用するポリシーを決定する2つのラベルがあります。
# モードごとのレベルラベルは、そのモードに適用するポリシーレベルを示す。
#
# MODEは`enforce`、`audit`、`warn`のいずれかでなければならない。
# LEVELは`privileged`、`baseline`、`restricted`のいずれかでなければならない。
pod-security.kubernetes.io/<MODE>: <LEVEL>
# オプション: モードごとのバージョンラベルは、Kubernetesのマイナーバージョンに同梱される
# バージョンにポリシーを固定するために使用できる(例えばv1.35など)。
#
# MODEは`enforce`、`audit`、`warn`のいずれかでなければならない。
# VERSIONは有効なKubernetesのマイナーバージョンか`latest`でなければならない。
pod-security.kubernetes.io/<MODE>-version: <VERSION>
名前空間ラベルでのPodセキュリティの標準の適用で使用例を確認できます。
Podは、DeploymentやJobのようなワークロードオブジェクトを作成することによって、しばしば間接的に生成されます。 ワークロードオブジェクトは_Pod template_を定義し、ワークロードリソースのコントローラーはそのテンプレートに基づきPodを作成します。 違反の早期発見を支援するために、auditモードとwarningモードは、ワークロードリソースに適用されます。 ただし、enforceモードはワークロードリソースには適用されず、結果としてのPodオブジェクトにのみ適用されます。
Podセキュリティの施行から exemptions を定義することで、特定の名前空間に関連するポリシーのために禁止されていたPodの作成を許可することができます。 Exemptionはアドミッションコントローラーの設定で静的に設定することができます。
Exemptionは明示的に列挙する必要があります。
Exemptionを満たしたリクエストは、アドミッションコントローラーによって 無視 されます(enforce、audit、warnのすべての動作がスキップされます)。Exemptionの次元は以下の通りです。
system:serviceaccount:kube-system:replicaset-controllerなど)は通常、除外してはいけません。そうした場合、対応するワークロードリソースを作成できるすべてのユーザーを暗黙的に除外してしまうためです。以下のPodフィールドに対する更新は、ポリシーチェックの対象外となります。つまり、Podの更新要求がこれらのフィールドを変更するだけであれば、Podが現在のポリシーレベルに違反していても拒否されることはありません。
seccomp.security.alpha.kubernetes.io/pod(非推奨)container.seccomp.security.alpha.kubernetes.io/*(非推奨)container.apparmor.security.beta.kubernetes.io/*.spec.activeDeadlineSecondsに対する有効な更新.spec.tolerationsに対する有効な更新このページではKubernetesのServiceAccountオブジェクトについて説明し、どのようにサービスアカウントが機能するか、使用例、制限、代替手段、追加のガイダンスとなるリソースへのリンクを紹介します。
サービスアカウントは、Kubernetesにおいて、Kubernetesクラスター内で固有のアイデンティティを提供する人間以外のアカウントの一種です。 アプリケーションPod、システムコンポーネント、およびクラスター内外のエンティティは、特定のServiceAccountの認証情報を使用してそのServiceAccountとして識別できます。 このアイデンティティは、APIサーバーへの認証やアイデンティティベースのセキュリティポリシーの実装など、さまざまな状況で役立ちます。
サービスアカウントは、APIサーバー内のServiceAccountオブジェクトとして存在します。 サービスアカウントには次の特性があります:
Namespaced: 各サービスアカウントはKubernetesのnamespaceにバインドされます。
各namespaceは作成時にdefault ServiceAccountを取得します。
Lightweight: サービスアカウントはクラスター内に存在し、Kubernetes APIで定義されています。 特定のタスクを有効にするためにサービスアカウントを素早く作成できます。
Portable: 複雑なコンテナ化されたワークロードの構成バンドルには、システムのコンポーネントのサービスアカウント定義が含まれる場合があります。 サービスアカウントの軽量性と名前空間内のアイデンティティは、構成をポータブルにします。
サービスアカウントは、クラスター内の認証された人間のユーザーであるユーザーアカウントとは異なります。 デフォルトでは、KubernetesのAPIサーバーにユーザーアカウントは存在しません。代わりに、APIサーバーはユーザーのアイデンティティを不透明なデータとして扱います。 複数の方法を使用して、ユーザーアカウントとして認証できます。 一部のKubernetesディストリビューションでは、APIサーバーでユーザーアカウントを表すカスタム拡張APIが追加されることがあります。
| 説明 | ServiceAccount | ユーザーまたはグループ |
|---|---|---|
| ロケーション | Kubernetes API (ServiceAccountオブジェクト) | 外部 |
| アクセス制御 | Kubernetes RBACまたはその他の認可メカニズム | Kubernetes RBACまたはその他のアイデンティティおよびアクセス管理メカニズム |
| 使用目的 | ワークロード、自動化 | 人間 |
クラスターを作成すると、Kubernetesはクラスター内の各Namespaceに対してdefaultという名前のServiceAccountオブジェクトを自動的に作成します。
各Namespaceのdefaultサービスアカウントは、ロールベースのアクセス制御(RBAC)が有効になっている場合、Kubernetesがすべての認証されたプリンシパルに付与するデフォルトのAPI検出権限以外の権限をデフォルトで取得しません。
Namespace内のdefault ServiceAccountオブジェクトを削除すると、コントロールプレーンが新しいServiceAccountオブジェクトを作成します。
NamespaceにPodをデプロイし、Podに手動でServiceAccountを割り当てない場合、KubernetesはそのNamespaceのdefault ServiceAccountをPodに割り当てます。
一般的なガイドラインとして、次のシナリオでサービスアカウントを使用できます:
example NamespaceのPodがkube-node-lease NamespaceのLeaseオブジェクトを読み取り、一覧、監視することを許可します。imagePullSecretを使用してプライベートイメージレジストリに認証する場合。Kubernetesサービスアカウントを使用するには、次の手順を実行します:
kubectlなどのKubernetesクライアントを使用してServiceAccountオブジェクトを作成するか、オブジェクトを定義するマニフェストを使用します。
RBACなどの認可メカニズムを使用してServiceAccountオブジェクトに権限を付与します。
Podの作成時にServiceAccountオブジェクトをPodに割り当てます。
外部サービスからのアイデンティティを使用している場合は、ServiceAccountトークンを取得し、そのサービスから使用します。
詳細な手順については、PodにServiceAccountを割り当てるを参照してください。
各ServiceAccountに必要な最小限の権限を付与するために、Kubernetesビルトインのロールベースのアクセス制御(RBAC)メカニズムを使用できます。 ServiceAccountにアクセスを付与するロールを作成し、そのロールをServiceAccountにバインドします。 RBACを使用すると、ServiceAccountの権限が最小限になるように定義できます。 PodがそのServiceAccountを使用している場合、そのPodは正しく機能するために必要な権限以上の権限を取得しません。
詳細な手順については、ServiceAccount権限を参照してください。
RBACを使用して、クラスターの異なるNamespaceにあるリソースに対して別のNamespaceのServiceAccountがアクションを実行できるようにすることができます。
例えば、dev NamespaceにサービスアカウントとPodがあり、そのPodがmaintenance Namespaceで実行されているJobを見る必要がある場合を考えてみましょう。
Jobオブジェクトをリストする権限を付与するRoleオブジェクトを作成できます。
次に、そのRoleをmaintenance NamespaceのServiceAccountオブジェクトにバインドするRoleBindingオブジェクトを作成します。
そうすることで、dev NamespaceのPodは、そのServiceAccountを使用してmaintenance NamespaceのJobオブジェクトをリストできます。
ServiceAccountをPodに割り当てるには、Podの仕様にあるspec.serviceAccountNameフィールドを設定します。
Kubernetesは、そのServiceAccountの認証情報をPodに自動的に提供します。
v1.22以降では、KubernetesはTokenRequest APIを使用して有効期間が短く自動的にローテーションされるトークンを取得し、そのトークンを投影ボリュームとしてPodにマウントします。
デフォルトではKubernetesは、ServiceAccountがdefault ServiceAccountか指定したカスタムServiceAccountであるかに関わらず、PodにそのServiceAccountの認証情報を提供します。
Kubernetesが指定されたServiceAccountまたはdefault ServiceAccountの認証情報を自動的に注入しないようにするには、Podの使用にあるautomountServiceAccountTokenフィールドをfalseに設定します。
1.22より前のバージョンでは、Kubernetesは有効期間の長い静的なトークンをSecretとしてPodに提供します。
ServiceAccountを標準以外の場所にマウントするための認証情報、またはAPIサーバー以外の対象向けの認証情報が必要な場合は、次のいずれかの方法を使用します:
Kubernetesクラスターの外部で実行されるアプリケーションの場合は、Secretに保存される有効期間の長いServiceAccountトークンの作成を検討するかもしれません。 これにより認証が可能になりますが、Kubernetesプロジェクトではこのアプローチを避けることを推奨しています。 長期間有効なBearerトークンは、一度漏洩するとトークンが悪用される可能性があるため、セキュリティリスクとなります。 代わりとなる手段を検討してください。 例えば、外部アプリケーションは、十分に保護された秘密鍵 と 証明書を使用して認証するか、独自に実装したWebhook認証などのカスタムメカニズムを使用して認証することもできます。
また、TokenRequestを使用して外部アプリケーションのために有効期間の短いトークンを取得することもできます。
Kubernetesは、ServiceAccountに追加できるkubernetes.io/enforce-mountable-secretsというアノテーションを提供しています。
このアノテーションを適用すると、ServiceAccountのシークレットは指定された種類のリソースにのみマウントできるため、クラスターのセキュリティ体制が強化されます。
マニフェストを使用してServiceAccountにアノテーションを追加できます:
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
kubernetes.io/enforce-mountable-secrets: "true"
name: my-serviceaccount
namespace: my-namespace
このアノテーションが"true"に設定されている場合、Kubernetesコントロールプレーンは、このServiceAccountのSecretが特定のマウント制限の対象であることを確認します。
secretsフィールドに表示される必要があります。envFromを使用して参照される各Secretの名前は、PodのServiceAccountのsecretsフィールドに表示される必要があります。imagePullSecretsを使用して参照される各Secretの名前は、PodのServiceAccountのsecretsフィールドに表示される必要があります。これらの制限を理解して適用することで、クラスター管理者はより厳格なセキュリティプロファイルを維持し、適切なリソースのみがシークレットにアクセスできるようにします。
ServiceAccountは、Kubernetes APIサーバーおよび信頼関係が存在する他のシステムに対して、署名されたJSON Web Tokens (JWTs) を使用して認証を行います。
トークンの発行方法(TokenRequestを使用して時間制限付きで発行されるか、Secretを使用して従来のメカニズムで発行されるか)に応じて、ServiceAccountトークンには有効期限、オーディエンス、トークンが有効になる時間などが含まれる場合があります。
ServiceAccountとして機能しているクライアントがKubernetes APIサーバーと通信しようとすると、クライアントはHTTPリクエストにAuthorization: Bearer <token>ヘッダーを含めます。
APIサーバーは、次のようにしてBearerトークンの有効性を確認します:
TokenRequest APIは、ServiceAccountに バインドされたトークン を生成します。 このバインディングは、そのServiceAccountとして機能しているクライアント(Podなど)のライフタイムにリンクされています。 バインドされたPodのサービスアカウントトークンのJWTスキーマとペイロードの例については、トークンボリューム投影を参照してください。
TokenRequest APIを使用して発行されたトークンの場合、APIサーバーは、そのオブジェクトの ユニークID と一致する、ServiceAccountを使用している特定のオブジェクト参照がまだ存在するかどうかも確認します。
PodにSecretとしてマウントされているレガシートークンの場合、APIサーバーはトークンをSecretと照合します。
認証プロセスの詳細については、認証を参照してください。
Kubernetesサービスアカウントの認証情報の検証が必要なサービスがある場合、次の方法を使用できます:
Kubernetesプロジェクトでは、TokenReview APIの使用を推奨しており、この方法ではSecret、ServiceAccount、Pod、NodeなどのAPIオブジェクトにバインドされたトークンが削除されると、そのトークンが無効になります。 例えば、投影されたServiceAccountトークンを含むPodを削除すると、クラスターはただちにそのトークンを無効にし、TokenReviewはただちに失敗します。 代わりにOIDC認証を使用する場合、トークンが有効期限のタイムスタンプに達するまで、クライアントはトークンを有効なものとして扱い続けます。
アプリケーションでは、受け入れるオーディエンスを常に定義し、トークンのオーディエンスがアプリケーションが期待するオーディエンスと一致するかどうかを確認する必要があります。 これにより、トークンのスコープが最小限に抑えられ、アプリケーション内でのみ使用でき、他の場所では使用できないようになります。
SPIFFE CSIドライバープラグインを使用して、SPIFFE SVID をX.509証明書ペアとしてPodに提供します。
PodSecurityPolicyの代わりに、次のいずれか、または両方を使用して、Podに対して同様の制限を適用できます:
移行ガイドについては、PodSecurityPolicyからビルトインのPodセキュリティアドミッションコントローラーへの移行を参照してください。 このAPIの削除に関する詳細は、PodSecurityPolicyの非推奨: 過去・現在・未来を参照してください。
Kubernetes v1.35を使用していない場合は、使用中のKubernetesバージョンのドキュメントを参照してください。
このページでは、Linuxオペレーティングシステムに固有のセキュリティ上の考慮事項とベストプラクティスについて説明します。
Linuxノードでは、メモリベースのボリューム(secretボリュームマウントや、medium: Memoryを指定したemptyDirなど)はtmpfsファイルシステムで実装されています。
スワップが設定されており、古いLinuxカーネルを使用している場合(または現在のカーネルで、Kubernetesがサポートしていない設定を使用している場合)、メモリベースのボリュームのデータが永続ストレージに書き込まれる可能性があります。
Linuxカーネルはバージョン6.3から公式にnoswapオプションをサポートしているため、ノードでスワップが有効になっている場合は、使用するカーネルバージョンを6.3以降にするか、バックポートによりnoswapオプションをサポートするバージョンを使用することが推奨されます。
詳細については、スワップメモリ管理を参照してください。
このページでは、Windowsオペレーティングシステムに特有のセキュリティ上の考慮事項とベストプラクティスについて説明します。
Windowsでは、Secretデータがノードのローカルストレージに平文で書き込まれます(Linuxのtmpfs、インメモリファイルシステムとは異なります)。 クラスターオペレーターは、次の両方の追加対策を講じる必要があります:
RunAsUsernameは、WindowsのPodまたはコンテナに対して、特定のユーザーとしてコンテナプロセスを実行するために指定できます。 これは、おおよそRunAsUserと同等です。
Windowsコンテナには、ContainerUserとContainerAdministratorという2つのデフォルトのユーザーアカウントが用意されています。 これら2つのユーザーアカウントの違いについては、Microsoftの Secure Windows containers ドキュメント内のContainerAdminとContainerUserのユーザーアカウントを使うタイミングに記載されています。
ローカルユーザーは、コンテナのビルドプロセス中にコンテナイメージに追加できます。
ContainerUserとして実行されますContainerAdministratorとして実行されますWindowsコンテナは、グループ管理サービスアカウントを利用することで、Active DirectoryのIDとして実行することもできます
Linux固有のPodセキュリティコンテキスト機構(SELinux、AppArmor、Seccomp、カスタムPOSIXケーパビリティなど)は、Windowsノードではサポートされていません。 特権コンテナは、Windowsではサポートされていません。 代わりに、WindowsではHostProcessコンテナを使用することで、Linuxの特権コンテナが実行する多くのタスクを実行できます。
このページではKubernetes APIへのアクセスコントロールの概要を説明します。
Kubernetes APIにはkubectlやクライアントライブラリ、あるいはRESTリクエストを用いてアクセスします。
APIアクセスには、人間のユーザーとKubernetesサービスアカウントの両方が認証可能です。
リクエストがAPIに到達すると、次の図のようにいくつかの段階を経ます。
一般的なKubernetesクラスターでは、APIはTLSで保護された443番ポートで提供されます。 APIサーバーは証明書を提示します。 この証明書は、プライベート認証局(CA)を用いて署名することも、一般に認知されているCAと連携した公開鍵基盤に基づき署名することも可能です。
クラスターがプライベート認証局を使用している場合、接続を信頼し、傍受されていないと確信できるように、クライアント上の~/.kube/configに設定されたそのCA証明書のコピーが必要です。
クライアントは、この段階でTLSクライアント証明書を提示することができます。
TLSが確立されると、HTTPリクエストは認証のステップに移行します。 これは図中のステップ1に該当します。 クラスター作成スクリプトまたはクラスター管理者は、1つまたは複数のAuthenticatorモジュールを実行するようにAPIサーバーを設定します。 Authenticatorについては、認証で詳しく説明されています。
認証ステップへの入力はHTTPリクエスト全体ですが、通常はヘッダとクライアント証明書の両方、またはどちらかを調べます。
認証モジュールには、クライアント証明書、パスワード、プレーントークン、ブートストラップトークン、JSON Web Tokens(サービスアカウントに使用)などがあります。
複数の認証モジュールを指定することができ、その場合、1つの認証モジュールが成功するまで、それぞれを順番に試行します。
認証できない場合、HTTPステータスコード401で拒否されます。
そうでなければ、ユーザーは特定のusernameとして認証され、そのユーザー名は後続のステップでの判断に使用できるようになります。
また、ユーザーのグループメンバーシップを提供する認証機関と、提供しない認証機関があります。
Kubernetesはアクセスコントロールの決定やリクエストログにユーザー名を使用しますが、Userオブジェクトを持たず、ユーザー名やその他のユーザーに関する情報をAPIはに保存しません。
リクエストが特定のユーザーからのものであると認証された後、そのリクエストは認可される必要があります。 これは図のステップ2に該当します。
リクエストには、リクエスト者のユーザー名、リクエストされたアクション、そのアクションによって影響を受けるオブジェクトを含める必要があります。 既存のポリシーで、ユーザーが要求されたアクションを完了するための権限を持っていると宣言されている場合、リクエストは承認されます。
例えば、Bobが以下のようなポリシーを持っている場合、彼は名前空間projectCaribou内のPodのみを読むことができます。
{
"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
"kind": "Policy",
"spec": {
"user": "bob",
"namespace": "projectCaribou",
"resource": "pods",
"readonly": true
}
}
Bobが次のようなリクエストをした場合、Bobは名前空間projectCaribouのオブジェクトを読むことが許可されているので、このリクエストは認可されます。
{
"apiVersion": "authorization.k8s.io/v1beta1",
"kind": "SubjectAccessReview",
"spec": {
"resourceAttributes": {
"namespace": "projectCaribou",
"verb": "get",
"group": "unicorn.example.org",
"resource": "pods"
}
}
}
Bobが名前空間projectCaribouのオブジェクトに書き込み(createまたはupdate)のリクエストをした場合、承認は拒否されます。
また、もしBobがprojectFishのような別の名前空間にあるオブジェクトを読み込む(get)リクエストをした場合も、承認は拒否されます。
Kubernetesの認可では、組織全体またはクラウドプロバイダー全体の既存のアクセスコントロールシステムと対話するために、共通のREST属性を使用する必要があります。 これらのコントロールシステムは、Kubernetes API以外のAPIとやり取りする可能性があるため、REST形式を使用することが重要です。
Kubernetesは、ABACモード、RBACモード、Webhookモードなど、複数の認可モジュールをサポートしています。 管理者はクラスターを作成する際に、APIサーバーで使用する認証モジュールを設定します。 複数の認可モジュールが設定されている場合、Kubernetesは各モジュールをチェックし、いずれかのモジュールがリクエストを認可した場合、リクエストを続行することができます。 すべてのモジュールがリクエストを拒否した場合、リクエストは拒否されます(HTTPステータスコード403)。
サポートされている認可モジュールを使用したポリシー作成の詳細を含む、Kubernetesの認可については、認可を参照してください。
アドミッションコントロールモジュールは、リクエストを変更したり拒否したりすることができるソフトウェアモジュールです。 認可モジュールが利用できる属性に加えて、アドミッションコントロールモジュールは、作成または修正されるオブジェクトのコンテンツにアクセスすることができます。
アドミッションコントローラーは、オブジェクトの作成、変更、削除、または接続(プロキシ)を行うリクエストに対して動作します。 アドミッションコントローラーは、単にオブジェクトを読み取るだけのリクエストには動作しません。 複数のアドミッションコントローラーが設定されている場合は、順番に呼び出されます。
これは図中のステップ3に該当します。
認証・認可モジュールとは異なり、いずれかのアドミッションコントローラーモジュールが拒否した場合、リクエストは即座に拒否されます。
オブジェクトを拒否するだけでなく、アドミッションコントローラーは、フィールドに複雑なデフォルトを設定することもできます。
利用可能なアドミッションコントロールモジュールは、アドミッションコントローラーに記載されています。
リクエストがすべてのアドミッションコントローラーを通過すると、対応するAPIオブジェクトの検証ルーチンを使って検証され、オブジェクトストアに書き込まれます(図のステップ4に該当します)。
Kubernetesの監査は、クラスター内の一連のアクションを文書化した、セキュリティに関連する時系列の記録を提供します。 クラスターは、ユーザー、Kubernetes APIを使用するアプリケーション、およびコントロールプレーン自身によって生成されるアクティビティを監査します。
詳しくは監査をご覧ください。
これまでの説明は、APIサーバーのセキュアポートに送信されるリクエストに適用されます(典型的なケース)。 APIサーバーは、実際には2つのポートでサービスを提供することができます。
デフォルトでは、Kubernetes APIサーバーは2つのポートでHTTPを提供します。
localhostポート:
--insecure-bind-addressフラグで変更することができます。“セキュアポート”:
--tls-cert-fileフラグで、鍵は--tls-private-key-fileフラグで設定します。--secure-portフラグで変更することができます。--bind-addressフラグで変更することができます。認証、認可、APIアクセスコントロールに関する詳しいドキュメントはこちらをご覧ください。
以下についても知ることができます。
Kubernetes RBACは、クラスターユーザーやワークロードがその役割を果たすために、必要なリソースへのアクセスしかできないようにするための重要なセキュリティコントロールです。 クラスターユーザーの権限を設計する際には、クラスター管理者が特権昇格が発生しうる領域を理解し、セキュリティインシデントを引き起こすリスクを減らすことが重要です。
ここで説明するグッドプラクティスは、一般的なRBACドキュメントと併せて読むことを推奨します。
理想的には、ユーザーやサービスには最小限の権限のみ割り当てるべきです。 権限は、その操作に明示的に必要なものだけを使用するべきです。 クラスターによって異なりますが、一般的なルールは次のとおりです:
cluster-adminアカウントを使用すべきではありません。
権限の低いアカウントに偽装権限を提供することで、クラスターリソースの誤った変更を回避できます。system:mastersグループにユーザーを追加しないでください。
このグループのメンバーであるユーザーは、すべてのRBAC権限をバイパスし、常に制限のないスーパーユーザーアクセス権限を持ちます。この権限はRoleBindingsまたはClusterRoleBindingsを削除しても取り消すことができません。
余談ですが、クラスターが認可ウェブフックを使用している場合、このグループのメンバーシップもそのウェブフックをバイパスします(そのグループのメンバーであるユーザーからのリクエストがウェブフックに送信されることはありません)理想的には、Podには強力な権限が付与されたサービスアカウントを割り当てられるべきではありません。 (例えば、特権昇格リスクにリストされている権限)。 強力な権限が必要な場合は、次のプラクティスを検討してください:
Kubernetesは、すべてのクラスターに必要とは限らないアクセスをデフォルトで提供します。
デフォルトで提供されるRBAC権限を確認することで、セキュリティを強化する機会が得られます。
一般的に、system:アカウントに提供される権限を変更するべきではありませんが、クラスター権限を強化するためのオプションがいくつか存在します:
system:unauthenticatedグループのバインディングを確認し、可能であれば削除します。
これにより、ネットワークレベルでAPIサーバーに接続できるすべてのユーザーにアクセスが許可されます。automountServiceAccountToken: falseを設定することで、サービスアカウントトークンのデフォルトの自動マウントを回避します。
詳細については、デフォルトのサービスアカウントトークンの使用を参照してください。
Podにこの値を設定すると、サービスアカウント設定が上書きされ、サービスアカウントトークンを必要とするワークロードは引き続きそれをマウントできます。冗長なエントリや特権昇格の可能性がないか、定期的にKubernetes RBAC設定を確認することが不可欠です。 攻撃者が削除されたユーザーと同じ名前のユーザーアカウントを作成できる場合、特にそのユーザーに割り当てられた権限を自動的に継承できます。
Kubernetes RBAC内には、ユーザーやサービスアカウントがクラスター内で特権昇格したり、クラスター外のシステムに影響を与えたりすることができる権限がいくつかあります。
このセクションは、クラスター運用者が意図した以上のクラスターへのアクセスを誤って許可しないようにするために注意を払うべき領域を示すことを目的としています。
一般に、Secretに対するgetアクセスを許可すると、ユーザーがその内容を読むことができることは明らかです。
また、listおよびwatchアクセスも、ユーザーがSecretの内容を読むことを事実上可能にします。
例えば、Listレスポンスが返却される(例: kubectl get secrets -A -o yaml)と、そのレスポンスにはすべてのSecretの内容が含まれます。
Namespace内でワークロード(PodやPodを管理するワークロードリソース)を作成する権限により、そのnamespace内のSecret、ConfigMap、PersistentVolumeなどのPodにマウントできる他の多くのリソースへのアクセスが暗黙的に許可されます。 さらに、Podは任意のServiceAccountとして実行できるため、ワークロードを作成する権限もまた、そのnamespace内の任意のサービスアカウントのAPIアクセスレベルを暗黙的に許可します。
特権付きPodを実行できるユーザーは、そのアクセス権を使用してノードへのアクセスを取得し、さらに特権昇格させる可能性があります。 適切に安全で隔離されたPodを作成できるユーザーや他のプリンシパルを完全に信頼していない場合は、ベースラインまたは制限付きPodセキュリティ標準を強制する必要があります。 Podのセキュリティアドミッションや他の(サードパーティ)メカニズムを使用して、その強制を実装できます。
これらの理由から、namespaceは異なる信頼レベルやテナンシーを必要とするリソースを分離するために使用されるべきです。 最小特権の原則に従い、最小限の権限セットを割り当てることがベストプラクティスとされていますが、namespace内の境界は弱いと考えるべきです。
誰か、または何らかのアプリケーションが、任意のPersistentVolumeを作成する権限を持っている場合、そのアクセスにはhostPathボリュームの作成も含まれており、これはPodが関連づけられたノードの基盤となるホストファイルシステムにアクセスできることを意味します。
その権限を与えることはセキュリティリスクとなります。
ホストファイルシステムに制限のないアクセス権を持つコンテナが特権昇格する方法は数多くあり、これには他のコンテナからのデータの読み取りや、Kubeletなどのシステムサービスの資格情報の悪用が含まれます。
PersistentVolumeオブジェクトを作成する権限を許可するのは、次の場合に限定するべきです:
永続ストレージへのアクセスが必要な場合、信頼できる管理者がPersistentVolumeを作成し、制約のあるユーザーはPersistentVolumeClaimを使用してそのストレージにアクセスするべきです。
proxyサブリソースへのアクセスノードオブジェクトのプロキシサブリソースへのアクセス権を持つユーザーは、Kubelet APIに対する権限を持ち、権限を持つノード上のすべてのPodでコマンドを実行できます。 このアクセスは監査ログやアドミッションコントロールをバイパスするため、このリソースに権限を付与する際には注意が必要です。
一般的に、RBACシステムはユーザーが所有する権限以上のクラスターロールを作成できないようにします。
この例外はescalate動詞です。
RBACのドキュメントに記載されているように、この権限を持つユーザーは事実上特権昇格させることができます。
escalate動詞と同様に、ユーザーにこの権限を付与すると、特権昇格に対するKubernetesビルトインの保護をバイパスし、ユーザーがすでに持っていない権限を持つロールへのバインディングを作成できるようになります。
この動詞は、ユーザーがクラスター内の他のユーザーになりすまし、そのユーザーの権限を取得することを可能にします。 権限を付与する場合は、なりすましアカウントを介して過剰な権限を取得できないように注意する必要があります。
CSR APIは、CSRに対するcreate権限とkubernetes.io/kube-apiserver-clientを署名者とするcertificatesigningrequests/approvalに対するupdate権限を持つユーザーが、クラスターに対して認証するための新しいクライアント証明書を作成できるようにします。
これらのクライアント証明書は、Kubernetesシステムコンポーネントの重複を含む任意の名前を持つことができます。
これにより、特権昇格が可能になります。
serviceaccounts/tokenに対するcreate権限を持つユーザーは、既存のサービスアカウント用のトークンを発行するためのTokenRequestsを作成できます。
validatingwebhookconfigurationsまたはmutatingwebhookconfigurationsを制御するユーザーは、クラスターに許可された任意のオブジェクトを読み取ることができるウェブフックを制御し、ウェブフックを変更する場合は許されたオブジェクトも変更できます。
Namespaceオブジェクトにおいてpatch操作を実行できるユーザーは(そのアクセス権を持つロールへのnamespace付きのRoleBindingを通じて)namespaceのラベルを変更できます。 Podのセキュリティアドミッションが使用されているクラスターでは、ユーザーは管理者が意図したより緩いポリシーをnamespaceに設定できる場合があります。 NetworkPolicyが使用されているクラスターでは、ユーザーは管理者が意図していないサービスへのアクセスを間接的に許可するラベルを設定できる場合があります。
クラスター内のオブジェクトを作成する権限を持つユーザーは、etcd used by Kubernetes is vulnerable to OOM attackで議論されているように、オブジェクトのサイズや数に基づいてサービス拒否を引き起こすほど大きなオブジェクトを作成できる可能性があります。 これは、半信頼または信頼されていないユーザーにシステムへの限定的なアクセスが許可されている場合、特にマルチテナントクラスターに関係する可能性があります。
この問題を緩和するための1つのオプションとして、リソースクォータを使用して作成可能なオブジェクトの量を制限することが考えられます。
Kubernetesでは、Secretは次のようなオブジェクトです。 パスワードやOAuthトークン、SSHキーのような機密の情報を保持します。
Secretは、機密情報の使用方法をより管理しやすくし、偶発的な漏洩のリスクを減らすことができます。Secretの値はbase64文字列としてエンコードされ、デフォルトでは暗号化されずに保存されますが、保存時に暗号化するように設定することもできます。
Podは、ボリュームマウントや環境変数など、さまざまな方法でSecretを参照できます。Secretは機密データ用に設計されており、ConfigMapは非機密データ用に設計されています。
以下の適切な使用方法は、クラスター管理者とアプリケーション開発者の両方を対象としています。 これらのガイドラインに従って、Secretオブジェクト内の機密情報のセキュリティを向上させ、Secretの効果的な管理を行ってください。
このセクションでは、クラスター管理者がクラスター内の機密情報のセキュリティを強化するために使用できる適切な方法を提供します。
デフォルトでは、Secretオブジェクトはetcd内で暗号化されていない状態で保存されます。
etcd内のSecretデータを暗号化するように構成する必要があります。
手順については、機密データ保存時の暗号化を参照してください。
Kubernetesのロールベースアクセス制御 (RBAC)などのアクセス制御メカニズムを計画する際、Secretオブジェクトへのアクセスに関する以下のガイドラインを考慮してください。
また、RBACの適切な使用方法の他のガイドラインにも従ってください。
watchまたはlistアクセスを、最上位の特権を持つシステムレベルのコンポーネントのみに制限してください。コンポーネントの通常の動作が必要とする場合にのみ、Secretへのgetアクセスを許可してください。get、watch、listアクセスを制限してください。etcdへのアクセスはクラスター管理者にのみ許可し、読み取り専用アクセスも許可してください。特定の注釈を持つSecretへのアクセスを制限するなど、より複雑なアクセス制御については、サードパーティの認証メカニズムを検討してください。listアクセスを暗黙的に許可すると、サブジェクトがSecretの内容を取得できるようになります。Secretを使用するPodを作成できるユーザーは、そのSecretの値も見ることができます。 クラスターのポリシーがユーザーにSecretを直接読むことを許可しない場合でも、同じユーザーがSecretを公開するPodを実行するアクセスを持つかもしれません。 このようなアクセスを持つユーザーによるSecretデータの意図的または偶発的な公開の影響を検出または制限することができます。 いくつかの推奨事項には以下があります:
使用しなくなった場合には、etcdが使用する永続ストレージを削除するかシュレッダーで処理してください。
複数のetcdインスタンスがある場合、インスタンス間の通信を暗号化されたSSL/TLS通信に設定して、転送中のSecretデータを保護してください。
外部のSecretストアプロバイダーを使用して機密データをクラスターの外部に保存し、その情報にアクセスするようにPodを構成できます。 Kubernetes Secrets Store CSI Driverは、kubeletが外部ストアからSecretを取得し、データにアクセスすることを許可された特定のPodにSecretをボリュームとしてマウントするDaemonSetです。
サポートされているプロバイダーの一覧については、Secret Store CSI Driverのプロバイダーを参照してください。
このセクションでは、Kubernetesリソースの作成と展開時に機密データのセキュリティを向上させるための開発者向けの適切な使用方法を提供します。
Pod内で複数のコンテナを定義し、そのうち1つのコンテナだけがSecretへのアクセスを必要とする場合、他のコンテナがそのSecretにアクセスできないようにボリュームマウントや環境変数の設定を行ってください。
アプリケーションは、環境変数やボリュームから機密情報を読み取った後も、その値を保護する必要があります。 例えば、アプリケーションは機密情報を平文でログに記録したり、信頼できない第三者に送信したりしないようにする必要があります。
Secretをマニフェストを介して設定し、秘密データをBase64でエンコードしている場合、このファイルを共有したりソースリポジトリにチェックインしたりすると、その秘密はマニフェストを読むことのできる全員に公開されます。
Kubernetes APIサーバーは、外部の関係者(ユーザーやサービス)がクラスターと対話するための主要なエントリポイントです。
この役割の一環として、APIサーバーには監査ログやアドミッションコントローラーなど、いくつかの重要なセキュリティ制御が組み込まれています。 しかし、これらの制御をバイパスしてクラスターの設定やコンテンツを変更する方法があります。
このページでは、Kubernetes APIサーバーに組み込まれているセキュリティ制御をバイパスする方法について説明します。 これにより、クラスター運用者やセキュリティアーキテクトは、これらのバイパスが適切に制限されるようにできます。
各ノードのkubeletは、特定のディレクトリに保存されているマニフェストや、特定のURLから取得したマニフェストをクラスター内のstatic Podとして読み込み、直接管理します。 APIサーバーはこれらのstatic Podを管理しません。 この場所への書き込みアクセス権を持つ攻撃者は、そのソースから読み込まれたstatic Podの設定を変更したり、新しいstatic Podを導入したりする可能性があります。
Static Podは、Kubernetes API内の他のオブジェクトへのアクセスが制限されています。
例えば、static PodにクラスターからSecretをマウントするように設定することはできません。
ただし、これらのPodは基盤となるノードからhostPathマウントを使用するなど、他のセキュリティ上機微な操作を行うことができます。
デフォルトでは、kubeletはミラーPodを作成し、static PodをKubernetes APIで参照できるようにします。 ただし、攻撃者がPod作成時に無効なNamespaceを指定した場合、Kubernetes APIで参照することはできず、影響を受けるホストにアクセスできるツールでのみ発見できます。
static Podがアドミッション制御に失敗した場合、kubeletはPodをAPIサーバーに登録しません。 ただし、Podはノード上で実行され続けます。 詳細については、kubeadm issue #1541を参照してください。
kubeletは通常、クラスターのワーカーノードのTCPポート10250で公開されるHTTP APIを提供します。 APIは、使用しているKubernetesディストリビューションによっては、コントロールプレーンノードでも公開される場合があります。 APIに直接アクセスすると、ノード上で実行されているPodに関する情報や、これらのPodからのログの開示、およびノード上で実行されているすべてのコンテナ内でのコマンド実行が可能になります。
KubernetesクラスターユーザーがNodeオブジェクトのサブリソースにRBACアクセスを持つ場合、そのアクセスはkubelet APIと対話するための認可を提供します。
正確なアクセスは、kubelet認証で詳しく説明されているように、付与されたサブリソースアクセスに依存します。
kubelet APIに直接アクセスすると、アドミッション制御の対象にならず、Kubernetesの監査ログにも記録されません。 このAPIに直接アクセスできる攻撃者は、特定のアクションを検出または防止する制御をバイパスできる可能性があります。
kubelet APIは、さまざまな方法でリクエストを認証するように構成できます。
デフォルトでは、kubeletの設定は匿名アクセスを許可します。
ほとんどのKubernetesプロバイダーは、デフォルトをwebhookおよび証明書認証を使用するように変更します。
これにより、コントロールプレーンは呼び出し元がnodes APIリソースまたはサブリソースにアクセスする権限があることを確認できます。
デフォルトの匿名アクセスでは、コントロールプレーンでこのアサーションは行われません。
nodes APIオブジェクトのサブリソースへのアクセスを制限します。
監視サービスなど、必要な場合にのみこのアクセスを許可してください。Kubernetesクラスターは、etcdをデータストアとして使用します。
etcdサービスは、TCPポート2379でリッスンします。
アクセスが必要なクライアントは、Kubernetes APIサーバーと使用しているバックアップツールのみです。
このAPIに直接アクセスすると、クラスター内のデータの開示または変更が可能になります。
etcd APIへのアクセスは通常、クライアント証明書認証によって管理されます。 etcdが信頼する認証局によって発行された証明書は、etcd内に保存されているデータへのフルアクセスを許可します。
etcdに直接アクセスすると、Kubernetesのアドミッション制御の対象にならず、Kubernetesの監査ログにも記録されません。 APIサーバーのetcdクライアント証明書の秘密鍵を読み取る権限を持つ(または新しい信頼できるクライアント証明書を作成できる)攻撃者は、クラスターのシークレットにアクセスしたり、アクセスルールを変更したりすることで、クラスター管理者権限を取得できます。 KubernetesのRBAC特権を昇格させなくとも、etcdを変更できる攻撃者は、任意のAPIオブジェクトを取得したり、クラスター内に新しいワークロードを作成したりできます。
多くのKubernetesプロバイダーは、相互TLS(クライアントとサーバーの両方が認証のために互いの証明書を検証)を使用するようにetcdを構成します。 etcd APIには広く受け入れられた認可の実装はありませんが、機能は存在します。 認可モデルが存在しないため、etcdへのクライアントアクセス権限を持つ証明書であれば、etcdへのフルアクセスを取得できます。 通常、ヘルスチェックのみに使用されるetcdクライアント証明書も、完全な読み取りおよび書き込みアクセスを付与できます。
Kubernetesクラスターの各ノードでは、コンテナと対話するためのアクセスはコンテナランタイム(1つ以上のランタイムを構成している場合はそれらのランタイム)によって制御されます。 通常、コンテナランタイムはkubeletがアクセスできるUnixソケットを公開します。 このソケットにアクセスできる攻撃者は、新しいコンテナを起動したり、実行中のコンテナと対話したりする可能性があります。
クラスターレベルでは、このアクセスの影響は、侵害されたノードで実行されているコンテナが、他のワーカーノードやコントロールプレーンのコンポーネントへの特権昇格のために、攻撃者が使用する可能性のあるSecretやその他の機密データにアクセスできるかどうかによって異なります。
rootユーザーにこのアクセスを制限してください。hostPathマウントの使用を、直接または親ディレクトリをマウントすることによって制限または禁止してください。
また、攻撃者がディレクトリ制限をバイパスするリスクを軽減するために、hostPathマウントは読み取り専用として設定する必要があります。Kubernetesのスケジューラーは、コントロールプレーンの中のもっとも重要なコンポーネントの一つです。
このドキュメントでは、Kubernetesスケジューラーのセキュリティ体制を向上させる方法について説明します。
設定が不適切なスケジューラーは、セキュリティ上の脆弱性を引き起こす可能性があります。 このようなスケジューラーは、特定のノードをターゲットにして、そのノードおよびリソースを共有しているワークロードやアプリケーションを強制的に退避させることができます。 この設定は、脆弱性のあるオートスケーラーを標的としたYoYo攻撃に対する防御を強化するのにも役立ちます。
認証設定を構成する際には、kube-schedulerの認証方式がkube-api-serverの認証方式と整合性を保つように設定することが重要です。 認証ヘッダーが欠落しているリクエストがあった場合、クラスター全体で認証方式を統一的に管理するために、kube-api-server経由で認証を行うようにしてください。
authentication-kubeconfig: スケジューラーがAPIサーバーから認証設定オプションを取得できるよう、適切なkubeconfigを設定するようにしてください。この kubeconfig ファイルは、厳格なファイル権限で保護する必要があります。authentication-tolerate-lookup-failure: この設定をfalseに設定すると、スケジューラーが 常に APIサーバーから認証設定を取得するようになります。authentication-skip-lookup: この設定をfalseに設定すると、スケジューラーが 常に APIサーバーから認証設定を取得するようになります。authorization-always-allow-paths: これらのパスは、匿名アクセス権限に適したデータを返すように設定する必要があります。デフォルト値は、/healthz,/readyz,/livezです。profiling: プロファイリングエンドポイントを無効化する場合はfalseに設定してください。これらのエンドポイントはデバッグ情報を提供しますが、本番環境のクラスターでは使用すべきではありません。サービス拒否攻撃や情報漏洩のリスクがあるためです。--profiling引数は非推奨となっており、現在はKubeScheduler DebuggingConfigurationを通じて指定できます。プロファイリング機能を無効化するには、kube-schedulerの設定ファイルで enableProfilingをfalseに設定してください。requestheader-client-ca-file: この引数の使用は避けてください。bind-address: 通常、kube-schedulerは外部からアクセス可能な状態にする必要はありません。バインドアドレスをlocalhostに設定することは、セキュリティ上推奨されるベストプラクティスです。permit-address-sharing: SO_REUSEADDRによる接続共有を無効にする場合は、この設定をfalseに設定してください。SO_REUSEADDRを使用すると、TIME_WAIT状態にある終了済み接続が再利用される可能性があります。permit-port-sharing: デフォルト値はfalseです。セキュリティ上の影響を十分に理解している場合を除き、デフォルト設定をそのまま使用してください。tls-cipher-suites: 常に、優先される暗号スイートのリストを明示的に指定してください。これにより、安全性の低い暗号スイートを使用した暗号化が実行されるのを防ぎます。Kubernetesのスケジューリングコードをベースとしたカスタムスケジューラーを使用する場合、クラスター管理者は、queueSort、prefilter、filter、permitといった拡張ポイントを使用するプラグインの設定には注意が必要です。
これらの拡張ポイントはスケジューリングプロセスの様々な段階を制御しており、設定を誤るとkube-schedulerのクラスター内での動作に影響を及ぼす可能性があります。
queueSort拡張ポイントを使用するプラグインは同時に1つだけ有効化できます。queueSortを使用するプラグインについては、特に慎重に検証する必要があります。prefilterまたはfilter拡張ポイントを実装するプラグインは、すべてのノードをスケジューリング不可と判定する可能性があります。これにより、新規Podのスケジューリングが完全に停止する恐れがあります。permit拡張ポイントを実装したプラグインは、Podのバインド処理を阻止または遅延させることができます。このようなプラグインは、クラスター管理者が十分に検証する必要があります。デフォルトプラグイン以外を使用する場合、queueSort、filter、permitの各拡張ポイントを無効化することを検討してください。具体的な手順は以下の通りです。
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: my-scheduler
plugins:
# Disable specific plugins for different extension points
# You can disable all plugins for an extension point using "*"
queueSort:
disabled:
- name: "*" # Disable all queueSort plugins
# - name: "PrioritySort" # Disable specific queueSort plugin
filter:
disabled:
- name: "*" # Disable all filter plugins
# - name: "NodeResourcesFit" # Disable specific filter plugin
permit:
disabled:
- name: "*" # Disables all permit plugins
# - name: "TaintToleration" # Disable specific permit plugin
これにより、my-schedulerというスケジューラープロファイルが作成されます。
Podの.specに.spec.schedulerNameの値が指定されていない場合、kube-schedulerはそのPodに対してデフォルトの設定とデフォルトプラグインを使用して動作します。
.spec.schedulerNameにmy-schedulerを指定したPodを定義すると、カスタム設定が適用されたkube-schedulerが起動します。
このカスタム設定では、queueSort、filter、permitの各拡張ポイントが無効化されています。
このKubeSchedulerConfigurationを使用し、かつカスタムスケジューラーを実行していない場合、.spec.schedulerNameにnonexistent-scheduler(またはクラスター内に存在しない任意のスケジューラー名)を指定したPodを定義しても、そのPodに関するイベントは生成されません。
クラスター管理者は、クラスターユーザーがノードにラベルを付与できないように設定する必要があります。
悪意のある攻撃者がnodeSelectorを利用することで、本来配置されるべきでないノードにワークロードをスケジュールすることが可能になります。
適切な認証メカニズムの選択はクラスターのセキュリティ確保において重要です。 Kubernetesはいくつかの組み込みのメカニズムを提供しており、それぞれに長所と短所があります。 クラスターに最適な認証メカニズムを選択する際は、これらを慎重に検討する必要があります。
一般的に、有効にする認証メカニズムをできるだけ少なくすることが推奨されています。 これはユーザー管理を単純化し、不要となったクラスターへのアクセス権をユーザーが保持し続けることを防ぐためです。
重要な注意点として、Kubernetesはクラスター内に組み込みのユーザーデータベースを持っていません。 代わりに、設定された認証システムからユーザー情報を取得し、それを使用して認可の判断を行います。 そのため、ユーザーアクセスを監査するには、設定されているすべての認証ソースの認証情報を確認する必要があります。
複数のユーザーが直接Kubernetes APIにアクセスする本番環境のクラスターでは、OIDCなどの外部認証ソースを使用することが推奨されています。 以下で説明するクライアント証明書やサービスアカウントトークンなどの内部認証メカニズムは、このユースケースには適していません。
Kubernetesは、kubeletがAPIサーバーに対して認証を行う場合など、システムコンポーネントにX509クライアント証明書認証を活用します。 このメカニズムはユーザー認証にも使用できますが、以下の制限により本番環境での使用には適さない可能性があります:
O値に埋め込まれているため、証明書の有効期間中はユーザーのグループメンバーシップを変更することができません。Kubernetesではコントロールプレーンノードのディスクにある静的なトークンファイルから認証情報を読み込むことができますが、以下の理由により本番環境のサーバーではこの方法は推奨されません:
ブートストラップトークンはノードをクラスターに参加させるために使用されます。 以下の理由により、ユーザー認証には推奨されません:
サービスアカウントシークレットは、クラスター内で実行されるワークロードがAPIサーバーに対して認証を行うためのオプションとして利用できます。 Kubernetes 1.23より前のバージョンではデフォルトのオプションでしたが、現在はTokenRequest APIトークンに置き換えられています。 これらのSecretはユーザー認証に使用できますが、以下の理由により一般的に不適切です:
TokenRequest APIは、APIサーバーまたはサードパーティシステムへのサービス認証のために有効期間の短い認証情報を生成するために有用なツールです。 ただし、認証情報の失効方法が無いため、一般的にユーザー認証には推奨されず、ユーザーへの認証情報の安全な配布が困難です。
TokenRequestトークンをサービス認証に使用する場合、トークンが漏洩した際の影響を軽減するために、短い有効期間を設定することが推奨されます。
Kubernetesは、OpenID Connect (OIDC)を使用した外部認証サービスとKubernetes APIとの統合をサポートしています。 Kubernetesをアイデンティティプロバイダーと統合するために使用できるソフトウェアは多岐にわたります。 しかし、KubernetesでOIDC認証を使用する際は、以下のセキュリティ強化策を考慮することが重要です:
Webhookトークン認証は、外部認証プロバイダーをKubernetesに統合するもう一つのオプションです。 この認証メカニズムを用いると、クラスター内部または外部で実行される認証サービスに対してWebhookを介して認証の判断を問い合わせることができます。 この認証メカニズムへの適合性は認証サービスに使用されるソフトウェアに依存する可能性が高く、Kubernetes特有の考慮事項があることに注意が必要です。
Webhook認証を設定するには、コントロールプレーンサーバーのファイルシステムへのアクセスが必要です。 そのため、プロバイダーが特別に利用可能にしない限り、マネージドKubernetesでは使用できません。 また、このアクセスをサポートするためにクラスターにインストールされるソフトウェアは高い権限で実行されるため、一般的なワークロードから分離する必要があります。
認証プロキシは、外部認証システムをKubernetesに統合するもう一つのオプションです。 この認証メカニズムでは、Kubernetesは認可のために割り当てるユーザー名とグループメンバーシップを示す特定のヘッダー値が設定されたリクエストをプロキシから受け取ることを想定しています。 この認証メカニズムを使用する際には、特定の考慮事項に注意する必要があります。
まず、トラフィックの傍受やスニッフィング攻撃のリスクを軽減するため、プロキシとKubernetes APIサーバー間では安全に設定されたTLSを使用する必要があります。 これにより、プロキシとKubernetes APIサーバー間の通信の安全性が確保されます。
次に、リクエストヘッダーを改ざんできる攻撃者がKubernetesリソースへの不正アクセスを取得できる可能性があることを認識することが重要です。 そのため、ヘッダーが適切に保護され、改ざんされないようにすることが重要です。
このチェックリストは、各トピックについて、より包括的な文書へのリンクとともにガイダンスの基本的なリストを提供することを目的としています。 網羅的なものではなく、進化することを目的としています。
この文書の読み方、使い方について:
system:mastersグループはブートストラップ後のユーザー認証またはコンポーネント認証に使用していません。--use-service-account-credentialsを有効にして実行しています。ブートストラップ後、ユーザーもコンポーネントもKubernetes APIに対してsystem:mastersとして認証しないでください。
同様に、すべてのkube-controller-managerをsystem:mastersとして実行することは避けてください。
実際には、system:mastersは管理者ユーザーとは対照的に、緊急アクセス用としてのみ使用してください。
多数のコンテナネットワークインターフェース(CNI)プラグインは、Podが通信できるネットワークリソースを制限する機能を提供します。 これは、ルールを定義するためのNamespaceリソースを提供するネットワークポリシーを通じて最も一般的に行われます。 各Namespaceですべてのegressとingressをブロックし、すべてのPodを選択するデフォルトのネットワークポリシーは、許可リストアプローチを採用してワークロードの見落としがないようにするのに役立ちます。
すべてのCNIプラグインが転送中の暗号化を提供するわけではありません。 選択したプラグインにこの機能がない場合、代替ソリューションとして、サービスメッシュを使用してその機能を提供することができます。
コントロールプレーンのetcdデータストアには、アクセスを制限し、インターネット上で公開されないようにする制御が必要です。 さらに、安全に通信するために相互TLS(mTLS)を使用する必要があります。 この認証局はetcdに固有のものである必要があります。
Kubernetes APIサーバーへの外部インターネットアクセスは、APIが公開されないように制限する必要があります。 多くのマネージドKubernetesディストリビューションは、デフォルトでAPIサーバーを公開しているため注意してください。 その場合、要塞ホストを使用してサーバーにアクセスできます。
kubeletのAPIアクセスは制限し、公開しないようにする必要があります。
--configフラグで設定ファイルが指定されていない場合、デフォルトの認証および認可設定は過度に許可されています。
Kubernetesのホスティングにクラウドプロバイダーを使用する場合、PodからクラウドメタデータAPI169.254.169.254へのアクセスも、情報が漏洩する可能性があるため、必要でない場合は制限またはブロックする必要があります。
LoadBalancerおよびExternalIPの制限付き使用の詳細についてはCVE-2020-8554: Man in the middle using LoadBalancer or ExternalIPsおよびDenyServiceExternalIPsアドミッションコントローラーを参照してください。
create、update、patch、deleteに対するRBAC権限は、必要な場合にのみ付与しています。RBAC認証は重要ですが、Podのリソース(またはPodを管理する任意のリソース)に対する認証を行うほど細かく設定することはできません。
唯一の細分性は、リソース自体に対するAPI動詞です。
たとえばPodに対するcreateです。
追加のアドミッションがなければ、これらのリソースを作成する権限によって、クラスターのスケジューリング可能なノードへの直接的な無制限のアクセスが許可されます。
Podセキュリティ標準は、セキュリティに関してPodSpecでフィールドを設定する方法を制限する、特権、ベースライン、制限の3つの異なるポリシーを定義します。
デフォルトで有効になっている新しいPodセキュリティアドミッション、またはサードパーティのアドミッションWebhookを使用して、Namespaceレベルで適用できます。 削除され置き換えられたPodSecurityPolicyアドミッションとは異なり、Podセキュリティアドミッションは、アドミッションWebhookや外部サービスと簡単に組み合わせることが可能な点に注意してください。
Podセキュリティアドミッションrestrictedポリシーは、Podセキュリティ標準セットの中で最も制限の厳しいポリシーで、複数のモードで動作可能です。
warn、audit、またはenforceを使用して、セキュリティのベストプラクティスに従って、最も適切なセキュリティコンテキストを段階的に適用します。
ただし、特定のユースケースでは、事前定義されたセキュリティ標準に加えて、Podが持つ権限とアクセスを制限するために、Podのセキュリティコンテキストを個別に調査する必要があります。
Podセキュリティの実践的なチュートリアルについては、ブログ投稿Kubernetes 1.23: Podセキュリティがベータ版に移行を参照してください。
メモリとCPUの制限を設定して、Podがノードで消費できるメモリとCPUリソースを制限し、悪意のあるワークロードや侵害されたワークロードによる潜在的なDoS攻撃を防ぐ必要があります。 このようなポリシーは、アドミッションコントローラーによって適用できます。 CPU制限により使用量が制限されるため、自動スケーリング機能や効率性、つまり利用可能なCPUリソースをベストエフォートで実行することに対して、意図しない影響が生じる可能性があります。
Seccompはセキュアコンピューティングモードの略で、バージョン2.6.12以降のLinuxカーネルの機能です。 プロセスの権限をサンドボックス化して、ユーザー空間からカーネルへの呼び出しを制限するために使用できます。 Kubernetesを使用すると、ノードに読み込まれたseccompプロファイルを、Podとコンテナに自動的に適用できます。
Seccompを使用すると、コンテナ内で利用可能なLinuxカーネルsyscall攻撃対象領域を減らすことで、ワークロードのセキュリティを向上できます。 seccompフィルターモードは、BPFを利用して、プロファイルという名前の特定のsyscallの許可または拒否リストを作成します。
Kubernetes 1.27以降、すべてのワークロードのデフォルトのseccompプロファイルとしてRuntimeDefaultの使用を有効にできます。
このトピックに関するセキュリティチュートリアルが利用可能です。
さらに、Kubernetes Security Profiles Operatorは、クラスターでのseccompの管理と使用を容易にするプロジェクトです。
AppArmorは、強制アクセス制御(MAC)を簡単に実装し、システムログを通じて監査を向上させることができるLinuxカーネルセキュリティモジュールです。 デフォルトのAppArmorプロファイルは、それをサポートするノードで強制されますが、カスタムプロファイルを構成することもできます。 seccompと同様に、AppArmorもプロファイルを通じて構成されます。 各プロファイルは、許可されていないリソースへのアクセスをブロックする強制モード(complain mode)か、違反のみを報告する苦情モード(enforce mode)で実行されます。 AppArmorプロファイルは、コンテナごとに注釈付きで適用され、プロセスが適切な権限を取得できるようにします。
SELinuxも、強制アクセス制御(MAC)などのアクセス制御セキュリティポリシーをサポートするLinuxカーネルセキュリティモジュールです。
SELinuxラベルは、コンテナまたはPodにsecurityContextセクションを介して割り当てることができます。
アプリケーションPodとKubernetes APIサーバーなど、機密性の異なる層にあるPodは、別々のノードにデプロイする必要があります。 ノード分離の目的は、アプリケーションコンテナのブレイクアウトを防ぎ、より機密性の高いアプリケーションへのアクセスを直接提供して、クラスター内で簡単にピボットできるようにすることです。 Podが誤って同じノードにデプロイされるのを防ぐために、この分離を実施する必要があります。 これは、次の機能を使用して実施できます。
コンテナのランタイム構成は、Podのコンテナを実行するために使用され、パフォーマンスのオーバーヘッドを犠牲にして、多少なりともホストからの分離を提供できます。
Podに必要なシークレットは、ConfigMapなどの代替手段ではなく、Kubernetes Secret内に保存する必要があります。 etcd内に保存されているシークレットリソースは、保存時に暗号化する必要があります。
シークレットを必要とするPodでは、ボリュームを介してシークレットが自動的にマウントされ、できればemptyDir.mediumオプションのようにメモリ内に保存される必要があります。
このメカニズムは、Secret Store CSIドライバーなどのボリュームとしてサードパーティのストレージからシークレットを挿入するためにも使用できます。
PodのサービスアカウントにシークレットへのRBACアクセスを提供するよりも、これを優先的に行う必要があります。
これにより、シークレットを環境変数またはファイルとしてPodに追加できます。
環境変数メソッドは、ファイルの権限メカニズムとは異なり、ログのクラッシュダンプとLinuxの環境変数の非機密性により、漏洩が発生しやすい可能性があることに注意してください。
サービスアカウントトークンは、それらを必要としないPodにマウントしないでください。
これは、サービスアカウント内でautomountServiceAccountTokenをfalseに設定して、Namespace全体に適用するか、Podに固有の設定にすることで構成できます。
Kubernetes v1.22以降では、時間制限のあるサービスアカウント認証情報にはバインドされたサービスアカウントを使用します。
コンテナイメージには、パッケージ化されたプログラムを実行するための最小限のものだけが含まれている必要があります。 できれば、プログラムとその依存関係のみで、最小限のベースからイメージを構築します。 特に、本番環境で使用するイメージには、シェルやデバッグユーティリティを含めないでください。 エフェメラル(一時的)なデバッグコンテナをトラブルシューティングに使用できます。
DockerfileのUSER命令を使用して、権限のないユーザーで直接起動するイメージを構築します。
セキュリティコンテキストを使用すると、イメージマニフェストで指定されていない場合でも、runAsUserおよびrunAsGroupを使用して特定のユーザーとグループでコンテナイメージを開始できます。
ただし、イメージレイヤーのファイル権限により、イメージを変更せずに新しい権限のないユーザーでプロセスを開始することが不可能になる場合があります。
イメージタグ、特にlatestタグを使用してイメージを参照することは避けてください。
タグの背後にあるイメージはレジストリで簡単に変更できます。
イメージマニフェストに固有の完全なsha256ダイジェストを使用することをお勧めします。
このポリシーは、ImagePolicyWebhookを介して適用できます。
イメージ署名は、デプロイ時に自動的にアドミッションコントローラーで検証して、信頼性と整合性を検証することもできます。
コンテナイメージをスキャンすると、重大な脆弱性がコンテナイメージと一緒にクラスターにデプロイされるのを防ぐことができます。 イメージスキャンは、コンテナイメージをクラスターにデプロイする前に完了する必要があり、通常はCI/CDパイプラインのデプロイプロセスの一部として行われます。 イメージスキャンの目的は、コンテナイメージ内の潜在的な脆弱性とその防止策に関する情報(共通脆弱性評価システム(CVSS)スコアなど)を取得することです。 イメージスキャンの結果をパイプラインのコンプライアンスルールと組み合わせると、適切にパッチが適用されたコンテナイメージのみが本番環境に導入されます。
次のリストは、クラスターとアプリケーションのセキュリティ体制を強化するために検討できるアドミッションコントローラーをいくつか示しています。 このドキュメントの他の部分で参照される可能性のあるコントローラーも含まれています。
この最初のアドミッションコントローラーグループには、デフォルトで有効になっているプラグインがあります。 何をしているのかよくわからない場合は、有効のままにしておいてください:
CertificateApprovalCertificateSigningCertificateSubjectRestrictionsystem:mastersの「グループ」(または「組織属性」)を指定するすべての証明書リクエストを拒否します。LimitRangerMutatingAdmissionWebhookPodSecurityResourceQuotaValidatingAdmissionWebhook2番目のグループには、デフォルトでは有効になっていませんが、GAステータスであり、セキュリティ体制を向上させるために推奨されるプラグインが含まれます:
DenyServiceExternalIPsService.spec.externalIPsフィールドの新規使用をすべて拒否します。
これは、CVE-2020-8554: Man in the middle using LoadBalancer or ExternalIPsの緩和策です。NodeRestrictionnode-restriction.kubernetes.io/アノテーションを使用するのを防ぎます。このアノテーションは、kubeletの認証情報にアクセスできる攻撃者が、制御対象ノードへのPodの配置に影響を与えるために使用する可能性があります。3番目のグループには、デフォルトでは有効になっていませんが、特定のユースケースで検討できるプラグインが含まれます:
AlwaysPullImagesImagePolicyWebhookこのチェックリストは、開発者の観点からKubernetes上で動作するアプリケーションのセキュリティ確保に関する基本的なガイドラインを提供することを目的としています。 このリストは包括的なものではなく、時間の経過とともに発展させていくことを意図しています。
この文書の読み方と使い方について:
開発者とはKubernetesクラスターのユーザーで、名前空間スコープのオブジェクトを操作する人を想定しています。以下のチェックリストは、Kubernetesにデプロイするほとんどのアプリケーションに適用されるベースセキュリティ強化の推奨事項を提供します。
default ServiceAccountの使用を避ける。代わりに、各ワークロードまたはマイクロサービス用にServiceAccountを作成する。automountServiceAccountTokenをfalseに設定する。securityContextの推奨事項runAsNonRoot: trueを設定する。runAsUserとrunAsGroupを使用する)、コンテナイメージ内のファイルやディレクトリに適切な権限を設定する。fsGroupを使用して補助グループを追加する。securityContextの推奨事項allowPrivilegeEscalation: falseを使用して権限昇格を無効にする。readOnlyRootFilesystem: trueでルートファイルシステムを読み取り専用に設定する。privileged: falseを設定)。system:unauthenticatedグループのバインディングを確認し、可能な限り削除する。これにより、ネットワークレベルでAPIサーバーに接続できる全ての人にアクセス権が与えられることを防ぐ。create、update、deleteの権限は慎重に許可する必要があります。 patch権限をNamespaceに対して許可すると、ユーザーが名前空間やデプロイメントのラベルを更新できるようになり、攻撃対象領域が拡大する可能性があります。
機密性の高いワークロードについては、許可される書き込みアクションをさらに制限する推奨ValidatingAdmissionPolicyの提供を検討してください。
クラスターがNetworkPolicyを提供し、適用していることを確認してください。 ユーザーが異なるクラスターにデプロイするアプリケーションを作成している場合、NetworkPolicyが利用可能で適用されているとみなすことができるかどうかを確認してください。
このガイドのこのセクションでは、Kubernetes環境の構成に応じて有用となる可能性があるいくつかの高度なセキュリティ強化ポイントについて説明します。
Podとコンテナ用のSecurity Contextを設定する。
一部のコンテナは、クラスターのデフォルトランタイムが提供するものとは異なる分離レベルを必要とする場合があります。
runtimeClassNameをpodspecで使用して、異なるランタイムクラスを定義できます。
機密性の高いワークロードについては、gVisorなどのカーネルエミュレーションツールや、kata-containersなどのメカニズムを使用した仮想化分離の使用を検討してください。
高い信頼性が要求される環境では、クラスターセキュリティをさらに向上させるために機密仮想マシンの使用を検討してください。