kubernetesのSecurity Contextについて少し・・・。

kubernetes

説明

kubernetes(k8s)のマニフェストにSecurity Contextを設定することで、コンテナに対しての権限設定をすることができます。

主に以下のものが設定できます。

・ファイルやオブジェクトのアクセス制御、ユーザID(UID)・グループ(GID)の設定
・SELinux設定
・特権モードor非特権モードの設定
・Capability(Linux Capabilities)の設定
・AppArmor:プロファイルを適用して、個々のプログラムの機能を制限
・Seccomp:プロセスのシステムコールをフィルタリング
・AllowPrivilegeEscalation:プロセスがその親プロセスよりも多くの特権を取得可能かどうかの制御
・readOnlyRootFilesystem:コンテナのルートファイルシステムを読み取り専用としてマウント

など様々な設定ができます。

今回はお試しで一部の機能について紹介します。
雰囲気だけでも掴んでいただけたらよさげです。

環境

・VirutalBox
・vagrant
・ubuntu仮想サーバ(k8sのホスト)
・minikube

以下のDockerfileを用意します。

$ vi Dockerfile
FROM  centos:centos7
RUN  yum update -y && \
     yum install -y epel-release  && \
     yum install -y libcap-ng-utils

イメージの作成

docker build --tag codemogu/centos:0.1 .

ファイルやオブジェクトのアクセス制御

Dockerでコンテナを作成すると、デフォルトの場合ユーザやグループの権限である、uidやgidはroot(0)となります。
こちらを変更する際は、k8sのマニフェストに「runAsUser」「runAsGroup」に記載する必要があります。今回は、2つのコンテナを作成してコンテナ同士のボリュームの共有を確認のためにしたいので、「fsGroup」の設定もします。

確認のためにDockerでコンテナを作ると権限は以下のようになります。

$ docker run -itd --name test_container codemogu/centos:0.1 /bin/sh
$ docker exec -it test_container /bin/bash

[root@hogehoge /]# id
uid=0(root) gid=0(root) groups=0(root)

①. Pod Security Contextを設定して、Pod全てに権限を付与し、ファイルを共有する

SecurityContextをcontainersと同じインデントの位置で設定することで、すべてのコンテナに同じ設定が追加されます。

マニフェストの作成

$vi security.yml
apiVersion: v1
kind: Pod
metadata:
  name: security
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  restartPolicy: OnFailure
  containers:
  - name: container1
    image: codemogu/centos:0.1
    command: ["/bin/sh"]
    args: ["-c", "while :; do sleep 10; done"]
    volumeMounts:
    - name: data-vol
      mountPath: /var/tmp/container1
  - name: container2
    image: codemogu/centos:0.1
    command: ["/bin/sh"]
    args: ["-c", "while :; do sleep 10; done"]
    volumeMounts:
    - name: data-vol
      mountPath: /var/tmp/container2
  volumes:
    - name: data-vol
      emptyDir:
  terminationGracePeriodSeconds: 0

実行&確認

$ kubectl apply -f security.yml
pod/security created

$ kubectl get po
NAME       READY   STATUS    RESTARTS   AGE
security   2/2     Running   0          3m18s

container1に入って、idの確認とテストファイルを作成します。

$ kubectl exec -it security -c container1 /bin/bash

bash-4.2$ id
uid=1000 gid=3000 groups=3000,2000

bash-4.2$ echo fafafa >> /var/tmp/container1/text.txt
bash-4.2$ cat /var/tmp/container1/text.txt
fafafa

container2に入ってidの確認とテストファイルが共有できているか確認します。

$ kubectl exec -it security -c container2 /bin/bash

bash-4.2$ id
uid=1000 gid=3000 groups=3000,2000

bash-4.2$ cat /var/tmp/container2/text.txt 
fafafa

確認できました。

②. コンテナ毎にSecurity Contextを設定して、ファイル共有できるか確認をする

SecurityContextをcontainersよりもインデントを下位に設定することで、コンテナ毎に設定ができます。

上記のマニフェスト書き方は違いますが、意味は同じです。

