@@ -52,7 +52,7 @@ Podに設定したセキュリティ設定はPod内の全てのコンテナに
52
52
53
53
設定ファイルの中の` runAsUser ` フィールドは、Pod内のコンテナに対して全てのプロセスをユーザーID 1000で実行するように指定します。
54
54
` 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にも含まれます。もしこのフィールドが指定されていない場合、空を意味します。
56
56
57
57
Podを作成してみましょう。
58
58
@@ -128,17 +128,176 @@ id
128
128
出力はこのようになります。
129
129
130
130
``` none
131
- uid=1000 gid=3000 groups=2000
131
+ uid=1000 gid=3000 groups=2000,3000,4000
132
132
```
133
133
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も含まれていることも確認できるでしょう。
135
135
136
136
shellから抜けましょう。
137
137
138
138
``` shell
139
139
exit
140
140
```
141
141
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
+
142
301
## Podのボリュームパーミッションと所有権変更ポリシーを設定する
143
302
144
303
{{< feature-state for_k8s_version="v1.23" state="stable" >}}
@@ -367,6 +526,41 @@ securityContext:
367
526
localhostProfile: my-profiles/profile-allow.json
368
527
` ` `
369
528
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
+
370
564
# # コンテナにSELinuxラベルをつける
371
565
372
566
コンテナにSELinuxラベルをつけるには、Pod・コンテナマニフェストの`securityContext`セクションに`seLinuxOptions`フィールドを追加してください。
@@ -386,24 +580,72 @@ SELinuxラベルを適用するには、ホストOSにSELinuxセキュリティ
386
580
387
581
# ## 効率的なSELinuxのボリューム再ラベル付け
388
582
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 >}}
390
590
391
591
デフォルトでは、コンテナランタイムは全てのPodのボリュームの全てのファイルに再帰的にSELinuxラベルを付与します。処理速度を上げるために、Kubernetesはマウントオプションで`-o context=`を使うことでボリュームのSELinuxラベルを即座に変更することができます。
392
592
393
593
この高速化の恩恵を受けるには、以下の全ての条件を満たす必要があります。
394
594
395
595
* Alphaフィーチャーゲートの`ReadWriteOncePod`と`SELinuxMountReadWriteOncePod`を有効にすること
396
- * Podが`accessModes: ["ReadWriteOncePod"]`でPersistentVolumeClaimを使うこと
596
+ * Podが適用可能な`accessModes`でPersistentVolumeClaimを使うこと
597
+ * ボリュームが`accessModes: ["ReadWriteOncePod"]`を持ち、フィーチャーゲート`SELinuxMountReadWriteOncePod`が有効であること
598
+ * または、ボリュームが他のアクセスモードを使用し、フィーチャーゲート`SELinuxMountReadWriteOncePod`と`SELinuxMount`の両方が有効であること
397
599
* 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`でマウントを行うとアナウンスしていること
400
603
401
604
それ以外のボリュームタイプでは、コンテナランタイムはボリュームに含まれる全てのinode(ファイルやディレクトリ)に対してSELinuxラベルを再帰的に変更します。
402
605
ボリューム内のファイルやディレクトリが増えるほど、ラベリングにかかる時間は増加します。
403
606
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
+
404
645
{{< 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までは、この要件は強制されません。
407
649
{{< /note >}}
408
650
409
651
# # 議論
@@ -442,3 +684,5 @@ kubectl delete pod security-context-demo-4
442
684
* [PodSecurity Admission](/docs/concepts/security/pod-security-admission/)
443
685
* [AllowPrivilegeEscalation design document](https://git.k8s.io/design-proposals-archive/auth/no-new-privs.md)
444
686
* 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