非 root ユーザーで Pod (コンテナ) を実行したときのケーパビリティー

この記事の続きで、非 root ユーザーの場合のケーパビリティーを EKS で確認したメモ。

準備

ノードのバージョンを確認する。

$ k get node -o wide
NAME                                                 STATUS   ROLES    AGE   VERSION               INTERNAL-IP       EXTERNAL-IP   OS-IMAGE         KERNEL-VERSION                CONTAINER-RUNTIME
ip-192-168-175-232.ap-northeast-1.compute.internal   Ready    <none>   43d   v1.21.5-eks-bc4871b   192.168.175.232   <none>        Amazon Linux 2   5.4.162-86.275.amzn2.x86_64   docker://20.10.7
ip-192-168-200-81.ap-northeast-1.compute.internal    Ready    <none>   43d   v1.21.5-eks-bc4871b   192.168.200.81    <none>        Amazon Linux 2   5.4.162-86.275.amzn2.x86_64   docker://20.10.7

ランタイムは Containerd ではなく Docker。

イメージを作る。

cat << EOF > Dockerfile
FROM ubuntu
RUN apt-get update && apt-get install -y \
    libcap-ng-utils
EOF
docker build -t pscap-ubuntu .

イメージを Docker Hub にプッシュする。

docker tag pscap-ubuntu sotosugi/pscap-ubuntu
docker push sotosugi/pscap-ubuntu

root ユーザー

EKS で実行する。

cat << EOF > pod1.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: pod1
  name: pod1
spec:
  containers:
  - args:
    - sleep
    - "3600"
    image: sotosugi/pscap-ubuntu
    name: pod1
EOF
k apply -f pod1.yaml

Pod の中から確認する。

$ k get po
NAME   READY   STATUS    RESTARTS   AGE
pod1   1/1     Running   0          3s
sotosugi@a483e7dfd6ad:~/workspace/2020/hisys/20220127_Capabliity
$ k exec -it pod1 -- /bin/bash
root@pod1:/# pscap -a
ppid  pid   name        command           capabilities
0     1     root        sleep             chown, dac_override, fowner, fsetid, kill, setgid, setuid, setpcap, net_bind_service, net_raw, sys_chroot, mknod, audit_write, setfcap
0     7     root        bash              chown, dac_override, fowner, fsetid, kill, setgid, setuid, setpcap, net_bind_service, net_raw, sys_chroot, mknod, audit_write, setfcap
root@pod1:/#

root ユーザー + --privileged

cat << EOF > pod2.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: pod2
  name: pod2
spec:
  containers:
  - args:
    - sleep
    - "3600"
    image: sotosugi/pscap-ubuntu
    name: pod2
    securityContext:
      privileged: true
EOF
k apply -f pod2.yaml

Pod の中から確認する。

$ k get po
NAME   READY   STATUS    RESTARTS   AGE
pod2   1/1     Running   0          7s
$ k exec -it pod2 -- /bin/bash
root@pod2:/# pscap -a
ppid  pid   name        command           capabilities
0     1     root        sleep             full
0     7     root        bash              full
root@pod2:/#

非 root ユーザー

cat << EOF > pod3.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: pod3
  name: pod3
spec:
  containers:
  - args:
    - sleep
    - "3600"
    image: sotosugi/pscap-ubuntu
    name: pod3
    securityContext:
      runAsUser: 65534
EOF
k apply -f pod3.yaml

Pod の中から確認する。

$ k get po
NAME   READY   STATUS    RESTARTS   AGE
pod3   1/1     Running   0          5s
$ k exec -it pod3 -- /bin/bash
nobody@pod3:/$ pscap -a
nobody@pod3:/$ ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
nobody       1     0  0 08:12 ?        00:00:00 sleep 3600
nobody       8     0  0 08:12 pts/0    00:00:00 /bin/bash
nobody      18     8  0 08:12 pts/0    00:00:00 ps -ef
nobody@pod3:/$

非 root ユーザー + --privileged

cat << EOF > pod4.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: pod4
  name: pod4
spec:
  containers:
  - args:
    - sleep
    - "3600"
    image: sotosugi/pscap-ubuntu
    name: pod4
    securityContext:
      privileged: true
      runAsUser: 65534
EOF
k apply -f pod4.yaml

Pod の中から確認する。

$ k get po
NAME   READY   STATUS    RESTARTS   AGE
pod4   1/1     Running   0          11s
$ k exec -it pod4 -- /bin/bash
nobody@pod4:/$ pscap -a
nobody@pod4:/$ ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
nobody       1     0  0 08:16 ?        00:00:00 sleep 3600
nobody       7     0  0 08:16 pts/0    00:00:00 /bin/bash
nobody      16     7  0 08:16 pts/0    00:00:00 ps -ef
nobody@pod4:/$

まとめ

docker run の場合と同じで、非 root ユーザーで実行している場合はそもそもケーパビリティーがなかった。なのでわざわざ Drop を書く必要はない。

補足

もしかして、pscap を実行するのにそもそも権限がいるのではないか?

念のためホストノード上から確認してみる。