$vi security2.yml
apiVersion: v1
kind: Pod
metadata:
  name: security
spec:
  restartPolicy: OnFailure
  securityContext:
    fsGroup: 2000
  containers:
  - name: container1
    image: codemogu/centos:0.1
    command: ["/bin/sh"]
    args: ["-c", "while :; do sleep 10; done"]
    volumeMounts:
    - name: data-vol
      mountPath: /var/tmp/container1
    securityContext:
      runAsUser: 1000
      runAsGroup: 3000
  - name: container2
    image: codemogu/centos:0.1
    command: ["/bin/sh"]
    args: ["-c", "while :; do sleep 10; done"]
    volumeMounts:
    - name: data-vol
      mountPath: /var/tmp/container2
    securityContext:
      runAsUser: 1000
      runAsGroup: 3000
  volumes:
    - name: data-vol
      emptyDir:
  terminationGracePeriodSeconds: 0

実行と確認方法は①を参考にやってください。

※fsGroupは「Pod Security Context」扱いなので、containers内のsecurityContextに記載して実行することはできません。

以上です。

Capability(ケーパビリティ)の設定

Capability設定ををして、コンテナに時間設定をできるようにする

LinuxにはCapabilityという設定がいくつか存在し、rootが持っている絶対的な権限を細かく分けて、必要な権限だけを与えることができるそうです。( ゚д゚)
pscapコマンドで一覧が確認できます。
コンテナの場合はDockerコマンドのオプションやkubernetesのマニフェストに記載することで、このCapability設定をすることができます。


たとえば、通常デフォルトのコンテナでは、時間の設定をする権限がなく、時間変更ができません。

$ docker run -itd --name test_container codemogu/centos:0.1 /bin/sh
$ docker exec -it test_container /bin/bash

[root@hogehoge /]# pscap
ppid  pid   name        command           capabilities
0     6     root        bash              chown, dac_override, fowner, fsetid, kill, setgid, setuid, setpcap, net_bind_service, net_raw, sys_chroot, mknod, audit_write, setfcap

[root@hogehoge /]# date -s "04/01 13:00 2020"
date: cannot set date: Operation not permitted

上記のように、rootユーザにも関わらず、日付の変更ができません。

kubernetesのマニフェストを用いて、Capability設定をコンテナに付加して、時間の変更できるようにします。

$vi security3.yml
apiVersion: v1
kind: Pod
metadata:
  name: security
spec:
  restartPolicy: OnFailure
  containers:
  - name: container1
    image: codemogu/centos:0.1
    securityContext:
      capabilities:
        add: ["SYS_TIME"]
    command: ["/bin/sh"]
    args: ["-c", "while :; do sleep 10; done"]
  terminationGracePeriodSeconds: 0

実行

$ kubectl apply -f security3.yml
pod/security created

コンテナに入って時間の変更

$ kubectl exec -it security -c container1 /bin/bash

[root@security /]# date -s "04/01 13:00 2020"
Wed Apr  1 13:00:00 UTC 2020
・
・
しばらくすると・・。
[root@security /]# date
Mon Jan  4 07:37:59 UTC 2021
もとに戻った( ゚Д゚)

コンテナの時間の変更はできるようになりました!しかしなぜ戻ってしまったかは不明です。
なにかしらのkubernetesの便利機能なのかなー。( ゚Д゚)
まあ今回はこれくらいでいいやー。

その他

SecurityContextには上記以外にもいろいろあるので、試してみてください。

・特権・非特権コンテナ

・
spec:
  privileged: true
・

・親よりも強いプロセスにするかどうか

・
containers:
- name: fafafa
  image: fafafa
  securityContext:
    allowPrivilegeEscalation: false
・

・ルートファイルシステムへの書き込みするかどうか

readOnlyRootFilesystem:false

・SELinuxの設定

・
・
securityContext:
  seLinuxOptions:
    level: "s0:c123,c456"
・
・

などなど調べたらいっぱい出てきます。

以上です。

コメント

タイトルとURLをコピーしました