はじめに
KubernetesでPodとコンテナに設定できるSecurity Contextについて簡単に紹介して、実際に動かしてみます。
Security Contextとは
Security Contextは、Podもしくはコンテナに権限やアクセス制御を設定できます。
いくつか例を挙げると、Security Contextでは、下記のような設定ができます。
- 非rootユーザーでのコンテナ実行
- ルートファイルシステムの読み取り専用
- 権限昇格の有無
- Capabilityの設定
設定によって、Podでまとめて設定できるもの、コンテナごとに設定できるものがあります。
非rootユーザーとして実行
下記の設定で非rootユーザーとして、プロセスを実行したり、ファイルの所有者を指定したりします。
runAsUser
: コンテナのプロセスのUIDを指定runAsGroup
: コンテナのプロセスのGIDを指定fsGroup
: マウントされたボリュームのファイルシステムのGIDを指定
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
containers:
- image: busybox
name: pod-with-sc
rootユーザーでの実行をブロック
runAsNonRoot
で、rootユーザーとしてプロセスが実行されるのを拒否します。
spec:
securityContext:
runAsNonRoot: true
containers:
- image: busybox
name: pod-with-sc
ルートファイルシステムを読み取り専用に
readOnlyRootFilesystem
で、ルートファイルシステムを読み取り専用にします。
containers:
- image: busybox
name: pod-with-sc
securityContext:
readOnlyRootFilesystem: true
権限昇格
allowPrivilegeEscalation
で、権限昇格を無効化します。
containers:
- image: busybox
name: pod-with-sc
securityContext:
allowPrivilegeEscalation: false
Capability
capabilities
で、Capabilityの設定ができます。
Capabilityとは、Linuxでのプログラムが実行できる権限を細かく分けたものです。
この設定で、不要なCapabilityの削除と、必要なCapabilityの追加ができます。
containers:
- image: busybox
name: pod-with-sc
securityContext:
capabilities:
drop: ["all"]
add: ["NET_BIND_SERVICE"]
試してみる
紹介した設定について、Security ContextなしのPodとありのPodを比較しながら試してみます。
Security ContextなしでPod実行
まずは、Security ContextなしのPodを実行します。
apiVersion: v1
kind: Pod
metadata:
name: pod-non-sc
spec:
containers:
- image: busybox
name: pod-non-sc
command: [ "sh", "-c", "sleep 3600" ]
volumeMounts:
- name: sc-vol
mountPath: /tmp/demo
volumes:
- name: sc-vol
emptyDir: {}
Podを作成します。
kubectl apply -f pod-non-sc.yml
Security ContextありでPod実行
次に、Security ContextありのPodを実行します。
Capabilityに関しては、とりあえずNET_BIND_SERVICE
だけ付与しています。
apiVersion: v1
kind: Pod
metadata:
name: pod-with-sc
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
runAsNonRoot: true
containers:
- image: busybox
name: pod-with-sc
command: [ "sh", "-c", "sleep 3600" ]
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: ["all"]
add: ["NET_BIND_SERVICE"]
volumeMounts:
- name: sc-vol
mountPath: /tmp/demo
volumes:
- name: sc-vol
emptyDir: {}
Podを作成します。
kubectl apply -f pod-with-sc.yml
動作確認
動作を比較していきます。
まずは、それぞれのPodのシェルに接続しておきます。
kubectl exec -it pod-non-sc -- sh
kubectl exec -it pod-with-sc -- sh
プロセスのユーザー
プロセスを確認します。
Security Contextを設定するとプロセスの実行ユーザーとグループが設定されたユーザーになっていることが確認できます。
# --- Security Contextなし ---
/ # ps -o pid,user,group,args
PID USER GROUP COMMAND
1 root root sleep 3600
7 root root sh
17 root root ps -o pid,user,group,args
# --- Security Contextあり ---
/ $ ps -o pid,user,group,args
PID USER GROUP COMMAND
1 1000 3000 sleep 3600
8 1000 3000 sh
19 1000 3000 ps -o pid,user,group,args
ボリュームの所有者
マウントしたボリュームのパスとそこで作成されたファイルの所有者を確認します。
ユーザーがrunAsUser
、グループがfsGroup
のIDになっていることが確認できます。
# --- Security Contextなし ---
/ $ cd tmp
/tmp # ls -l
total 4
drwxrwxrwx 2 root root 4096 Jun 19 05:29 demo
/tmp # cd demo
/tmp/demo # echo hello > testfile
/tmp/demo # ls -l
total 4
-rw-r--r-- 1 root root 6 Jun 19 05:36 testfile
# --- Security Contextあり ---
/ $ cd tmp
/tmp $ ls -l
total 4
drwxrwsrwx 2 root 2000 4096 Jun 19 05:29 demo
/tmp $ cd demo
/tmp/demo $ echo hello > testfile
/tmp/demo $ ls -l
total 4
-rw-r--r-- 1 1000 2000 6 Jun 19 05:37 testfile
ルートファイルシステムの書き込み
ルートファイルシステムの書き込みについても確認します。
設定していると、Read-onlyというエラーになり、書き込みができなくなっています。
# --- Security Contextなし ---
/ # echo hello > testfile
/ # ls
bin dev etc home proc root sys testfile tmp usr var
# --- Security Contextあり ---
/ $ echo hello > testfile
sh: can't create testfile: Read-only file system
権限昇格
権限昇格が可能か確認します。
su
コマンドで試してみると、昇格できないようになっていることが確認できます。
# --- Security Contextなし ---
/ # su -c ls
bin dev etc home proc root sys testfile tmp usr var
# --- Security Contextあり ---
/ $ su -c ls
su: must be suid to work properly
Capability
最後にCapabilityについて確認します。
試しにPIDが1のプロセスを確認すると、NET_BIND_SERVICE
のビットだけ立っていることが確認できます。
# --- Security Contextなし ---
/ $ cat /proc/1/status
...
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
CapBnd: 00000000a80425fb
...
# --- Security Contextあり ---
/ $ cat /proc/1/status
...
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000000000000400
...
Capabilityのビットについては、capability.hから確認してください。