前回の記事では seccomp (Secure computing mode) に入門するために「Docker と seccomp」を組み合わせて試した.docker run
コマンドの --security-opt
オプションを使って seccomp プロファイルを指定した.
今回は「Kubernetes と seccomp」を組み合わせて試す.設定や手順などは以下のドキュメントに詳しく載っている.
検証環境
まず,kind を使って検証環境を構築する.以下の kind-config.yaml
のように,ワーカーノードに seccomp プロファイルを置いたホスト側のディレクトリをマウントする(kubelet に読み込ませる).ドキュメントには ./profiles
と書いてあるけど,今回は Docker for Mac を使っていて,マウントできるディレクトリに制限(設定次第)があるため,今回は Mac 側の /tmp/seccomp-profiles
に置いた.
apiVersion: kind.x-k8s.io/v1alpha4 kind: Cluster nodes: - role: control-plane - role: worker extraMounts: - hostPath: /tmp/seccomp-profiles containerPath: /var/lib/kubelet/seccomp/profiles
さっそく kind で Kubernetes クラスターを構築する.準備 OK 💡
$ kind create cluster --config=kind-config.yaml Creating cluster "kind" ... ✓ Ensuring node image (kindest/node:v1.21.1) 🖼 ✓ Preparing nodes 📦 📦 ✓ Writing configuration 📜 ✓ Starting control-plane 🕹️ ✓ Installing CNI 🔌 ✓ Installing StorageClass 💾 ✓ Joining worker nodes 🚜 $ kubectl get nodes NAME STATUS ROLES AGE VERSION kind-control-plane Ready control-plane,master 2m20s v1.21.1 kind-worker Ready <none> 113s v1.21.1
なお,seccomp は kubelet に設定する.以下のドキュメントを見ると,--seccomp-profile-root
オプションに関する記載がある.Kubernetes 1.23 から /seccomp
ディレクトリに変更すると書いてあり,覚えておこう!
検証 : mkdir
システムコールを制限する
前回の記事と同じく Ubuntu で mkdir
システムコールを制限して,mkdir
コマンドの挙動を確認する.まず,何も指定せず,デフォルト設定のまま Pod で Ubuntu を起動する.
apiVersion: v1 kind: Pod metadata: name: ubuntu spec: containers: - name: ubuntu image: ubuntu:21.10 command: - sleep - infinity
kubectl exec
コマンドで Pod に接続をして,問題なく mkdir
コマンドを実行できる.
$ kubectl apply -f ubuntu.yaml pod/ubuntu created $ kubectl exec -it ubuntu -- /bin/sh # mkdir sample-dir
次に seccomp プロファイルを指定した Pod で Ubuntu を起動する.前回の記事と同じく Docker (Moby) のデフォルトプロファイルから mkdir
システムコールのエントリーを削除した deny-mkdir.json
を作る.
$ diff -u default.json deny-mkdir.json @@ -200,7 +200,6 @@ "membarrier", "memfd_create", "mincore", - "mkdir", "mkdirat", "mknod", "mknodat",
そして以下のように spec.securityContext.seccompProfile
に seccomp プロファイルを指定する.プロファイルはワーカーノードにマウントしているため,参照できるようになっている.なお,ドキュメントにも書いてあるけど,Kubernetes v1.19 より前はアノテーションとして annotations.seccomp.security.alpha.kubernetes.io/pod
に seccomp プロファイルを指定していた.今後は spec.securityContext.seccompProfile
を使う.
apiVersion: v1 kind: Pod metadata: name: ubuntu-deny-mkdir spec: securityContext: seccompProfile: type: Localhost localhostProfile: profiles/deny-mkdir.json containers: - name: ubuntu image: ubuntu:21.10 command: - sleep - infinity
同じく kubectl exec
コマンドで Pod に接続をすると,今度は mkdir
コマンドを実行できなくなった.実際に Operation not permitted
とエラーになった.
$ kubectl apply -f ubuntu-deny-mkdir.yaml pod/ubuntu-deny-mkdir created $ kubectl exec -it ubuntu-deny-mkdir -- /bin/sh # mkdir sample-dir mkdir: cannot create directory 'sample-dir': Operation not permitted
RuntimeDefault
プロファイル
さっきは spec.securityContext.seccompProfile.type
に Localhost
を指定したけど,他にも spec.securityContext.seccompProfile.type
に RuntimeDefault
を指定することができる.これはコンテナランタイム側のデフォルトプロファイルを設定することになる.Docker for Mac なら containerd あたり?
apiVersion: v1 kind: Pod metadata: name: ubuntu-runtime-default spec: securityContext: seccompProfile: type: RuntimeDefault containers: - name: ubuntu image: ubuntu:21.10 command: - sleep - infinity
実際に動作確認をすると問題なく mkdir
コマンドを実行することができた.最低限 RuntimeDefault
を設定しておくと良さそう.
$ kubectl apply -f ubuntu-runtime-default.yaml pod/ubuntu-runtime-default created $ kubectl exec -it ubuntu-runtime-default -- /bin/sh # mkdir sample-dir
seccomp アクション SCMP_ACT_LOG
ドキュメントを読んでいたら,システムコールを洗い出すための seccomp アクションとして SCMP_ACT_LOG
の例が紹介されていた.実際にシステムコールを制限することはせず,syslog
にログとして書き出せる.調査目的なら使えそう.
{ "defaultAction": "SCMP_ACT_LOG" }
お掃除
検証が終わったら Kubernetes クラスターを削除しておく.
$ kind delete cluster
まとめ
コンテナワークロードのセキュリティ対策として,前回の「Docker と seccomp」の組み合わせに続き「Kubernetes と seccomp」の組み合わせを試した.Pod の spec.securityContext
には他にも多くの設定項目があるため,一歩一歩学んでいくぞ!