コンテナアプリケーションに不要な権限を与えない
第3回~第5回の「コンテナ技術の基礎(1)」「コンテナ技術の基礎(2)」「コンテナ技術の基礎(3)」でも紹介しましたが、KubernetesのコンテナではUser namespaceが分離されていません。
ホストのrootはコンテナのrootと違うものではないということです。これでは困るので主にCapabilityを使ってコンテナのrootは本来持っている権限は制限されていますが、設定次第で緩和もできます。CapabilityはKubernetesマニフェストのspec.containers.securityContext.capabilitiesで指定します。以降、断りがない限り、紹介する機能はマニフェストで指定します。
Kubernetes Hardening Guidanceでは特権からの保護の観点で以下が推奨されています。
- 非rootユーザーで動作するコンテナを使用する
- 以下の方法で特権コンテナのデプロイを防止する
- rootでの実行やrootへの昇格を許可するコンテナを拒否する
- AppArmor, seccompなどを利用して特権操作を拒否する
- hostPID, hostIPC, hostNetwork, hostPathの許可のような脱獄に使われる機能を拒否する
非rootユーザーで動作するコンテナを使用する
非rootユーザーで動作するコンテナを使用する場合はDockerfileでUSERを明示的に指定します。USERを指定しない場合は実行ユーザーはrootになります。この設定をしなくても後述する「runAsUser」を使えば実行ユーザーを指定できます。
しかし、米国家安全保障局(NSA:National Security Agency)や米国土安全保障省サイバーセキュリティ・インフラストラクチャセキュリティ庁(CISA)から公開された、Kubernetes環境に対する脅威やリスクを最小限に抑えるための対策を解説したセキュリティガイダンス「Kubernetes Hardening Guidance」によると、より確実にするために両方指定することが推奨されています。
rootでの実行やrootへの昇格を許可するコンテナを拒否する
rootでのコンテナの実行やrootへの昇格を拒否するように設定する場合はSecurityContextを利用します。SecurityContextにはContainer単位で指定する項目と、Pod単位で指定する項目があります。 Container/Podの両方に設定されている場合はContainerの値が優先されます。
「rootでの実行やrootへの昇格を許可するコンテナを拒否する」という意味で関連する各項目と推奨される設定は次の通りです。
# | 項目 | 機能概要 | 設定対象 | 推奨設定 |
---|---|---|---|---|
1 | runAsUser | コンテナのプロセスUIDを指定する。指定したUID 以外のプロセス起動はできない | Pod/Container | 指定する |
2 | runAsGroup | コンテナのプロセスGIDを指定する。指定したGID 以外のプロセス起動はできない | Pod/Container | 指定する |
3 | runAsNonRoot | Trueを指定しコンテナがrootで動作した場合、起動に失敗する | Pod/Container | true |
4 | supplementalGroups | コンテナのプロセスGIDに加えて追加したいgroupsをリストで指定する | Pod | 指定する |
5 | fsGroup | VolumeのGIDに指定されたものをセットする | Pod | 指定する |
6 | privileged | コンテナを特権モードで実行するか指定する | Container | false(デフォルト) |
7 | allowPrivilegeEscalation | 親プロセスよりも多くの権限を取得できるかを制御する。setuidフラグのついたプログラムを実行できない | Container | false |
8 | capabilities | カーネルレベルのアクセス許可を細かく制御する | Container | 指定しない |
これらの設定が漏れてクラスタ内に特権を持ったPodがデプロイされるのを検知し防止できます。こちらについては、Azure Policyを使ったSecurityContextの設定の検査の話として、次回の記事で紹介します。
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
containers:
- name: sec-ctx-demo
# ...
securityContext:
allowPrivilegeEscalation: false
# ...
AppArmorによる保護
MAC(Mandantory Access Control、強制アクセス制限)を使った保護を実現するのがAppArmorです。AKSではAppArmorがデフォルトで有効になっており、「/proc」や「/sys」へのアクセスが制限されています。デフォルトのProfileで制限されている内容はこちらで確認できます。
seccompによる保護
コンテナのプロセスから呼び出せるシステムコールを制限することで特権からの保護できるのがseccompです。Dockerではseccompはデフォルトで有効になっていますが、Kubernetesではデフォルトでは有効になっていません。有効にする場合はここでもSecurityContextを利用します。
# | 項目 | 機能概要 | 設定対象 | 推奨設定 |
---|---|---|---|---|
9 | seccompProfile | seccompを適用する | Pod | runtime/default |
ホストのネームスペース共有の無効化
hostPID, hostIPC, hostNetwork, hostPathはそれぞれ以下のような効果がある設定です。デフォルトで無効になっています。通常の業務アプリケーションを動かす場合にこれらを有効にする必要は多くはありませんが、クラスタの監視やログ収集やデバッグ等を行いたい場面などは必要に応じて有効化しましょう。
# | 項目 | 効果 |
---|---|---|
1 | hostPID | Nodeで動作しているPIDを参照し操作できる |
2 | hostIPC | Node内でSystem V プロセス間通信オブジェクトとPOSIXメッセージキューを使った通信ができる |
3 | hostNetwork | Nodeのネットワークを共有する |
4 | hostPath | Nodeの特定のパスをマウントする |