Container Service for Kubernetes (ACK) を使用すると、特権モード、ルート実行、hostPath ボリューム、ServiceAccount トークンマウントに関する制限など、コンテナエスケープおよび権限昇格のリスクを低減するコントロールにより、Pod セキュリティを強化できます。
コンテナエスケープの重要性
コンテナエスケープにより、攻撃者はコンテナからホストへの権限を昇格させ、ホストを制御できるようになります。このリスクは、Kubernetes の以下の 2 つのデフォルト動作によって生じます。
デフォルトのルートコンテキスト。 コンテナプロセスはデフォルトでルートとして実行されます。Docker は Linux capabilities を使用してルートを制限しますが、デフォルトの capabilities セットは広範です。
cap_chown, cap_dac_override, cap_fowner, cap_fsetid, cap_kill, cap_setgid, cap_setuid, cap_setpcap, cap_net_bind_service, cap_net_raw, cap_sys_chroot, cap_mknod, cap_audit_write, cap_setfcap
コンテナ化アプリケーションを侵害した攻撃者は、これらの capabilities を使用して、ホスト上の Secrets、ConfigMap、その他の機密データを読み取ることができます。特権モードは避けてください。特権モードでは、ホストのルートユーザーが持つすべての Linux capabilities が付与されます。
kubelet 経由でのノード全体の API アクセス。 Kubernetes ワーカーノードは、ノードオーソライザーを使用して kubelet API リクエストを管理します。これにより、各 kubelet には、そのノード上の Pod に関連する Services、Endpoints、Nodes、Pods、Secrets、ConfigMaps、永続ボリューム (PV)、永続ボリューム要求 (PVC) への読み取りアクセスが付与されるとともに、ノードステータス、Pod ステータス、Events への書き込みアクセスも付与されます。また、TLS ブートストラッピング用の CertificateSigningRequest (CSR) API への読み取り/書き込みアクセスおよび、委任された認証と権限付与のために TokenReview と SubjectAccessReview を作成する機能も付与されます。
デフォルトで、ACK クラスターは NodeRestriction アドミッションコントローラーを有効にしており、各 kubelet が自身のノードおよびバインドされた Pod のみを変更できるように制限しています。ただし、NodeRestriction のみでは、攻撃者が Kubernetes API をクエリしてクラスター情報を収集することを防ぐことはできません。
施行メカニズム
ACK は、Open Policy Agent (OPA) および Gatekeeper 上に構築された Pod セキュリティポリシー をサポートしており、Pod の作成および更新リクエストを定義済みのルールに対して検証し、準拠していないリクエストを拒否します。以下に示す各推奨事項には、名前空間レベルで適用可能な事前定義済みの ACK ポリシーが用意されています。
Pod セキュリティ推奨事項
一般的な攻撃ベクターに対する多層防御として、以下の 9 つのコントロールを組み合わせて適用してください。
1. 特権コンテナの禁止
特権コンテナは、ホストのルートユーザーが持つすべての Linux capabilities を継承します。ほとんどのワークロードでは特権コンテナは不要です。特権モードを禁止することで、攻撃者がホストリソースに直接アクセスすることを防ぎます。
制限対象フィールド:
|
フィールド |
許可される値 |
|
|
未定義、 |
|
|
未定義、 |
指定された名前空間全体でこの制限を適用するには、ACKPSPPrivilegedContainer ポリシーをデプロイします。
2. 非ルートユーザーとして Pod を実行
コンテナはデフォルトでルートとして実行されます。ルートコンテナにシェルアクセスを得た攻撃者は、ホストへの侵入を非常に容易に行えます。コンテナを非ルートユーザーとして実行することで、侵害時の影響範囲を限定できます。
以下のいずれかのアプローチを使用します。
-
コンテナイメージからシェルを削除します。
-
Dockerfile に
USER命令を追加します。 -
podSpec 内で
spec.securityContext.runAsUserおよびrunAsGroupを設定します。
指定された名前空間内でコンテナを実行できるユーザーおよびグループを制限するには、ACKPSPAllowedUsers ポリシーをデプロイします。
3. Docker-in-Docker および Docker.sock マウントの禁止
Docker-in-Docker を使用するか、Docker.sock をマウントしてコンテナ内でイメージをビルドまたは実行すると、コンテナプロセスがノードを制御できるようになります。
代わりに、以下の代替イメージビルド手法を使用します。
4. hostPath ボリュームの制限
hostPath ボリュームはホストディレクトリを Pod 内にマウントします。書き込みアクセス権を持つルートコンテナは、kubelet 設定を変更したり、マウントパス外のファイル(例:/etc/shadow)へのシンボリックリンクを作成したり、SSH キーをインストールしたり、ホストの Secrets を読み取ったり、その他の悪意のある操作を実行できます。hostPath マウントを読み取り専用に設定することで、被害を限定します。
volumeMounts:
- name: hostPath-volume
readOnly: true
mountPath: /host-path
指定された名前空間内でマウント可能なホストディレクトリを制限するには、ACKPSPHostFilesystem ポリシーをデプロイします。
5. リソースリクエストおよびリミットの設定
リソースリクエストおよびリミットが設定されていない Pod は、ノードの CPU およびメモリを枯渇させ、kubelet をクラッシュさせたり、他の Pod をエビクトしたりする可能性があります。リソース競合を軽減するために、リクエストおよびリミットを設定します。
podSpec 内で CPU およびメモリの リクエストおよびリミット を指定します。名前空間に リソースクォータ を適用して、すべてのコンテナがリクエストおよびリミットを宣言することを必須にします。LimitRange を使用して、コンテナ単位のデフォルト値および上限/下限を設定します。
指定された名前空間内でリソースリミットを適用するには、ACKContainerLimits ポリシーをデプロイします。
6. 権限昇格の禁止
権限昇格により、プロセスがランタイム中に権限を昇格させることができます(例:SUID または SGID バイナリ(sudo など)を実行)。これを無効化することで、非ルートプロセスがルートレベルのアクセス権を再取得することを防ぎます。
制限対象フィールド:
|
フィールド |
許可される値 |
|
|
|
securityContext:
allowPrivilegeEscalation: false
指定された名前空間内でこの設定を適用するには、ACKPSPAllowPrivilegeEscalationContainer ポリシーをデプロイします。
7. 自動的な ServiceAccount トークンマウントの無効化
Kubernetes API へのアクセスを必要としない Pod については、自動的な ServiceAccount トークンマウントを無効化して、Pod が侵害された場合のトークン漏洩を防ぎます。
特定の Pod に対してトークンマウントを無効化します。
apiVersion: v1
kind: Pod
metadata:
name: pod-no-automount
spec:
automountServiceAccountToken: false
特定の ServiceAccount を使用するすべての Pod に対してトークンマウントを無効化します。
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-no-automount
automountServiceAccountToken: false
トークンマウントを無効化しても、Pod が Kubernetes API に到達できなくなるわけではありません。Pod は引き続き API サーバーへのネットワーク接続を確立できます。API アクセスを完全にブロックするには、ACK クラスターの API サーバーエンドポイントの公開範囲を制限し、ネットワークポリシーを構成します。
指定された名前空間内のアプリケーションポッド全体で automountServiceAccountToken: false を適用するには、ACKBlockAutomountToken ポリシーをデプロイします。
8. サービス検出の無効化
他のクラスターサービスを必要としない Pod については、サービスリンクを無効化し、DNS ポリシーを変更することで、Pod が侵害された場合に攻撃者が列挙できる情報を制限します。
apiVersion: v1
kind: Pod
metadata:
name: pod-no-service-info
spec:
dnsPolicy: Default # 値 Default は DNS ポリシーのデフォルト設定を意味しません。
enableServiceLinks: false
デフォルトでは、Pod の DNS ポリシー は ClusterFirst であり、クエリはクラスター内 CoreDNS サービス経由でルーティングされます。dnsPolicy: Default を設定すると、DNS クエリはノードのリゾルバー経由で処理されます。enableServiceLinks: false を設定すると、名前空間内の Services が 環境変数 として注入されなくなります。
これらの設定は、CoreDNS への直接アクセスをブロックしません。攻撃者は依然として dig SRV *.*.svc.cluster.local @$CLUSTER_DNS_IP を実行してクラスターサービスを列挙できます。ネットワークポリシーを使用して、サービス検出を完全に制限します。
9. 読み取り専用のルートファイルシステムの使用
読み取り専用のルートファイルシステムにより、攻撃者がアプリケーションバイナリや設定ファイルを上書きすることを防げます。アプリケーションがディスクへの書き込みを必要とする場合は、代わりに tmpfs ボリュームまたはマウントされた永続ボリュームを使用します。
制限対象フィールド:
|
フィールド |
許可される値 |
|
|
|
securityContext:
readOnlyRootFilesystem: true
指定された名前空間内の Pod に対して読み取り専用のルートファイルシステムを適用するには、ACKPSPReadOnlyRootFilesystem ポリシーをデプロイします。
次のステップ
-
すべての 事前定義済み ACK セキュリティポリシー を確認します。
-
ネットワークポリシーを使用して、Pod 間および Pod から API サーバーへのトラフィックを制限します。