コンテナアプリケーションに不要な権限を与えない

第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の特定のパスをマウントする