LoginSignup
5
0

More than 1 year has passed since last update.

seccompとInspektor Gadgetで目指すセキュアなKubernetes

Last updated at Posted at 2022-12-13

ZOZOでSREをしている @calorie です。よろしくお願いします。

この記事について

seccompとInspektor Gadgetを使いPodのシェルへのアクセスを制限する様子を紹介します。

seccomp

seccompはシステムコールを制限するためのカーネルの機能です。以下のスライドが詳しいです。

Kubernetesではノードにseccomp profileをロードし、Podから参照することで使えます。

seccomp profileを書いてシステムコールを制限できればセキュアなPodが手に入りますが、
人の手でシステムコールを取捨選択するのは大抵の場合難しいはずです。

なので、seccomp profileを自動生成したいです。
有名なものであればdocker-slimが挙げられますが、ドキュメントを見る限りはイメージからseccomp profileを生成しているので、実際にリクエストを流しシステムコールをトレースした上で生成できるInspektor Gadgetを紹介します。

Inspektor Gadget

Inspektor GadgetはeBPFをベースとしたKubernetesのリソースをデバッグするためのツール群です。
kubectlを拡張するpluginとして提供されるため手軽に扱うことができます。

以下のような機能が含まれます。

  • network policyやseccomp profileを生成する kubectl gadget advise
  • kubectl topではモニタリングできないカーネルレベルのBPFプログラムのリソース使用状況を表示する kubectl gadget top ebpf
  • tcpdumpなしでTCPをトレースする kubectl gadget trace tcp

など他にも多くの機能があります。
最近のKubeConのサイドイベントでは kubectl gadget trace tcp を使ってデバッグする様子が発表されました。

今回は kubectl gadget advise を使いseccomp profileを生成しPodのシェルへのアクセスを制限する様子を紹介します。

seccompとInspektor Gadgetによるシステムコールの制限

以下のドキュメントに沿って実際にローカルで挙動を確認します。

前準備

kubectl gadget advise がArm64のMacで動かないためx86_64のMacにMinikubeを立てて実行します。今後に期待。

$ minikube start --driver=hyperkit -p=play-ground

Inspektor Gadgetをインストール、デプロイします。

$ kubectl krew install gadget
$ kubectl gadget deploy

$ kubectl get pods -n gadget
NAME           READY   STATUS    RESTARTS   AGE
gadget-h65xz   1/1     Running   0          22h

traceloopなどを実行するPodが立ち上がったことが確認できます。
Inspektor Gadgetの詳しいアーキテクチャについてはドキュメントから参照できます。

次にKubernetes Security Profiles Operatorをインストールします。

デモで使うpythonアプリなどをapplyします。YAMLはリポジトリのものを参照してください。

$ kubectl apply -f docs/examples/seccomp/basic.yaml

トレース

kubectl gadget advise seccomp-profile start でトレースを開始します。

$ kubectl gadget advise seccomp-profile start -m seccomp-profile -n seccomp-demo -p hello-python
TAyR9BXes6GU04rG

pythonアプリのPodを立ててリクエストを流します。

$ kubectl apply -f docs/examples/seccomp/unconfined.yaml
$ kubectl port-forward service/hello-python-service -n seccomp-demo 8080:6000 &
$ curl localhost:8080
$ kill %1

seccomp profileの生成

トレースを止めるとseccomp profileがノードの /var/lib/kubelet/seccomp/operator/{namespace}/{pod_name}.json に生成されます。今回の例では /var/lib/kubelet/seccomp/operator/gadget/hello-python.json です。

$ kubectl gadget advise seccomp-profile stop TAyR9BXes6GU04rG
$ kubectl get seccompprofile -n gadget
NAME            STATUS      AGE
hello-python                9s

しかし、minikubeではうまく生成できずissueもあるため、今回は直接ノードにsshし生成されたseccomp profileを書き込みました。

$ minikube ssh -p play-ground
$ sudo vi /var/lib/kubelet/seccomp/hello-python.json
hello-python.json
{
  "defaultAction": "SCMP_ACT_ERRNO",
  "architectures": [
    "SCMP_ARCH_X86_64",
    "SCMP_ARCH_X86",
    "SCMP_ARCH_X32"
  ],
  "syscalls": [
    {
      "names": [
        "accept4",
        "access",
        "arch_prctl",
        "bind",
        "brk",
        "capget",
        "capset",
        "chdir",
        "chmod",
        "chown",
        "clock_gettime",
        "clone",
        "close",
        "connect",
        "dup",
        "dup2",
        "epoll_create",
        "epoll_create1",
        "epoll_ctl",
        "epoll_pwait",
        "epoll_wait",
        "eventfd2",
        "execve",
        "exit_group",
        "fcntl",
        "fstat",
        "fstatfs",
        "futex",
        "getcwd",
        "getdents64",
        "getegid",
        "geteuid",
        "getgid",
        "getpid",
        "getppid",
        "getrandom",
        "getsockname",
        "getsockopt",
        "gettid",
        "gettimeofday",
        "getuid",
        "io_setup",
        "ioctl",
        "link",
        "listen",
        "lseek",
        "lstat",
        "mkdir",
        "mmap",
        "mprotect",
        "munmap",
        "nanosleep",
        "newfstatat",
        "openat",
        "pipe2",
        "poll",
        "prctl",
        "pread64",
        "prlimit64",
        "pwrite64",
        "read",
        "readlink",
        "readv",
        "recvfrom",
        "rename",
        "rt_sigaction",
        "rt_sigprocmask",
        "rt_sigreturn",
        "rt_sigsuspend",
        "set_robust_list",
        "set_tid_address",
        "setgid",
        "setgroups",
        "setpgid",
        "setsockopt",
        "setuid",
        "socket",
        "socketpair",
        "stat",
        "sysinfo",
        "tgkill",
        "uname",
        "unlink",
        "vfork",
        "wait4",
        "write",
        "writev"
      ],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
}

docs/examples/seccomp/confined.yamllocalhostProfilehello-python.json に変更しapplyした後bashでログインしようとすると、seccompによって弾かれることが確認できます。

$ kubectl apply -f docs/examples/seccomp/confined.yaml
$ kubectl exec -it -n seccomp-demo hello-python -- /bin/bash
bash: initialize_job_control: getpgrp failed: Success
command terminated with exit code 1

上記の hello-python.json において SCMP_ACT_ERRNOSCMP_ACT_LOG にするとシステムコールは実行しつつログに吐き出すようにもできます。

おわりに

seccompとInspektor GadgetでPodから実行されるシステムコールを制限する様子を紹介しました。
次はBPFの理解を深めるため880ページあるこちらの本を読みたいと思います。

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0