容器安全

Kubernetes提供了多种机制来限制容器的行为,减少容器攻击面,保证系统安全性。

  • Security Context:限制容器的行为,包括Capabilities、ReadOnlyRootFilesystem、Privileged、RunAsNonRoot、RunAsUser以及SELinuxOptions等
  • Pod Security Policy:集群级的Pod安全策略,自动为集群内的Pod和Volume设置Security Context
  • Sysctls:允许容器设置内核参数,分为安全Sysctls和非安全Sysctls
  • AppArmor:限制应用的访问权限
  • Seccomp:Secure computing mode的缩写,限制容器应用可执行的系统调用

Security Context 安全上下文

Security Context的目的是限制不可信容器的行为,保护系统和其他容器不受其影响。 Kubernetes提供了三种配置Security Context的方法:

  • Container-level Security Context:仅应用到指定的容器
  • Pod-level Security Context:应用到Pod内所有容器以及Volume
  • Pod Security Policies(PSP):应用到集群内部所有Pod以及Volume

Container-level Security Context

Container-level Security Context仅应用到指定的容器上,并且不会影响Volume。比如设置容器运行在特权模式:

apiVersion: v1
kind: Pod
metadata:
  name: hello-world
spec:
  containers:
    - name: hello-world-container
      # The container definition
      # ...
      securityContext:
        privileged: true

Pod-level Security Context

Pod-level Security Context应用到Pod内所有容器,并且还会影响Volume(包括fsGroup和selinuxOptions)。

apiVersion: v1
kind: Pod
metadata:
  name: hello-world
spec:
  containers:
  # specification of the pod's containers
  # ...
  securityContext:
    fsGroup: 1234
    supplementalGroups: [5678]
    seLinuxOptions:
      level: "s0:c123,c456"

Pod Security Policies(PSP)

Pod Security Policies(PSP)是集群级的Pod安全策略,自动为集群内的Pod和Volume设置Security Context。 使用PSP需要API Server开启extensions/v1beta1/podsecuritypolicy,并且配置PodSecurityPolicy admission控制器。 支持的控制项

控制项    | 说明
privileged    | 运行特权容器
defaultAddCapabilities    | 可添加到容器的Capabilities
requiredDropCapabilities    |会从容器中删除的Capabilities
volumes|    控制容器可以使用哪些volume
hostNetwork|    host网络
hostPorts    |允许的host端口列表
hostPID|    使用host PID namespace
hostIPC|    使用host IPC namespace
seLinux    | SELinux Context
runAsUser|    user ID
supplementalGroups    |允许的补充用户组
fsGroup|    volume FSGroup
readOnlyRootFilesystem    |只读根文件系统

示例

限制容器的host端口范围为8000-8080:

apiVersion: extensions/v1beta1
kind: PodSecurityPolicy
metadata:
  name: permissive
spec:
  seLinux:
    rule: RunAsAny
  supplementalGroups:
    rule: RunAsAny
  runAsUser:
    rule: RunAsAny
  fsGroup:
    rule: RunAsAny
  hostPorts:
  - min: 8000
    max: 8080
  volumes:
  - '*'

SELinux

SELinux (Security-Enhanced Linux) 是一种强制访问控制(mandatory access control)的实现。它的作法是以最小权限原则(principle of least privilege)为基础,在Linux核心中使用Linux安全模块(Linux Security Modules)。SELinux主要由美国国家安全局开发,并于2000年12月22日发行给开放源代码的开发社区。 可以通过runcon来为进程设置安全策略,ls和ps的-Z参数可以查看文件或进程的安全策略。

开启与关闭SELinux

修改/etc/selinux/config文件方法:
开启:SELINUX=enforcing
关闭:SELINUX=disabled
通过命令临时修改:
开启:setenforce 1
关闭:setenforce 0
查询SELinux状态:getenforce

示例

apiVersion: v1
kind: Pod
metadata:
  name: hello-world
spec:
  containers:
  - image: gcr.io/google_containers/busybox:1.24
    name: test-container
    command:
    - sleep
    - "6000"
    volumeMounts:
    - mountPath: /mounted_volume
      name: test-volume
  restartPolicy: Never
  hostPID: false
  hostIPC: false
  securityContext:
    seLinuxOptions:
      level: "s0:c2,c3"
  volumes:
  - name: test-volume
    emptyDir: {}

这会自动给docker容器生成如下的HostConfig.Binds:

/var/lib/kubelet/pods/f734678c-95de-11e6-89b0-42010a8c0002/volumes/kubernetes.io~empty-dir/test-volume:/mounted_volume:Z
/var/lib/kubelet/pods/f734678c-95de-11e6-89b0-42010a8c0002/volumes/kubernetes.io~secret/default-token-88xxa:/var/run/secrets/kubernetes.io/serviceaccount:ro,Z
/var/lib/kubelet/pods/f734678c-95de-11e6-89b0-42010a8c0002/etc-hosts:/etc/hosts

对应的volume也都会正确设置SELinux:

$ ls -Z /var/lib/kubelet/pods/f734678c-95de-11e6-89b0-42010a8c0002/volumes
drwxr-xr-x. root root unconfined_u:object_r:svirt_sandbox_file_t:s0:c2,c3 kubernetes.io~empty-dir
drwxr-xr-x. root root unconfined_u:object_r:svirt_sandbox_file_t:s0:c2,c3 kubernetes.io~secret

关于SELinux的介绍可以参考: 图文教程:SELinux政策实施详解 这篇文章以漫画的形式来讲解 , 深入浅出

Sysctls

sysctl接口允许允许管理员在系统运行的状态下动态修改内核参数。 设置的参数在/proc/sys下可以看到。 其配置参数包含了多个Linux的多个子系统,比如:

  • kernel(以kernel.开头的参数)
  • networking(以net.开头的参数)
  • virtual memory (以vm.开头的参数)
  • MDADM (以dev.开头的参数)

