apparmor小记
容器得到快速发展,但是安全依然不容忽视,,apparmor浮出了水面,字面意思为应用盔甲,下面就来简单介绍下。
介绍
这是一个linux的内核安全模块,是一个MAC(强制控制存取)系统,和Selinux类似的一种访问控制系统,每个进程都可以相应的有自己的安全配置文件,这文件里面用来指定允许或者禁止某种功能,例如网络端口、访问、文件相关的读写以及执行等,比如linux发行版unbuntu、debian等都是内置的。能限制程序在一组有限的资源,那就能限制容器对资源的访问。
需要安装软件包apparmor-utils
工作模式
ApppArmor有两种工作模式:
- Enforced/Confined: 严格按照配置文件来限制对应的进程访问OS资源的行为,拒绝不在配置范围内的进程运行。
- Complaining/Learning: 仅记录进程行为,不对其进行限制。
常用命令
-
apparmor_status:看AppArmor配置文件的当前状态的
-
apparmor_parser:这个就是将AppArmor配置文件直接加载到内核
-
apparmor_parser -R :删除配置
-
aa-complain:这个可以把AppArmor配置文件设置为complain模式
-
aa-enforce:将AppArmor配置文件设置为enforce模式
访问文件权限的模式
AppArmor对于程序多手段限制,文件系统方面如下:
字符 | 意思 |
---|---|
r | read |
w | write |
a | append |
k | file locking |
l | link |
x | execute |
1、版本不能太老不要小于1.4,当然一般都满足:kubectl describe node|grep AppArmor或者如下验证:
kubectl get nodes -o=jsonpath=$'{@.metadata.name}: {@.status.nodeInfo.kubeletVersion}\n'
2、linux内核启用AppArmor这个模块,查看
cat /sys/module/apparmor/parameters/enabled
Y 表示启用
N表示未启用
3、是容器运行得支持,现在Docker是支持的
4、配置已经加载 命令 apparmor_parser
5、查看apparmor状态命令aa-status
如何限制容器对目录或者文件访问
执行一个带有apparmor配置的pod步骤大概如下:
1、确定策略名称
2、加载策略
3、修改pod-yaml文件
4、kubectl apply -f xxxx.yaml
注意:如果想要pod使用apparmor,限制对容器资源的操作,就得先声明让容器使用apparmor,不然默认情况下是不具备apparmor这种能力的。
容器运行时,如docker, cri-d, containerd 等都支持使用 apparmor
使用apparmor需要创建一个profile,这个 profile可以通过学习得到(扫码目标程序运行时生成的auditlog),也可以手工创建,我们这里手工创建一个。
profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
file,
# Deny all file writes.
deny /** w,
}
解释一下。file
,允许对文件系统的全部访问,deny /** w, 禁止对 / root 目录的写。
保存这个文件到 /etc/apparmor.d 目录下,起名为k8s-apparmor-example-deny-write 。然后用apparmor_parser 来读取,如果没有这个apparmor_parser,请用apt 安装一下。
# apparmor_parser -r ./k8s-apparmor-example-deny-write -v
Replacement succeeded for "k8s-apparmor-example-deny-write".
读取后,我们用aa_status 可以读取到
# aa-status | grep -A 5 -B 5 k8s-apparmor-example-deny-write
/usr/sbin/tcpdump
/{,usr/}sbin/dhclient
cri-containerd.apparmor.d
docker-default
ippusbxd
k8s-apparmor-example-deny-write <<< -----
lsb_release
man_filter
也可以
# cat /sys/kernel/security/apparmor/profiles
docker-default (enforce)
snap.lxd.migrate (enforce)
snap.lxd.lxd (enforce)
snap.lxd.lxc-to-lxd (enforce)
snap.lxd.lxc (enforce)
snap.lxd.hook.install (enforce)
snap.lxd.hook.remove (enforce)
snap.lxd.daemon (enforce)
snap.lxd.hook.configure (enforce)
snap.lxd.check-kernel (enforce)
snap.lxd.buginfo (enforce)
snap.lxd.benchmark (enforce)
snap.lxd.activate (enforce)
snap-update-ns.lxd (enforce)
/snap/snapd/16292/usr/lib/snapd/snap-confine (enforce)
/snap/snapd/16292/usr/lib/snapd/snap-confine//mount-namespace-capture-helper (enforce)
/snap/snapd/16010/usr/lib/snapd/snap-confine (enforce)
/snap/snapd/16010/usr/lib/snapd/snap-confine//mount-namespace-capture-helper (enforce)
ippusbxd (enforce)
cri-containerd.apparmor.d (enforce)
/usr/lib/snapd/snap-confine (enforce)
/usr/lib/snapd/snap-confine//mount-namespace-capture-helper (enforce)
/usr/sbin/chronyd (enforce)
/home/ubuntu/apparmor/example.sh (enforce)
/{,usr/}sbin/dhclient (enforce)
/usr/lib/connman/scripts/dhclient-script (enforce)
/usr/lib/NetworkManager/nm-dhcp-helper (enforce)
/usr/lib/NetworkManager/nm-dhcp-client.action (enforce)
/usr/sbin/tcpdump (enforce)
kubearmor-default-nginx (enforce)
k8s-apparmor-example-deny-write (enforce)
man_groff (enforce)
man_filter (enforce)
/usr/bin/man (enforce)
nvidia_modprobe (enforce)
nvidia_modprobe//kmod (enforce)
lsb_release (enforce)
可以看到,k8s-apparmor-example-deny-write已经load profile,且是enforce的。
然后我们用可以安装启用了apparmor的pod 了。
对pod启用apparmor的命令是
$ cat apparmor-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: hello-apparmor
annotations:
# Tell Kubernetes to apply the AppArmor profile "k8s-apparmor-example-deny-write".
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" ]
$ kubectl create -f apparmor-pod.yaml
可以看到在annotation里有
kubearmor-policy: enabled kubearmor-visibility: process,file,network,capabilities
尝试在POD里创建文件到/ 会被apparmor拒绝。
$ kubectl exec -it po/hello-apparmor -- sh
# mkdir /asdfasdf
mkdir: can't create directory '/asdfasdf': Permission denied
通过这个命令也能看到POD被赋予了什么profile.
kubectl exec <PODNAME> cat /proc/1/attr/current
跳过apparmor
1. 直接更改AppArmor 的配置文件
这里以mysqld为例:
# 给/etc/apparmor.d/user.sbin.mysqld里添加如下内容
# pid,socket等文件目录
/opt/mysql/* rw,
# 数据目录内容
/opt/mysql/data/ r,
/opt/mysql/data/** rwk,
#日志文件内容
/opt/mysql/log/ r,
/opt/mysql/log** rw,
重载 AppArmor 服务
# systemctl reload apparmor
再次重启 MySQL ,启动成功。
# systemctl start mysql
2. 改变 AppArmor 的默认工作模式,由强制模式改为抱怨模式:
得先安装 apparmor-utils 包,里面包含了很多有用的程序来操作 AppArmor .
# apt-get install apparmor-utils
单独配置 MySQL 服务进入抱怨模式:
# aa-complain /etc/apparmor.d/usr.sbin.mysqld
Setting /etc/apparmor.d/usr.sbin.mysqld to complain mode.
重载 AppArmor
# systemctl reload apparmor
启动 MySQL 服务
# systemctl restart mysql
在使用Apparmor时,报错apparmor filesystem is not mounted问题解决办法:
$ sudo apparmor_status
apparmor module is loaded.
apparmor filesystem is not mounted.
修改/etc/default/grub文件,设置GRUB_CMDLINE_LINUX_DEFAULT
为"apparmor=1 security=apparmor"。
然后运行grub2-mkconfig -o /boot/grub2/grub.conf
(追加的文件以实际grub.conf为主,efi的与此不同),重启操作系统reboot
参考文档:
https://zhuanlan.zhihu.com/p/540279876
https://new.qq.com/rain/a/20220802A0346Z00
https://zhuanlan.zhihu.com/p/445535991
https://segmentfault.com/a/1190000010966281