2.17. Linux ユーザー名前空間での Pod の実行
Linux ユーザー名前空間を使用すると、管理者はコンテナーのユーザーおよびグループ識別子 (UID および GID) を分離できるため、実行されているホストシステムとは異なる権限セットを、ユーザー名前空間でコンテナーに付与できます。これにより、ユーザー名前空間内で完全な権限を使用してプロセスを実行することをコンテナーに許可する一方で、ホストマシンに対する操作の権限をプロセスに与えないことが可能になります。
デフォルトでは、コンテナーはホストユーザー名前空間で実行されます。コンテナーをホストのユーザー名前空間で実行することは、そのユーザー名前空間でのみ使用可能な機能がコンテナーに必要な場合に便利です。しかし、ホストの名前空間で Pod を実行すると、コンテナーブレイクアウトの可能性など、セキュリティー上の懸念が生じます。コンテナーブレイクアウトが発生すると、別のコンテナー内のプロセスがホスト上に脱出し、そのプロセスがホスト上またはコンテナー内のファイルにアクセスしたり、ファイルを変更したりできるようになります。
個々のユーザー名前空間でコンテナーを実行すると、コンテナーブレイクアウトや、侵害されたコンテナーから他の Pod やノード自体に及ぶ可能性のあるその他のいくつかの脆弱性を軽減できます。
隔離されたユーザー名前空間で Pod を実行すると、Pod コンテナー内の UID/GID がホスト上の UID/GID と一致しなくなります。ファイルシステムの所有権が正しく機能するように、Linux カーネルは ID-mapped マウントを使用します。ID マップマウントは、仮想ファイルシステム (VFS) レイヤーにおいて、コンテナーとホスト間でユーザー ID を変換するものです。
現時点では、ネットワークファイルシステム (NFS) やその他のネットワーク/分散ファイルシステムなど、すべてのファイルシステムが ID-mapped マウントをサポートしているわけではありません。ID-mapped マウントをサポートしていないベンダーが提供する、NFS を基盤とした永続ボリュームを使用している Pod は、ユーザー名前空間で実行される際に、アクセスや権限の問題が発生する可能性があります。この動作は OpenShift Container Platform に固有のものではありません。これは、Kubernetes v1.33 以降のすべての Kubernetes ディストリビューションに適用されます。
ストレージオプションに対するユーザー名前空間のサポート状況を確認するには、OpenShift Container Platform でサポートされている CSI ドライバーを 参照してください。
2.17.1. Linux ユーザー名前空間のサポートの設定 リンクのコピーリンクがクリップボードにコピーされました!
Linux ユーザー名前空間を設定するには、次の手順に示すように、Pod 仕様で hostUsers パラメーターを false に設定し、その他のいくつかの設定を行います。
ユーザー名前空間でワークロードを実行すると、fsGroup、runAsGroup、runAsUser、supplementalGroups などの Security Context Constraints (SCC) フィールドに、RunAsAny を安全に設定できるようになります。これは、コンテナー外部の UID や GID が、これらのフィールドが表すコンテナー内部の UID や GID と異なるためです。
セキュリティーを強化するために、restricted-v3 または nested-container SCC を使用できます。これらは、Linux ユーザー名前空間内のワークロード向けに特別に設計されたものです。SCC に userNamespaceLevel: RequirePodLevel フィールドを設定すると、ワークロードが必ずユーザー名前空間で実行されます。SCC の詳細は、「Security Context Constraints の管理」を参照してください。
ワークロードに対して特定の SCC を必須とするには、oc adm policy add-scc-to-user コマンドまたは oc adm policy add-scc-to-group コマンドを使用して、特定のユーザーまたはグループに SCC を追加できます。詳細は、「OpenShift CLI 管理者コマンドリファレンス」を参照してください。
また、必要に応じて、Pod 仕様の procMount パラメーターを使用して、Pod 内の /proc ファイルシステムを unmasked に設定することもできます。一般的に安全であると考えられている /proc を unmasked に設定すると、コンテナーランタイムのデフォルトのマスキング動作がバイパスされるため、userNamespaceLevel を RequirePodLevel に設定する SCC でのみ使用する必要があります。
前提条件
-
restricted-v3またはnested-containerSCC で設定されたユーザーとして、またはいずれかの SCC で設定されたユーザーグループのユーザーとして、OpenShift Container Platform クラスターにログインします。または、ワークロードオブジェクトで、restricted-v3またはnested-containerSCC を直接設定することもできます。
手順
次のコマンドを実行して、Pod がデプロイされている OpenShift Container Platform の namespace のデフォルトユーザー ID (UID) およびグループ ID (GID) の範囲を編集します。
$ oc edit ns/<namespace_name>namespace の例
apiVersion: v1 kind: Namespace metadata: annotations: openshift.io/description: "" openshift.io/display-name: "" openshift.io/requester: system:admin openshift.io/sa.scc.mcs: s0:c27,c24 openshift.io/sa.scc.supplemental-groups: 1000/10000 openshift.io/sa.scc.uid-range: 1000/10000 # ... name: userns # ...各項目の説明:
metadata.annotations.openshift.io/sa.scc.supplemental-groups-
Pod 仕様で必要なデフォルトの GID を指定します。Linux ユーザー名前空間の範囲は
65535以下である必要があります。デフォルトは1000000000/10000です。 metadata.annotations.openshift.io/sa.scc.uid-range-
Pod 仕様で必要なデフォルトの UID を指定します。Linux ユーザー名前空間の範囲は
65535以下である必要があります。デフォルトは1000000000/10000です。
注記範囲 1000/10000 は、ID 1000 から始まる 10,000 個の値を意味するため、1000 から 10,999 までの範囲の ID を指定します。
適切な SCC を使用して動作するように設定したワークロードを作成し、
hostUsersパラメーターをfalseに設定して、Linux ユーザー名前空間の使用を有効にします。以下のような YAML ファイルを作成します。
Pod 仕様の例
apiVersion: v1 kind: Pod metadata: name: userns-pod spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault hostUsers: false containers: name: userns-container image: registry.access.redhat.com/ubi9 command: ["sleep", "1000"] securityContext: runAsUser: 1000 runAsGroup: 1000 runAsNonRoot: true procMount: Unmasked capabilities: add: - "SETGID" - "SETUID" # ...各項目の説明:
spec.hostUsers-
Pod をユーザー名前空間で実行するかどうかを指定します。
falseの場合、Pod は Pod 用に作成した新しいユーザー名前空間で実行されます。trueの場合、Pod はホストのユーザー名前空間で実行されます。デフォルトはtrueです。 spec.containers.securityContext.runAsUser-
コンテナー内で実行されるプロセスのユーザー ID を指定します。これは、
namespaceオブジェクトで設定した範囲内に収まっている必要があります。 spec.containers.securityContext.runAsGroup-
コンテナー内で実行されるプロセスのグループ ID を指定します。これは、
namespaceオブジェクトで設定した範囲内に収まっている必要があります。 spec.containers.securityContext.runAsNonRoot- コンテナー内のプロセスを 0 以外の UID を持つユーザーで実行することを指定します。
spec.containers.securityContext.procMount-
コンテナーに使用する proc マウントのタイプを指定します。
unmasked値を設定すると、コンテナーの/procファイルシステムが、コンテナーのプロセスによって読み取り/書き込み可能な状態でマウントされます。デフォルトはDefaultです。この値はオプションです。 spec.containers.securityContext.capabilities.add-
ユーザー名前空間に設定する Linux 機能を指定します。これにより、完全なルートアクセスを与えることなく特権アクションが許可されます。技術的に言えば、ユーザー名前空間の中でケイパビリティーを設定する方が、ユーザー名前空間の外で設定するよりも安全です。ケイパビリティーのスコープがユーザー名前空間の内部にあることで制限され、一般的に安全であると考えられるためです。しかし、信頼できないワークロードに
CAP_SYS_ADMINなどの Pod ケイパビリティーを付与すると、コンテナー化されたプロセスがアクセスできる潜在的なカーネルの攻撃対象領域が広がり、悪用可能な脆弱性が発見されるおそれがあります。したがって、ユーザー名前空間内のケイパビリティーは、Pod セキュリティーアドミッションではbaselineレベルで許可されます。この値はオプションです。
以下のコマンドを実行してオブジェクトを作成します。
$ oc create -f <file_name>.yaml
検証
作成した Pod 内のコンテナーで使用されているユーザー ID とグループ ID を確認します。Pod は Linux ユーザー名前空間内にあります。
Pod 内のコンテナーでシェルセッションを開始します。
$ oc rsh -c <container_name> pod/<pod_name>コマンドの例
$ oc rsh -c userns-container pod/userns-podコンテナー内で使用されているユーザー ID とグループ ID を表示します。
sh-5.1$ id出力例
uid=1000(1000) gid=1000(1000) groups=1000(1000)1 - 1
- コンテナーの UID とグループは、Pod 仕様で設定したものと同じである必要があります。
コンテナーのユーザー名前空間で使用されているユーザー ID を表示します。
sh-5.1$ lsns -t user出力例
NS TYPE NPROCS PID USER COMMAND 4026532447 user 3 1 1000 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 10001 - 1
- プロセスの UID は、Pod 仕様で設定したものと同じである必要があります。
次のコマンドを使用して、コンテナーシェルセッションを終了します。
sh-5.1$ exit
ノードによって使用されている UID を確認します。ノードは Linux ユーザー名前空間の外部にあります。このユーザー ID がコンテナーで使用されている UID と異なっている必要があります。
そのノードのデバッグセッションを開始します。
$ oc debug node/ci-ln-z5vppzb-72292-8zp2b-worker-c-q8sh9コマンドの例
$ oc debug node/ci-ln-z5vppzb-72292-8zp2b-worker-c-q8sh9/hostをデバッグシェル内のルートディレクトリーとして設定します。sh-5.1# chroot /hostノードによって使用されている UID を表示します。
sh-5.1# lsns -t userコマンドの例
NS TYPE NPROCS PID USER COMMAND 4026531837 user 233 1 root /usr/lib/systemd/systemd --switched-root --system --deserialize 28 4026532447 user 1 4767 2908816384 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 10001 - 1
- UID は、Pod 仕様で設定したものと異なる必要があります。
次のコマンドを使用してデバッグセッションを終了します。
sh-5.1# exitsh-5.1# exit
/procファイルシステムがコンテナーにunmaskedの状態でマウントされていることを確認します。これは、次のコマンドの出力に、読み取り/書き込み権限 (rw) が含まれていることからわかります。$ oc exec <pod_name> -- mount | grep /proc出力例
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)