namespaced 和 node-level 的sysctl参数: namespaced级别的sysctl参数运行每个pod各自配置而不冲突。 要在pod的语境里(编排文件中)使用, 必须namespaced级别的sysctl, 这些sysctl参数包括:

  • kernel.shm*,
  • kernel.msg*,
  • kernel.sem,
  • fs.mqueue.*,
  • net.*. 对于node-level级别的sysctl参数,比如vm.开头,dev.开头的参数, 如果要进行设置,需要管理员在node节点上配置(比如写node的/etc/sysctl.conf文件),或者用DaemonSet启动一个有系统特权的容器来进行设置。 Sysctls允许容器设置内核参数,分为安全Sysctls和非安全Sysctls
  • 安全Sysctls:即设置后不影响其他Pod的内核选项,只作用在容器namespace中,默认开启。包括以下几种
    • kernel.shm_rmid_forced : 这个参数启用后,会销毁未被使用的共享内存, 不要轻易开启
    • net.ipv4.ip_local_port_range: 表示用于向外连接的端口范围。缺省情况下很小:32768到61000
    • net.ipv4.tcp_syncookies: 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭
  • 非安全Sysctls:即设置好有可能影响其他Pod和Node上其他服务的内核选项,默认禁止。如果使用,需要管理员在配置kubelet时开启,如kubelet --experimental-allowed-unsafe-sysctls 'kernel.msg*,net.ipv4.route.min_pmtu' Sysctls还在alpha阶段,需要通过Pod annotation设置,如:
    apiVersion: v1
    kind: Pod
    metadata:
    name: sysctl-example
    annotations:
      security.alpha.kubernetes.io/sysctls: kernel.shm_rmid_forced=1
      security.alpha.kubernetes.io/unsafe-sysctls: net.ipv4.route.min_pmtu=1000,kernel.msgmax=1 2 3
    spec:
    ...
    

关于sysctl的介绍可以参考sysctl.conf学习和调优设置Linux内核参数 /etc/sysctl.conf

AppArmor

AppArmor(Application Armor)是Linux内核的一个安全模块,允许系统管理员将每个程序与一个安全配置文件关联,从而限制程序的功能。通过它你可以指定程序可以读、写或运行哪些文件,是否可以打开网络端口等。作为对传统Unix的自主访问控制模块的补充,AppArmor提供了强制访问控制机制。 在使用AppArmor之前需要注意

  • Kubernetes版本>=v1.4
  • apiserver和kubelet已开启AppArmor特性,--feature-gates=AppArmor=true
  • 已开启apparmor内核模块,通过cat /sys/module/apparmor/parameters/enabled查看
  • 仅支持docker container runtime
  • AppArmor profile已经加载到内核,通过cat /sys/kernel/security/apparmor/profiles查看 AppArmor还在alpha阶段,需要通过Pod annotation container.apparmor.security.beta.kubernetes.io/来设置。可选的值包括
  • runtime/default: 使用Container Runtime的默认配置
  • localhost/: 使用已加载到内核的AppArmor profile
$ sudo apparmor_parser -q <<EOF
#include <tunables/global>

profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
  #include <abstractions/base>

  file,

  # Deny all file writes.
  deny /** w,
}
EOF'

$ kubectl create -f /dev/stdin <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: hello-apparmor
  annotations:
    container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-deny-write
spec:
  containers:
  - name: hello
    image: busybox
    command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]
EOF
pod "hello-apparmor" created

$ kubectl exec hello-apparmor cat /proc/1/attr/current
k8s-apparmor-example-deny-write (enforce)

$ kubectl exec hello-apparmor touch /tmp/test
touch: /tmp/test: Permission denied
error: error executing remote command: command terminated with non-zero exit code: Error executing in Docker Container: 1

Seccomp

Seccomp是Secure computing mode的缩写,它是Linux内核提供的一个操作,用于限制一个进程可以执行的系统调用.Seccomp需要有一个配置文件来指明容器进程允许和禁止执行的系统调用。 在Kubernetes中,需要将seccomp配置文件放到/var/lib/kubelet/seccomp目录中(可以通过kubelet选项--seccomp-profile-root修改)。比如禁止chmod的格式为

$ cat /var/lib/kubelet/seccomp/chmod.json
{
    "defaultAction": "SCMP_ACT_ALLOW",
    "syscalls": [
        {
            "name": "chmod",
            "action": "SCMP_ACT_ERRNO"
        }
    ]
}

Seccomp还在alpha阶段,需要通过Pod annotation设置,包括:

  • security.alpha.kubernetes.io/seccomp/pod:应用到该Pod的所有容器
  • security.alpha.kubernetes.io/seccomp/container/:应用到指定容器

而value有三个选项:

  • runtime/default: 使用Container Runtime的默认配置
  • unconfined: 允许所有系统调用
  • localhost/: 使用Node本地安装的seccomp,需要放到/var/lib/kubelet/seccomp目录中

比如使用刚才创建的seccomp配置:

apiVersion: v1
kind: Pod
metadata:
  name: trustworthy-pod
  annotations:
    seccomp.security.alpha.kubernetes.io/pod: localhost/chmod
spec:
  containers:
    - name: trustworthy-container
      image: sotrustworthy:latest

参考文献

容器安全 Kubernetes集群安全配置案例 轻松了解Kubernetes认证功能 Kubernetes技术分析之安全 Kubernetes双向TLS配置-Centos7

Copyright © suredandan 2018 all right reserved,powered by GitbookUpdateTime: 2020-04-09 16:42:03

results matching ""

    No results matching ""