一度 Pod を消して片方のノードを Cordon する。

$ k delete po --all
pod "pod1" deleted
pod "pod2" deleted
pod "pod3" deleted
pod "pod4" deleted
$ k get node
NAME                                                 STATUS   ROLES    AGE   VERSION
ip-192-168-175-232.ap-northeast-1.compute.internal   Ready    <none>   43d   v1.21.5-eks-bc4871b
ip-192-168-200-81.ap-northeast-1.compute.internal    Ready    <none>   43d   v1.21.5-eks-bc4871b
$ k cordon ip-192-168-175-232.ap-northeast-1.compute.internal
node/ip-192-168-175-232.ap-northeast-1.compute.internal cordoned
$ k get node
NAME                                                 STATUS                     ROLES    AGE   VERSION
ip-192-168-175-232.ap-northeast-1.compute.internal   Ready,SchedulingDisabled   <none>   43d   v1.21.5-eks-bc4871b
ip-192-168-200-81.ap-northeast-1.compute.internal    Ready                      <none>   43d   v1.21.5-eks-bc4871b

再び Pod を作成する。

$ k apply -f .
pod/pod1 created
pod/pod2 created
pod/pod3 created
pod/pod4 created
$ k get po -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP                NODE                                                NOMINATED NODE   READINESS GATES
pod1   1/1     Running   0          14s   192.168.255.108   ip-192-168-200-81.ap-northeast-1.compute.internal   <none>           <none>
pod2   1/1     Running   0          14s   192.168.211.63    ip-192-168-200-81.ap-northeast-1.compute.internal   <none>           <none>
pod3   1/1     Running   0          14s   192.168.196.0     ip-192-168-200-81.ap-northeast-1.compute.internal   <none>           <none>
pod4   1/1     Running   0          14s   192.168.242.153   ip-192-168-200-81.ap-northeast-1.compute.internal   <none>           <none>

SSM でノードに入り、ノードに pscap をインストールする。

yum -y install libcap-ng-utils

Docker コンテナとプロセスを確認する。

[root@ip-192-168-200-81 ~]# docker ps | grep sleep
a011874308c3   sotosugi/pscap-ubuntu                                                        "sleep 3600"             6 minutes ago   Up 6 minutes             k8s_pod3_pod3_default_522f8e93-5071-4f9d-8208-b41737fe05cc_0
a98b9cf6e0db   sotosugi/pscap-ubuntu                                                        "sleep 3600"             6 minutes ago   Up 6 minutes             k8s_pod4_pod4_default_e9c04a65-70f1-461d-b88e-b94a76c513a7_0
a529af7e125a   sotosugi/pscap-ubuntu                                                        "sleep 3600"             6 minutes ago   Up 6 minutes             k8s_pod1_pod1_default_b3c7857b-5d7f-4363-b860-e7732e18e538_0
0501ad27ec3f   sotosugi/pscap-ubuntu                                                        "sleep 3600"             6 minutes ago   Up 6 minutes             k8s_pod2_pod2_default_aee19f59-6020-4d7f-b494-dfffdb30e727_0
[root@ip-192-168-200-81 ~]# ps -ef | grep sleep
root     24277 24256  0 08:23 ?        00:00:00 sleep 3600
root     24351 24329  0 08:23 ?        00:00:00 sleep 3600
nfsnobo+ 24425 24405  0 08:23 ?        00:00:00 sleep 3600
nfsnobo+ 24497 24476  0 08:23 ?        00:00:00 sleep 3600
root     32404 26138  0 08:30 pts/0    00:00:00 grep --color=auto sleep
[root@ip-192-168-200-81 ~]#

このままでは対応がわからないので、inspect で調べる。

[root@ip-192-168-200-81 ~]# docker inspect a529af7e125a | grep Pid # これは pod1 なので root ユーザー
            "Pid": 24351,
            "PidMode": "",
            "PidsLimit": null,
[root@ip-192-168-200-81 ~]# docker inspect 0501ad27ec3f | grep Pid # これは pod2 なので root ユーザー + 特権
            "Pid": 24277,
            "PidMode": "",
            "PidsLimit": null,
[root@ip-192-168-200-81 ~]# docker inspect a011874308c3 | grep Pid # これは pod3 なので非 root ユーザー
            "Pid": 24497,
            "PidMode": "",
            "PidsLimit": null,
[root@ip-192-168-200-81 ~]# docker inspect a98b9cf6e0db | grep Pid # これは pod4 なので非 root ユーザー + 特権
            "Pid": 24425,
            "PidMode": "",
            "PidsLimit": null,
[root@ip-192-168-200-81 ~]#

ケーパビリティーを確認する。

[root@ip-192-168-200-81 ~]# pscap -a | grep -e 24351 -e 24277 -e 24497 -e 24425
24256 24277 root        sleep             full
24329 24351 root        sleep             chown, dac_override, fowner, fsetid, kill, setgid, setuid, setpcap, net_bind_service, net_raw, sys_chroot, mknod, audit_write, setfcap
[root@ip-192-168-200-81 ~]#

やはり非 root ユーザーで実行したときはケーパビリティーはなかった。