Kubernetes セキュリティコンテキストとは?ポッドを保護する方法を解説
Kubernetes の各リソースに必要な権限を割り当てると同時に、権限の過剰な付与を回避する必要があります。最小権限の原則に従って権限を細かく定義するにはどうすればよいでしょうか。
その解決策となるのがセキュリティコンテキストです。
この記事では、Kubernetes におけるセキュリティコンテキストの基本として、概要と仕組み、定義方法、使用時に留意したい制限事項などをわかりやすく解説します。
関 連 記 事
Kubernetesとは? | Kubernetesセキュリティ の基礎 | Kubernetesアーキテクチャの 設計方法 |
AWSのEKS (Elastic Kubernetes Service) | Kubernetesの クラスターとは? | Kubernetes のノードとは? |
KubernetesのPodとは? | KubernetesのHelmとは? | クラウドセキュリティと ランタイムインサイト |
Kubernetes セキュリティコンテキストとは
Kubernetesにおけるセキュリティコンテキストとは、管理者がセキュリティ関連のパラメータをリソース単位で定義するためのツールです。ホストサーバー上のリソースへのアクセスに必要な特定の権限を各リソースに割り当てながら、特に必要のないリソースへのアクセスを拒否することができます。
Kubernetes では、個々のポッドやコンテナ権限をセキュリティコンテキストで定義します。セキュリティコンテキストを使用すると、外部ファイルへのアクセス権や特権モードで実行する権限などをコンテナやポッドに付与できます。
内部と外部のセキュリティコンテキスト
Kubernetesセキュリティコンテキストには、定義できるルールに応じて Kubernetes 自体の内部で適用されるものと、外部のセキュリティコンテキストツール(AppArmor やSELinuxなど)に統合されるものがあるという点が少し複雑です。
そのため、セキュリティコンテキストは、内部でポッドやコンテナの特定の権限を定義したり、ホスト上で実行される外部のセキュリティツールとKubernetesとを統合したりする手段として考えることができます。
セキュリティコンテキストと RBACの違い
セキュリティコンテキストと Kubernetes ロールベースのアクセス制御(RBAC)は、似ていますが、明確な違いがあります。主なものは次のとおりです。
- リソースの範囲: RBAC はポッドやノード、クラスター全体など、さまざまなリソースに適用できます。一方、セキュリティコンテキストはポッドにのみ権限を割り当てます。
- アクション: RBAC は、管理者が RBAC ポリシー内で定義できる「動詞」に基づいてさまざまな権限を付与できます。セキュリティコンテキストは、特権モードでの実行のように事前に定義された特定の種類の機能のみを割り当てるため、RBAC よりも限定的です(ただし、SELinux や AppArmor を使用してルールを定義する場合はセキュリティコンテキストの方が柔軟です)。
- 拡張性: 前述のとおり、セキュリティコンテキストは SELinux や AppArmor などの外部フレームワークと統合することによって拡張できます。Kubernetes RBAC では、外部ツールを使用してポリシーを定義することはできません。
つまり、セキュリティコンテキストは、RBAC では管理できないコンテナやポッドのセキュリティ権限を追加で定義する手段であると考えられます。ほとんどの Kubernetes 環境では、セキュリティコンテキストと RBAC を同時に使用することによって相互に補完することができます。
セキュリティコンテキストと Pod Security Policiesの違い
セキュリティコンテキストで定義できるセキュリティルールのほとんどはPod Security Policies でも構成できますが、これらは異なるツールです。
KubernetesがセキュリティコンテキストPod Security Policieの両方をサポートしている理由は、セキュリティコンテキストが本来、Pod Security Policiesの代替品であるためです。Pod Security Policiesを使用すれば、クラスター内で実行されているすべてのポッドの権限を構成できますが、個々のポッドに適用できるセキュリティコンテキストの方が細かい制御が可能です。
Kubernetes バージョン1.21では、Pod Security Policiesは非推奨とされていましたが、現時点では引き続きサポートされています。Pod Security PoliciesはKubernetes 1.25で完全に削除されるため、定義済みのPod Security Policiesはその時点で無視されることになります。
内部セキュリティコンテキストの使用方法
Kubernetes では、セキュリティコンテキストを簡単に使用できます
SELinux や AppArmorと 統合せず、内部のセキュリティコンテキストのみ使用している場合は特に手軽です。一般的な使用方法は、ポッドのデプロイ時に作成するデプロイメントファイル内に、セキュリティコンテキストコードのブロックを含めるだけです。
たとえば、次のブロックでは、Kubernetesにユーザー ID が「1000」のポッドを実行するよう指示しています。また、ポッド内のすべてのコンテナに「2000」のグループ ID を割り当てています。
Spec:
securityContext:
runAsUser: 1000
fsGroup: 2000
RBAC とは異なり、セキュリティコンテキストでは、セキュリティルールを適用するために複数の種類のファイル(Role や RoleBinding など)を定義する必要はありません。デプロイメントを宣言する際に必要なセキュリティコンテキストコードを追加するだけです。そこから先は Kubernetes が自動的にルールを適用します。
セキュリティコンテキストで割り当て(または拒否)が可能な権限の種類の概要については、Kubernetes のドキュメントを参照しましょう。ほとんどの管理者は、ユーザーIDやグループIDに関する権限に加え、ポッドやコンテナを特権モードで実行できるパラメータの価値に気付くのではないでしょうか。
特権モードで実行しているコンテナは、ホスト上のカーネルレベルのリソースに対して、rootとして実行するプロセスとほぼ同じアクセス権を持つため、通常は特権モードを許可しません。代わりに、コンテナやポッドによる特定のポートへのバインド、または特定の外部バイナリの実行を許可し、それ以外はコンテナ外のリソースへのアクセスを拒否するなど、権限を細かく定義します。
外部セキュリティコンテキストの使用方法
SELinux や AppArmor のような外部ツールに基づいてセキュリティコンテキストを適用するには、もう少し手間がかかります。ここでは、基本的な手順をご紹介します。
SELinux または AppArmor モジュールの読み込み
最初に、使用するフレームワーク(SELinux や AppArmor など)に関連付けられたカーネルモジュールが、コンテナやポッドをホストするノードにインストールされ、読み込まれていることを確認する必要があります。
ほとんどの場合、Kubernetes はポッドやコンテナを自動的にノードに割り当てるため、どのノードがどのコンテナやポッドをホストするかを事前に知ることはできません。そのため、これらのフレームワークを使用してセキュリティコンテキストを定義する場合、通常はクラスターのすべてのノードに AppArmor または SELinux をインストールする必要があります。
プロファイルの読み込み
モジュールを読み込んだら、権限の定義に使用する AppArmor または SELinux のプロファイルを読み込む必要があります。たとえば、この AppArmor プロファイルは、ファイルの書き込み機能を拒否します。
#include <tunables/global>
profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
#include <abstractions/base>
file,
# Deny all file writes.
deny /** w,
}
Code language: HTML, XML (xml)
ノードのファイルシステム内で、Kubernetes が読み込める場所にプロファイルを保存します。
ここでも、たいていはどのノードがどのコンテナやポッドを実行するかはわからないため、クラスター内の各ノードにプロファイルを読み込む必要があります。
各ノードに SSH を設定してプロファイルを手動で適用するのを避けるためなど、これを効果的に行う方法については、ノードプロファイルに関する Kubernetes のドキュメントを参照しましょう。
Kubernetes でのプロファイルの適用
最後に、外部のセキュリティコンテキストプロファイルを参照し、デプロイメントに適用するよう Kubernetes に指示するセキュリティコンテキストブロックをデプロイメントファイルに追加します。
apiVersion: v1
kind: Pod
metadata:
name: apparmor-demo
annotations:
container.apparmor.security.beta.kubernetes.io/hello: /path/to/policy-file
Code language: JavaScript (javascript)
次のコマンドで宣言を適用します。
kubectl create -f ./deployment.yml
これで、Kubernetes はデプロイメントファイル内で直接構成したセキュリティコンテキストと同じように、AppArmor や SELinux で構成したポリシーを適用するようになります。
セキュリティコンテキストの制約
Kubernetes セキュリティコンテキストは、特定の種類の権限を細かく定義するための強力なツールです。ただし、現時点ではいくつかの大きな制約があります。
Windows 非対応
まず、セキュリティコンテキストツールは現在、Linux ベースのサーバー上で有効な特権と権限にのみ対応しています。Kubernetes で Windows コンテナを実行する場合、セキュリティコンテキストは役に立ちません。
ポッド/コンテナレベルのセキュリティに限定
セキュリティコンテキストは、ポッドまたはコンテナの権限のみ定義することができます。スタックの他のレイヤの特権は制御できません。
当然ながら、セキュリティコンテキストで適用できるルールのほとんどは、コンテナまたはポッドに適用した場合にのみ意味を持ちます。たとえば、あるノードに非特権モードで実行するように指示しても意味はありません。
ここでは、セキュリティコンテキストがあくまでポッドまたはコンテナレベルのセキュリティ問題に対処するためのツールであることがポイントです。ノード、ユーザー、サービスアカウントなどを保護するには、RBACなどの他のツールが必要となります。
進化する機能
セキュリティコンテキストは Kubernetes の比較的新しい機能であり、現在も進化し続けています。一部のパラメータ(Kubernetes 1.20 でベータ版が導入された fsGroupChangePolicy など)はまだ完全にサポートされておらず、今後さらに定義が追加される可能性があります。
そのため、現在、本番環境のクラスターでセキュリティコンテキストを使用することは確かに可能ですが、特定の種類の定義が今後のリリースで変更される可能性があるため、この機能の進化に注意深く目を向けることが重要です。
非効率なツール
ここまでに述べたとおり、一部の(特にSELinuxやAppArmorプロファイルを使用する)セキュリティコンテキストの主な制約として、クラスターのすべてのノードには外部リソースをデプロイする必要があります。このプロセスを自動化する方法もありますが、自動化を設定するだけでもかなりの手間がかかります。また、異なる Linux ディストリビューションを実行しているノードがある場合、デプロイメントが複雑になる可能性があります。その場合、AppArmorやSELinuxの設定をディストリビューションごとにカスタマイズしなければならなくなるでしょう。
まとめ
Kubernetesにおけるセキュリティコンテキストは、課題の多いツールです。
将来的には、ノードをまたいだポリシープロファイルのデプロイメントを簡素化するツールの出現が期待されます。しかし、現時点では、ノードの設定にかかる労力を侮ってはいけません。
そんな短所があるにもかかわらず、現状のセキュリティコンテキストは、Kubernetes クラスターにおけるアクセス制御の潜在的な欠点を補う重要なリソースであると言えます。範囲が限定されており、それ自体が完全なアクセス制御ソリューションというわけではありませんが、クラスター全体のセキュリティを強化する手段として活用することをおすすめします。