@@ -52,7 +52,7 @@ Podに設定したセキュリティ設定はPod内の全てのコンテナに
5252
5353設定ファイルの中の` runAsUser ` フィールドは、Pod内のコンテナに対して全てのプロセスをユーザーID 1000で実行するように指定します。
5454` runAsGroup ` フィールドはPod内のコンテナに対して全てのプロセスをプライマリーグループID 3000で実行するように指定します。このフィールドが省略されたときは、コンテナのプライマリーグループIDはroot(0)になります。` runAsGroup ` が指定されている場合、作成されたファイルもユーザー1000とグループ3000の所有物になります。
55- また` fsGroup ` も指定されているため、全てのコンテナ内のプロセスは補助グループID 2000にも含まれます。` /data/demo ` ボリュームとこのボリュームに作成されたファイルはグループID 2000になります。
55+ また` fsGroup ` も指定されているため、全てのコンテナ内のプロセスは補助グループID 2000にも含まれます。` /data/demo ` ボリュームとこのボリュームに作成されたファイルはグループID 2000になります。加えて、 ` supplementalGroups ` フィールドが指定されている場合、全てのコンテナ内のプロセスは指定されている補助グループIDにも含まれます。もしこのフィールドが指定されていない場合、空を意味します。
5656
5757Podを作成してみましょう。
5858
@@ -128,17 +128,176 @@ id
128128出力はこのようになります。
129129
130130``` none
131- uid=1000 gid=3000 groups=2000
131+ uid=1000 gid=3000 groups=2000,3000,4000
132132```
133133
134- 出力から` runAsGroup ` フィールドと同じく` gid ` が3000になっていることが確認できるでしょう。` runAsGroup ` が省略された場合、` gid ` は0(root)になり、そのプロセスはグループroot(0)とグループroot(0)に必要なグループパーミッションを持つグループが所有しているファイルを操作することができるようになります。
134+ 出力から` runAsGroup ` フィールドと同じく` gid ` が3000になっていることが確認できるでしょう。` runAsGroup ` が省略された場合、` gid ` は0(root)になり、そのプロセスはグループroot(0)とグループroot(0)に必要なグループパーミッションを持つグループが所有しているファイルを操作することができるようになります。また、 ` groups ` の出力に、 ` gid ` に加えて、 ` fsGroups ` 、 ` supplementalGroups ` フィールドで指定したグループIDも含まれていることも確認できるでしょう。
135135
136136shellから抜けましょう。
137137
138138``` shell
139139exit
140140```
141141
142+ ### コンテナイメージ内の` /etc/group ` から暗黙的にマージされるグループ情報
143+
144+ Kubernetesは、デフォルトでは、Podで定義された情報に加えて、コンテナイメージ内の` /etc/group ` のグループ情報をマージします。
145+
146+ {{% code_sample file="pods/security/security-context-5.yaml" %}}
147+
148+ このPodはsecurity contextで` runAsUser ` 、` runAsGroup ` 、` supplementalGroups ` フィールドが指定されています。しかし、コンテナ内のプロセスには、コンテナイメージ内の` /etc/group ` に定義されたグループIDが、補助グループとして付与されていることが確認できるでしょう。
149+
150+ Podを作成してみましょう。
151+
152+ ``` shell
153+ kubectl apply -f https://k8s.io/examples/pods/security/security-context-5.yaml
154+ ```
155+
156+ Podのコンテナが実行されていることを確認します。
157+
158+ ``` shell
159+ kubectl get pod security-context-demo
160+ ```
161+
162+ 実行中のコンテナでshellを取ります。
163+
164+ ``` shell
165+ kubectl exec -it security-context-demo -- sh
166+ ```
167+
168+ プロセスのユーザー、グループ情報を確認します。
169+
170+ ``` shell
171+ $ id
172+ ```
173+
174+ 出力はこのようになります。
175+
176+ ``` none
177+ uid=1000 gid=3000 groups=3000,4000,50000
178+ ```
179+
180+ ` groups ` にグループID` 50000 ` が含まれていることが確認できるでしょう。これは、ユーザー(` uid=1000 ` )がコンテナイメージで定義されており、コンテナイメージ内の` /etc/group ` でグループ(` gid=50000 ` )に所属しているためです。
181+
182+ コンテナイメージの` /etc/group ` の内容を確認してみましょう。
183+
184+ ``` shell
185+ $ cat /etc/group
186+ ```
187+
188+ ユーザー` 1000 ` がグループ` 50000 ` に所属していることが確認できるでしょう。
189+
190+ ``` none
191+ ...
192+ user-defined-in-image:x:1000:
193+ group-defined-in-image:x:50000:user-defined-in-image
194+ ```
195+
196+ shellから抜けましょう。
197+
198+ ``` shell
199+ exit
200+ ```
201+
202+ {{<note >}}
203+ _ 暗黙的にマージされる_ 補助グループはボリュームアクセスを行う際にセキュリティ上の懸念を引き起こすことがあります(詳細は[ kubernetes/kubernetes #112879 ] ( https://issue.k8s.io/112879 ) を参照してください)。回避したい場合、次節を参照してください。
204+ {{</note >}}
205+
206+ ## Podにfine-grained(きめ細かい) SupplementalGroups controlを設定する {#supplementalgroupspolicy}
207+
208+ {{< feature-state feature_gate_name="SupplementalGroupsPolicy" >}}
209+
210+ この機能はkubeletとkube-apiseverに` SupplementalGroupsPolicy `
211+ [ フィーチャーゲート] ( /docs/reference/command-line-tools-reference/feature-gates/ ) を設定し、Podの` .spec.securityContext.supplementalGroupsPolicy ` フィールドを指定することで利用できます。
212+
213+ ` supplementalGroupsPolicy ` フィールドは、Pod内のコンテナプロセスに付与される補助グループを、どのように決定するかを定義します。有効な値は次の2つです。
214+
215+ * ` Merge ` : ` /etc/group ` で定義されている、コンテナのプライマリユーザーが所属するグループをマージします。指定されていない場合、このポリシーがデフォルトです。
216+
217+ * ` Strict ` : ` fsGroup ` 、` supplementalGroups ` 、` runAsGroup ` フィールドで指定されたグループのみ補助グループに指定されます。つまり、` /etc/group ` で定義された、コンテナのプライマリユーザーのグループ情報はマージされません。
218+
219+ この機能が有効な場合、` .status.containerStatuses[].user.linux ` フィールドで、コンテナの最初のプロセスに付与されたユーザー、グループ情報が確認出来ます。暗黙的なグループIDが付与されているかどうかを確認するのに便利でしょう。
220+
221+ {{% code_sample file="pods/security/security-context-6.yaml" %}}
222+
223+ このPodマニフェストは` supplementalGroupsPolicy=Strict ` を指定しています。` /etc/group ` に定義されているグループ情報が、コンテナ内のプロセスの補助グループにマージされないことが確認できるでしょう。
224+
225+ Podを作成してみましょう。
226+
227+ ``` shell
228+ kubectl apply -f https://k8s.io/examples/pods/security/security-context-6.yaml
229+ ```
230+
231+ Podのコンテナが実行されていることを確認します。
232+
233+ ``` shell
234+ kubectl get pod security-context-demo
235+ ```
236+
237+ プロセスのユーザー、グループ情報を確認します。
238+
239+ ``` shell
240+ kubectl exec -it security-context-demo -- id
241+ ```
242+
243+ 出力はこのようになります。
244+
245+ ``` none
246+ uid=1000 gid=3000 groups=3000,4000
247+ ```
248+
249+ Podのステータスを確認します。
250+
251+ ``` shell
252+ kubectl get pod security-context-demo -o yaml
253+ ```
254+
255+ ` status.containerStatuses[].user.linux ` フィールドでコンテナの最初のプロセスに付与されたユーザー、グループ情報が確認出来ます。
256+
257+ ``` none
258+ ...
259+ status:
260+ containerStatuses:
261+ - name: sec-ctx-demo
262+ user:
263+ linux:
264+ gid: 3000
265+ supplementalGroups:
266+ - 3000
267+ - 4000
268+ uid: 1000
269+ ...
270+ ```
271+
272+ {{<note >}}
273+ ` status.containerStatuses[].user.linux ` フィールドで公開されているユーザー、グループ情報は、コンテナの最初のプロセスに、_ 最初に付与された_ 情報であることに注意してください。
274+ もしそのプロセスが、自身のユーザー、グループ情報を変更できるシステムコール(例えば [ ` setuid(2) ` ] ( https://man7.org/linux/man-pages/man2/setuid.2.html ) ,
275+ [ ` setgid(2) ` ] ( https://man7.org/linux/man-pages/man2/setgid.2.html ) ,
276+ [ ` setgroups(2) ` ] ( https://man7.org/linux/man-pages/man2/setgroups.2.html ) 等)を実行する権限を持っている場合、プロセス自身で動的に変更が可能なためです。
277+ つまり、実際にプロセスに付与されているユーザー、グループ情報は動的に変化します。
278+ {{</note >}}
279+
280+ ### 利用可能な実装 {#implementations-supplementalgroupspolicy}
281+
282+ {{% thirdparty-content %}}
283+
284+ 下記のコンテナランタイムがfine-grained(きめ細かい) SupplementalGroups controlを実装しています。
285+
286+ CRI実装:
287+ - [ containerd] ( https://containerd.io/ ) v2.0以降
288+ - [ CRI-O] ( https://cri-o.io/ ) v1.31以降
289+
290+ ノードのステータスでこの機能が利用可能かどうか確認出来ます。
291+
292+ ``` yaml
293+ apiVersion : v1
294+ kind : Node
295+ ...
296+ status :
297+ features :
298+ supplementalGroupsPolicy : true
299+ ` ` `
300+
142301## Podのボリュームパーミッションと所有権変更ポリシーを設定する
143302
144303{{< feature-state for_k8s_version="v1.23" state="stable" >}}
@@ -367,6 +526,41 @@ securityContext:
367526 localhostProfile: my-profiles/profile-allow.json
368527` ` `
369528
529+ # # コンテナにAppArmorプロフィールを設定する
530+
531+ コンテナにAppArmorプロフィールを設定するには、`securityContext`セクションに`appAormorProfile`フィールドを含めてください。
532+ ` appAormerProfile` フィールドには、`type`フィールドと`localhostProfile`フィールドから構成される[AppArmorProfile](/docs/reference/generated/kubernetes-api/{{< param "version"
533+ >}}/#apparmorprofile-v1-core)オブジェクトが入ります。`type`フィールドの有効なオプションは`RuntimeDefault`(デフォルト)、`Unconfined`、`Localhost`です。
534+ ` localhostProfile` は`type`が`Localhost`のときには必ず設定しなければなりません。この値はノードで事前に設定されたプロフィール名を示します。Podは事前にどのノードにスケジュールされるかわからないため、指定されたプロフィールはPodがスケジュールされ得る全てのノードにロードされている必要があります。カスタムプロフィールをセットアップする方法は[Setting up nodes with profiles](/docs/tutorials/security/apparmor/#setting-up-nodes-with-profiles)を参照してください。
535+
536+ 注意 : ` containers[*].securityContext.appArmorProfile.type` が明示的に`RuntimeDefault`に設定されている場合は、もしノードでAppArmorが有効化されていなければ、Podの作成は許可されません。
537+ しかし、`containers[*].securityContext.appArmorProfile.type`が設定されていない場合、AppArmorが有効化されていれば、デフォルト(`RuntimeDefault`)が適用されます。もし、AppArmorが無効化されている場合は、Podの作成は許可されますが、コンテナには`RuntimeDefault`プロフィールの制限は適用されません。
538+
539+ これは、AppArmorプロフィールとして、ノードのコンテナランタイムのデフォルトプロフィールを設定する例です。
540+
541+ ` ` ` yaml
542+ ...
543+ containers:
544+ - name: container-1
545+ securityContext:
546+ appArmorProfile:
547+ type: RuntimeDefault
548+ ` ` `
549+
550+ これは、AppArmorプロフィールとして、`k8s-apparmor-example-deny-write`という名前で事前に設定されたプロフィールを設定する例です。
551+
552+ ` ` ` yaml
553+ ...
554+ containers:
555+ - name: container-1
556+ securityContext:
557+ appArmorProfile:
558+ type: Localhost
559+ localhostProfile: k8s-apparmor-example-deny-write
560+ ` ` `
561+
562+ より詳細な内容については[Restrict a Container's Access to Resources with AppArmor](/docs/tutorials/security/apparmor/)を参照してください。
563+
370564# # コンテナにSELinuxラベルをつける
371565
372566コンテナにSELinuxラベルをつけるには、Pod・コンテナマニフェストの`securityContext`セクションに`seLinuxOptions`フィールドを追加してください。
@@ -386,24 +580,72 @@ SELinuxラベルを適用するには、ホストOSにSELinuxセキュリティ
386580
387581# ## 効率的なSELinuxのボリューム再ラベル付け
388582
389- {{< feature-state for_k8s_version="v1.25" state="alpha" >}}
583+ {{< feature-state feature_gate_name="SELinuxMountReadWriteOncePod" >}}
584+
585+ {{< note >}}
586+ Kubernetes v1.27で、`ReadWriteOncePod` アクセスモードを使用するボリューム(およびPersistentVolumeClaim)にのみ、この機能の限定的な機能が早期提供されています。
587+
588+ Alphaフィーチャーとして、`SELinuxMount`[フィーチャーゲート](/docs/reference/command-line-tools-reference/feature-gates/)を有効にすることで、以下で説明するように、他の種類のPersistentVolumeClaimにもパフォーマンス改善の範囲を広げる事ができます。
589+ {{< /note >}}
390590
391591デフォルトでは、コンテナランタイムは全てのPodのボリュームの全てのファイルに再帰的にSELinuxラベルを付与します。処理速度を上げるために、Kubernetesはマウントオプションで`-o context=<label>`を使うことでボリュームのSELinuxラベルを即座に変更することができます。
392592
393593この高速化の恩恵を受けるには、以下の全ての条件を満たす必要があります。
394594
395595* Alphaフィーチャーゲートの`ReadWriteOncePod`と`SELinuxMountReadWriteOncePod`を有効にすること
396- * Podが`accessModes: ["ReadWriteOncePod"]`でPersistentVolumeClaimを使うこと
596+ * Podが適用可能な`accessModes`でPersistentVolumeClaimを使うこと
597+ * ボリュームが`accessModes: ["ReadWriteOncePod"]`を持ち、フィーチャーゲート`SELinuxMountReadWriteOncePod`が有効であること
598+ * または、ボリュームが他のアクセスモードを使用し、フィーチャーゲート`SELinuxMountReadWriteOncePod`と`SELinuxMount`の両方が有効であること
397599* Pod(またはPersistentVolumeClaimを使っている全てのコンテナ)に`seLinuxOptions`が設定されていること
398- * 対応するPersistentVolumeが{{< glossary_tooltip text="CSI" term_id="csi" >}}ドライバーを利用するボリュームか、レガシー`iscsi`ボリュームタイプを利用するボリュームであること
399- * CSIドライバーを利用するボリュームを利用している場合、そのCSIドライバーがCSIドライバーインスタンスで`spec.seLinuxMount: true`を指定したときに`-o context`でマウントを行うとアナウンスしていること
600+ * 対応するPersistentVolumeが以下のいずれかであること
601+ * レガシーのin-treeボリュームの場合、`iscs`、`rbd`、`fc`ボリュームタイプであること
602+ * または、{{< glossary_tooltip text="CSI" term_id="csi" >}}ドライバーを使用するボリュームで、そのCSIドライバーがCSIドライバーインスタンスで`spec.seLinuxMount: true`を指定したときに`-o context`でマウントを行うとアナウンスしていること
400603
401604それ以外のボリュームタイプでは、コンテナランタイムはボリュームに含まれる全てのinode(ファイルやディレクトリ)に対してSELinuxラベルを再帰的に変更します。
402605ボリューム内のファイルやディレクトリが増えるほど、ラベリングにかかる時間は増加します。
403606
607+ # # `/proc`ファイルシステムへのアクセスを管理する {#proc-access}
608+
609+ {{< feature-state feature_gate_name="ProcMountType" >}}
610+
611+ OCI runtime specificationに準拠するランタイムでは、コンテナはデフォルトで、いくつかの複数のパスはマスクされ、かつ、読み取り専用のモードで実行されます。
612+ その結果、コンテナのマウントネームスペース内にはこれらのパスが存在し、あたかもコンテナが隔離されたホストであるかのように機能しますが、コンテナプロセスはそれらのパスに書き込むことはできません。
613+ マスクされるパスおよび読み取り専用のパスのリストは次のとおりです。
614+
615+ - マスクされるパス :
616+ - ` /proc/asound`
617+ - ` /proc/acpi`
618+ - ` /proc/kcore`
619+ - ` /proc/keys`
620+ - ` /proc/latency_stats`
621+ - ` /proc/timer_list`
622+ - ` /proc/timer_stats`
623+ - ` /proc/sched_debug`
624+ - ` /proc/scsi`
625+ - ` /sys/firmware`
626+ - ` /sys/devices/virtual/powercap`
627+
628+ - 読み取り専用のパス :
629+ - ` /proc/bus`
630+ - ` /proc/fs`
631+ - ` /proc/irq`
632+ - ` /proc/sys`
633+ - ` /proc/sysrq-trigger`
634+
635+ 一部のPodでは、デフォルトでパスがマスクされるのを回避したい場合があります。このようなケースで最も一般的なのは、Kubernetesコンテナ(Pod内のコンテナ)内でコンテナを実行しようとする場合です。
636+
637+ ` securityContext` の`procMount`フィールドを使用すると、コンテナの`/proc`を`Unmasked`にしたり、コンテナプロセスによって読み書き可能な状態でマウントすることができます。この設定は、`/proc`以外の`/sys/firmware`にも適用されます。
638+
639+ ` ` ` yaml
640+ ...
641+ securityContext:
642+ procMount: Unmasked
643+ ` ` `
644+
404645{{< note >}}
405- Kubernetes 1.25では、kubeletは再起動後にボリュームラベルを追跡できなくなります。言い換えると、kubeletはPodの中のラベルのコンフリクトが解消されるまで"conflicting
406- SELinux labels of volume"というようなエラーでPodの起動を拒否する可能性があるということです。Kubeletを再起動する前に必ずノードを[完全にdrain](https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/)された状態にしてください。
646+ ` procMount` をUnmaskedに設定するには、Podの`spec.hostUsers`の値が`false`である必要があります。
647+ つまり、Unmaskedな`/proc`やUnmaskedな`/sys`を使用したいコンテナは、[user namespace](/docs/concepts/workloads/pods/user-namespaces/)内で動作している必要があります。
648+ Kubernetes v1.12からv1.29までは、この要件は強制されません。
407649{{< /note >}}
408650
409651# # 議論
@@ -442,3 +684,5 @@ kubectl delete pod security-context-demo-4
442684* [PodSecurity Admission](/docs/concepts/security/pod-security-admission/)
443685* [AllowPrivilegeEscalation design document](https://git.k8s.io/design-proposals-archive/auth/no-new-privs.md)
444686* Linuxのセキュリティについてさらに知りたい場合は、[Overview of Linux Kernel Security Features](https://www.linux.com/learn/overview-linux-kernel-security-features)を確認してください(注: 一部の情報は古くなっています)。
687+ * Linux pods向けの[User Namespaces](/docs/concepts/workloads/pods/user-namespaces/)について確認してください。
688+ * [Masked Paths in the OCI Runtime Specification](https://github.com/opencontainers/runtime-spec/blob/f66aad47309/config-linux.md#masked-paths)
0 commit comments