二十五、K8s系统强化1- 系统安全与apparmor
使用apparmor保护K8s集群
一、实验环境:
底层系统为ubuntu18.04,然后在每个node上安装k8s,并构建集群。Master node的IP地址为192.168.26.71/24,两个Worker node的IP地址为192.168.26.72/24、192.168.26.73/24。
二、系统安全:
1.去除多余的系统模块
由于容器运行在在操作系统上,虽然看似独立,其实也使用了宿主机的CPU、内存、内核等资源,我们在容器内做的操作,也会在操作系统内有所反应。同样的,操作系统中的漏洞也可能会影响到容器。例如,容器运行时会加载底层操作系统Linux内核中的模块,如果宿主机Linux的内核中加载了有漏洞的模块, 则也会影响到容器的安全,所以我们也需要在操作系统层面进行加固。
为了保证容器中不会加载底层操作系统的恶意代码,我们首先需要去除底层操作系统中不必要的系统模块。
例如,我们首先生成一个容器pod1,yaml文件如下:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod1
name: pod1
spec:
terminationGracePeriodSeconds: 0
containers:
- image: centos
command: ["sh","-c","sleep 10000000"]
imagePullPolicy: IfNotPresent
name: pod1
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
现在我们可以查看pod1部署在哪个worker node上:
root@vms71:~/system-security# kubectl get pod pod1 -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod1 1/1 Running 0 86s 10.244.5.238 vms72.rhce.cc <none> <none>
可以看到,其运行在worker1上。那么我们可以切换到worker1这台设备,查看其加载了多少个内核模块:
root@vms72:~# lsmod | wc -l
123
可以看到是123个。紧接着,我们进入到pod1中,也查看其中存在多少个内核模块:
[root@pod1 /]# lsmod | wc -l
123
可以看到,也是123三个。紧接着我们在worker1上加载一个存在漏洞的内核模块,然后观察pod1中的变化:
root@vms72:~# modprobe pcspkr
root@vms72:~# lsmod | grep pcspkr
pcspkr 16384 0
进入pod1中,查看是否变为了124个模块,并且多添加了一个pcspkr模块:
[root@pod1 /]# lsmod | wc -l
124
[root@pod1 /]# lsmod | grep pcspkr
pcspkr 16384 0
可以看到,在pod1中,也加载了pcspkr模块。那么,一旦宿主机被通过pcspkr模块工具,也会影响到容器。最后,我们需要在worker1上删除掉这个存在漏洞的模块。
modprobe -r pcspkr
注意,我们可以通过修改Linux操作系统的/etc/modprobe.d/xxxx.conf文件,决定Linux能够加载哪些模块。这样的话方便我们将存在风险的模块加入黑名单中,保证Linux系统和容器的安全:
root@vms72:/etc/modprobe.d# cat blacklist.conf
# This file lists those modules which we don't want to be loaded by
# alias expansion, usually so some other driver will be loaded for the
# device instead.
# evbug is a debug tool that should be loaded explicitly
blacklist evbug
# these drivers are very simple, the HID drivers are usually preferred
blacklist usbmouse
blacklist usbkbd
# replaced by e100
blacklist eepro100
# replaced by tulip
blacklist de4x5
.........
例如,在这里我们可以在其目录下,任何为.conf的文件中,将不必要的模块通过blacklist禁用掉。
2.最小权限原则
最小权限原则 (PoLP) 是一种信息安全概念,即为用户提供执行其工作职责所需的最小权限等级或许可。主要可以通过如下方式在系统中进行实现:
- 在内部、云、DevOps环境和端点中,审核整个环境以查找特权帐户(例如密码、SSH密钥、密码哈希和访问密钥)。
- 消除不必要的本地管理员权限,并确保所有人类用户和非人类用户仅具有执行其工作所需的权限。
- 将管理员帐户与标准帐户分开,并隔离特权用户会话。
- 将特权管理员帐户凭据提供给数字保管库,以开始保护和管理这些帐户。
- 每次使用后,立即轮换所有管理员密码,以使按键记录软件可能已捕获的所有凭据无效,并降低哈希传递的风险。
- 持续监视与管理员帐户有关的所有活动,以快速检测和警告可能表明正在进行攻击的异常活动。
- 启用即时访问特权升级,允许用户根据需要临时访问特权帐户或运行特权命令。
三、Apparmor:
1.Apparmor概述:
Apparmor 是一个 Linux 内核安全模块,它补充了标准的基于 Linux 用户和组的安全模块将程序限制为有限资源集的权限。
AppArmor 可以配置为任何应用程序减少潜在的攻击面,并且提供更加深入的防御。 AppArmor 是通过配置文件进行配置的,这些配置文件被调整为允许特定程序或者容器访问,如 Linux 功能、网络访问、文件权限等。 每个配置文件都可以在强制(enforcing)模式(阻止访问不允许的资源)或投诉(complain)模式 (仅报告冲突)下运行。
注意:Apparmor存在于ubuntu系统,如果是在centos/redhat系统中,请使用selinux。
2.操作系统层面的apparmor运用
因为在很早的 Debian 和 Ubuntu 发行版内核中,就自带了 AppArmor 模块。因此只需要使用 apt 安装用户空间的命令组件即可。apparmor-utils 是一组用户空间的命令行实用工具,可以帮助我们很好的管理 AppArmor 。后两者是一些预先配置的配置文件,这些配置文件一般来说是比较完善的,但是也需要根据实际需要进行修改。
apt install apparmor-utils apparmor-profiles apparmor-profiles-extra
然后查看apparmor是否开启:
root@ubuntu:~# aa-enabled
Yes
AppArmor 通过配置文件来管理各个程序的权限。配置文件的文件名通常是其控制的程序的完整路径名(比如 /etc/apparmor.d/usr.sbin.nginx 是控制 Nginx 的配置文件) 。生效的配置文件的位置是 /etc/apparmor.d,而提供的一些可选配置文件夹位于 /usr/share/apparmor/profiles 里。可以通过软连接的方法,将这些配置连接到 /etc/apparmor.d,从而启用配置。
ln -s /usr/share/apparmor/extra-profiles/usr.sbin.sshd /etc/apparmor.d
进入到/etc/apparmor.d/目录下,可以查看到如下的内容:
root@ubuntu:/etc/apparmor.d# ls
abstractions nvidia_modprobe usr.bin.evince usr.lib.libreoffice.program.oosplash usr.sbin.cups-browsed usr.sbin.nscd
apache2.d sbin.dhclient usr.bin.firefox usr.lib.libreoffice.program.senddoc usr.sbin.cupsd usr.sbin.rsyslogd
bin.ping sbin.klogd usr.bin.irssi usr.lib.libreoffice.program.soffice.bin usr.sbin.dnsmasq usr.sbin.smbd
disable sbin.syslogd usr.bin.man usr.lib.libreoffice.program.xpdfimport usr.sbin.identd usr.sbin.smbldap-useradd
force-complain sbin.syslog-ng usr.bin.pidgin usr.lib.snapd.snap-confine.real usr.sbin.ippusbxd usr.sbin.sshd
local tunables usr.bin.totem usr.sbin.apt-cacher-ng usr.sbin.mdnsd usr.sbin.tcpdump
lsb_release usr.bin.chromium-browser usr.bin.totem-previewers usr.sbin.avahi-daemon usr.sbin.nmbd usr.sbin.traceroute
例如usr.bin.evince文件,则是表示对操作系统中/usr/bin/evince进行管控。我们可以通过配置对应的文件,达到对于程序进行访问控制的要求。下面我们来看一个典型的配置文件 /etc/apparmor.d/usr.sbin.nginx (需要自己生成):
#include <tunables/global>
/usr/sbin/nginx {
#include <abstractions/apache2-common>
#include <abstractions/base>
capability dac_override,
capability setgid,
capability setuid,
deny /srv/private/** rw,
/etc/nginx/** r,
/srv/www/** r,
/var/lib/nginx/ rw,
/var/log/nginx/* w,
/var/www/html r,
/etc/group r,
/etc/nginx/cert.d/* r,
/etc/nginx/conf.d/* r,
/etc/nsswitch.conf r,
/etc/passwd r,
/etc/ssl/openssl.cnf r,
/run/nginx.pid rw,
/usr/lib/nginx/** m,
/usr/share/nginx/modules-available/* r,
/var/lib/nginx/** rw,
}
如何一步步完成这个文件的配置,为如下5给步奏:
-
首先使用 aa-autodep <程序名,比如 nginx> 来生成一个初始化的配置文件。这个文件目前没有任何规则。
-
第二步,使用 aa-complain <程序名> 来将这个配置文件启动complain,这时候会记录所有需要授权的行为。
-
第三步,过一段时间后,使用 aa-logprof。这一步非常关键,这个命令会读取日志中所有操作,然后逐条询问之后是否允许这样的操作。(A 运行,D 不允许, I 忽略,G 改用通配符,N 修改规则)。然后把你的要求写入到对应的配置文件中去,从而形成了符合你需求的配置文件。
-
第四步,根据你的预期可以直接修改规则配置文件。
-
第五步,测试一段时间且规则没有问题后,可以使用 aa-enforce <程序名> 开启 enforce 模式。
具体步骤请参考: https://www.elliot98.top/post/tech/apparmor/
3.K8s中的apparmor运用
上面提到了apparmor在Linux系统中的使用,我们也可以将apparmor的规则运用在pod中。
首先,由于我们不知道pod部署具体部署在哪个node上,于是可以在所有的worker node上的/etc/apparmor.d写下如下的规则(文件名自定义即可,不需要和在Linux上直接使用apparmor一样表示具体的管控路径):
#include <tunables/global>
profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
#include <abstractions/base>
file,
# Deny all file writes.
deny /** w,
}
其中,#include <abstractions/base>表示允许预定义的一些操作,file的表示允许了所有的读写操作,deny /** w表示不允许对所有文件的写操作。这也是我们编写apparmor规则的方式,由于deny的优先级高于permit的优先级,所以我们可以先permit比较大范围的操作,然后通过deny的方式,拒绝掉其中一些我们存在问题的操作。
接下来,我们可以在worker上启用这一个规则,命令如下:
apparmor_parser -q k8s-apparmor-example-deny-write #规则的文件名
启用完成后,我们可以使用命令查看是否运行成功:
apparmor_status | grep k8s-apparmor-example-deny-write # 规则名
除此之外,如下命令表示删除规则:
apparmor_parser -R 规则文件名
而在规则更新后,可以使用如下命令替换规则:
apparmor_parser -r 规则文件名
接下来,我们将运行一个带有拒绝写入配置文件的简单 “Hello AppArmor” pod,yaml文件如下:
apiVersion: v1
kind: Pod
metadata:
name: hello-apparmor
annotations:
# Tell Kubernetes to apply the AppArmor profile "k8s-apparmor-example-deny-write".
# Note that this is ignored if the Kubernetes node is not running version 1.4 or greater.
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" ]
相比于没有使用apparmor规则的pod,此pod特殊在添加了如果的内容:
annotations:
# Tell Kubernetes to apply the AppArmor profile "k8s-apparmor-example-deny-write".
# Note that this is ignored if the Kubernetes node is not running version 1.4 or greater.
container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-deny-write
首先,container.apparmor.security.beta.kubernetes.io内容为固定;由于一个pod中可以存在多个容器,所以hello指定了具体应用规则的容器;localhost为关键字,表示运行在pod所在的节点;最后k8s-apparmor-example-deny-write为运行节点上所使用的apparmor规则。
容器创建完成后,我们可以通过检查该配置文件的 proc attr 来验证容器是否实际使用该配置文件运行:
root@vms71:~/system-security# kubectl exec hello-apparmor -- cat /proc/1/attr/current
k8s-apparmor-example-deny-write (enforce)
最后,我们可以看到如果试图通过写入文件来违反配置文件,会发生什么情况:
root@vms71:~/system-security# kubectl exec hello-apparmor -- touch /tmp/test
touch: /tmp/test: Permission denied
command terminated with exit code 1
可以看到,操作已经被deny掉了。
参考资料来源:
《老段CKS课程》
最小权限原则 (PoLP):https://www.cyberark.com/zh-hans/what-is/least-privilege/
浅谈Linux 强制访问控制 AppArmor:https://www.elliot98.top/post/tech/apparmor/
K8s apparmor:https://kubernetes.io/zh/docs/tutorials/clusters/apparmor/#举例
更多推荐
所有评论(0)