【実務・中級編】 Kubernetes Pod Security Admissionによる特権コンテナの実行制限 – インフラ・ネットワーク & クラウドセキュリティ防御ガイド

なぜ「特権コンテナ」を許してはいけないのか?― Kubernetes要塞化の最前線

現場でインシデント対応をしていると、いまだに「開発の利便性」という名の免罪符で、安易に privileged: true を設定されたPodに出くわす。正直に言おう。特権コンテナを許可した時点で、そのKubernetesクラスタの防御ラインは崩壊しているも同然だ。

今回は、Pod Security Admission (PSA) を使い、この「パンドラの箱」を物理的に封鎖する方法を解説する。教科書的な説明は飛ばす。実戦でどう防ぐか、その一点に絞る。

—

1. なぜ「特権コンテナ」がクラスタの終焉を招くのか

攻撃者の視点で見れば、privileged: true は「ホストOSへのパスポート」だ。

もしあなたのWebアプリにRCE(リモートコード実行)の脆弱性があり、そのPodが特権モードで動いていたらどうなるか。攻撃者は以下のPoCのような手法で、ノードを完全に掌握する。

# 攻撃者がコンテナ内で実行するコマンド例
# 特権コンテナなら、ホストのディスクを直接マウントして書き換え可能
mkdir /mnt/host
mount /dev/sda1 /mnt/host
# ホストのSSH鍵を書き換え、バックドアを仕込む
echo "ssh-ed25519 AAAA... attacker@evil" >> /mnt/host/root/.ssh/authorized_keys

これだけで、コンテナを脱出し、物理(または仮想)ノードそのものが乗っ取られる。一度ノードが落ちれば、他のPodのシークレット情報も、クラスタの管理者権限も、全て筒抜けだ。

—

2. Pod Security Admission (PSA) で「拒絶」を自動化する

「気をつける」という運用ルールは必ず破られる。だからこそ、KubernetesのAdmission Controllerで「設定できないようにする」のがプロの仕事だ。

まず、Namespaceに対してポリシーを適用する。今回は最も厳格な restricted プロファイルを推奨する。

Namespaceの設定ファイル(policy.yaml)

apiVersion: v1
kind: Namespace
metadata:
  name: production-app
  labels:
    # 違反するPodの実行を「拒否」し、警告をログに出す設定
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: latest
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

これを適用した状態で、もし誰かが特権コンテナをデプロイしようとすると、Kubernetes APIは即座に拒絶する。

—

3. 「運用」で詰まないための実装例

「厳格にしすぎると開発が止まる」と文句を言うエンジニアがいるなら、正しいPod定義をテンプレートとして渡せばいい。以下は、SecurityContextを適切に設定した、実務で使える最小権限のテンプレートだ。

安全なPod定義(deployment.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: secure-app
spec:
  template:
    spec:
      securityContext:
        # 特権昇格を禁止
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 2000
      containers:
      - name: app
        image: my-app:latest
        securityContext:
          # ここが肝:特権モードを徹底的に排除
          allowPrivilegeEscalation: false
          capabilities:
            drop:
              - ALL # 全てのLinux能力を剥奪する
          readOnlyRootFilesystem: true # 書き込み不可にするのが理想

—

4. 現場の教訓:なぜ「不要」を削るのか

特権コンテナの禁止だけでなく、hostPath マウントの禁止もセットで行う必要がある。これらは、万が一アプリケーションに脆弱性があった際、「被害をコンテナ内に閉じ込める(Containment)」ための最後の砦だ。

現場でよくある失敗は、「特定のライブラリが必要だから」といって安易に権限を広げること。解決策はシンプルだ。

  • 必要な権限は capabilities で個別に付与する(例: NET_BIND_SERVICE のみ許可するなど)。
  • ReadOnlyRootFilesystem を徹底し、ログや一時ファイルは emptyDir に逃がす。

最後に:セキュリティは「性悪説」で構築せよ

「自分のチームは大丈夫」という慢心が、大規模な情報漏洩を引き起こす。Kubernetesの要塞化は、一度設定して終わりではない。開発者が新しいコンテナを作るたびに、PSAの監査ログをチェックし、ポリシー違反が出ていないかを監視する文化を作ること。

もしあなたがリードエンジニアなら、今回紹介した設定をCI/CDパイプラインに組み込み、「セキュリティポリシーに違反するコードはデプロイすらできない」という鉄の掟を自動化して実装してほしい。

それが、エンジニアとしての責任ある仕事のあり方だと、私は信じている。

コメント

タイトルとURLをコピーしました