zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Kubernetes SecurityContext 安全上下文 容器添加禁用内核功能及阻止对容器根文件系统的写入

Kubernetes内核安全容器 功能 添加 写入 文件系统
2023-09-14 09:15:18 时间

过去, 传统的 UNIX 实现只区分特权和非特权进程, 但是经过多年的发展, Linux已经可以通过内核功能支持更细粒度的权限系统。

相比于让容器运行在特权模式下以给予其无限的权限, 一个更加安全的做法是只给予它使用真正需要的内核功能的权限。

Kubernetes允许为特定的容器添加内核功能, 或禁用部分内核功能, 以允许对容器进行更加精细的权限控制, 限制攻击者潜在侵入的影响。
 

例如,一个容器通常不允许修改系统时间(硬件时钟的时间)。 可以通过在pod-with-defaults-pod中修改设定时间来验证:

$ kubectl exec -it pod-with-defaults -- date +尧T -s "12:00:00"
date: can'七 se七 date: Operation not permitted

 如果需要允许容器修改系统时间, 可以在容器的capabilites里add 一项名为CAP_SYS_TIME的功能, 如以下代码清单所示。

[root@k8s-master ~]# cat test.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-add-settime-capability
spec:
  containers:
  - name: main
    image: alpine
    command: ["/bin/sleep","9999999"]
    securityContext:
      capabilities:
        add:
        - SYS_TIME


在内核功能 securityContext中添加或禁用,在这里添加了 SYS_TIME功能

在新的容器中运行同样的命令,可以成功修改系统时间:

[root@k8s-master ~]# kubectl exec -it   pod-add-settime-capability  sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # date
Mon Aug  9 01:35:37 UTC 2021
/ # date +%T -s "12:00:00"
12:00:00
/ # date
Mon Aug  9 12:00:02 UTC 2021
/ # exit

为了阻止容器的此种行为, 需要如以下代码清单所示, 在容器securiyContext.capability.drop 列表中加入此项, 以禁用这个修改文件所有者的内核功能。

[root@k8s-master ~]# cat test.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-drop-chown-capability
spec:
  containers:
  - name: main
    image: alpine
    command: ["/bin/sleep","9999999"]
    securityContext:
      capabilities:
        drop:
        - CHOWN


[root@k8s-master ~]# kubectl exec -it pod-drop-chown-capability sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ 

# chown guest /tmp
chown: /tmp: Operation not permitted

这里已经对容器安全上下文的大部分选项研究完毕。 下面再介绍一个选项。
 

阻止对容器根文件系统的写入


因为安全原因你可能需要阻止容器中的进程对容器的根文件系统进行写入,仅允许它们写入挂载的存储卷。

假如你在运行一个有隐藏漏洞, 可以允许攻击者写入文件系统的 PHP 应用。 这些 PHP 文件在构建时放入容器的镜像中, 并且在容器的根文件系统中提供服务。 由于漏洞的存在, 攻击者可以修改这些文件, 在其中注入恶意代码。

这一类攻击可以通过阻止容器写入自己的根文件系统(应用的可执行代码的通常储存位置)来防止。 可以如以下代码清单所示, 将容器的 securityContext.readOnlyRootFilesystem 设置为 true来实现。

[root@k8s-master ~]# cat test1.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-with-readonly-filesystem
spec:
  containers:
  - name: main
    image: alpine
    command: ["/bin/sleep", "999999"]
    securityContext:
      readOnlyRootFilesystem: true
    volumeMounts:
    - name: my-volume
      mountPath: /volume
      readOnly: false
  volumes:
  - name: my-volume
    emptyDir: {}

 这个容器的根文件系统不允许写入,但是向/volume写入是允许的, 因为这个目录挂载了一个存储卷。

这个pod中的容器虽然以root用户运行, 拥有/目录的写权限, 但在该目录下写入一个文件会失败:

[root@k8s-master ~]# kubectl get pod
NAME                           READY   STATUS    RESTARTS   AGE
pod-with-readonly-filesystem   1/1     Running   0          2m40s

[root@k8s-master ~]# kubectl exec -it pod-with-readonly-filesystem sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # touch /newfile
touch: /newfile: Read-only file system

另 一方面, 对挂载的卷的写入是允许的:

/ # touch /volume/newfile
/ # exit

如以上例子所示, 如果容器的根文件系统是只读的, 你很可能需要为应用会写入的每一个目录(如日志、 磁盘缓存等)挂载存储卷。
 

提示为了增强安全性, 请将在生产环境运行的容器的readOnlyRootFilesystem选项设置为true。