什么是Seccomp?

Seccomp(全称:secure computing mode)在2.6.12版本(2005年3月8日)中引入linux内核,是一种限制系统调用的安全机制。在严格模式下,将进程可用的系统调用限制为四种:readwriteexitsigreturn,其他的系统调用都会杀死进程。过滤模式下,可以指定允许那些系统调用,Seccomp进行过滤的方式是基于使用SECCOMP_MODE_FILTER模式的BPF过滤器,并且系统调用过滤的方式与对数据包的过滤方式相同。例如,您可能希望为进程提供CAP_NET_ADMIN功能,但通过阻塞accept和accept4系统调用的方式不允许它接受套接字上的连接。

从linux/seccomp.h 的内核源代码中看,seccomp_data结构的样子如下:

    struct seccomp_data { 
            int nr;
            __u32 arch;
            __u64 instruction_pointer;
            __u64 args[6];
    };

通过该结构可以看出,我们可以基于syscall,基于其参数或基于它们的组合进行过滤。

kubernetes中的seccomp

Seccomp在Kubernetes 1.3版本中作为Alpha功能引入,使用PodSecurityPolicy上的注释将Seccomp配置文件应用于所需的Pod。

例如我们要将一个seccomp profile 设置到某个pod范围:

annotations:
  seccomp.security.alpha.kubernetes.io/pod: "localhost/profile.json"

或者我们设置到容器范围:

annotations:
  container.security.alpha.kubernetes.io/<container-name>: "localhost/profile.json"

在1.19版中,Seccomp 功能 GA,将新的seccompProfile字段添加到pod和容器的securityContext对象中。

apiVersion: v1
kind: Pod
metadata:
  name: audit-pod
  labels:
    app: audit-pod
spec:
  securityContext:
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: test-container
    image: hashicorp/http-echo:0.2.3
    args:
    - "-text=just made some syscalls!"
    securityContext:
      allowPrivilegeEscalation: false

此处我们可以看到我们使用了RuntimeDefault, 该type是k8s默认的容器运行时profile。

此处可能的值为:

  • Unconfined - 如果没有其他选择,Seccomp不会应用于容器进程(这是Kubernetes中的默认设置)。
  • RuntimeDefault - 使用默认的容器运行时配置文件。
  • Localhost - 指定自定有的profile文件。当type 为该值时,此时必须指定localhostProfile字段的值。

比如:

apiVersion: v1
kind: Pod
metadata:
  name: violation-pod
  labels:
    app: violation-pod
spec:
  securityContext:
    seccompProfile:
      type: Localhost
      localhostProfile: profiles/fine-grained.json
  containers:
  - name: test-container
    image: hashicorp/http-echo:0.2.3
    args:
    - "-text=just made some syscalls!"
    securityContext:
      allowPrivilegeEscalation: false
 

我们看下fine-grained.json的值:

{
    "defaultAction": "SCMP_ACT_ERRNO",
    "architectures": [
        "SCMP_ARCH_X86_64",
        "SCMP_ARCH_X86",
        "SCMP_ARCH_X32"
    ],
    "syscalls": [
        {
            "names": [
                "accept4",
                "epoll_wait",
                "pselect6",
                "futex",
                "madvise",
                "epoll_ctl",
                "getsockname",
                "setsockopt",
                "vfork",
                "mmap",
                "read",
                "write",
                "close",
                "arch_prctl",
                "sched_getaffinity",
                "munmap",
                "brk",
                "rt_sigaction",
                "rt_sigprocmask",
                "sigaltstack",
                "gettid",
                "clone",
                "bind",
                "socket",
                "openat",
                "readlinkat",
                "exit_group",
                "epoll_create1",
                "listen",
                "rt_sigreturn",
                "sched_yield",
                "clock_gettime",
                "connect",
                "dup2",
                "epoll_pwait",
                "execve",
                "exit",
                "fcntl",
                "getpid",
                "getuid",
                "ioctl",
                "mprotect",
                "nanosleep",
                "open",
                "poll",
                "recvfrom",
                "sendto",
                "set_tid_address",
                "setitimer",
                "writev"
            ],
            "action": "SCMP_ACT_ALLOW"
        }
    ]
}

请注意,对现有注释的支持已被弃用,并将在1.22版中删除。此外,作为确保Kubelet向后兼容的一部分,将以以下优先级顺序执行Seccomp配置文件:

  • 容器Spec中通过seccompProfile 字段指定
  • 容器 注释指定
  • Pod Spec中通过seccompProfile 字段指定
  • Pod 注释指定

总结

Seccomp类似一个沙箱。

我们通过指定seccompProfile, Kubernetes允许将加载到节点上的seccomp配置文件自动应用于Pod和容器。

这样我们的应用程序就在一个沙箱中执行了,在安全性上有很大的提升,并且Seccomp可以让你更加精细化控制系统调用。


iyacontrol
1.4k 声望2.7k 粉丝

专注kubernetes,devops,aiops,service mesh。